diff options
author | Matthew Smith <mgsmith@netgate.com> | 2020-07-24 13:38:03 -0500 |
---|---|---|
committer | Matthew Smith <mgsmith@netgate.com> | 2020-11-05 17:41:01 +0000 |
commit | bd50ed18de83493b119e67897a5fa9ba9c7e763e (patch) | |
tree | 6cce31f5795f25c34bf7badfbfec5152a3d67ca0 | |
parent | d4a547144ffc0f68538d5a89ce7d41cd739a33d2 (diff) |
tap: allow change of carrier state on host
Type: feature
Add a function to adjust the link state of the host side of a tap
interface. If an application (e.g. route protocol daemons) running on
the host uses netlink to monitor interface state, a plugin
could use this function to communicate a loss of connectivity
to the application by making the interface appear to go down.
Requires a somewhat recent kernel. E.g. it does not have any effect
on CentOS 7 but it works on CentOS 8.
Change-Id: I677ee7889d2eb142e2395bea98f0b4d7e7e7f810
Signed-off-by: Matthew Smith <mgsmith@netgate.com>
-rw-r--r-- | src/vnet/devices/tap/tap.c | 41 | ||||
-rw-r--r-- | src/vnet/devices/tap/tap.h | 2 | ||||
-rw-r--r-- | src/vnet/devices/virtio/virtio.c | 1 | ||||
-rw-r--r-- | src/vnet/devices/virtio/virtio.h | 1 |
4 files changed, 45 insertions, 0 deletions
diff --git a/src/vnet/devices/tap/tap.c b/src/vnet/devices/tap/tap.c index aa9182a58f7..94a91e5509a 100644 --- a/src/vnet/devices/tap/tap.c +++ b/src/vnet/devices/tap/tap.c @@ -751,6 +751,12 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP; vnet_hw_interface_set_flags (vnm, vif->hw_if_index, VNET_HW_INTERFACE_FLAG_LINK_UP); + /* + * Host tun/tap driver link carrier state is "up" at creation. The + * driver never changes this unless the backend (VPP) changes it using + * TUNSETCARRIER ioctl(). See tap_set_carrier(). + */ + vif->host_carrier_up = 1; vif->cxq_vring = NULL; goto done; @@ -987,6 +993,41 @@ tap_dump_ifs (tap_interface_details_t ** out_tapids) return 0; } +/* + * Set host tap/tun interface carrier state so it will appear to host + * applications that the interface's link state changed. + * + * If the kernel we're building against does not have support for the + * TUNSETCARRIER ioctl command, do nothing. + */ +int +tap_set_carrier (u32 hw_if_index, u32 carrier_up) +{ + int ret = 0; +#ifdef TUNSETCARRIER + vnet_main_t *vnm = vnet_get_main (); + vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); + virtio_main_t *mm = &virtio_main; + virtio_if_t *vif; + int *fd; + + vif = pool_elt_at_index (mm->interfaces, hi->dev_instance); + vec_foreach (fd, vif->tap_fds) + { + ret = ioctl (*fd, TUNSETCARRIER, &carrier_up); + if (ret < 0) + { + clib_warning ("ioctl (TUNSETCARRIER) returned %d", ret); + break; + } + } + if (!ret) + vif->host_carrier_up = (carrier_up != 0); +#endif + + return ret; +} + static clib_error_t * tap_mtu_config (vlib_main_t * vm, unformat_input_t * input) { diff --git a/src/vnet/devices/tap/tap.h b/src/vnet/devices/tap/tap.h index 46f13a4e274..42283281448 100644 --- a/src/vnet/devices/tap/tap.h +++ b/src/vnet/devices/tap/tap.h @@ -108,6 +108,8 @@ int tap_csum_offload_enable_disable (vlib_main_t * vm, u32 sw_if_index, int enable_disable); int tap_dump_ifs (tap_interface_details_t ** out_tapids); +int tap_set_carrier (u32 hw_if_index, u32 carrier_up); + #endif /* _VNET_DEVICES_VIRTIO_TAP_H_ */ diff --git a/src/vnet/devices/virtio/virtio.c b/src/vnet/devices/virtio/virtio.c index 8209a46b52f..925ad092b91 100644 --- a/src/vnet/devices/virtio/virtio.c +++ b/src/vnet/devices/virtio/virtio.c @@ -345,6 +345,7 @@ virtio_show (vlib_main_t * vm, u32 * hw_if_indices, u8 show_descr, u32 type) if (type == VIRTIO_IF_TYPE_TAP) vlib_cli_output (vm, " host-mac-addr: %U", format_ethernet_address, vif->host_mac_addr); + vlib_cli_output (vm, " host-carrier-up: %u", vif->host_carrier_up); vec_foreach_index (i, vif->vhost_fds) str = format (str, " %d", vif->vhost_fds[i]); diff --git a/src/vnet/devices/virtio/virtio.h b/src/vnet/devices/virtio/virtio.h index 86660a1f933..fda72365db9 100644 --- a/src/vnet/devices/virtio/virtio.h +++ b/src/vnet/devices/virtio/virtio.h @@ -169,6 +169,7 @@ typedef struct ip4_address_t host_ip4_addr; u8 host_ip4_prefix_len; u8 host_ip6_prefix_len; + u8 host_carrier_up; /* host tun/tap driver link carrier state */ }; struct /* native virtio */ { |