]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
interfaces: handle correctly operation conversation of a port
authorVincent Bernat <vincent@bernat.im>
Sun, 13 Mar 2016 16:54:07 +0000 (17:54 +0100)
committerVincent Bernat <vincent@bernat.im>
Sun, 13 Mar 2016 16:54:07 +0000 (17:54 +0100)
When a port was regular and become an enslaved member of a bond, we
created a different port. Since we now keep the old ports around, the
old port may still attract a lot of things, like specific configuration
or VLAN. Therefore, we handle the conversion of a port from one kind to
another.

Another idea would be to not do special handling for bonds. Only old
kernels need that. We could remove that later.

src/daemon/interfaces-linux.c
src/daemon/interfaces.c
src/daemon/lldpd.c
src/daemon/lldpd.h

index be4668f703bd2bfa59d333ac98dcd2703b1f5b2f..340b9e8db9a6c1136175b49e069c4021f83655f2 100644 (file)
@@ -520,7 +520,7 @@ iface_bond_close(struct lldpd *cfg, struct lldpd_hardware *hardware)
            hardware->h_ifname);
        interfaces_setup_multicast(cfg, hardware->h_ifname, 1);
        interfaces_setup_multicast(cfg, master->name, 1);
-       free(hardware->h_data);
+       free(hardware->h_data); hardware->h_data = NULL;
        return 0;
 }
 
@@ -537,6 +537,7 @@ iflinux_handle_bond(struct lldpd *cfg, struct interfaces_device_list *interfaces
        struct interfaces_device *master;
        struct lldpd_hardware *hardware;
        struct bond_master *bmaster;
+       int created;
        TAILQ_FOREACH(iface, interfaces, next) {
                if (!(iface->type & IFACE_PHYSICAL_T)) continue;
                if (iface->ignore) continue;
@@ -545,10 +546,10 @@ iflinux_handle_bond(struct lldpd *cfg, struct interfaces_device_list *interfaces
                master = iface->upper;
                log_debug("interfaces", "%s is an acceptable enslaved device (master=%s)",
                    iface->name, master->name);
+               created = 0;
                if ((hardware = lldpd_get_hardware(cfg,
                            iface->name,
-                           iface->index,
-                           &bond_ops)) == NULL) {
+                           iface->index)) == NULL) {
                        if  ((hardware = lldpd_alloc_hardware(cfg,
                                    iface->name,
                                    iface->index)) == NULL) {
@@ -556,14 +557,29 @@ iflinux_handle_bond(struct lldpd *cfg, struct interfaces_device_list *interfaces
                                    iface->name);
                                continue;
                        }
+                       created = 1;
+               }
+               if (hardware->h_flags) continue;
+               if (hardware->h_ops != &bond_ops) {
+                       if (!created) {
+                               log_debug("interfaces",
+                                   "bond %s is converted from another type of interface",
+                                   hardware->h_ifname);
+                               if (hardware->h_ops && hardware->h_ops->cleanup)
+                                       hardware->h_ops->cleanup(cfg, hardware);
+                               levent_hardware_release(hardware);
+                               levent_hardware_init(hardware);
+                       }
                        bmaster = hardware->h_data = calloc(1, sizeof(struct bond_master));
                        if (!bmaster) {
                                log_warn("interfaces", "not enough memory");
                                lldpd_hardware_cleanup(cfg, hardware);
                                continue;
                        }
-                       bmaster->index = master->index;
-                       strlcpy(bmaster->name, master->name, IFNAMSIZ);
+               } else bmaster = hardware->h_data;
+               bmaster->index = master->index;
+               strlcpy(bmaster->name, master->name, IFNAMSIZ);
+               if (hardware->h_ops != &bond_ops) {
                        if (iface_bond_init(cfg, hardware) != 0) {
                                log_warn("interfaces", "unable to initialize %s",
                                    hardware->h_ifname);
@@ -572,15 +588,11 @@ iflinux_handle_bond(struct lldpd *cfg, struct interfaces_device_list *interfaces
                        }
                        hardware->h_ops = &bond_ops;
                        hardware->h_mangle = 1;
+               }
+               if (created)
                        interfaces_helper_add_hardware(cfg, hardware);
-               } else {
-                       if (hardware->h_flags) continue; /* Already seen this time */
-                       bmaster = hardware->h_data;
-                       memset(bmaster, 0, sizeof(struct bond_master));
-                       bmaster->index = master->index;
-                       strlcpy(bmaster->name, master->name, IFNAMSIZ);
+               else
                        lldpd_port_cleanup(&hardware->h_lport, 0);
-               }
 
                hardware->h_flags = iface->flags;
                iface->ignore = 1;
index 09aeff8801145ac142c260f7de5b542208f30f42..eab788930fa97c320d8484ef18c225aa8a844a6c 100644 (file)
@@ -188,7 +188,7 @@ iface_append_vlan(struct lldpd *cfg,
     struct interfaces_device *lower)
 {
        struct lldpd_hardware *hardware =
-           lldpd_get_hardware(cfg, lower->name, lower->index, NULL);
+           lldpd_get_hardware(cfg, lower->name, lower->index);
        struct lldpd_port *port;
        struct lldpd_vlan *v;
 
@@ -331,8 +331,7 @@ interfaces_helper_chassis(struct lldpd *cfg,
 
                if ((hardware = lldpd_get_hardware(cfg,
                            iface->name,
-                           iface->index,
-                           NULL)) == NULL)
+                           iface->index)) == NULL)
                        /* That's odd. Let's skip. */
                        continue;
 
@@ -575,6 +574,7 @@ interfaces_helper_physical(struct lldpd *cfg,
 {
        struct interfaces_device *iface;
        struct lldpd_hardware *hardware;
+       int created;
 
        TAILQ_FOREACH(iface, interfaces, next) {
                if (!(iface->type & IFACE_PHYSICAL_T)) continue;
@@ -582,10 +582,10 @@ interfaces_helper_physical(struct lldpd *cfg,
 
                log_debug("interfaces", "%s is an acceptable ethernet device",
                    iface->name);
+               created = 0;
                if ((hardware = lldpd_get_hardware(cfg,
                            iface->name,
-                           iface->index,
-                           ops)) == NULL) {
+                           iface->index)) == NULL) {
                        if  ((hardware = lldpd_alloc_hardware(cfg,
                                    iface->name,
                                    iface->index)) == NULL) {
@@ -593,6 +593,21 @@ interfaces_helper_physical(struct lldpd *cfg,
                                    iface->name);
                                continue;
                        }
+                       created = 1;
+               }
+               if (hardware->h_flags)
+                       continue;
+               if (hardware->h_ops != ops) {
+                       if (!created) {
+                               log_debug("interfaces",
+                                   "interface %s is converted from another type of interface",
+                                   hardware->h_ifname);
+                               if (hardware->h_ops && hardware->h_ops->cleanup) {
+                                       hardware->h_ops->cleanup(cfg, hardware);
+                                       levent_hardware_release(hardware);
+                                       levent_hardware_init(hardware);
+                               }
+                       }
                        if (init(cfg, hardware) != 0) {
                                log_warnx("interfaces",
                                    "unable to initialize %s",
@@ -603,11 +618,11 @@ interfaces_helper_physical(struct lldpd *cfg,
                        hardware->h_ops = ops;
                        hardware->h_mangle = (iface->upper &&
                            iface->upper->type & IFACE_BOND_T);
+               }
+               if (created)
                        interfaces_helper_add_hardware(cfg, hardware);
-               } else {
-                       if (hardware->h_flags) continue; /* Already seen this time */
+               else
                        lldpd_port_cleanup(&hardware->h_lport, 0);
-               }
 
                hardware->h_flags = iface->flags;   /* Should be non-zero */
                iface->ignore = 1;                  /* Future handlers
@@ -627,6 +642,8 @@ interfaces_helper_physical(struct lldpd *cfg,
 #ifdef ENABLE_DOT3
                if (iface->upper && iface->upper->type & IFACE_BOND_T)
                        hardware->h_lport.p_aggregid = iface->upper->index;
+               else
+                       hardware->h_lport.p_aggregid = 0;
 #endif
        }
 }
index 1f90867f6f4ee86e9ffe82e6f2d23e0a23c231e8..b0c93ccd3fe09e7a31bdf0235f6be7851ba0f91f 100644 (file)
@@ -127,13 +127,12 @@ usage(void)
 }
 
 struct lldpd_hardware *
-lldpd_get_hardware(struct lldpd *cfg, char *name, int index, struct lldpd_ops *ops)
+lldpd_get_hardware(struct lldpd *cfg, char *name, int index)
 {
        struct lldpd_hardware *hardware;
        TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
                if ((strcmp(hardware->h_ifname, name) == 0) &&
-                   (hardware->h_ifindex == index) &&
-                   ((!ops) || (ops == hardware->h_ops)))
+                   (hardware->h_ifindex == index))
                        break;
        }
        return hardware;
index aacb39e4d38da49725b52a4526211d476aedb62c..9ec91e9f13caee039908d294da208bf333915073 100644 (file)
@@ -101,7 +101,7 @@ struct lldpd;
 
 /* lldpd.c */
 struct lldpd_hardware  *lldpd_get_hardware(struct lldpd *,
-    char *, int, struct lldpd_ops *);
+    char *, int);
 struct lldpd_hardware  *lldpd_alloc_hardware(struct lldpd *, char *, int);
 void    lldpd_hardware_cleanup(struct lldpd*, struct lldpd_hardware *);
 struct lldpd_mgmt *lldpd_alloc_mgmt(int family, void *addr, size_t addrsize, u_int32_t iface);