1 /*
2  * Copyright 2019, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include "hash.h"
20 
21 #include <linux/if_ether.h>
22 #include <stdint.h>
23 #include <string.h>
24 
25 // Format macros for printf, e.g. printf("MAC address: " PRIMAC, MACARG(mac))
26 #define PRIMAC "%02x:%02x:%02x:%02x:%02x:%02x"
27 #define MACARG(x) (x)[0], (x)[1], (x)[2], (x)[3],(x)[4], (x)[5]
28 
29 struct MacAddress {
MacAddressMacAddress30     MacAddress() {
31         memset(addr, 0, sizeof(addr));
32     }
MacAddressMacAddress33     MacAddress(uint8_t b1, uint8_t b2, uint8_t b3,
34                uint8_t b4, uint8_t b5, uint8_t b6) {
35         addr[0] = b1; addr[1] = b2; addr[2] = b3;
36         addr[3] = b4; addr[4] = b5; addr[5] = b6;
37     }
38     uint8_t addr[ETH_ALEN];
isBroadcastMacAddress39     bool isBroadcast() const {
40         return memcmp(addr, "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ALEN) == 0;
41     }
isMulticastMacAddress42     bool isMulticast() const {
43         return addr[0] & 0x01;
44     }
emptyMacAddress45     bool empty() const {
46         return memcmp(addr, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0;
47     }
48     uint8_t operator[](size_t index) const {
49         return addr[index];
50     }
51 } __attribute__((__packed__));
52 
53 namespace std {
54 template<> struct hash<MacAddress> {
55     size_t operator()(const MacAddress& addr) const {
56         size_t seed = 0;
57         // Treat the first 4 bytes as an uint32_t to save some computation
58         hash_combine(seed, *reinterpret_cast<const uint32_t*>(addr.addr));
59         // And the remaining 2 bytes as an uint16_t
60         hash_combine(seed, *reinterpret_cast<const uint16_t*>(addr.addr + 4));
61         return seed;
62     }
63 };
64 }
65 
66 inline bool operator==(const MacAddress& left, const MacAddress& right) {
67     return memcmp(left.addr, right.addr, ETH_ALEN) == 0;
68 }
69 
70 inline bool operator!=(const MacAddress& left, const MacAddress& right) {
71     return memcmp(left.addr, right.addr, ETH_ALEN) != 0;
72 }
73 
74