2 * QEMU rocker switch emulation - front-panel ports
4 * Copyright (c) 2014 Scott Feldman <sfeldma@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include "net/clients.h"
20 #include "rocker_hw.h"
21 #include "rocker_fp.h"
22 #include "rocker_world.h"
44 char *fp_port_get_name(FpPort
*port
)
49 bool fp_port_get_link_up(FpPort
*port
)
51 return !qemu_get_queue(port
->nic
)->link_down
;
54 void fp_port_get_info(FpPort
*port
, RockerPortList
*info
)
56 info
->value
->name
= g_strdup(port
->name
);
57 info
->value
->enabled
= port
->enabled
;
58 info
->value
->link_up
= fp_port_get_link_up(port
);
59 info
->value
->speed
= port
->speed
;
60 info
->value
->duplex
= port
->duplex
;
61 info
->value
->autoneg
= port
->autoneg
;
64 void fp_port_get_macaddr(FpPort
*port
, MACAddr
*macaddr
)
66 memcpy(macaddr
->a
, port
->conf
.macaddr
.a
, sizeof(macaddr
->a
));
69 void fp_port_set_macaddr(FpPort
*port
, MACAddr
*macaddr
)
71 /* XXX TODO implement and test setting mac addr
72 * XXX memcpy(port->conf.macaddr.a, macaddr.a, sizeof(port->conf.macaddr.a));
76 uint8_t fp_port_get_learning(FpPort
*port
)
78 return port
->learning
;
81 void fp_port_set_learning(FpPort
*port
, uint8_t learning
)
83 port
->learning
= learning
;
86 int fp_port_get_settings(FpPort
*port
, uint32_t *speed
,
87 uint8_t *duplex
, uint8_t *autoneg
)
90 *duplex
= port
->duplex
;
91 *autoneg
= port
->autoneg
;
96 int fp_port_set_settings(FpPort
*port
, uint32_t speed
,
97 uint8_t duplex
, uint8_t autoneg
)
99 /* XXX validate inputs */
102 port
->duplex
= duplex
;
103 port
->autoneg
= autoneg
;
108 bool fp_port_from_pport(uint32_t pport
, uint32_t *port
)
110 if (pport
< 1 || pport
> ROCKER_FP_PORTS_MAX
) {
117 int fp_port_eg(FpPort
*port
, const struct iovec
*iov
, int iovcnt
)
119 NetClientState
*nc
= qemu_get_queue(port
->nic
);
122 qemu_sendv_packet(nc
, iov
, iovcnt
);
128 static int fp_port_can_receive(NetClientState
*nc
)
130 FpPort
*port
= qemu_get_nic_opaque(nc
);
132 return port
->enabled
;
135 static ssize_t
fp_port_receive_iov(NetClientState
*nc
, const struct iovec
*iov
,
138 FpPort
*port
= qemu_get_nic_opaque(nc
);
140 return world_ingress(port
->world
, port
->pport
, iov
, iovcnt
);
143 static ssize_t
fp_port_receive(NetClientState
*nc
, const uint8_t *buf
,
146 const struct iovec iov
= {
147 .iov_base
= (uint8_t *)buf
,
151 return fp_port_receive_iov(nc
, &iov
, 1);
154 static void fp_port_cleanup(NetClientState
*nc
)
158 static void fp_port_set_link_status(NetClientState
*nc
)
160 FpPort
*port
= qemu_get_nic_opaque(nc
);
162 rocker_event_link_changed(port
->r
, port
->pport
, !nc
->link_down
);
165 static NetClientInfo fp_port_info
= {
166 .type
= NET_CLIENT_OPTIONS_KIND_NIC
,
167 .size
= sizeof(NICState
),
168 .can_receive
= fp_port_can_receive
,
169 .receive
= fp_port_receive
,
170 .receive_iov
= fp_port_receive_iov
,
171 .cleanup
= fp_port_cleanup
,
172 .link_status_changed
= fp_port_set_link_status
,
175 World
*fp_port_get_world(FpPort
*port
)
180 void fp_port_set_world(FpPort
*port
, World
*world
)
182 DPRINTF("port %d setting world \"%s\"\n", port
->index
, world_name(world
));
186 bool fp_port_enabled(FpPort
*port
)
188 return port
->enabled
;
191 static void fp_port_set_link(FpPort
*port
, bool up
)
193 NetClientState
*nc
= qemu_get_queue(port
->nic
);
195 if (up
== nc
->link_down
) {
197 nc
->info
->link_status_changed(nc
);
201 void fp_port_enable(FpPort
*port
)
203 fp_port_set_link(port
, true);
204 port
->enabled
= true;
205 DPRINTF("port %d enabled\n", port
->index
);
208 void fp_port_disable(FpPort
*port
)
210 port
->enabled
= false;
211 fp_port_set_link(port
, false);
212 DPRINTF("port %d disabled\n", port
->index
);
215 FpPort
*fp_port_alloc(Rocker
*r
, char *sw_name
,
216 MACAddr
*start_mac
, unsigned int index
,
219 FpPort
*port
= g_malloc0(sizeof(FpPort
));
227 port
->pport
= index
+ 1;
229 /* front-panel switch port names are 1-based */
231 port
->name
= g_strdup_printf("%sp%d", sw_name
, port
->pport
);
233 memcpy(port
->conf
.macaddr
.a
, start_mac
, sizeof(port
->conf
.macaddr
.a
));
234 port
->conf
.macaddr
.a
[5] += index
;
235 port
->conf
.bootindex
= -1;
236 port
->conf
.peers
= *peers
;
238 port
->nic
= qemu_new_nic(&fp_port_info
, &port
->conf
,
239 sw_name
, NULL
, port
);
240 qemu_format_nic_info_str(qemu_get_queue(port
->nic
),
241 port
->conf
.macaddr
.a
);
248 void fp_port_free(FpPort
*port
)
250 qemu_del_nic(port
->nic
);
255 void fp_port_reset(FpPort
*port
)
257 fp_port_disable(port
);
258 port
->speed
= 10000; /* 10Gbps */
259 port
->duplex
= DUPLEX_FULL
;