af_packet: fix the broken functionality upon admin down 05/38405/3
authorMohsin Kazmi <sykazmi@cisco.com>
Tue, 7 Mar 2023 11:07:56 +0000 (11:07 +0000)
committerDamjan Marion <dmarion@0xa5.net>
Fri, 10 Mar 2023 15:54:22 +0000 (15:54 +0000)
Type: fix

In vpp, file descriptor handler closes the fd upon error
if there is no error handling function is registered.
This patch fixes the issue for af_packet interface by
registering the error handling function.

Errors will also be gracefully logged.

Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
Change-Id: I260d780ac54ffd0199dcd6ca5b95e5afe957e968

src/plugins/af_packet/af_packet.c
src/plugins/af_packet/device.c

index b2f860e..f505fac 100644 (file)
@@ -110,6 +110,26 @@ af_packet_fd_read_ready (clib_file_t * uf)
   return 0;
 }
 
+static clib_error_t *
+af_packet_fd_error (clib_file_t *uf)
+{
+  af_packet_main_t *apm = &af_packet_main;
+  clib_error_t *err = 0;
+  u64 u64;
+
+  int ret = read (uf->file_descriptor, (char *) &u64, sizeof (u64));
+
+  if (ret < 0)
+    {
+      err = clib_error_return_unix (0, "");
+      vlib_log_notice (apm->log_class, "fd %u %U", uf->file_descriptor,
+                      format_clib_error, err);
+      clib_error_free (err);
+    }
+
+  return 0;
+}
+
 static int
 is_bridge (const u8 * host_if_name)
 {
@@ -146,6 +166,7 @@ af_packet_set_rx_queues (vlib_main_t *vm, af_packet_if_t *apif)
       {
        clib_file_t template = { 0 };
        template.read_function = af_packet_fd_read_ready;
+       template.error_function = af_packet_fd_error;
        template.file_descriptor = rx_queue->fd;
        template.private_data = rx_queue->queue_index;
        template.flags = UNIX_FILE_EVENT_EDGE_TRIGGERED;
index 27f5559..fc6733f 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <af_packet/af_packet.h>
 #include <vnet/devices/virtio/virtio_std.h>
+#include <vnet/devices/netlink.h>
 
 #define foreach_af_packet_tx_func_error               \
 _(FRAME_NOT_READY, "tx frame not ready")              \
@@ -654,63 +655,25 @@ 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)
-    {
-      vlib_log_warn (apm->log_class, "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)
-    {
-      vlib_log_warn (apm->log_class,
-                    "af_packet_%s ioctl could not retrieve eth name",
-                    apif->host_if_name);
-      goto error;
-    }
+    return 0; /* no error */
 
   apif->is_admin_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
 
-  if ((rv = ioctl (fd, SIOCGIFFLAGS, &ifr)) < 0)
-    {
-      vlib_log_warn (apm->log_class, "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;
-      ifr.ifr_flags |= IFF_UP;
+      vnet_netlink_set_link_state (apif->host_if_index, 1);
     }
   else
     {
       hw_flags = 0;
-      ifr.ifr_flags &= ~IFF_UP;
-    }
-
-  if ((rv = ioctl (fd, SIOCSIFFLAGS, &ifr)) < 0)
-    {
-      vlib_log_warn (apm->log_class, "af_packet_%s error: %d",
-                    apif->is_admin_up ? "up" : "down", rv);
-      goto error;
+      vnet_netlink_set_link_state (apif->host_if_index, 0);
     }
 
   vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
 
-error:
-  if (0 <= fd)
-    close (fd);
-
   return 0;                    /* no error */
 }