From: Vincent Bernat Date: Sun, 13 Mar 2016 16:54:07 +0000 (+0100) Subject: interfaces: handle correctly operation conversation of a port X-Git-Tag: 0.9.2~35 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=32945d6a96ec2fc4eec82cc5702adbb7dfbf75d4;p=thirdparty%2Flldpd.git interfaces: handle correctly operation conversation of a port 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. --- diff --git a/src/daemon/interfaces-linux.c b/src/daemon/interfaces-linux.c index be4668f7..340b9e8d 100644 --- a/src/daemon/interfaces-linux.c +++ b/src/daemon/interfaces-linux.c @@ -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; diff --git a/src/daemon/interfaces.c b/src/daemon/interfaces.c index 09aeff88..eab78893 100644 --- a/src/daemon/interfaces.c +++ b/src/daemon/interfaces.c @@ -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 } } diff --git a/src/daemon/lldpd.c b/src/daemon/lldpd.c index 1f90867f..b0c93ccd 100644 --- a/src/daemon/lldpd.c +++ b/src/daemon/lldpd.c @@ -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; diff --git a/src/daemon/lldpd.h b/src/daemon/lldpd.h index aacb39e4..9ec91e9f 100644 --- a/src/daemon/lldpd.h +++ b/src/daemon/lldpd.h @@ -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);