Index: if_etherbridge.c =================================================================== RCS file: /cvs/src/sys/net/if_etherbridge.c,v retrieving revision 1.3 diff -u -p -r1.3 if_etherbridge.c --- if_etherbridge.c 24 Feb 2021 08:23:04 -0000 1.3 +++ if_etherbridge.c 24 Feb 2021 12:56:47 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: if_etherbridge.c,v 1.3 2021/02/24 08:23:04 dlg Exp $ */ +/* $OpenBSD: if_etherbridge.c,v 1.2 2021/02/24 01:20:03 dlg Exp $ */ /* * Copyright (c) 2018, 2021 David Gwynne @@ -156,20 +156,26 @@ etherbridge_destroy(struct etherbridge * } static struct eb_list * -etherbridge_list(struct etherbridge *eb, const struct ether_addr *ea) +etherbridge_list(struct etherbridge *eb, uint64_t eba) { - uint16_t hash = stoeplitz_eaddr(ea->ether_addr_octet); + uint16_t hash; + + eba ^= eba >> 32; + eba ^= eba >> 16; + + hash = stoeplitz_h16(eba); hash &= ETHERBRIDGE_TABLE_MASK; + return (&eb->eb_table[hash]); } static struct eb_entry * -ebl_find(struct eb_list *ebl, const struct ether_addr *ea) +ebl_find(struct eb_list *ebl, uint64_t eba) { struct eb_entry *ebe; SMR_TAILQ_FOREACH(ebe, ebl, ebe_lentry) { - if (ETHER_IS_EQ(ea, &ebe->ebe_addr)) + if (ebe->ebe_addr == eba) return (ebe); } @@ -191,8 +197,11 @@ ebl_remove(struct eb_list *ebl, struct e static inline int ebt_cmp(const struct eb_entry *aebe, const struct eb_entry *bebe) { - return (memcmp(&aebe->ebe_addr, &bebe->ebe_addr, - sizeof(aebe->ebe_addr))); + if (aebe->ebe_addr > bebe->ebe_addr) + return (1); + if (aebe->ebe_addr < bebe->ebe_addr) + return (-1); + return (0); } RBT_GENERATE(eb_tree, eb_entry, ebe_tentry, ebt_cmp); @@ -251,14 +260,21 @@ ebe_free(void *arg) } void * -etherbridge_resolve(struct etherbridge *eb, const struct ether_addr *ea) +etherbridge_resolve_ea(struct etherbridge *eb, + const struct ether_addr *ea) { - struct eb_list *ebl = etherbridge_list(eb, ea); + return (etherbridge_resolve(eb, eb_addr_get(ea))); +} + +void * +etherbridge_resolve(struct etherbridge *eb, uint64_t eba) +{ + struct eb_list *ebl = etherbridge_list(eb, eba); struct eb_entry *ebe; SMR_ASSERT_CRITICAL(); - ebe = ebl_find(ebl, ea); + ebe = ebl_find(ebl, eba); if (ebe != NULL) { if (ebe->ebe_type == EBE_DYNAMIC) { int diff = getuptime() - ebe->ebe_age; @@ -273,23 +289,28 @@ etherbridge_resolve(struct etherbridge * } void -etherbridge_map(struct etherbridge *eb, void *port, +etherbridge_map_ea(struct etherbridge *eb, void *port, const struct ether_addr *ea) { + etherbridge_map(eb, port, eb_addr_get(ea)); +} + +void +etherbridge_map(struct etherbridge *eb, void *port, uint64_t eba) +{ struct eb_list *ebl; struct eb_entry *oebe, *nebe; unsigned int num; void *nport; int new = 0; - if (ETHER_IS_MULTICAST(ea->ether_addr_octet) || - ETHER_IS_EQ(ea->ether_addr_octet, etheranyaddr)) + if ((eba & 0x010000000000) || (eba == 0)) return; - ebl = etherbridge_list(eb, ea); + ebl = etherbridge_list(eb, eba); smr_read_enter(); - oebe = ebl_find(ebl, ea); + oebe = ebl_find(ebl, eba); if (oebe == NULL) new = 1; else { @@ -325,7 +346,7 @@ etherbridge_map(struct etherbridge *eb, refcnt_init(&nebe->ebe_refs); nebe->ebe_etherbridge = eb; - nebe->ebe_addr = *ea; + nebe->ebe_addr = eba; nebe->ebe_port = nport; nebe->ebe_type = EBE_DYNAMIC; nebe->ebe_age = getuptime(); @@ -374,14 +395,14 @@ int etherbridge_add_addr(struct etherbridge *eb, void *port, const struct ether_addr *ea, unsigned int type) { + uint64_t eba = eb_addr_get(ea); struct eb_list *ebl; struct eb_entry *nebe; unsigned int num; void *nport; int error = 0; - if (ETHER_IS_MULTICAST(ea->ether_addr_octet) || - ETHER_IS_EQ(ea->ether_addr_octet, etheranyaddr)) + if ((eba & 0x010000000000) || (eba == 0)) return (EADDRNOTAVAIL); nport = eb_port_take(eb, port); @@ -398,12 +419,12 @@ etherbridge_add_addr(struct etherbridge refcnt_init(&nebe->ebe_refs); nebe->ebe_etherbridge = eb; - nebe->ebe_addr = *ea; + nebe->ebe_addr = eba; nebe->ebe_port = nport; nebe->ebe_type = type; nebe->ebe_age = getuptime(); - ebl = etherbridge_list(eb, ea); + ebl = etherbridge_list(eb, eba); mtx_enter(&eb->eb_lock); num = eb->eb_num + 1; @@ -431,14 +452,15 @@ etherbridge_add_addr(struct etherbridge int etherbridge_del_addr(struct etherbridge *eb, const struct ether_addr *ea) { + uint64_t eba = eb_addr_get(ea); struct eb_list *ebl; struct eb_entry *oebe; const struct eb_entry key = { - .ebe_addr = *ea, + .ebe_addr = eba, }; int error = 0; - ebl = etherbridge_list(eb, ea); + ebl = etherbridge_list(eb, eba); mtx_enter(&eb->eb_lock); oebe = ebt_find(eb, &key); @@ -607,8 +629,7 @@ etherbridge_rtfind(struct etherbridge *e eb_port_ifname(eb, bareq.ifba_ifsname, sizeof(bareq.ifba_ifsname), ebe->ebe_port); - memcpy(&bareq.ifba_dst, &ebe->ebe_addr, - sizeof(bareq.ifba_dst)); + eb_addr_set(&bareq.ifba_dst, ebe->ebe_addr); memset(&bareq.ifba_dstsa, 0, sizeof(bareq.ifba_dstsa)); eb_port_sa(eb, &bareq.ifba_dstsa, ebe->ebe_port); @@ -678,4 +699,29 @@ etherbridge_get_tmo(struct etherbridge * bparam->ifbrp_ctime = eb->eb_max_age; return (0); +} + +uint64_t +eb_addr_get(const struct ether_addr *ea) +{ + uint64_t eba = 0; + size_t i; + + for (i = 0; i < nitems(ea->ether_addr_octet); i++) { + eba <<= 8; + eba |= ea->ether_addr_octet[i]; + } + + return (eba); +} + +void +eb_addr_set(struct ether_addr *ea, uint64_t eba) +{ + size_t i = nitems(ea->ether_addr_octet); + + do { + ea->ether_addr_octet[--i] = eba; + eba >>= 8; + } while (i > 0); } Index: if_etherbridge.h =================================================================== RCS file: /cvs/src/sys/net/if_etherbridge.h,v retrieving revision 1.2 diff -u -p -r1.2 if_etherbridge.h --- if_etherbridge.h 24 Feb 2021 01:20:03 -0000 1.2 +++ if_etherbridge.h 24 Feb 2021 12:56:48 -0000 @@ -42,7 +42,7 @@ struct eb_entry { #define ebe_tentry _ebe_entries._ebe_tentry #define ebe_qentry _ebe_entries._ebe_qentry - struct ether_addr ebe_addr; + uint64_t ebe_addr; void *ebe_port; unsigned int ebe_type; #define EBE_DYNAMIC 0x0 @@ -81,9 +81,12 @@ int etherbridge_up(struct etherbridge * int etherbridge_down(struct etherbridge *); void etherbridge_destroy(struct etherbridge *); -void etherbridge_map(struct etherbridge *, void *, - const struct ether_addr *); -void *etherbridge_resolve(struct etherbridge *, const struct ether_addr *); +void etherbridge_map(struct etherbridge *, void *, uint64_t); +void etherbridge_map_ea(struct etherbridge *, void *, + const struct ether_addr *); +void *etherbridge_resolve(struct etherbridge *, uint64_t); +void *etherbridge_resolve_ea(struct etherbridge *, + const struct ether_addr *); void etherbridge_detach_port(struct etherbridge *, void *); /* ioctl support */ @@ -102,5 +105,8 @@ etherbridge_num(const struct etherbridge { return (eb->eb_num); } + +uint64_t eb_addr_get(const struct ether_addr *); +void eb_addr_set(struct ether_addr *, uint64_t); #endif /* _NET_ETHERBRIDGE_H_ */ Index: if_veb.c =================================================================== RCS file: /cvs/src/sys/net/if_veb.c,v retrieving revision 1.8 diff -u -p -r1.8 if_veb.c --- if_veb.c 24 Feb 2021 01:20:03 -0000 1.8 +++ if_veb.c 24 Feb 2021 12:56:48 -0000 @@ -72,17 +72,8 @@ #include #endif -union veb_addr { - struct ether_addr ea; - uint64_t word; -}; - -static const union veb_addr veb_8021_group = { - .ea = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 } -}; -static const union veb_addr veb_8021_group_mask = { - .ea = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0 } -}; +#define IEEE8021_PREFIX 0x0180c2000000 +#define IEEE8021_PREFIX_MASK 0xfffffffffff0 /* SIOCBRDGIFFLGS, SIOCBRDGIFFLGS */ #define VEB_IFBIF_FLAGS (IFBIF_LEARNING|IFBIF_DISCOVER|IFBIF_BLOCKNONIP) @@ -932,7 +923,7 @@ veb_port_input(struct ifnet *ifp0, struc struct veb_softc *sc = p->p_veb; struct ifnet *ifp = &sc->sc_if; struct ether_header *eh; - union veb_addr dst = { .word = 0 }; + uint64_t dst; #if NBPFILTER > 0 caddr_t if_bpf; #endif @@ -946,10 +937,10 @@ veb_port_input(struct ifnet *ifp0, struc return (m); eh = mtod(m, struct ether_header *); - dst.ea = *(struct ether_addr *)eh->ether_dhost; + dst = eb_addr_get((struct ether_addr *)eh->ether_dhost); /* Is this a MAC Bridge component Reserved address? */ - if ((dst.word & veb_8021_group_mask.word) == veb_8021_group.word) + if ((dst & IEEE8021_PREFIX_MASK) == IEEE8021_PREFIX) goto drop; #if NVLAN > 0 @@ -1009,18 +1000,17 @@ veb_port_input(struct ifnet *ifp0, struc if (ISSET(p->p_bif_flags, IFBIF_LEARNING)) { etherbridge_map(&sc->sc_eb, p, - (struct ether_addr *)eh->ether_shost); + eb_addr_get((struct ether_addr *)eh->ether_shost)); } CLR(m->m_flags, M_BCAST|M_MCAST); SET(m->m_flags, M_PROTO1); - if (!ETHER_IS_MULTICAST(eh->ether_dhost)) { + if ((dst & 0x010000000000) == 0) { struct veb_port *tp = NULL; smr_read_enter(); - tp = etherbridge_resolve(&sc->sc_eb, - (struct ether_addr *)eh->ether_dhost); + tp = etherbridge_resolve(&sc->sc_eb, dst); m = veb_transmit(sc, p, tp, m); smr_read_leave(); @@ -1029,8 +1019,7 @@ veb_port_input(struct ifnet *ifp0, struc /* unknown unicast address */ } else { - SET(m->m_flags, - ETHER_IS_BROADCAST(eh->ether_dhost) ? M_BCAST : M_MCAST); + SET(m->m_flags, (dst == 0xffffffffffff) ? M_BCAST : M_MCAST); } veb_broadcast(sc, p, m); Index: if_bpe.c =================================================================== RCS file: /cvs/src/sys/net/if_bpe.c,v retrieving revision 1.17 diff -u -p -r1.17 if_bpe.c --- if_bpe.c 24 Feb 2021 02:04:03 -0000 1.17 +++ if_bpe.c 24 Feb 2021 12:56:48 -0000 @@ -268,7 +268,7 @@ bpe_start(struct ifnet *ifp) struct ether_addr *endpoint; smr_read_enter(); - endpoint = etherbridge_resolve(&sc->sc_eb, + endpoint = etherbridge_resolve_ea(&sc->sc_eb, (struct ether_addr *)ceh->ether_dhost); if (endpoint == NULL) { /* "flood" to unknown hosts */ @@ -763,7 +763,7 @@ bpe_input(struct ifnet *ifp0, struct mbu ceh = (struct ether_header *)(itagp + 1); - etherbridge_map(&sc->sc_eb, ceh->ether_shost, + etherbridge_map_ea(&sc->sc_eb, ceh->ether_shost, (struct ether_addr *)beh->ether_shost); m_adj(m, sizeof(*beh) + sizeof(*itagp)); Index: if_gre.c =================================================================== RCS file: /cvs/src/sys/net/if_gre.c,v retrieving revision 1.167 diff -u -p -r1.167 if_gre.c --- if_gre.c 24 Feb 2021 03:20:48 -0000 1.167 +++ if_gre.c 24 Feb 2021 12:56:48 -0000 @@ -1363,7 +1363,7 @@ nvgre_input(const struct gre_tunnel *key return (0); eh = mtod(m, struct ether_header *); - etherbridge_map(&sc->sc_eb, (void *)&key->t_dst, + etherbridge_map_ea(&sc->sc_eb, (void *)&key->t_dst, (struct ether_addr *)eh->ether_shost); SET(m->m_pkthdr.csum_flags, M_FLOWID); @@ -3658,7 +3658,7 @@ nvgre_start(struct ifnet *ifp) const union gre_addr *endpoint; smr_read_enter(); - endpoint = etherbridge_resolve(&sc->sc_eb, + endpoint = etherbridge_resolve_ea(&sc->sc_eb, (struct ether_addr *)eh->ether_dhost); if (endpoint == NULL) { /* "flood" to unknown hosts */