]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
priv: disable LLDP in firmware for Intel X7xx cards on FreeBSD master
authorJohn W. O'Brien <john@saltant.com>
Sat, 11 May 2024 22:49:42 +0000 (18:49 -0400)
committerVincent Bernat <vincent@bernat.ch>
Sun, 12 May 2024 17:00:20 +0000 (19:00 +0200)
NEWS
README.md
src/daemon/priv-bsd.c

diff --git a/NEWS b/NEWS
index 33076e4f61f8d4a0ff41b5e4c8363ca32b0f3508..f02685193cfb3c4ae7802c01f236c0271bd8a71c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ lldpd (1.0.19)
  * Changes:
    + Support of both Apple Silicon and Intel for macOS package.
    + Add cvlan/svlan/tpmr capabilities.
+   + Disable LLDP in firmware for Intel X7xx cards on FreeBSD.
 
 lldpd (1.0.18)
  * Changes (breaking):
index e19bf5ccb93e812ca503a73b28bc3622e96dff60..c753b669b33e29d5c60acc4b19f104f9448666ea 100644 (file)
--- a/README.md
+++ b/README.md
@@ -449,8 +449,15 @@ for f in /sys/kernel/debug/i40e/*/command; do
     echo lldp stop > $f
 done
 ```
+On FreeBSD, use `sysctl` stop the embedded LLDP daemon:
+```sh
+for oid in $(sysctl -Nq dev.ixl | grep fw_lldp); do
+    sysctl $oid=0
+done
+```
 This may also apply to the `ice` (Intel E8xx cards) driver. These
-steps are not necessary with a recent version of `lldpd` (1.0.11+).
+steps are not necessary with a recent version of `lldpd` (1.0.11+ for
+Linux, 1.0.19+ for FreeBSD).
 
 ## License
 
index 61f332a567f169ec783dcc6e41604d771fafe806..b687cbea16dec7fb16ff4e725aec7a0a92820c2e 100644 (file)
 
 #include "lldpd.h"
 
+#include <ctype.h>
 #include <unistd.h>
+#include <net/if.h>
 #include <net/bpf.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/sysctl.h>
 #include <sys/ioctl.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <string.h>
 
+#if defined HOST_OS_FREEBSD
+#  include <net/if_mib.h>
+
+/* Quirks needed by some additional interfaces. Currently, this is limited to
+ * disabling LLDP firmware for ixl. OpenBSD and NetBSD disable the ixl
+ * firmware LLDP agent upon driver attach. */
+static void
+asroot_iface_init_quirks(int ifindex, char *name)
+{
+       int sysctl_oid[6];
+       int fw_lldp = 0;
+       size_t driver_name_len;
+       char *driver_name = NULL;
+       char *sysctl_name = NULL;
+
+       /* Check driver. */
+       sysctl_oid[0] = CTL_NET;
+       sysctl_oid[1] = PF_LINK;
+       sysctl_oid[2] = NETLINK_GENERIC;
+       sysctl_oid[3] = IFMIB_IFDATA;
+       sysctl_oid[4] = ifindex;
+       sysctl_oid[5] = IFDATA_DRIVERNAME;
+
+       if (sysctl(sysctl_oid, 6, NULL, &driver_name_len, 0, 0) < 0) {
+               log_warn("interfaces", "unable to get driver name length");
+               goto end;
+       }
+
+       if ((driver_name = malloc(driver_name_len)) == NULL) {
+               log_warnx("interfaces", "insufficient memory for driver name");
+               goto end;
+       }
+
+       if (sysctl(sysctl_oid, 6, driver_name, &driver_name_len, 0, 0) < 0) {
+               log_warn("interfaces", "unable to get driver name");
+               goto end;
+       }
+
+       if (driver_name_len < 4 || strncmp("ixl", driver_name, 3) ||
+           !isdigit(driver_name[3])) {
+               /* Not ixl */
+               goto end;
+       }
+
+       log_info("interfaces", "ixl driver detected for %s, disabling LLDP in firmware",
+           name);
+
+       if (asprintf(&sysctl_name, "dev.ixl.%s.fw_lldp", driver_name + 3) == -1) {
+               log_warnx("interfaces", "insufficient memory for sysctl name");
+               goto end;
+       }
+       if (sysctlbyname(sysctl_name, NULL, NULL, &fw_lldp, sizeof(fw_lldp)) < 0) {
+               log_warn("interfaces",
+                   "unable to disable LLDP in firmware for %s via %s", name,
+                   sysctl_name);
+               goto end;
+       }
+
+end:
+       if (driver_name != NULL) free(driver_name);
+       if (sysctl_name != NULL) free(sysctl_name);
+}
+#endif /* HOST_OS_FREEBSD */
+
 int
 asroot_iface_init_os(int ifindex, char *name, int *fd)
 {
@@ -124,6 +191,9 @@ asroot_iface_init_os(int ifindex, char *name, int *fd)
                log_info("privsep", "unable to lock BPF interface %s", name);
                return rc;
        }
+#endif
+#if defined HOST_OS_FREEBSD
+       asroot_iface_init_quirks(ifindex, name);
 #endif
        return 0;
 }