1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * From FreeBSD 2.2.7: Fundamental constants relating to ethernet. 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * Copyright (C) 2020, Broadcom. 5*4882a593Smuzhiyun * 6*4882a593Smuzhiyun * Unless you and Broadcom execute a separate written software license 7*4882a593Smuzhiyun * agreement governing use of this software, this software is licensed to you 8*4882a593Smuzhiyun * under the terms of the GNU General Public License version 2 (the "GPL"), 9*4882a593Smuzhiyun * available at http://www.broadcom.com/licenses/GPLv2.php, with the 10*4882a593Smuzhiyun * following added to such license: 11*4882a593Smuzhiyun * 12*4882a593Smuzhiyun * As a special exception, the copyright holders of this software give you 13*4882a593Smuzhiyun * permission to link this software with independent modules, and to copy and 14*4882a593Smuzhiyun * distribute the resulting executable under terms of your choice, provided that 15*4882a593Smuzhiyun * you also meet, for each linked independent module, the terms and conditions of 16*4882a593Smuzhiyun * the license of that module. An independent module is a module which is not 17*4882a593Smuzhiyun * derived from this software. The special exception does not apply to any 18*4882a593Smuzhiyun * modifications of the software. 19*4882a593Smuzhiyun * 20*4882a593Smuzhiyun * 21*4882a593Smuzhiyun * <<Broadcom-WL-IPTag/Dual:>> 22*4882a593Smuzhiyun */ 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun #ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */ 25*4882a593Smuzhiyun #define _NET_ETHERNET_H_ 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun #ifndef _TYPEDEFS_H_ 28*4882a593Smuzhiyun #include "typedefs.h" 29*4882a593Smuzhiyun #endif 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun /* This marks the start of a packed structure section. */ 32*4882a593Smuzhiyun #include <packed_section_start.h> 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun /* 35*4882a593Smuzhiyun * The number of bytes in an ethernet (MAC) address. 36*4882a593Smuzhiyun */ 37*4882a593Smuzhiyun #define ETHER_ADDR_LEN 6 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun /* 40*4882a593Smuzhiyun * The number of bytes in the type field. 41*4882a593Smuzhiyun */ 42*4882a593Smuzhiyun #define ETHER_TYPE_LEN 2 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun /* 45*4882a593Smuzhiyun * The number of bytes in the trailing CRC field. 46*4882a593Smuzhiyun */ 47*4882a593Smuzhiyun #define ETHER_CRC_LEN 4 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun /* 50*4882a593Smuzhiyun * The length of the combined header. 51*4882a593Smuzhiyun */ 52*4882a593Smuzhiyun #define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun /* 55*4882a593Smuzhiyun * The minimum packet length. 56*4882a593Smuzhiyun */ 57*4882a593Smuzhiyun #define ETHER_MIN_LEN 64 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun /* 60*4882a593Smuzhiyun * The minimum packet user data length. 61*4882a593Smuzhiyun */ 62*4882a593Smuzhiyun #define ETHER_MIN_DATA 46 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun /* 65*4882a593Smuzhiyun * The maximum packet length. 66*4882a593Smuzhiyun */ 67*4882a593Smuzhiyun #define ETHER_MAX_LEN 1518 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun /* 70*4882a593Smuzhiyun * The maximum packet user data length. 71*4882a593Smuzhiyun */ 72*4882a593Smuzhiyun #define ETHER_MAX_DATA 1500 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun /* ether types */ 75*4882a593Smuzhiyun #define ETHER_TYPE_MIN 0x0600 /* Anything less than MIN is a length */ 76*4882a593Smuzhiyun #define ETHER_TYPE_IP 0x0800 /* IP */ 77*4882a593Smuzhiyun #define ETHER_TYPE_ARP 0x0806 /* ARP */ 78*4882a593Smuzhiyun #define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */ 79*4882a593Smuzhiyun #define ETHER_TYPE_IPV6 0x86dd /* IPv6 */ 80*4882a593Smuzhiyun #define ETHER_TYPE_BRCM 0x886c /* Broadcom Corp. */ 81*4882a593Smuzhiyun #define ETHER_TYPE_802_1X 0x888e /* 802.1x */ 82*4882a593Smuzhiyun #define ETHER_TYPE_802_1X_PREAUTH 0x88c7 /* 802.1x preauthentication */ 83*4882a593Smuzhiyun #define ETHER_TYPE_WAI 0x88b4 /* WAI */ 84*4882a593Smuzhiyun #define ETHER_TYPE_89_0D 0x890d /* 89-0d frame for TDLS */ 85*4882a593Smuzhiyun #define ETHER_TYPE_RRB ETHER_TYPE_89_0D /* RRB 802.11r 2008 */ 86*4882a593Smuzhiyun #define ETHER_TYPE_1905_1 0x893a /* IEEE 1905.1 MCDU */ 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun #define ETHER_TYPE_PPP_SES 0x8864 /* PPPoE Session */ 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun #define ETHER_TYPE_IAPP_L2_UPDATE 0x6 /* IAPP L2 update frame */ 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun /* Broadcom subtype follows ethertype; First 2 bytes are reserved; Next 2 are subtype; */ 93*4882a593Smuzhiyun #define ETHER_BRCM_SUBTYPE_LEN 4 /* Broadcom 4 byte subtype */ 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun /* ether header */ 96*4882a593Smuzhiyun #define ETHER_DEST_OFFSET (0 * ETHER_ADDR_LEN) /* dest address offset */ 97*4882a593Smuzhiyun #define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN) /* src address offset */ 98*4882a593Smuzhiyun #define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN) /* ether type offset */ 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun /* 101*4882a593Smuzhiyun * A macro to validate a length with 102*4882a593Smuzhiyun */ 103*4882a593Smuzhiyun #define ETHER_IS_VALID_LEN(foo) \ 104*4882a593Smuzhiyun ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun #define ETHER_FILL_MCAST_ADDR_FROM_IP(ea, mgrp_ip) { \ 107*4882a593Smuzhiyun ((uint8 *)ea)[0] = 0x01; \ 108*4882a593Smuzhiyun ((uint8 *)ea)[1] = 0x00; \ 109*4882a593Smuzhiyun ((uint8 *)ea)[2] = 0x5e; \ 110*4882a593Smuzhiyun ((uint8 *)ea)[3] = ((mgrp_ip) >> 16) & 0x7f; \ 111*4882a593Smuzhiyun ((uint8 *)ea)[4] = ((mgrp_ip) >> 8) & 0xff; \ 112*4882a593Smuzhiyun ((uint8 *)ea)[5] = ((mgrp_ip) >> 0) & 0xff; \ 113*4882a593Smuzhiyun } 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun #ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */ 116*4882a593Smuzhiyun /* 117*4882a593Smuzhiyun * Structure of a 10Mb/s Ethernet header. 118*4882a593Smuzhiyun */ 119*4882a593Smuzhiyun BWL_PRE_PACKED_STRUCT struct ether_header { 120*4882a593Smuzhiyun uint8 ether_dhost[ETHER_ADDR_LEN]; 121*4882a593Smuzhiyun uint8 ether_shost[ETHER_ADDR_LEN]; 122*4882a593Smuzhiyun uint16 ether_type; 123*4882a593Smuzhiyun } BWL_POST_PACKED_STRUCT; 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun /* 126*4882a593Smuzhiyun * Structure of a 48-bit Ethernet address. 127*4882a593Smuzhiyun */ 128*4882a593Smuzhiyun BWL_PRE_PACKED_STRUCT struct ether_addr { 129*4882a593Smuzhiyun uint8 octet[ETHER_ADDR_LEN]; 130*4882a593Smuzhiyun } BWL_POST_PACKED_STRUCT; 131*4882a593Smuzhiyun #endif /* __INCif_etherh */ 132*4882a593Smuzhiyun #ifdef __INCif_etherh 133*4882a593Smuzhiyun #endif /* !__INCif_etherh Quick and ugly hack for VxWorks */ 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun /* 136*4882a593Smuzhiyun * Takes a pointer, set, test, clear, toggle locally admininistered 137*4882a593Smuzhiyun * address bit in the 48-bit Ethernet address. 138*4882a593Smuzhiyun */ 139*4882a593Smuzhiyun #define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2)) 140*4882a593Smuzhiyun #define ETHER_IS_LOCALADDR(ea) (((uint8 *)(ea))[0] & 2) 141*4882a593Smuzhiyun #define ETHER_CLR_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xfd)) 142*4882a593Smuzhiyun #define ETHER_TOGGLE_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2)) 143*4882a593Smuzhiyun 144*4882a593Smuzhiyun /* Takes a pointer, marks unicast address bit in the MAC address */ 145*4882a593Smuzhiyun #define ETHER_SET_UNICAST(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1)) 146*4882a593Smuzhiyun 147*4882a593Smuzhiyun /* 148*4882a593Smuzhiyun * Takes a pointer, returns true if a 48-bit multicast address 149*4882a593Smuzhiyun * (including broadcast, since it is all ones) 150*4882a593Smuzhiyun */ 151*4882a593Smuzhiyun #define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1) 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun /* compare two ethernet addresses - assumes the pointers can be referenced as shorts */ 154*4882a593Smuzhiyun #if defined(DONGLEBUILD) && defined(__ARM_ARCH_7A__) && !defined(BCMFUZZ) 155*4882a593Smuzhiyun #define eacmp(a, b) (((*(const uint32 *)(a)) ^ (*(const uint32 *)(b))) || \ 156*4882a593Smuzhiyun ((*(const uint16 *)(((const uint8 *)(a)) + 4)) ^ \ 157*4882a593Smuzhiyun (*(const uint16 *)(((const uint8 *)(b)) + 4)))) 158*4882a593Smuzhiyun 159*4882a593Smuzhiyun #define ehcmp(a, b) ((((const uint32 *)(a))[0] ^ ((const uint32 *)(b))[0]) || \ 160*4882a593Smuzhiyun (((const uint32 *)(a))[1] ^ ((const uint32 *)(b))[1]) || \ 161*4882a593Smuzhiyun (((const uint32 *)(a))[2] ^ ((const uint32 *)(b))[2]) || \ 162*4882a593Smuzhiyun ((*(const uint16 *)(((const uint32 *)(a)) + 3)) ^ \ 163*4882a593Smuzhiyun (*(const uint16 *)(((const uint32 *)(b)) + 3)))) 164*4882a593Smuzhiyun #else 165*4882a593Smuzhiyun #define eacmp(a, b) ((((const uint16 *)(a))[0] ^ ((const uint16 *)(b))[0]) | \ 166*4882a593Smuzhiyun (((const uint16 *)(a))[1] ^ ((const uint16 *)(b))[1]) | \ 167*4882a593Smuzhiyun (((const uint16 *)(a))[2] ^ ((const uint16 *)(b))[2])) 168*4882a593Smuzhiyun 169*4882a593Smuzhiyun #define ehcmp(a, b) ((((const uint16 *)(a))[0] ^ ((const uint16 *)(b))[0]) | \ 170*4882a593Smuzhiyun (((const uint16 *)(a))[1] ^ ((const uint16 *)(b))[1]) | \ 171*4882a593Smuzhiyun (((const uint16 *)(a))[2] ^ ((const uint16 *)(b))[2]) | \ 172*4882a593Smuzhiyun (((const uint16 *)(a))[3] ^ ((const uint16 *)(b))[3]) | \ 173*4882a593Smuzhiyun (((const uint16 *)(a))[4] ^ ((const uint16 *)(b))[4]) | \ 174*4882a593Smuzhiyun (((const uint16 *)(a))[5] ^ ((const uint16 *)(b))[5]) | \ 175*4882a593Smuzhiyun (((const uint16 *)(a))[6] ^ ((const uint16 *)(b))[6])) 176*4882a593Smuzhiyun #endif /* DONGLEBUILD && __ARM_ARCH_7A__ */ 177*4882a593Smuzhiyun 178*4882a593Smuzhiyun #define ether_cmp(a, b) eacmp(a, b) 179*4882a593Smuzhiyun 180*4882a593Smuzhiyun /* copy an ethernet address - assumes the pointers can be referenced as shorts */ 181*4882a593Smuzhiyun #if defined(DONGLEBUILD) && defined(__ARM_ARCH_7A__) && !defined(BCMFUZZ) 182*4882a593Smuzhiyun #define eacopy(s, d) \ 183*4882a593Smuzhiyun do { \ 184*4882a593Smuzhiyun (*(uint32 *)(d)) = (*(const uint32 *)(s)); \ 185*4882a593Smuzhiyun (*(uint16 *)(((uint8 *)(d)) + 4)) = (*(const uint16 *)(((const uint8 *)(s)) + 4)); \ 186*4882a593Smuzhiyun } while (0) 187*4882a593Smuzhiyun #else 188*4882a593Smuzhiyun #define eacopy(s, d) \ 189*4882a593Smuzhiyun do { \ 190*4882a593Smuzhiyun ((uint16 *)(d))[0] = ((const uint16 *)(s))[0]; \ 191*4882a593Smuzhiyun ((uint16 *)(d))[1] = ((const uint16 *)(s))[1]; \ 192*4882a593Smuzhiyun ((uint16 *)(d))[2] = ((const uint16 *)(s))[2]; \ 193*4882a593Smuzhiyun } while (0) 194*4882a593Smuzhiyun #endif /* DONGLEBUILD && __ARM_ARCH_7A__ */ 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun #define ether_copy(s, d) eacopy(s, d) 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun /* Copy an ethernet address in reverse order */ 199*4882a593Smuzhiyun #define ether_rcopy(s, d) \ 200*4882a593Smuzhiyun do { \ 201*4882a593Smuzhiyun ((uint16 *)(d))[2] = ((uint16 *)(s))[2]; \ 202*4882a593Smuzhiyun ((uint16 *)(d))[1] = ((uint16 *)(s))[1]; \ 203*4882a593Smuzhiyun ((uint16 *)(d))[0] = ((uint16 *)(s))[0]; \ 204*4882a593Smuzhiyun } while (0) 205*4882a593Smuzhiyun 206*4882a593Smuzhiyun /* Copy 14B ethernet header: 32bit aligned source and destination. */ 207*4882a593Smuzhiyun #define ehcopy32(s, d) \ 208*4882a593Smuzhiyun do { \ 209*4882a593Smuzhiyun ((uint32 *)(d))[0] = ((const uint32 *)(s))[0]; \ 210*4882a593Smuzhiyun ((uint32 *)(d))[1] = ((const uint32 *)(s))[1]; \ 211*4882a593Smuzhiyun ((uint32 *)(d))[2] = ((const uint32 *)(s))[2]; \ 212*4882a593Smuzhiyun ((uint16 *)(d))[6] = ((const uint16 *)(s))[6]; \ 213*4882a593Smuzhiyun } while (0) 214*4882a593Smuzhiyun 215*4882a593Smuzhiyun /* Dongles use bcmutils functions instead of macros. 216*4882a593Smuzhiyun * Possibly slower but saves over 800 bytes off THUMB dongle image. 217*4882a593Smuzhiyun */ 218*4882a593Smuzhiyun 219*4882a593Smuzhiyun extern const struct ether_addr ether_bcast; 220*4882a593Smuzhiyun extern const struct ether_addr ether_null; 221*4882a593Smuzhiyun extern const struct ether_addr ether_ipv6_mcast; 222*4882a593Smuzhiyun 223*4882a593Smuzhiyun extern int ether_isbcast(const void *ea); 224*4882a593Smuzhiyun extern int ether_isnulladdr(const void *ea); 225*4882a593Smuzhiyun 226*4882a593Smuzhiyun #define ETHER_ISBCAST(ea) ether_isbcast(ea) 227*4882a593Smuzhiyun 228*4882a593Smuzhiyun #if defined(__ARM_ARCH_7A__) && !defined(BCMFUZZ) 229*4882a593Smuzhiyun #define ETHER_ISNULLADDR(ea) (((*(const uint32 *)(ea)) | \ 230*4882a593Smuzhiyun (*(const uint16 *)(((const uint8 *)(ea)) + 4))) == 0) 231*4882a593Smuzhiyun #else 232*4882a593Smuzhiyun #define ETHER_ISNULLADDR(ea) ether_isnulladdr(ea) 233*4882a593Smuzhiyun #endif /* __ARM_ARCH_7A__ */ 234*4882a593Smuzhiyun 235*4882a593Smuzhiyun #define ETHER_ISNULLDEST(da) ((((const uint16 *)(da))[0] | \ 236*4882a593Smuzhiyun ((const uint16 *)(da))[1] | \ 237*4882a593Smuzhiyun ((const uint16 *)(da))[2]) == 0) 238*4882a593Smuzhiyun #define ETHER_ISNULLSRC(sa) ETHER_ISNULLDEST(sa) 239*4882a593Smuzhiyun 240*4882a593Smuzhiyun #define ETHER_MOVE_HDR(d, s) \ 241*4882a593Smuzhiyun do { \ 242*4882a593Smuzhiyun struct ether_header t; \ 243*4882a593Smuzhiyun t = *(struct ether_header *)(s); \ 244*4882a593Smuzhiyun *(struct ether_header *)(d) = t; \ 245*4882a593Smuzhiyun } while (0) 246*4882a593Smuzhiyun 247*4882a593Smuzhiyun #define ETHER_ISUCAST(ea) ((((uint8 *)(ea))[0] & 0x01) == 0) 248*4882a593Smuzhiyun 249*4882a593Smuzhiyun /* This marks the end of a packed structure section. */ 250*4882a593Smuzhiyun #include <packed_section_end.h> 251*4882a593Smuzhiyun 252*4882a593Smuzhiyun #endif /* _NET_ETHERNET_H_ */ 253