2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <folly/Bits.h>
22 #include <folly/Range.h>
29 * MacAddress represents an IEEE 802 MAC address.
33 static constexpr size_t SIZE = 6;
34 static const MacAddress BROADCAST;
35 static const MacAddress ZERO;
38 * Construct a zero-initialized MacAddress.
41 memset(&bytes_, 0, 8);
45 * Parse a MacAddress from a human-readable string.
46 * The string must contain 6 one- or two-digit hexadecimal
47 * numbers, separated by dashes or colons.
48 * Examples: 00:02:C9:C8:F9:68 or 0-2-c9-c8-f9-68
50 explicit MacAddress(StringPiece str);
53 * Construct a MAC address from its 6-byte binary value
55 static MacAddress fromBinary(ByteRange value) {
57 ret.setFromBinary(value);
62 * Construct a MacAddress from a uint64_t in network byte order.
64 * The first two bytes are ignored, and the MAC address is taken from the
67 * This is a static method rather than a constructor to avoid confusion
68 * between host and network byte order constructors.
70 static MacAddress fromNBO(uint64_t value) {
71 return MacAddress(value);
75 * Construct a MacAddress from a uint64_t in host byte order.
77 * The most significant two bytes are ignored, and the MAC address is taken
78 * from the least significant 6 bytes.
80 * This is a static method rather than a constructor to avoid confusion
81 * between host and network byte order constructors.
83 static MacAddress fromHBO(uint64_t value) {
84 return MacAddress(Endian::big(value));
88 * Construct the multicast MacAddress for the specified multicast IPv6
91 static MacAddress createMulticast(IPAddressV6 addr);
94 * Get a pointer to the MAC address' binary value.
96 * The returned value points to internal storage inside the MacAddress
97 * object. It is only valid as long as the MacAddress, and its contents may
98 * change if the MacAddress is updated.
100 const uint8_t* bytes() const {
105 * Return the address as a uint64_t, in network byte order.
107 * The first two bytes will be 0, and the subsequent 6 bytes will contain
108 * the address in network byte order.
110 uint64_t u64NBO() const {
111 return packedBytes();
115 * Return the address as a uint64_t, in host byte order.
117 * The two most significant bytes will be 0, and the remaining 6 bytes will
118 * contain the address. The most significant of these 6 bytes will contain
119 * the first byte that appear on the wire, and the least significant byte
120 * will contain the last byte.
122 uint64_t u64HBO() const {
123 // Endian::big() does what we want here, even though we are converting
124 // from big-endian to host byte order. This swaps if and only if
125 // the host byte order is little endian.
126 return Endian::big(packedBytes());
130 * Return a human-readable representation of the MAC address.
132 std::string toString() const;
135 * Update the current MacAddress object from a human-readable string.
137 void parse(StringPiece str);
140 * Update the current MacAddress object from a 6-byte binary representation.
142 void setFromBinary(ByteRange value);
144 bool isBroadcast() const {
145 return *this == BROADCAST;
147 bool isMulticast() const {
148 return getByte(0) & 0x1;
150 bool isUnicast() const {
151 return !isMulticast();
155 * Return true if this MAC address is locally administered.
157 * Locally administered addresses are assigned by the local network
158 * administrator, and are not guaranteed to be globally unique. (It is
159 * similar to IPv4's private address space.)
161 * Note that isLocallyAdministered() will return true for the broadcast
162 * address, since it has the locally administered bit set.
164 bool isLocallyAdministered() const {
165 return getByte(0) & 0x2;
168 // Comparison operators.
170 bool operator==(const MacAddress& other) const {
171 // All constructors and modifying methods make sure padding is 0,
172 // so we don't need to mask these bytes out when comparing here.
173 return packedBytes() == other.packedBytes();
176 bool operator<(const MacAddress& other) const {
177 return u64HBO() < other.u64HBO();
180 bool operator!=(const MacAddress& other) const {
181 return !(*this == other);
184 bool operator>(const MacAddress& other) const {
185 return other < *this;
188 bool operator>=(const MacAddress& other) const {
189 return !(*this < other);
192 bool operator<=(const MacAddress& other) const {
193 return !(*this > other);
197 explicit MacAddress(uint64_t valueNBO) {
198 memcpy(&bytes_, &valueNBO, 8);
199 // Set the pad bytes to 0.
200 // This allows us to easily compare two MacAddresses,
201 // without having to worry about differences in the padding.
206 /* We store the 6 bytes starting at bytes_[2] (most significant)
207 through bytes_[7] (least).
208 bytes_[0] and bytes_[1] are always equal to 0 to simplify comparisons.
210 unsigned char bytes_[8];
212 inline uint64_t getByte(size_t index) const {
213 return bytes_[index + 2];
216 uint64_t packedBytes() const {
218 memcpy(&u64, bytes_, 8);
223 /* Define toAppend() so to<string> will work */
225 typename std::enable_if<IsSomeString<Tgt>::value>::type
226 toAppend(MacAddress address, Tgt* result) {
227 toAppend(address.toString(), result);
230 std::ostream& operator<<(std::ostream& os, MacAddress address);