From 9703528f37317a0b71dbbf9c5f7c2a13631181fc Mon Sep 17 00:00:00 2001 From: dlg Date: Fri, 26 Feb 2021 01:28:51 +0000 Subject: [PATCH] use a uint64_t for the ethernet address in the etherbridge table. testing has shown up to a 30% improvement in the veb forwarding rate with this change. an earlier diff was tested by hrvoje popovski tested on amd64 and sparc64 --- sys/net/if_bpe.c | 6 ++-- sys/net/if_etherbridge.c | 67 +++++++++++++++++++++++++--------------- sys/net/if_etherbridge.h | 13 +++++--- sys/net/if_gre.c | 6 ++-- sys/net/if_veb.c | 30 +++++------------- 5 files changed, 64 insertions(+), 58 deletions(-) diff --git a/sys/net/if_bpe.c b/sys/net/if_bpe.c index 9f008b5b92e..1a4b7525adf 100644 --- a/sys/net/if_bpe.c +++ b/sys/net/if_bpe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bpe.c,v 1.17 2021/02/24 02:04:03 dlg Exp $ */ +/* $OpenBSD: if_bpe.c,v 1.18 2021/02/26 01:28:51 dlg Exp $ */ /* * Copyright (c) 2018 David Gwynne * @@ -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 mbuf *m) 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)); diff --git a/sys/net/if_etherbridge.c b/sys/net/if_etherbridge.c index 03ee76c7a2b..451781a9908 100644 --- a/sys/net/if_etherbridge.c +++ b/sys/net/if_etherbridge.c @@ -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.4 2021/02/26 01:28:51 dlg Exp $ */ /* * Copyright (c) 2018, 2021 David Gwynne @@ -156,20 +156,22 @@ etherbridge_destroy(struct etherbridge *eb) } 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); - hash &= ETHERBRIDGE_TABLE_MASK; + uint16_t hash; + + hash = stoeplitz_h64(eba) & 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 +193,11 @@ ebl_remove(struct eb_list *ebl, struct eb_entry *ebe) 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 +256,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) +{ + return (etherbridge_resolve(eb, ether_addr_to_e64(ea))); +} + +void * +etherbridge_resolve(struct etherbridge *eb, uint64_t eba) { - struct eb_list *ebl = etherbridge_list(eb, ea); + 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,8 +285,14 @@ etherbridge_resolve(struct etherbridge *eb, const struct ether_addr *ea) } 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, ether_addr_to_e64(ea)); +} + +void +etherbridge_map(struct etherbridge *eb, void *port, uint64_t eba) { struct eb_list *ebl; struct eb_entry *oebe, *nebe; @@ -282,14 +300,13 @@ etherbridge_map(struct etherbridge *eb, void *port, void *nport; int new = 0; - if (ETHER_IS_MULTICAST(ea->ether_addr_octet) || - ETHER_IS_EQ(ea->ether_addr_octet, etheranyaddr)) + if (ETH64_IS_MULTICAST(eba) || ETH64_IS_ANYADDR(eba)) 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 +342,7 @@ etherbridge_map(struct etherbridge *eb, void *port, 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 +391,14 @@ int etherbridge_add_addr(struct etherbridge *eb, void *port, const struct ether_addr *ea, unsigned int type) { + uint64_t eba = ether_addr_to_e64(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 (ETH64_IS_MULTICAST(eba) || ETH64_IS_ANYADDR(eba)) return (EADDRNOTAVAIL); nport = eb_port_take(eb, port); @@ -398,12 +415,12 @@ etherbridge_add_addr(struct etherbridge *eb, void *port, 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 +448,15 @@ etherbridge_add_addr(struct etherbridge *eb, void *port, int etherbridge_del_addr(struct etherbridge *eb, const struct ether_addr *ea) { + uint64_t eba = ether_addr_to_e64(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 +625,7 @@ etherbridge_rtfind(struct etherbridge *eb, struct ifbaconf *baconf) 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)); + ether_e64_to_addr(&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); diff --git a/sys/net/if_etherbridge.h b/sys/net/if_etherbridge.h index fa675b48905..e5246cd62d8 100644 --- a/sys/net/if_etherbridge.h +++ b/sys/net/if_etherbridge.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_etherbridge.h,v 1.2 2021/02/24 01:20:03 dlg Exp $ */ +/* $OpenBSD: if_etherbridge.h,v 1.3 2021/02/26 01:28:51 dlg Exp $ */ /* * Copyright (c) 2018, 2021 David Gwynne @@ -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 */ diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index ec4344e2d6b..12b4c9376a2 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_gre.c,v 1.167 2021/02/24 03:20:48 dlg Exp $ */ +/* $OpenBSD: if_gre.c,v 1.168 2021/02/26 01:28:51 dlg Exp $ */ /* $NetBSD: if_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */ /* @@ -1363,7 +1363,7 @@ nvgre_input(const struct gre_tunnel *key, struct mbuf *m, int hlen, 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 */ diff --git a/sys/net/if_veb.c b/sys/net/if_veb.c index 3df480c7673..72f113e9c75 100644 --- a/sys/net/if_veb.c +++ b/sys/net/if_veb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_veb.c,v 1.9 2021/02/26 00:16:41 deraadt Exp $ */ +/* $OpenBSD: if_veb.c,v 1.10 2021/02/26 01:28:51 dlg Exp $ */ /* * Copyright (c) 2021 David Gwynne @@ -72,18 +72,6 @@ #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 } } -}; - /* SIOCBRDGIFFLGS, SIOCBRDGIFFLGS */ #define VEB_IFBIF_FLAGS (IFBIF_LEARNING|IFBIF_DISCOVER|IFBIF_BLOCKNONIP) @@ -932,7 +920,7 @@ veb_port_input(struct ifnet *ifp0, struct mbuf *m, void *brport) 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 +934,10 @@ veb_port_input(struct ifnet *ifp0, struct mbuf *m, void *brport) return (m); eh = mtod(m, struct ether_header *); - dst.ea = *(struct ether_addr *)eh->ether_dhost; + dst = ether_addr_to_e64((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 (ETH64_IS_8021_RSVD(dst)) goto drop; #if NVLAN > 0 @@ -1008,19 +996,18 @@ veb_port_input(struct ifnet *ifp0, struct mbuf *m, void *brport) eh = mtod(m, struct ether_header *); if (ISSET(p->p_bif_flags, IFBIF_LEARNING)) { - etherbridge_map(&sc->sc_eb, p, + etherbridge_map_ea(&sc->sc_eb, p, (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 (!ETH64_IS_MULTICAST(dst)) { 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 +1016,7 @@ veb_port_input(struct ifnet *ifp0, struct mbuf *m, void *brport) /* unknown unicast address */ } else { - SET(m->m_flags, - ETHER_IS_BROADCAST(eh->ether_dhost) ? M_BCAST : M_MCAST); + SET(m->m_flags, ETH64_IS_BROADCAST(dst) ? M_BCAST : M_MCAST); } veb_broadcast(sc, p, m); -- 2.20.1