summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2021-02-26 01:12:37 +0000
committerdlg <dlg@openbsd.org>2021-02-26 01:12:37 +0000
commitcf89a71d9e248649a2adb23d76cc1cef5a7a7bba (patch)
treec21cca81adc626cc347ce05c6f69e87cad565830
parentAdd my copyright since I added most of the content (diff)
downloadwireguard-openbsd-cf89a71d9e248649a2adb23d76cc1cef5a7a7bba.tar.xz
wireguard-openbsd-cf89a71d9e248649a2adb23d76cc1cef5a7a7bba.zip
add some helpers for working with ethernet addresses as uint64_t
the main bits are ether_addr_to_e64 and ether_e64_to addr for loading an ethernet address into a uin64_t and visa versa. there's also some macros for testing if an address in a uint64_t is multicast, broadcast, anyaddr, or if it's an 802.1q reserved multicast group address. the reason for this functionality is once you have an ethernet address as a uint64_t, operations like compares, bit tests, and so on are fast and easy. tested on amd64 and sparc64
-rw-r--r--sys/net/if_ethersubr.c27
-rw-r--r--sys/netinet/if_ether.h23
2 files changed, 48 insertions, 2 deletions
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 47d74957fdf..aeee969f26a 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ethersubr.c,v 1.270 2021/02/06 13:15:37 bluhm Exp $ */
+/* $OpenBSD: if_ethersubr.c,v 1.271 2021/02/26 01:12:37 dlg Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */
/*
@@ -996,3 +996,28 @@ ether_delmulti(struct ifreq *ifr, struct arpcom *ac)
*/
return (ENETRESET);
}
+
+uint64_t
+ether_addr_to_e64(const struct ether_addr *ea)
+{
+ uint64_t e64 = 0;
+ size_t i;
+
+ for (i = 0; i < nitems(ea->ether_addr_octet); i++) {
+ e64 <<= 8;
+ e64 |= ea->ether_addr_octet[i];
+ }
+
+ return (e64);
+}
+
+void
+ether_e64_to_addr(struct ether_addr *ea, uint64_t e64)
+{
+ size_t i = nitems(ea->ether_addr_octet);
+
+ do {
+ ea->ether_addr_octet[--i] = e64;
+ e64 >>= 8;
+ } while (i > 0);
+}
diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h
index 8ae1f2b3bce..04d92124df6 100644
--- a/sys/netinet/if_ether.h
+++ b/sys/netinet/if_ether.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ether.h,v 1.78 2020/07/22 02:16:02 dlg Exp $ */
+/* $OpenBSD: if_ether.h,v 1.79 2021/02/26 01:12:37 dlg Exp $ */
/* $NetBSD: if_ether.h,v 1.22 1996/05/11 13:00:00 mycroft Exp $ */
/*
@@ -116,6 +116,24 @@ struct ether_vlan_header {
(addr)[3] | (addr)[4] | (addr)[5]) == 0x00)
#define ETHER_IS_EQ(a1, a2) (memcmp((a1), (a2), ETHER_ADDR_LEN) == 0)
+/*
+ * It can be faster to work with ethernet addresses as a uint64_t.
+ * Provide some constants and functionality centrally to better
+ * support this.
+ */
+
+#define ETH64_IS_MULTICAST(_e64) ((_e64) & 0x010000000000ULL)
+#define ETH64_IS_BROADCAST(_e64) ((_e64) == 0xffffffffffffULL)
+#define ETH64_IS_ANYADDR(_e64) ((_e64) == 0x000000000000ULL)
+
+#define ETH64_8021_RSVD_PREFIX 0x0180c2000000ULL
+#define ETH64_8021_RSVD_MASK 0xfffffffffff0ULL
+#define ETH64_IS_8021_RSVD(_e64) \
+ (((_e64) & ETH64_8021_RSVD_MASK) == ETH64_8021_RSVD_PREFIX)
+
+/*
+ * Ethernet MTU constants.
+ */
#define ETHERMTU (ETHER_MAX_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
#define ETHERMIN (ETHER_MIN_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
@@ -272,6 +290,9 @@ const struct ether_brport *
const struct ether_brport *
ether_brport_get_locked(struct ifnet *);
+uint64_t ether_addr_to_e64(const struct ether_addr *);
+void ether_e64_to_addr(struct ether_addr *, uint64_t);
+
/*
* Ethernet multicast address structure. There is one of these for each
* multicast address or range of multicast addresses that we are supposed