diff options
author | Jeff Shaw <jeffrey.b.shaw@intel.com> | 2016-08-04 16:51:37 -0400 |
---|---|---|
committer | Jeff Shaw <jeffrey.b.shaw@intel.com> | 2016-08-12 16:58:05 -0400 |
commit | c4da7ab60ca11bc8d2cf683a68fa56483da01243 (patch) | |
tree | 9469eb0ddb37e9e7de7df0fe6bc819054cd8856b /router | |
parent | adff8bfb431798fc1d4e4571d53074dc3438d14f (diff) |
[router] Handle initial tap link state.
When an interface is tapped, the tap inherits the link state of the
underlying device.
Also, the hw vector was being resized in the time between getting
the interface and when the hw_address was referenced, leading to
a segmentation fault. Resolve the issue by saving the mac
address contents on the stack before passing to other functions.
Change-Id: I4b5b31e438159a83ddfea808882503775b1fcd1a
Signed-off-by: Jeff Shaw <jeffrey.b.shaw@intel.com>
Diffstat (limited to 'router')
-rw-r--r-- | router/router/router.c | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/router/router/router.c b/router/router/router.c index 5df86f0..ee23a3d 100644 --- a/router/router/router.c +++ b/router/router/router.c @@ -331,21 +331,56 @@ set_tap_hwaddr(vlib_main_t *m, char *name, u8 *hwaddr) return rc; } +static int +set_tap_link_state(vlib_main_t *m, char *name, u16 flags) +{ + int fd, rc; + struct ifreq ifr; + + fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (fd < 0) + return -1; + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, (char *)name, sizeof(ifr.ifr_name) - 1); + + rc = ioctl(fd, SIOCGIFFLAGS, &ifr); + if (rc < 0) + goto out; + + if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) + ifr.ifr_flags |= (IFF_UP | IFF_RUNNING); + else + ifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING); + + rc = ioctl(fd, SIOCSIFFLAGS, &ifr) < 0 ? -1 : 0; +out: + close(fd); + return rc; +} + static clib_error_t * do_tap_connect(vlib_main_t *m, char *name, u32 iface, u32 *tap) { vnet_hw_interface_t *hw = vnet_get_hw_interface(rm.vnet_main, iface); + vnet_sw_interface_t *sw = vnet_get_sw_interface(rm.vnet_main, iface); + u64 hw_address = 0; *tap = ~0; if (!hw) return clib_error_return(0, "invalid interface"); + else if (hw->hw_address) + memcpy(&hw_address, hw->hw_address, 6); - if (vnet_tap_connect(m, (u8 *)name, hw->hw_address, tap)) + if (vnet_tap_connect(m, (u8 *)name, (u8 *)&hw_address, tap)) return clib_error_return(0, "failed to connect tap"); - if (set_tap_hwaddr(m, name, hw->hw_address)) + if (set_tap_hwaddr(m, name, (u8 *)&hw_address)) return clib_error_return(0, "failed to set tap hw address"); + if (set_tap_link_state(m, name, sw->flags)) + return clib_error_return(0, "failed to set tap link state"); + if (set_int_l2_mode(m, rm.vnet_main, MODE_L2_XC, *tap, 0, 0, 0, iface)) return clib_error_return(0, "failed to xconnect to interface"); |