[systemd-devel] [PATCH] v3 Read NIC partitions on Dell Servers

jharg93 at gmail.com jharg93 at gmail.com
Tue Nov 10 12:57:48 PST 2015


From: Jordan Hargrave <jharg93 at gmail.com>

I removed the SMBIOS-specific code, this code is for partition detection only.

This patch will read NIC partition info from VPD on Dell Servers

It creates a new environment variable 'ID_NET_NAME_PARTITION'
with the format '<port>_<partition>'

Signed-off-by: Jordan Hargrave <jharg93 at gmail.com>
---
 src/udev/udev-builtin-net_id.c | 127 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index ef9c398..69dd9fd 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -119,16 +119,131 @@ struct netnames {
         bool mac_valid;
 
         struct udev_device *pcidev;
+        struct udev_device *physdev;
         char pci_slot[IFNAMSIZ];
         char pci_path[IFNAMSIZ];
         char pci_onboard[IFNAMSIZ];
         const char *pci_onboard_label;
+        int  npar_port;
+        int  npar_pfi;
 
         char usb_ports[IFNAMSIZ];
         char bcma_core[IFNAMSIZ];
         char ccw_group[IFNAMSIZ];
 };
 
+#define FLAG_IOV 0x80
+#define FLAG_NPAR 0x1000
+
+#define VPDI_TAG 0x82
+#define VPDR_TAG 0x90
+
+struct vpd_tag
+{
+        char          cc[2];
+        unsigned char len;
+        char          data[1];
+};
+
+/* Read VPD tag ID */
+static int vpd_readtag(int fd, int *len)
+{
+        unsigned char tag, tlen[2];
+
+        if (read(fd, &tag, 1) != 1)
+                return -1;
+        if (tag == 0x00 || tag == 0xFF || tag == 0x7F)
+                return -1;
+        if (tag & 0x80) {
+                if (read(fd, tlen, 2) != 2)
+                        return -1;
+                *len = tlen[0] + (tlen[1] << 8);
+                return tag;
+        }
+        *len = (tag & 0x7);
+        return (tag & ~0x7);
+}
+
+static void *vpd_findtag(void *buf, int len, const char *sig)
+{
+        int off, siglen;
+        struct vpd_tag *t;
+
+        off = 0;
+        siglen = strlen(sig);
+        while (off < len) {
+                t = (struct vpd_tag *)((unsigned char *)buf + off);
+                if (!memcmp(t->data, sig, siglen))
+                        return t;
+                off += (t->len + 3);
+        }
+        return NULL;
+}
+
+static void dev_pci_npar_dcm(struct udev_device *dev, struct netnames *names,
+                             int len, const char *dcm,
+                             const char *fmt, int step)
+{
+        int domain, bus, slot, func, off, mydf;
+        int port, df, pfi, flag;
+
+        if (sscanf(udev_device_get_sysname(names->physdev), "%x:%x:%x.%u",
+                   &domain, &bus, &slot, &func) != 4)
+                return;
+        mydf = (slot << 3) + func;
+        for (off=3; off<len; off+=step) {
+                sscanf(dcm+off, fmt, &port, &df, &pfi, &flag);
+                if ((flag & FLAG_NPAR) && mydf == df) {
+                        names->npar_port = port;
+                        names->npar_pfi = pfi;
+                }
+        }
+}
+
+static void dev_pci_npar(struct udev_device *dev, struct netnames *names) {
+        const char *filename;
+        int len, fd;
+        struct vpd_tag *dcm;
+        void *buf;
+
+        /* Search for VPD or IOV VPD */
+        filename = strjoina(udev_device_get_syspath(names->physdev), "/vpd");
+        if ((fd = open(filename, O_RDONLY)) < 0) {
+                return;
+        }
+        if (vpd_readtag(fd, &len) != VPDI_TAG) {
+                goto done;
+        }
+        lseek(fd, len, SEEK_CUR);
+
+        /* Check VPD-R */
+        if (vpd_readtag(fd, &len) != VPDR_TAG) {
+                goto done;
+        }
+        buf = alloca(len);
+        if (read(fd, buf, len) != len) {
+                goto done;
+        }
+
+        /* Check for DELL VPD tag */
+        if (!vpd_findtag(buf, len, "DSV1028VPDR.VER")) {
+                goto done;
+        }
+
+        /* Find DCM/DC2 tag */
+        if ((dcm = vpd_findtag(buf, len, "DCM")) != NULL) {
+                dev_pci_npar_dcm(dev, names, dcm->len, dcm->data,
+                                 "%1x%1x%2x%6x", 10);
+        }
+        else if ((dcm = vpd_findtag(buf, len, "DC2")) != NULL) {
+                dev_pci_npar_dcm(dev, names, dcm->len, dcm->data,
+                                 "%1x%2x%2x%6x", 11);
+        }
+ done:
+        close(fd);
+        return;
+}
+
 /* retrieve on-board index number and label from firmware */
 static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) {
         unsigned dev_port = 0;
@@ -277,6 +392,7 @@ out:
 
 static int names_pci(struct udev_device *dev, struct netnames *names) {
         struct udev_device *parent;
+        char path[256];
 
         assert(dev);
         assert(names);
@@ -301,8 +417,14 @@ static int names_pci(struct udev_device *dev, struct netnames *names) {
                 if (!names->pcidev)
                         return -ENOENT;
         }
+        /* find SR-IOV parent device */
+        snprintf(path, sizeof(path), "%s/physfn", udev_device_get_syspath(names->pcidev));
+        names->physdev = udev_device_new_from_syspath(names->pcidev, path);
+        if (!names->physdev)
+                names->physdev = names->pcidev;
         dev_pci_onboard(dev, names);
         dev_pci_slot(dev, names);
+dev_pci_npar(dev, names);
         return 0;
 }
 
@@ -563,6 +685,11 @@ static int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool
                 if (names.pci_slot[0])
                         if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_slot) < (int)sizeof(str))
                                 udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
+
+
+                if (names.npar_port)
+                        if (snprintf(str, sizeof(str), "%d_%d", names.npar_port, names.npar_pfi) < (int)sizeof(str))
+                                udev_builtin_add_property(dev, test, "ID_NET_NAME_PARTITION", str);
                 goto out;
         }
 
-- 
2.5.0



More information about the systemd-devel mailing list