From: Vincent Bernat Date: Sun, 11 Aug 2013 20:07:57 +0000 (+0200) Subject: interfaces: abstract a bit MAC address mangling for bonding devices X-Git-Tag: 0.7.7~31 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5347914ef1fc0bb6628b998c1abc3bb1838f8fb1;p=thirdparty%2Flldpd.git interfaces: abstract a bit MAC address mangling for bonding devices A variable in `struct lldpd_hardware` control the mangling. On the other end, `hardware->h_ops->send()` should not be called directly anymore. Instead, `interfaces_helper_send()` should be used instead. --- diff --git a/src/daemon/cdp.c b/src/daemon/cdp.c index 7dcdb120..bf5921d9 100644 --- a/src/daemon/cdp.c +++ b/src/daemon/cdp.c @@ -205,7 +205,7 @@ cdp_send(struct lldpd *global, POKE_RESTORE(pos_checksum); if (!(POKE_UINT16(ntohs(checksum)))) goto toobig; - if (hardware->h_ops->send(global, hardware, + if (interfaces_send_helper(global, hardware, (char *)packet, end - packet) == -1) { log_warn("cdp", "unable to send packet on real device for %s", hardware->h_ifname); diff --git a/src/daemon/edp.c b/src/daemon/edp.c index 80109376..4a9cfbdc 100644 --- a/src/daemon/edp.c +++ b/src/daemon/edp.c @@ -200,7 +200,7 @@ edp_send(struct lldpd *global, checksum = frame_checksum(pos_edp, v, 0); if (!(POKE_UINT16(ntohs(checksum)))) goto toobig; - if (hardware->h_ops->send(global, hardware, + if (interfaces_send_helper(global, hardware, (char *)packet, end - packet) == -1) { log_warn("edp", "unable to send packet on real device for %s", hardware->h_ifname); diff --git a/src/daemon/interfaces-linux.c b/src/daemon/interfaces-linux.c index 804d5eed..63b96a66 100644 --- a/src/daemon/interfaces-linux.c +++ b/src/daemon/interfaces-linux.c @@ -465,23 +465,6 @@ iface_bond_init(struct lldpd *cfg, struct lldpd_hardware *hardware) return 0; } -static int -iface_bond_send(struct lldpd *cfg, struct lldpd_hardware *hardware, - char *buffer, size_t size) -{ - log_debug("interfaces", "send PDU to bonded device %s", - hardware->h_ifname); - if (size < 2 * ETHER_ADDR_LEN) { - log_warnx("interfaces", - "packet to send on %s is too small!", - hardware->h_ifname); - return 0; - } - interfaces_helper_mangle_mac(cfg, buffer + ETHER_ADDR_LEN); - return write(hardware->h_sendfd, - buffer, size); -} - static int iface_bond_recv(struct lldpd *cfg, struct lldpd_hardware *hardware, int fd, char *buffer, size_t size) @@ -531,7 +514,7 @@ iface_bond_close(struct lldpd *cfg, struct lldpd_hardware *hardware) } struct lldpd_ops bond_ops = { - .send = iface_bond_send, + .send = iflinux_eth_send, .recv = iface_bond_recv, .cleanup = iface_bond_close, }; @@ -575,6 +558,7 @@ iflinux_handle_bond(struct lldpd *cfg, struct interfaces_device_list *interfaces continue; } hardware->h_ops = &bond_ops; + hardware->h_mangle = 1; TAILQ_INSERT_TAIL(&cfg->g_hardware, hardware, h_entries); } else { if (hardware->h_flags) continue; /* Already seen this time */ diff --git a/src/daemon/interfaces.c b/src/daemon/interfaces.c index f1c5fa43..6fc8fbbc 100644 --- a/src/daemon/interfaces.c +++ b/src/daemon/interfaces.c @@ -558,33 +558,45 @@ interfaces_helper_physical(struct lldpd *cfg, } /** - * Mangle the MAC address to avoid duplicates. + * Send the packet using the hardware function. Optionnaly mangle the MAC address. * * With bonds, we have duplicate MAC address on different physical - * interfaces. We need to alter the source MAC address when we send on - * an inactive slave. We try to set "local" bit to 1 first. If it is - * already set to 1, use an unused MAC address instead. + * interfaces. We need to alter the source MAC address when we send on an + * inactive slave. The `h_mangle` flah is used to know if we need to do + * something like that. */ -void -interfaces_helper_mangle_mac(struct lldpd *cfg, char *src_mac) +int +interfaces_send_helper(struct lldpd *cfg, + struct lldpd_hardware *hardware, + char *buffer, size_t size) { + if (size < 2 * ETHER_ADDR_LEN) { + log_warnx("interfaces", + "packet to send on %s is too small!", + hardware->h_ifname); + return 0; + } + if (hardware->h_mangle) { #define MAC_UL_ADMINISTERED_BIT_MASK 0x02 - char arbitrary[] = { 0x00, 0x60, 0x08, 0x69, 0x97, 0xef}; - - switch (cfg->g_config.c_bond_slave_src_mac_type) { - case LLDP_BOND_SLAVE_SRC_MAC_TYPE_LOCALLY_ADMINISTERED: - if (*src_mac & MAC_UL_ADMINISTERED_BIT_MASK) { - /* If locally administered bit already set, - * use zero mac - */ + char *src_mac = buffer + ETHER_ADDR_LEN; + char arbitrary[] = { 0x00, 0x60, 0x08, 0x69, 0x97, 0xef}; + + switch (cfg->g_config.c_bond_slave_src_mac_type) { + case LLDP_BOND_SLAVE_SRC_MAC_TYPE_LOCALLY_ADMINISTERED: + if (*src_mac & MAC_UL_ADMINISTERED_BIT_MASK) { + /* If locally administered bit already set, + * use zero mac + */ + memset(src_mac, 0, ETHER_ADDR_LEN); + break; + } + case LLDP_BOND_SLAVE_SRC_MAC_TYPE_FIXED: + memcpy(src_mac, arbitrary, ETHER_ADDR_LEN); + break; + case LLDP_BOND_SLAVE_SRC_MAC_TYPE_ZERO: memset(src_mac, 0, ETHER_ADDR_LEN); - return; + break; } - case LLDP_BOND_SLAVE_SRC_MAC_TYPE_FIXED: - memcpy(src_mac, arbitrary, ETHER_ADDR_LEN); - return; - case LLDP_BOND_SLAVE_SRC_MAC_TYPE_ZERO: - memset(src_mac, 0, ETHER_ADDR_LEN); - return; } + return hardware->h_ops->send(cfg, hardware, buffer, size); } diff --git a/src/daemon/lldp.c b/src/daemon/lldp.c index 7d99b27c..3d60563b 100644 --- a/src/daemon/lldp.c +++ b/src/daemon/lldp.c @@ -424,7 +424,7 @@ lldp_send(struct lldpd *global, POKE_END_LLDP_TLV)) goto toobig; - if (hardware->h_ops->send(global, hardware, + if (interfaces_send_helper(global, hardware, (char *)packet, pos - packet) == -1) { log_warn("lldp", "unable to send packet on real device for %s", hardware->h_ifname); diff --git a/src/daemon/lldpd.h b/src/daemon/lldpd.h index da8aea8a..659e3e60 100644 --- a/src/daemon/lldpd.h +++ b/src/daemon/lldpd.h @@ -364,7 +364,8 @@ void interfaces_helper_mgmt(struct lldpd *, void interfaces_helper_vlan(struct lldpd *, struct interfaces_device_list *); #endif -void interfaces_helper_mangle_mac(struct lldpd *, char *); +int interfaces_send_helper(struct lldpd *, + struct lldpd_hardware *, char *, size_t); void interfaces_setup_multicast(struct lldpd *, const char *, int); int interfaces_routing_enabled(struct lldpd *); diff --git a/src/daemon/sonmp.c b/src/daemon/sonmp.c index 444b4ef2..75638d1c 100644 --- a/src/daemon/sonmp.c +++ b/src/daemon/sonmp.c @@ -249,7 +249,7 @@ sonmp_send(struct lldpd *global, POKE_SAVE(end))) goto toobig; - if (hardware->h_ops->send(global, hardware, + if (interfaces_send_helper(global, hardware, (char *)packet, end - packet) == -1) { log_warn("sonmp", "unable to send packet on real device for %s", hardware->h_ifname); @@ -263,7 +263,7 @@ sonmp_send(struct lldpd *global, PEEK_DISCARD(ETHER_ADDR_LEN - 1); /* Modify the last byte of the MAC address */ (void)POKE_UINT8(1); - if (hardware->h_ops->send(global, hardware, + if (interfaces_send_helper(global, hardware, (char *)packet, end - packet) == -1) { log_warn("sonmp", "unable to send second SONMP packet on real device for %s", hardware->h_ifname); diff --git a/src/lldpd-structs.h b/src/lldpd-structs.h index 396c2e16..848fd667 100644 --- a/src/lldpd-structs.h +++ b/src/lldpd-structs.h @@ -371,6 +371,7 @@ struct lldpd_hardware { struct lldpd *h_cfg; /* Pointer to main configuration */ void *h_recv; /* FD for reception */ int h_sendfd; /* FD for sending, only used by h_ops */ + int h_mangle; /* 1 if we have to mangle the MAC address */ struct lldpd_ops *h_ops; /* Hardware-dependent functions */ void *h_data; /* Hardware-dependent data */ void *h_timer; /* Timer for this port */