summaryrefslogtreecommitdiffstats
path: root/src/vnet/devices/af_packet/af_packet.c
diff options
context:
space:
mode:
authorRay Kinsella <ray.kinsella@intel.com>2017-04-21 12:24:43 +0100
committerDamjan Marion <dmarion.lists@gmail.com>2017-04-28 08:01:12 +0000
commitc855b73f785b3c4c1756927ad542de13ba193b6f (patch)
tree282b4c2ee5b34f20bb9a71b130f20181c55179e5 /src/vnet/devices/af_packet/af_packet.c
parentd77630adaf48f05766c33ec60ef19ed50acae161 (diff)
af_packet: reflect admin device state on host
Setting the interface state in VPP on an af_packet device, was not being reflected on the host. This implied the user had to set the device state in VPP and then on the host, in order to put the interface into an 'up' state. This changes makes the device state consisent in VPP and the host. Change-Id: I6dc6aee79503e04576683db937b861337a2b375b Signed-off-by: Ray Kinsella <ray.kinsella@intel.com>
Diffstat (limited to 'src/vnet/devices/af_packet/af_packet.c')
-rw-r--r--src/vnet/devices/af_packet/af_packet.c50
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);