X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fvnet%2Fdevices%2Faf_packet%2Fdevice.c;h=b9492b36a693ef2ee5b8993646ad66ddd584f5fd;hb=b795bd0c5cadfc6734ee8b2355cbc3965be0a1c1;hp=9a94fc5e4a9f432e1a1d40dada33bd849c961128;hpb=22db11b491f80539438418eaaa0aa864202dadf6;p=vpp.git diff --git a/src/vnet/devices/af_packet/device.c b/src/vnet/devices/af_packet/device.c index 9a94fc5e4a9..b9492b36a69 100644 --- a/src/vnet/devices/af_packet/device.c +++ b/src/vnet/devices/af_packet/device.c @@ -18,6 +18,10 @@ */ #include +#include +#include +#include +#include #include #include @@ -92,11 +96,7 @@ af_packet_interface_tx (vlib_main_t * vm, struct tpacket2_hdr *tph; u32 frame_not_ready = 0; - if (PREDICT_FALSE (apif->lockp != 0)) - { - while (__sync_lock_test_and_set (apif->lockp, 1)) - ; - } + clib_spinlock_lock_if_init (&apif->lockp); while (n_left > 0) { @@ -132,11 +132,11 @@ af_packet_interface_tx (vlib_main_t * vm, tph->tp_status = TP_STATUS_SEND_REQUEST; n_sent++; next: + tx_frame = (tx_frame + 1) % frame_num; + /* check if we've exhausted the ring */ if (PREDICT_FALSE (frame_not_ready + n_sent == frame_num)) break; - - tx_frame = (tx_frame + 1) % frame_num; } CLIB_MEMORY_BARRIER (); @@ -159,8 +159,7 @@ af_packet_interface_tx (vlib_main_t * vm, } } - if (PREDICT_FALSE (apif->lockp != 0)) - *apif->lockp = 0; + clib_spinlock_unlock_if_init (&apif->lockp); if (PREDICT_FALSE (frame_not_ready)) vlib_error_count (vm, node->node_index, @@ -210,17 +209,63 @@ af_packet_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, af_packet_if_t *apif = pool_elt_at_index (apm->interfaces, hw->dev_instance); u32 hw_flags; + int rv, fd = socket (AF_UNIX, SOCK_DGRAM, 0); + struct ifreq ifr; + + if (0 > fd) + { + clib_unix_warning ("af_packet_%s could not open socket", + apif->host_if_name); + return 0; + } + + /* if interface is a bridge ignore */ + if (apif->host_if_index < 0) + goto error; /* no error */ + + /* use host_if_index in case host name has changed */ + ifr.ifr_ifindex = apif->host_if_index; + if ((rv = ioctl (fd, SIOCGIFNAME, &ifr)) < 0) + { + clib_unix_warning ("af_packet_%s ioctl could not retrieve eth name", + apif->host_if_name); + goto error; + } apif->is_admin_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0; + if ((rv = ioctl (fd, SIOCGIFFLAGS, &ifr)) < 0) + { + clib_unix_warning ("af_packet_%s error: %d", + apif->is_admin_up ? "up" : "down", rv); + goto error; + } + if (apif->is_admin_up) - hw_flags = VNET_HW_INTERFACE_FLAG_LINK_UP; + { + hw_flags = VNET_HW_INTERFACE_FLAG_LINK_UP; + ifr.ifr_flags |= IFF_UP; + } else - hw_flags = 0; + { + hw_flags = 0; + ifr.ifr_flags &= ~IFF_UP; + } + + if ((rv = ioctl (fd, SIOCSIFFLAGS, &ifr)) < 0) + { + clib_unix_warning ("af_packet_%s error: %d", + apif->is_admin_up ? "up" : "down", rv); + goto error; + } vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags); - return 0; +error: + if (0 <= fd) + close (fd); + + return 0; /* no error */ } static clib_error_t * @@ -232,6 +277,54 @@ af_packet_subif_add_del_function (vnet_main_t * vnm, return 0; } +static clib_error_t *af_packet_set_mac_address_function + (struct vnet_hw_interface_t *hi, char *address) +{ + af_packet_main_t *apm = &af_packet_main; + af_packet_if_t *apif = + pool_elt_at_index (apm->interfaces, hi->dev_instance); + int rv, fd = socket (AF_UNIX, SOCK_DGRAM, 0); + struct ifreq ifr; + + if (0 > fd) + { + clib_unix_warning ("af_packet_%s could not open socket", + apif->host_if_name); + return 0; + } + + /* if interface is a bridge ignore */ + if (apif->host_if_index < 0) + goto error; /* no error */ + + /* use host_if_index in case host name has changed */ + ifr.ifr_ifindex = apif->host_if_index; + if ((rv = ioctl (fd, SIOCGIFNAME, &ifr)) < 0) + { + clib_unix_warning + ("af_packet_%s ioctl could not retrieve eth name, error: %d", + apif->host_if_name, rv); + goto error; + } + + clib_memcpy (ifr.ifr_hwaddr.sa_data, address, 6); + ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; + + if ((rv = ioctl (fd, SIOCSIFHWADDR, &ifr)) < 0) + { + clib_unix_warning ("af_packet_%s ioctl could not set mac, error: %d", + apif->host_if_name, rv); + goto error; + } + +error: + + if (0 <= fd) + close (fd); + + return 0; /* no error */ +} + /* *INDENT-OFF* */ VNET_DEVICE_CLASS (af_packet_device_class) = { .name = "af-packet", @@ -245,6 +338,7 @@ VNET_DEVICE_CLASS (af_packet_device_class) = { .clear_counters = af_packet_clear_hw_interface_counters, .admin_up_down_function = af_packet_interface_admin_up_down, .subif_add_del_function = af_packet_subif_add_del_function, + .mac_addr_change_function = af_packet_set_mac_address_function, }; VLIB_DEVICE_TX_FUNCTION_MULTIARCH (af_packet_device_class,