Line data Source code
1 : /* 2 : * Copyright (c) 2018 Cisco and/or its affiliates. 3 : * Licensed under the Apache License, Version 2.0 (the "License"); 4 : * you may not use this file except in compliance with the License. 5 : * You may obtain a copy of the License at: 6 : * 7 : * http://www.apache.org/licenses/LICENSE-2.0 8 : * 9 : * Unless required by applicable law or agreed to in writing, software 10 : * distributed under the License is distributed on an "AS IS" BASIS, 11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : * See the License for the specific language governing permissions and 13 : * limitations under the License. 14 : */ 15 : 16 : #ifndef __MAC_ADDRESS_H__ 17 : #define __MAC_ADDRESS_H__ 18 : 19 : #include <vlib/vlib.h> 20 : 21 : typedef struct mac_address_t_ 22 : { 23 : union 24 : { 25 : u8 bytes[6]; 26 : struct 27 : { 28 : u32 first_4; 29 : u16 last_2; 30 : } __clib_packed u; 31 : }; 32 : } mac_address_t; 33 : 34 : STATIC_ASSERT ((sizeof (mac_address_t) == 6), 35 : "MAC address must represent the on wire format"); 36 : 37 : extern const mac_address_t ZERO_MAC_ADDRESS; 38 : 39 : always_inline u64 40 4 : ethernet_mac_address_u64 (const u8 * a) 41 : { 42 4 : return (((u64) a[0] << (u64) (5 * 8)) 43 4 : | ((u64) a[1] << (u64) (4 * 8)) 44 4 : | ((u64) a[2] << (u64) (3 * 8)) 45 4 : | ((u64) a[3] << (u64) (2 * 8)) 46 4 : | ((u64) a[4] << (u64) (1 * 8)) | ((u64) a[5] << (u64) (0 * 8))); 47 : } 48 : 49 : always_inline void 50 4 : ethernet_mac_address_from_u64 (u64 u, u8 * a) 51 : { 52 : i8 ii; 53 : 54 28 : for (ii = 5; ii >= 0; ii--) 55 : { 56 24 : a[ii] = u & 0xFF; 57 24 : u = u >> 8; 58 : } 59 4 : } 60 : 61 : static inline int 62 : ethernet_mac_address_is_multicast_u64 (u64 a) 63 : { 64 : return (a & (1ULL << (5 * 8))) != 0; 65 : } 66 : 67 : static inline int 68 252 : ethernet_mac_address_is_zero (const u8 * mac) 69 : { 70 252 : return ((*((u32 *) mac) == 0) && (*((u16 *) (mac + 4)) == 0)); 71 : } 72 : 73 : static inline void 74 504 : ethernet_mac_address_generate (u8 * mac) 75 : { 76 504 : u32 rnd = clib_cpu_time_now (); 77 504 : rnd = random_u32 (&rnd); 78 : 79 504 : memcpy (mac + 2, &rnd, sizeof (rnd)); 80 504 : mac[0] = 2; 81 504 : mac[1] = 0xfe; 82 504 : } 83 : 84 : static inline int 85 271373 : ethernet_mac_address_equal (const u8 * a, const u8 * b) 86 : { 87 520995 : return ((*((u32 *) a) == (*((u32 *) b))) && 88 249622 : (*((u16 *) (a + 4)) == (*((u16 *) (b + 4))))); 89 : } 90 : 91 : static_always_inline void 92 68968 : mac_address_from_bytes (mac_address_t * mac, const u8 * bytes) 93 : { 94 : /* zero out the last 2 bytes, then copy over only 6 */ 95 68968 : clib_memcpy_fast (mac->bytes, bytes, 6); 96 68968 : } 97 : 98 : static_always_inline void 99 : mac_address_to_bytes (const mac_address_t * mac, u8 * bytes) 100 : { 101 : /* zero out the last 2 bytes, then copy over only 6 */ 102 : clib_memcpy_fast (bytes, mac->bytes, 6); 103 : } 104 : 105 : static_always_inline int 106 8 : mac_address_is_zero (const mac_address_t * mac) 107 : { 108 8 : return (0 == mac->u.first_4 && 0 == mac->u.last_2); 109 : } 110 : 111 : static_always_inline u64 112 85 : mac_address_as_u64 (const mac_address_t * mac) 113 : { 114 85 : volatile u64 as_u64 = 0; 115 : 116 85 : clib_memcpy ((void *) &as_u64, mac->bytes, 6); 117 : 118 85 : return as_u64; 119 : } 120 : 121 : static_always_inline void 122 0 : mac_address_from_u64 (mac_address_t * mac, u64 u) 123 : { 124 0 : clib_memcpy (mac->bytes, &u, 6); 125 0 : } 126 : 127 : static_always_inline void 128 9258 : mac_address_copy (mac_address_t * dst, const mac_address_t * src) 129 : { 130 9258 : mac_address_from_bytes (dst, src->bytes); 131 9258 : } 132 : 133 : static_always_inline int 134 20299 : mac_address_cmp (const mac_address_t * a, const mac_address_t * b) 135 : { 136 20299 : return (memcmp (a->bytes, b->bytes, 6)); 137 : } 138 : 139 : static_always_inline int 140 8 : mac_address_equal (const mac_address_t * a, const mac_address_t * b) 141 : { 142 8 : return (a->u.last_2 == b->u.last_2 && a->u.first_4 == b->u.first_4); 143 : } 144 : 145 : static_always_inline void 146 0 : mac_address_set_zero (mac_address_t * mac) 147 : { 148 0 : mac->u.first_4 = 0; 149 0 : mac->u.last_2 = 0; 150 0 : } 151 : 152 : static_always_inline int 153 : mac_address_n_bits_set (const mac_address_t * a) 154 : { 155 : return (count_set_bits (mac_address_as_u64 (a))); 156 : } 157 : 158 : extern void mac_address_increment (mac_address_t * mac); 159 : extern uword unformat_mac_address_t (unformat_input_t * input, 160 : va_list * args); 161 : extern u8 *format_mac_address_t (u8 * s, va_list * args); 162 : 163 : #endif 164 : 165 : /* 166 : * fd.io coding-style-patch-verification: ON 167 : * 168 : * Local Variables: 169 : * eval: (c-set-style "gnu") 170 : * End: 171 : */