summaryrefslogblamecommitdiffstats
path: root/net/hub.c
blob: 1375738bf121475ee5f4dfd8b717f4f60ca7c895 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14













                                                                             
                       
                       
                            
                    
                    
                
                     
                              
                         


                                                                             
                                                                     




                             
                      
































                                                                        
                                        





                                            
                                                  
     
               















                                        
                                                        









                                                         
                                              
                        


         
                 

 
                                                       






                                                                   
                                                           






                                                                            
                                                    






                                                     
                                      
                               
                                            




                                            

                                                                  
 
                       









                                                    
                                                                       










                                               
                             
                                                   
                                                            


                                                                           

                                                              













                                     
                                                



                     

                                                                
                                             


                     
                       












                                                    
                                              



              









                                                 
                                                         
                                
                                          
                                                     

                                          
             






                                               
                                              
   
                                                      


                     
                                                      

                                                          
                                        










                                                   
                                                            
                                                        

                                        
                                   
 
                                                      
                  
                                 
 









                                                                       

             







                                              
                         






                                                
                                                                      



                                       
                                       

                            




                                              






                                       
                                                        
         
                                                           
                                                                            


         








                                                            
                                                                 



                              
/*
 * Hub net client
 *
 * Copyright IBM, Corp. 2012
 *
 * Authors:
 *  Stefan Hajnoczi   <stefanha@linux.vnet.ibm.com>
 *  Zhi Yong Wu       <wuzhy@linux.vnet.ibm.com>
 *
 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
 * See the COPYING.LIB file in the top-level directory.
 *
 */

#include "qemu/osdep.h"
#include "qapi/error.h"
#include "monitor/monitor.h"
#include "net/net.h"
#include "clients.h"
#include "hub.h"
#include "qemu/iov.h"
#include "qemu/error-report.h"
#include "sysemu/qtest.h"

/*
 * A hub broadcasts incoming packets to all its ports except the source port.
 * Hubs can be used to provide independent emulated network segments.
 */

typedef struct NetHub NetHub;

typedef struct NetHubPort {
    NetClientState nc;
    QLIST_ENTRY(NetHubPort) next;
    NetHub *hub;
    int id;
} NetHubPort;

struct NetHub {
    int id;
    QLIST_ENTRY(NetHub) next;
    int num_ports;
    QLIST_HEAD(, NetHubPort) ports;
};

static QLIST_HEAD(, NetHub) hubs = QLIST_HEAD_INITIALIZER(&hubs);

static ssize_t net_hub_receive(NetHub *hub, NetHubPort *source_port,
                               const uint8_t *buf, size_t len)
{
    NetHubPort *port;

    QLIST_FOREACH(port, &hub->ports, next) {
        if (port == source_port) {
            continue;
        }

        qemu_send_packet(&port->nc, buf, len);
    }
    return len;
}

static ssize_t net_hub_receive_iov(NetHub *hub, NetHubPort *source_port,
                                   const struct iovec *iov, int iovcnt)
{
    NetHubPort *port;
    ssize_t len = iov_size(iov, iovcnt);

    QLIST_FOREACH(port, &hub->ports, next) {
        if (port == source_port) {
            continue;
        }

        qemu_sendv_packet(&port->nc, iov, iovcnt);
    }
    return len;
}

static NetHub *net_hub_new(int id)
{
    NetHub *hub;

    hub = g_malloc(sizeof(*hub));
    hub->id = id;
    hub->num_ports = 0;
    QLIST_INIT(&hub->ports);

    QLIST_INSERT_HEAD(&hubs, hub, next);

    return hub;
}

static bool net_hub_port_can_receive(NetClientState *nc)
{
    NetHubPort *port;
    NetHubPort *src_port = DO_UPCAST(NetHubPort, nc, nc);
    NetHub *hub = src_port->hub;

    QLIST_FOREACH(port, &hub->ports, next) {
        if (port == src_port) {
            continue;
        }

        if (qemu_can_send_packet(&port->nc)) {
            return true;
        }
    }

    return false;
}

static ssize_t net_hub_port_receive(NetClientState *nc,
                                    const uint8_t *buf, size_t len)
{
    NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);

    return net_hub_receive(port->hub, port, buf, len);
}

static ssize_t net_hub_port_receive_iov(NetClientState *nc,
                                        const struct iovec *iov, int iovcnt)
{
    NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);

    return net_hub_receive_iov(port->hub, port, iov, iovcnt);
}

static void net_hub_port_cleanup(NetClientState *nc)
{
    NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);

    QLIST_REMOVE(port, next);
}

static NetClientInfo net_hub_port_info = {
    .type = NET_CLIENT_DRIVER_HUBPORT,
    .size = sizeof(NetHubPort),
    .can_receive = net_hub_port_can_receive,
    .receive = net_hub_port_receive,
    .receive_iov = net_hub_port_receive_iov,
    .cleanup = net_hub_port_cleanup,
};

static NetHubPort *net_hub_port_new(NetHub *hub, const char *name,
                                    NetClientState *hubpeer)
{
    NetClientState *nc;
    NetHubPort *port;
    int id = hub->num_ports++;
    char default_name[128];

    if (!name) {
        snprintf(default_name, sizeof(default_name),
                 "hub%dport%d", hub->id, id);
        name = default_name;
    }

    nc = qemu_new_net_client(&net_hub_port_info, hubpeer, "hub", name);
    port = DO_UPCAST(NetHubPort, nc, nc);
    port->id = id;
    port->hub = hub;

    QLIST_INSERT_HEAD(&hub->ports, port, next);

    return port;
}

/**
 * Create a port on a given hub
 * @hub_id: Number of the hub
 * @name: Net client name or NULL for default name.
 * @hubpeer: Peer to use (if "netdev=id" has been specified)
 *
 * If there is no existing hub with the given id then a new hub is created.
 */
NetClientState *net_hub_add_port(int hub_id, const char *name,
                                 NetClientState *hubpeer)
{
    NetHub *hub;
    NetHubPort *port;

    QLIST_FOREACH(hub, &hubs, next) {
        if (hub->id == hub_id) {
            break;
        }
    }

    if (!hub) {
        hub = net_hub_new(hub_id);
    }

    port = net_hub_port_new(hub, name, hubpeer);
    return &port->nc;
}

/**
 * Find a available port on a hub; otherwise create one new port
 */
NetClientState *net_hub_port_find(int hub_id)
{
    NetHub *hub;
    NetHubPort *port;
    NetClientState *nc;

    QLIST_FOREACH(hub, &hubs, next) {
        if (hub->id == hub_id) {
            QLIST_FOREACH(port, &hub->ports, next) {
                nc = port->nc.peer;
                if (!nc) {
                    return &(port->nc);
                }
            }
            break;
        }
    }

    nc = net_hub_add_port(hub_id, NULL, NULL);
    return nc;
}

/**
 * Print hub configuration
 */
void net_hub_info(Monitor *mon)
{
    NetHub *hub;
    NetHubPort *port;

    QLIST_FOREACH(hub, &hubs, next) {
        monitor_printf(mon, "hub %d\n", hub->id);
        QLIST_FOREACH(port, &hub->ports, next) {
            monitor_printf(mon, " \\ %s", port->nc.name);
            if (port->nc.peer) {
                monitor_printf(mon, ": ");
                print_net_client(mon, port->nc.peer);
            } else {
                monitor_printf(mon, "\n");
            }
        }
    }
}

/**
 * Get the hub id that a client is connected to
 *
 * @id: Pointer for hub id output, may be NULL
 */
int net_hub_id_for_client(NetClientState *nc, int *id)
{
    NetHubPort *port;

    if (nc->info->type == NET_CLIENT_DRIVER_HUBPORT) {
        port = DO_UPCAST(NetHubPort, nc, nc);
    } else if (nc->peer != NULL && nc->peer->info->type ==
            NET_CLIENT_DRIVER_HUBPORT) {
        port = DO_UPCAST(NetHubPort, nc, nc->peer);
    } else {
        return -ENOENT;
    }

    if (id) {
        *id = port->hub->id;
    }
    return 0;
}

int net_init_hubport(const Netdev *netdev, const char *name,
                     NetClientState *peer, Error **errp)
{
    const NetdevHubPortOptions *hubport;
    NetClientState *hubpeer = NULL;

    assert(netdev->type == NET_CLIENT_DRIVER_HUBPORT);
    assert(!peer);
    hubport = &netdev->u.hubport;

    if (hubport->has_netdev) {
        hubpeer = qemu_find_netdev(hubport->netdev);
        if (!hubpeer) {
            error_setg(errp, "netdev '%s' not found", hubport->netdev);
            return -1;
        }
    }

    net_hub_add_port(hubport->hubid, name, hubpeer);

    return 0;
}

/**
 * Warn if hub configurations are likely wrong
 */
void net_hub_check_clients(void)
{
    NetHub *hub;
    NetHubPort *port;
    NetClientState *peer;

    QLIST_FOREACH(hub, &hubs, next) {
        int has_nic = 0, has_host_dev = 0;

        QLIST_FOREACH(port, &hub->ports, next) {
            peer = port->nc.peer;
            if (!peer) {
                warn_report("hub port %s has no peer", port->nc.name);
                continue;
            }

            switch (peer->info->type) {
            case NET_CLIENT_DRIVER_NIC:
                has_nic = 1;
                break;
            case NET_CLIENT_DRIVER_USER:
            case NET_CLIENT_DRIVER_TAP:
            case NET_CLIENT_DRIVER_SOCKET:
            case NET_CLIENT_DRIVER_VDE:
            case NET_CLIENT_DRIVER_VHOST_USER:
                has_host_dev = 1;
                break;
            default:
                break;
            }
        }
        if (has_host_dev && !has_nic) {
            warn_report("hub %d with no nics", hub->id);
        }
        if (has_nic && !has_host_dev && !qtest_enabled()) {
            warn_report("hub %d is not connected to host network", hub->id);
        }
    }
}

bool net_hub_flush(NetClientState *nc)
{
    NetHubPort *port;
    NetHubPort *source_port = DO_UPCAST(NetHubPort, nc, nc);
    int ret = 0;

    QLIST_FOREACH(port, &source_port->hub->ports, next) {
        if (port != source_port) {
            ret += qemu_net_queue_flush(port->nc.incoming_queue);
        }
    }
    return ret ? true : false;
}
me/block.c?id=a069e2f1372a0a823ab506fc019852a2a652aa54'>^
5a612c009e ^

892b7de832 ^




eba25057b9 ^




d5249393ef ^
eba25057b9 ^
3b9f94e1a8 ^
eba25057b9 ^





d5249393ef ^
67b915a5dd ^
7ccfb2eb5f ^
0badc1ee0e ^
69bef7931e ^


eba25057b9 ^


ea2384d36e ^
fe235a06e1 ^




eba25057b9 ^


d5249393ef ^
eba25057b9 ^
fc01f7e7f9 ^
84a12e6648 ^





















88d88798b7 ^












98289620e0 ^
b65a5e12a4 ^

83f6409109 ^


1cec71e359 ^
83f6409109 ^
88d88798b7 ^
19cb37389f ^
66f82ceed6 ^

39508e7adb ^











98289620e0 ^
ef8104378c ^
84a12e6648 ^
98289620e0 ^
9e0b22f4f2 ^

1cec71e359 ^




88d88798b7 ^










8a22f02a88 ^
83f6409109 ^
b65a5e12a4 ^
88d88798b7 ^




83f6409109 ^

c6684249fd ^





7cddd3728e ^

c6684249fd ^





38f3ef574b ^

c6684249fd ^
















5696c6e350 ^
34b5d2c68e ^
f3a5d3f8a1 ^
c6684249fd ^
7cddd3728e ^
f500a6d3c2 ^
f8ea0b00e0 ^
08a00559f0 ^
5696c6e350 ^
ef8104378c ^
c98ac35d87 ^
1a39685910 ^
f8ea0b00e0 ^
5696c6e350 ^
83f6409109 ^
34b5d2c68e ^

c98ac35d87 ^

83f6409109 ^

c6684249fd ^
c98ac35d87 ^
34b5d2c68e ^

c98ac35d87 ^



ea2384d36e ^

51762288b4 ^

65a9bb25d6 ^
51762288b4 ^
3d9f2d2af6 ^
51762288b4 ^


d470ad42ac ^



396759ad4a ^
b192af8acc ^
396759ad4a ^

51762288b4 ^





7e382003f1 ^
51762288b4 ^





c3993cdca3 ^
cddff5bae1 ^












543770bd2e ^
























cddff5bae1 ^
f80f267373 ^





















9e8f1835ea ^



















c3993cdca3 ^



53e8ae0100 ^
c3993cdca3 ^



53e8ae0100 ^

92196b2f56 ^
53e8ae0100 ^
92196b2f56 ^
c3993cdca3 ^
53e8ae0100 ^
c3993cdca3 ^
53e8ae0100 ^
c3993cdca3 ^

53e8ae0100 ^
c3993cdca3 ^






b541155587 ^





20018e12cf ^


6cd5c9d7b2 ^
20018e12cf ^

89bd030533 ^


6cd5c9d7b2 ^
89bd030533 ^

e037c09c78 ^

20018e12cf ^

e037c09c78 ^
20018e12cf ^

d736f119da ^











38701b6aef ^






5d2318499f ^






53a7d04185 ^






0b50cc8853 ^
73176bee99 ^


b1e6fc0817 ^
73176bee99 ^

b1e6fc0817 ^
73176bee99 ^


73176bee99 ^

418690447a ^
3f48686fac ^
f87a0e29a9 ^
3f48686fac ^
f87a0e29a9 ^
418690447a ^


b1e6fc0817 ^


8e2160e2c7 ^

0b50cc8853 ^
8e2160e2c7 ^

0b50cc8853 ^
8e2160e2c7 ^

0b50cc8853 ^


91a097e747 ^



5a9347c673 ^
91a097e747 ^
f87a0e29a9 ^

e35bdc123a ^
f87a0e29a9 ^
0b50cc8853 ^
91a097e747 ^

818584a43a ^
0b50cc8853 ^
0b50cc8853 ^
abb06c5ac1 ^

0b50cc8853 ^
8e2160e2c7 ^
0b50cc8853 ^

f3930ed0bb ^
6cd5c9d7b2 ^
b541155587 ^
8e2160e2c7 ^
20018e12cf ^
89bd030533 ^
20018e12cf ^
d736f119da ^

38701b6aef ^
5d2318499f ^
53a7d04185 ^
f3930ed0bb ^


8e2160e2c7 ^


f3930ed0bb ^
8e2160e2c7 ^

f3930ed0bb ^
8e2160e2c7 ^


abb06c5ac1 ^
f3930ed0bb ^


6cd5c9d7b2 ^
b541155587 ^
8e2160e2c7 ^
20018e12cf ^
89bd030533 ^
20018e12cf ^
d736f119da ^

38701b6aef ^
5d2318499f ^
53a7d04185 ^
f3930ed0bb ^

db95dbba3b ^









f30c66ba6e ^

db95dbba3b ^




























d736f119da ^

db95dbba3b ^









d736f119da ^

db95dbba3b ^

317fc44ef2 ^
8e2160e2c7 ^

317fc44ef2 ^
8e2160e2c7 ^

317fc44ef2 ^
8e2160e2c7 ^

b8816a4386 ^

91a097e747 ^

5a9347c673 ^
91a097e747 ^
317fc44ef2 ^
f87a0e29a9 ^
e35bdc123a ^
f87a0e29a9 ^
317fc44ef2 ^

8bfea15dda ^
317fc44ef2 ^
8e2160e2c7 ^
317fc44ef2 ^

6858eba09e ^



e94d3dba6a ^
6858eba09e ^

e94d3dba6a ^

61f09cea01 ^




6858eba09e ^


6473069416 ^
6858eba09e ^

e94d3dba6a ^

61f09cea01 ^

6858eba09e ^


91ef38257a ^
6cd5c9d7b2 ^
b541155587 ^
db95dbba3b ^

8e2160e2c7 ^
20018e12cf ^
89bd030533 ^
20018e12cf ^
38701b6aef ^
6858eba09e ^
5d2318499f ^
53a7d04185 ^
f3930ed0bb ^

7b27245239 ^

61de4c6808 ^
7b27245239 ^




20cca275c6 ^
7b27245239 ^
7b27245239 ^


91a097e747 ^

2a3d4331fa ^
91a097e747 ^
57f9db9a94 ^
91a097e747 ^


57f9db9a94 ^
91a097e747 ^

f87a0e29a9 ^
57f9db9a94 ^
f87a0e29a9 ^


e35bdc123a ^


91a097e747 ^



91a097e747 ^
46f5ac205a ^
91a097e747 ^

46f5ac205a ^

91a097e747 ^
f87a0e29a9 ^
46f5ac205a ^
f87a0e29a9 ^
e35bdc123a ^



91a097e747 ^

636ea3708c ^


6913c0c2ce ^
15489c769b ^
6913c0c2ce ^
15489c769b ^






9aebf3b892 ^
636ea3708c ^
6913c0c2ce ^

0c5e94ee83 ^
7f06d47eff ^
0c5e94ee83 ^

15489c769b ^
0c5e94ee83 ^

6913c0c2ce ^


15489c769b ^
6913c0c2ce ^

824808dd77 ^





6913c0c2ce ^


15489c769b ^

6913c0c2ce ^

01a5650179 ^




0f12264e7a ^
01a5650179 ^







680c7f9606 ^
01a5650179 ^




680c7f9606 ^
01a5650179 ^
680c7f9606 ^

01a5650179 ^









180ca19ae0 ^
01a5650179 ^




180ca19ae0 ^
01a5650179 ^




180ca19ae0 ^
01a5650179 ^





0f12264e7a ^





01a5650179 ^
180ca19ae0 ^





01a5650179 ^

01a5650179 ^


680c7f9606 ^















cb3e7f08ae ^
180ca19ae0 ^
cb3e7f08ae ^
180ca19ae0 ^
680c7f9606 ^






c5f3014b82 ^
18edf289a8 ^







62392ebb09 ^




91a097e747 ^
91a097e747 ^








f87a0e29a9 ^




692e01a27c ^
e35bdc123a ^




692e01a27c ^



818584a43a ^
415bbca86d ^
818584a43a ^


5a9347c673 ^




18edf289a8 ^



fd17146cd9 ^

















b6ce07aa83 ^
5791533251 ^
b6ad491a49 ^

5791533251 ^
5696c6e350 ^
82dc8b4110 ^
5791533251 ^

035fccdf79 ^
62392ebb09 ^
6913c0c2ce ^
818584a43a ^
18edf289a8 ^
62392ebb09 ^
34b5d2c68e ^
5791533251 ^
6405875cdd ^
707ff8282b ^
5791533251 ^
62392ebb09 ^







9b7e869167 ^

62392ebb09 ^



5a9347c673 ^









456736710d ^
f30c66ba6e ^
5696c6e350 ^
456736710d ^
129c7d1c53 ^






456736710d ^


4a0082401a ^
765003db02 ^

18edf289a8 ^

6913c0c2ce ^
6913c0c2ce ^
82dc8b4110 ^

62392ebb09 ^
82dc8b4110 ^
b64ec4e4ad ^

8be25de643 ^












b64ec4e4ad ^
5791533251 ^
d3faa13e5f ^


82dc8b4110 ^
0ebd24e0a2 ^



18edf289a8 ^

0ebd24e0a2 ^
53fec9d3fd ^

415bbca86d ^
818584a43a ^







543770bd2e ^





692e01a27c ^

c2ad1b0c46 ^




91af701412 ^
5791533251 ^
66f82ceed6 ^
82dc8b4110 ^
01a5650179 ^
5791533251 ^
01a5650179 ^

51762288b4 ^
01a5650179 ^
3baca89139 ^

18edf289a8 ^
5791533251 ^

18edf289a8 ^

5791533251 ^


5e5c4f63f4 ^








5577fff738 ^
5e5c4f63f4 ^
5577fff738 ^
5e5c4f63f4 ^


7dc847ebba ^
ca6b6e1e68 ^
cb3e7f08ae ^
5e5c4f63f4 ^



5e5c4f63f4 ^




de3b53f007 ^



















cb3e7f08ae ^
de3b53f007 ^


5791533251 ^
f54120ff1a ^

53a2951312 ^

b6ce07aa83 ^
de3b53f007 ^
053e1578c9 ^
ea2384d36e ^
c2ad1b0c46 ^
53a2951312 ^
e3fa4bfa72 ^
053e1578c9 ^
34b5d2c68e ^
83f6409109 ^
129c7d1c53 ^






53a2951312 ^
053e1578c9 ^








53a2951312 ^







91a097e747 ^


035fccdf79 ^
17b005f1d4 ^
f54120ff1a ^
46f5ac205a ^
f54120ff1a ^





035fccdf79 ^

c2ad1b0c46 ^
129c7d1c53 ^
f54120ff1a ^
f54120ff1a ^
053e1578c9 ^


17b005f1d4 ^
053e1578c9 ^
17b005f1d4 ^
053e1578c9 ^

46f5ac205a ^
053e1578c9 ^


98289620e0 ^
c2ad1b0c46 ^

17b005f1d4 ^
c2ad1b0c46 ^
f54120ff1a ^
17b005f1d4 ^
5acd9d81e1 ^
84d18f065f ^
34b5d2c68e ^
f54120ff1a ^
6963a30d82 ^
cd5d031e75 ^


cd5d031e75 ^
6963a30d82 ^

f54120ff1a ^


3121fb45b0 ^

9eab154415 ^

c1cef67251 ^

481e0eeef4 ^

c1cef67251 ^
148eb13c84 ^

69b736e765 ^
148eb13c84 ^
859443b0fb ^
148eb13c84 ^











859443b0fb ^
148eb13c84 ^










cc02214097 ^

148eb13c84 ^





cc02214097 ^









ffd1a5a25c ^
e0995dc3da ^

ffd1a5a25c ^


0b3ca76e52 ^



e0995dc3da ^
ffd1a5a25c ^




33a610c398 ^





9eab154415 ^









33a610c398 ^


3121fb45b0 ^

46181129ea ^
9eab154415 ^

33a610c398 ^




9eab154415 ^













33a610c398 ^

cc02214097 ^
33a610c398 ^
481e0eeef4 ^













33a610c398 ^












78e421c9fb ^
33a610c398 ^
78e421c9fb ^
33a610c398 ^





9eab154415 ^

3121fb45b0 ^
ffd1a5a25c ^

9eab154415 ^






33a610c398 ^















































78e421c9fb ^
33a610c398 ^
78e421c9fb ^
33a610c398 ^





e0995dc3da ^
ffd1a5a25c ^

33a610c398 ^