summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vnet/devices/af_packet/af_packet.c45
-rw-r--r--src/vnet/devices/virtio/vhost-user.c10
-rw-r--r--src/vnet/interface.c7
3 files changed, 50 insertions, 12 deletions
diff --git a/src/vnet/devices/af_packet/af_packet.c b/src/vnet/devices/af_packet/af_packet.c
index 46bb42a4f47..500460126a8 100644
--- a/src/vnet/devices/af_packet/af_packet.c
+++ b/src/vnet/devices/af_packet/af_packet.c
@@ -19,6 +19,8 @@
#include <linux/if_ether.h>
#include <linux/if_packet.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -212,9 +214,10 @@ af_packet_create_if (vlib_main_t * vm, u8 * host_if_name, u8 * hw_addr_set,
u32 * sw_if_index)
{
af_packet_main_t *apm = &af_packet_main;
- int ret, fd = -1;
+ int ret, fd = -1, fd2 = -1;
struct tpacket_req *rx_req = 0;
struct tpacket_req *tx_req = 0;
+ struct ifreq ifr;
u8 *ring = 0;
af_packet_if_t *apif = 0;
u8 hw_addr[6];
@@ -248,14 +251,46 @@ 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;
- host_if_index = if_nametoindex ((const char *) host_if_name);
+ /*
+ * make sure host side of interface is 'UP' before binding AF_PACKET
+ * socket on it.
+ */
+ if ((fd2 = socket (AF_UNIX, SOCK_DGRAM, 0)) < 0)
+ {
+ DBG_SOCK ("Failed to create socket");
+ ret = VNET_API_ERROR_SYSCALL_ERROR_1;
+ goto error;
+ }
- if (!host_if_index)
+ clib_memcpy (ifr.ifr_name, (const char *) host_if_name,
+ vec_len (host_if_name));
+ if ((ret = ioctl (fd2, SIOCGIFINDEX, &ifr)) < 0)
{
- DBG_SOCK ("Wrong host interface name");
+ clib_unix_warning ("af_packet_create error: %d", ret);
+ close (fd2);
return VNET_API_ERROR_INVALID_INTERFACE;
}
+ host_if_index = ifr.ifr_ifindex;
+ if ((ret = ioctl (fd2, SIOCGIFFLAGS, &ifr)) < 0)
+ {
+ clib_unix_warning ("af_packet_create error: %d", ret);
+ goto error;
+ }
+
+ if (!(ifr.ifr_flags & IFF_UP))
+ {
+ ifr.ifr_flags |= IFF_UP;
+ if ((ret = ioctl (fd2, SIOCSIFFLAGS, &ifr)) < 0)
+ {
+ clib_unix_warning ("af_packet_create error: %d", ret);
+ goto error;
+ }
+ }
+
+ if (fd2 > -1)
+ close (fd2);
+
ret = create_packet_v2_sock (host_if_index, rx_req, tx_req, &fd, &ring);
if (ret != 0)
@@ -347,6 +382,8 @@ af_packet_create_if (vlib_main_t * vm, u8 * host_if_name, u8 * hw_addr_set,
return 0;
error:
+ if (fd2 > -1)
+ close (fd2);
vec_free (host_if_name_dup);
vec_free (rx_req);
vec_free (tx_req);
diff --git a/src/vnet/devices/virtio/vhost-user.c b/src/vnet/devices/virtio/vhost-user.c
index 7e10a60f5fb..4e745d662fb 100644
--- a/src/vnet/devices/virtio/vhost-user.c
+++ b/src/vnet/devices/virtio/vhost-user.c
@@ -2548,16 +2548,14 @@ vhost_user_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index,
u32 flags)
{
vnet_hw_interface_t *hif = vnet_get_hw_interface (vnm, hw_if_index);
- uword is_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
vhost_user_main_t *vum = &vhost_user_main;
vhost_user_intf_t *vui =
pool_elt_at_index (vum->vhost_user_interfaces, hif->dev_instance);
+ u32 hw_flags = 0;
+ vui->admin_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
+ hw_flags = vui->admin_up ? VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
- vui->admin_up = is_up;
-
- if (is_up && vui->is_up)
- vnet_hw_interface_set_flags (vnm, vui->hw_if_index,
- VNET_HW_INTERFACE_FLAG_LINK_UP);
+ vnet_hw_interface_set_flags (vnm, vui->hw_if_index, hw_flags);
return /* no error */ 0;
}
diff --git a/src/vnet/interface.c b/src/vnet/interface.c
index 36793f1177e..d85d864839e 100644
--- a/src/vnet/interface.c
+++ b/src/vnet/interface.c
@@ -485,10 +485,13 @@ vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index,
error = call_elf_section_interface_callbacks
(vnm, sw_if_index, flags,
vnm->sw_interface_admin_up_down_functions);
- si->flags = old_flags;
if (error)
- goto done;
+ {
+ /* restore flags on error */
+ si->flags = old_flags;
+ goto done;
+ }
if (si->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
{