4 * Copyright IBM, Corp. 2012
10 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
11 * See the COPYING.LIB file in the top-level directory.
20 * A hub broadcasts incoming packets to all its ports except the source port.
21 * Hubs can be used to provide independent network segments, also confusingly
22 * named the QEMU 'vlan' feature.
25 typedef struct NetHub NetHub;
27 typedef struct NetHubPort {
29 QLIST_ENTRY(NetHubPort) next;
36 QLIST_ENTRY(NetHub) next;
38 QLIST_HEAD(, NetHubPort) ports;
41 static QLIST_HEAD(, NetHub) hubs = QLIST_HEAD_INITIALIZER(&hubs);
43 static ssize_t net_hub_receive(NetHub *hub, NetHubPort *source_port,
44 const uint8_t *buf, size_t len)
48 QLIST_FOREACH(port, &hub->ports, next) {
49 if (port == source_port) {
53 qemu_send_packet(&port->nc, buf, len);
58 static ssize_t net_hub_receive_iov(NetHub *hub, NetHubPort *source_port,
59 const struct iovec *iov, int iovcnt)
64 QLIST_FOREACH(port, &hub->ports, next) {
65 if (port == source_port) {
69 ret = qemu_sendv_packet(&port->nc, iov, iovcnt);
74 static NetHub *net_hub_new(int id)
78 hub = g_malloc(sizeof(*hub));
81 QLIST_INIT(&hub->ports);
83 QLIST_INSERT_HEAD(&hubs, hub, next);
88 static ssize_t net_hub_port_receive(VLANClientState *nc,
89 const uint8_t *buf, size_t len)
91 NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);
93 return net_hub_receive(port->hub, port, buf, len);
96 static ssize_t net_hub_port_receive_iov(VLANClientState *nc,
97 const struct iovec *iov, int iovcnt)
99 NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);
101 return net_hub_receive_iov(port->hub, port, iov, iovcnt);
104 static void net_hub_port_cleanup(VLANClientState *nc)
106 NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);
108 QLIST_REMOVE(port, next);
111 static NetClientInfo net_hub_port_info = {
112 .type = NET_CLIENT_OPTIONS_KIND_HUBPORT,
113 .size = sizeof(NetHubPort),
114 .receive = net_hub_port_receive,
115 .receive_iov = net_hub_port_receive_iov,
116 .cleanup = net_hub_port_cleanup,
119 static NetHubPort *net_hub_port_new(NetHub *hub, const char *name)
123 int id = hub->num_ports++;
124 char default_name[128];
127 snprintf(default_name, sizeof(default_name),
128 "hub%dport%d", hub->id, id);
132 nc = qemu_new_net_client(&net_hub_port_info, NULL, NULL, "hub", name);
133 port = DO_UPCAST(NetHubPort, nc, nc);
137 QLIST_INSERT_HEAD(&hub->ports, port, next);
143 * Create a port on a given hub
144 * @name: Net client name or NULL for default name.
146 * If there is no existing hub with the given id then a new hub is created.
148 VLANClientState *net_hub_add_port(int hub_id, const char *name)
153 QLIST_FOREACH(hub, &hubs, next) {
154 if (hub->id == hub_id) {
160 hub = net_hub_new(hub_id);
163 port = net_hub_port_new(hub, name);
168 * Print hub configuration
170 void net_hub_info(Monitor *mon)
175 QLIST_FOREACH(hub, &hubs, next) {
176 monitor_printf(mon, "hub %d\n", hub->id);
177 QLIST_FOREACH(port, &hub->ports, next) {
178 monitor_printf(mon, " port %d peer %s\n", port->id,
179 port->nc.peer ? port->nc.peer->name : "<none>");
185 * Get the hub id that a client is connected to
187 * @id Pointer for hub id output, may be NULL
189 int net_hub_id_for_client(VLANClientState *nc, int *id)
193 if (nc->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
194 port = DO_UPCAST(NetHubPort, nc, nc);
195 } else if (nc->peer != NULL && nc->peer->info->type ==
196 NET_CLIENT_OPTIONS_KIND_HUBPORT) {
197 port = DO_UPCAST(NetHubPort, nc, nc->peer);
208 int net_init_hubport(const NetClientOptions *opts, const char *name,
209 VLANClientState *peer)
211 const NetdevHubPortOptions *hubport;
213 assert(opts->kind == NET_CLIENT_OPTIONS_KIND_HUBPORT);
214 hubport = opts->hubport;
216 /* Treat hub port like a backend, NIC must be the one to peer */
221 net_hub_add_port(hubport->hubid, name);