vhost-user: Interface state updates
Fix inconsistencies between admin and link interface states
Admin down should imply link down:
link_up = admin_up && link_ready
Change-Id: I4d668d82d035b5d2ae508727f34f1722a0c3e677
Signed-off-by: Juraj Sloboda <jsloboda@cisco.com>
diff --git a/src/vnet/devices/virtio/vhost_user.c b/src/vnet/devices/virtio/vhost_user.c
index 863cebe..f7730c7 100644
--- a/src/vnet/devices/virtio/vhost_user.c
+++ b/src/vnet/devices/virtio/vhost_user.c
@@ -236,15 +236,16 @@
vhost_user_update_iface_state (vhost_user_intf_t * vui)
{
/* if we have pointers to descriptor table, go up */
- int is_up = vhost_user_intf_ready (vui);
- if (is_up != vui->is_up)
+ int is_ready = vhost_user_intf_ready (vui);
+ if (is_ready != vui->is_ready)
{
DBG_SOCK ("interface %d %s", vui->sw_if_index,
- is_up ? "ready" : "down");
- vnet_hw_interface_set_flags (vnet_get_main (), vui->hw_if_index,
- is_up ? VNET_HW_INTERFACE_FLAG_LINK_UP :
- 0);
- vui->is_up = is_up;
+ is_ready ? "ready" : "down");
+ if (vui->admin_up)
+ vnet_hw_interface_set_flags (vnet_get_main (), vui->hw_if_index,
+ is_ready ? VNET_HW_INTERFACE_FLAG_LINK_UP
+ : 0);
+ vui->is_ready = is_ready;
}
vhost_user_rx_thread_placement ();
vhost_user_tx_thread_placement (vui);
@@ -290,7 +291,7 @@
n = read (uf->file_descriptor, ((char *) &buff), 8);
DBG_SOCK ("if %d KICK queue %d", uf->private_data >> 8, qid);
if (!vui->vrings[qid].started ||
- (vhost_user_intf_ready (vui) != vui->is_up))
+ (vhost_user_intf_ready (vui) != vui->is_ready))
{
vlib_worker_thread_barrier_sync (vlib_get_main ());
vui->vrings[qid].started = 1;
@@ -364,7 +365,7 @@
vui->clib_file_index = ~0;
}
- vui->is_up = 0;
+ vui->is_ready = 0;
for (q = 0; q < VHOST_VRING_MAX_N; q++)
vhost_user_vring_close (vui, q);
@@ -505,7 +506,7 @@
ASSERT (vui->virtio_net_hdr_sz < VLIB_BUFFER_PRE_DATA_SIZE);
vnet_hw_interface_set_flags (vnm, vui->hw_if_index, 0);
- vui->is_up = 0;
+ vui->is_ready = 0;
/*for (q = 0; q < VHOST_VRING_MAX_N; q++)
vhost_user_vring_close(&vui->vrings[q]); */
@@ -1395,7 +1396,7 @@
strncpy (vui->sock_filename, sock_filename,
ARRAY_LEN (vui->sock_filename) - 1);
vui->sock_errno = 0;
- vui->is_up = 0;
+ vui->is_ready = 0;
vui->feature_mask = feature_mask;
vui->clib_file_index = ~0;
vui->log_base_addr = 0;
diff --git a/src/vnet/devices/virtio/vhost_user.h b/src/vnet/devices/virtio/vhost_user.h
index ff06695..5bc3608 100644
--- a/src/vnet/devices/virtio/vhost_user.h
+++ b/src/vnet/devices/virtio/vhost_user.h
@@ -253,7 +253,7 @@
typedef struct
{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
- u32 is_up;
+ u32 is_ready;
u32 admin_up;
u32 unix_server_index;
u32 clib_file_index;
diff --git a/src/vnet/devices/virtio/vhost_user_inline.h b/src/vnet/devices/virtio/vhost_user_inline.h
index 9f61351..7e988eb 100644
--- a/src/vnet/devices/virtio/vhost_user_inline.h
+++ b/src/vnet/devices/virtio/vhost_user_inline.h
@@ -251,6 +251,12 @@
vq->int_deadline = vlib_time_now (vm) + vum->coalesce_time;
}
+static_always_inline u8
+vui_is_link_up (vhost_user_intf_t * vui)
+{
+ return vui->admin_up && vui->is_ready;
+}
+
#endif
/*
diff --git a/src/vnet/devices/virtio/vhost_user_output.c b/src/vnet/devices/virtio/vhost_user_output.c
index 029c0c0..f4d1c2c 100644
--- a/src/vnet/devices/virtio/vhost_user_output.c
+++ b/src/vnet/devices/virtio/vhost_user_output.c
@@ -248,7 +248,7 @@
goto done3;
}
- if (PREDICT_FALSE (!vui->is_up))
+ if (PREDICT_FALSE (!vui->is_ready))
{
error = VHOST_USER_TX_FUNC_ERROR_NOT_READY;
goto done3;
@@ -621,11 +621,17 @@
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;
+ u8 link_old, link_new;
- vnet_hw_interface_set_flags (vnm, vui->hw_if_index, hw_flags);
+ link_old = vui_is_link_up (vui);
+
+ vui->admin_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
+
+ link_new = vui_is_link_up (vui);
+
+ if (link_old != link_new)
+ vnet_hw_interface_set_flags (vnm, vui->hw_if_index, link_new ?
+ VNET_HW_INTERFACE_FLAG_LINK_UP : 0);
return /* no error */ 0;
}