diff options
Diffstat (limited to 'src/vnet/devices/af_packet/af_packet.c')
-rw-r--r-- | src/vnet/devices/af_packet/af_packet.c | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/src/vnet/devices/af_packet/af_packet.c b/src/vnet/devices/af_packet/af_packet.c index 7464d4e629d..92bd109296c 100644 --- a/src/vnet/devices/af_packet/af_packet.c +++ b/src/vnet/devices/af_packet/af_packet.c @@ -19,6 +19,7 @@ #include <linux/if_ether.h> #include <linux/if_packet.h> +#include <dirent.h> #include <vlib/vlib.h> #include <vlib/unix/unix.h> @@ -82,26 +83,35 @@ af_packet_fd_read_ready (unix_file_t * uf) } static int -create_packet_v2_sock (u8 * name, tpacket_req_t * rx_req, +is_bridge (const u8 * host_if_name) +{ + u8 *s; + DIR *dir = NULL; + + s = format (0, "/sys/class/net/%s/bridge%c", host_if_name, 0); + dir = opendir ((char *) s); + vec_free (s); + + if (dir) + { + closedir (dir); + return 0; + } + + return -1; +} + +static int +create_packet_v2_sock (int host_if_index, tpacket_req_t * rx_req, tpacket_req_t * tx_req, int *fd, u8 ** ring) { int ret, err; struct sockaddr_ll sll; - uint host_if_index; int ver = TPACKET_V2; socklen_t req_sz = sizeof (struct tpacket_req); u32 ring_sz = rx_req->tp_block_size * rx_req->tp_block_nr + tx_req->tp_block_size * tx_req->tp_block_nr; - host_if_index = if_nametoindex ((const char *) name); - - if (!host_if_index) - { - DBG_SOCK ("Wrong host interface name"); - ret = VNET_API_ERROR_INVALID_INTERFACE; - goto error; - } - if ((*fd = socket (AF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) { DBG_SOCK ("Failed to create socket"); @@ -190,6 +200,7 @@ af_packet_create_if (vlib_main_t * vm, u8 * host_if_name, u8 * hw_addr_set, uword *p; uword if_index; u8 *host_if_name_dup = vec_dup (host_if_name); + int host_if_index = -1; p = mhash_get (&apm->if_index_by_host_if_name, host_if_name); if (p) @@ -209,15 +220,29 @@ af_packet_create_if (vlib_main_t * vm, u8 * host_if_name, u8 * hw_addr_set, tx_req->tp_block_nr = AF_PACKET_TX_BLOCK_NR; tx_req->tp_frame_nr = AF_PACKET_TX_FRAME_NR; - ret = create_packet_v2_sock (host_if_name, rx_req, tx_req, &fd, &ring); + host_if_index = if_nametoindex ((const char *) host_if_name); + + if (!host_if_index) + { + DBG_SOCK ("Wrong host interface name"); + return VNET_API_ERROR_INVALID_INTERFACE; + } + + ret = create_packet_v2_sock (host_if_index, rx_req, tx_req, &fd, &ring); if (ret != 0) goto error; + ret = is_bridge (host_if_name); + + if (ret == 0) /* is a bridge, ignore state */ + host_if_index = -1; + /* So far everything looks good, let's create interface */ pool_get (apm->interfaces, apif); if_index = apif - apm->interfaces; + apif->host_if_index = host_if_index; apif->fd = fd; apif->rx_ring = ring; apif->tx_ring = ring + rx_req->tp_block_size * rx_req->tp_block_nr; @@ -341,6 +366,7 @@ af_packet_delete_if (vlib_main_t * vm, u8 * host_if_name) vec_free (apif->host_if_name); apif->host_if_name = NULL; + apif->host_if_index = -1; mhash_unset (&apm->if_index_by_host_if_name, host_if_name, &if_index); |