diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2024-12-18 01:56:06 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2024-12-18 01:56:06 +0000 |
commit | 0997867132da18eb092a181b15e7c9260826b42f (patch) | |
tree | 6d5bc14c42a0229e2431dacee3294135a3e2a861 /sys | |
parent | a2c69727983b83013ad811606cd0f8bd8b8e8144 (diff) |
let LLDP packets fall through to being handled on the port interfaces.
802.1ax says that LLDP packets sent to the multicast groups listed
in 802.1ab (the lldp spec) should be treated as "control frames"
so they can be processed by an lldp agent on physical interface.
in our situation that means we shouldn't aggregate LLDP packets so
they appear to enter the system on aggr(4) interfaces, we should
let the physical port interfaces handle them. this will allow
AF_FRAME sockets listening on aggr port interfaces receive lldp
packets.
jmatthew@ says it looks good.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/if_aggr.c | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/sys/net/if_aggr.c b/sys/net/if_aggr.c index ca59131da7f..399c8efd32b 100644 --- a/sys/net/if_aggr.c +++ b/sys/net/if_aggr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_aggr.c,v 1.46 2024/09/04 07:54:52 mglocker Exp $ */ +/* $OpenBSD: if_aggr.c,v 1.47 2024/12/18 01:56:05 dlg Exp $ */ /* * Copyright (c) 2019 The University of Queensland @@ -744,34 +744,23 @@ aggr_start(struct ifqueue *ifq) smr_read_leave(); } -static inline int -aggr_eh_is_slow(const struct ether_header *eh) -{ - uint64_t dst; - - if (eh->ether_type != htons(ETHERTYPE_SLOW)) - return (0); - - dst = ether_addr_to_e64((struct ether_addr *)eh->ether_dhost); - return (dst == LACP_ADDR_SLOW_E64); -} - -static void -aggr_input(struct ifnet *ifp0, struct mbuf *m) +static inline struct mbuf * +aggr_input_control(struct aggr_port *p, struct mbuf *m) { - struct arpcom *ac0 = (struct arpcom *)ifp0; - struct aggr_port *p = ac0->ac_trunkport; - struct aggr_softc *sc = p->p_aggr; - struct ifnet *ifp = &sc->sc_if; struct ether_header *eh; int hlen = sizeof(*eh); + uint16_t etype; + uint64_t dst; - if (!ISSET(ifp->if_flags, IFF_RUNNING)) - goto drop; + if (ISSET(m->m_flags, M_VLANTAG)) + return (m); eh = mtod(m, struct ether_header *); - if (!ISSET(m->m_flags, M_VLANTAG) && - __predict_false(aggr_eh_is_slow(eh))) { + etype = eh->ether_type; + dst = ether_addr_to_e64((struct ether_addr *)eh->ether_dhost); + + if (__predict_false(etype == htons(ETHERTYPE_SLOW) && + dst == LACP_ADDR_SLOW_E64)) { unsigned int rx_proto = AGGR_PROTO_RX_LACP; struct ether_slowproto_hdr *sph; int drop = 0; @@ -781,7 +770,7 @@ aggr_input(struct ifnet *ifp0, struct mbuf *m) m = m_pullup(m, hlen); if (m == NULL) { /* short++ */ - return; + return (NULL); } eh = mtod(m, struct ether_header *); } @@ -808,12 +797,46 @@ aggr_input(struct ifnet *ifp0, struct mbuf *m) goto drop; else task_add(systq, &p->p_rxm_task); - return; + return (NULL); + default: + break; + } + } else if (__predict_false(etype == htons(ETHERTYPE_LLDP) && + ETH64_IS_8021_RSVD(dst))) { + /* look at the last nibble of the 802.1 reserved address */ + switch (dst & 0xf) { + case 0x0: /* Nearest Customer Bridge */ + case 0x3: /* Non-TPMR Bridge */ + case 0xe: /* Nearest Bridge */ + p->p_input(p->p_ifp0, m); + return (NULL); default: break; } } + return (m); + +drop: + m_freem(m); + return (NULL); +} + +static void +aggr_input(struct ifnet *ifp0, struct mbuf *m) +{ + struct arpcom *ac0 = (struct arpcom *)ifp0; + struct aggr_port *p = ac0->ac_trunkport; + struct aggr_softc *sc = p->p_aggr; + struct ifnet *ifp = &sc->sc_if; + + if (!ISSET(ifp->if_flags, IFF_RUNNING)) + goto drop; + + m = aggr_input_control(p, m); + if (m == NULL) + return; + if (__predict_false(!p->p_collecting)) goto drop; |