2 * Copyright 2014 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 <boost/operators.hpp>
23 #include <folly/Bits.h>
24 #include <folly/Conv.h>
31 * MacAddress represents an IEEE 802 MAC address.
33 class MacAddress : private boost::totally_ordered<MacAddress> {
35 static constexpr size_t SIZE = 6;
36 static const MacAddress BROADCAST;
37 static const MacAddress ZERO;
40 * Construct a zero-initialized MacAddress.
43 memset(&bytes_, 0, 8);
47 * Parse a MacAddress from a human-readable string.
48 * The string must contain 6 one- or two-digit hexadecimal
49 * numbers, separated by dashes or colons.
50 * Examples: 00:02:C9:C8:F9:68 or 0-2-c9-c8-f9-68
52 explicit MacAddress(StringPiece str);
55 * Construct a MAC address from its 6-byte binary value
57 static MacAddress fromBinary(ByteRange value) {
59 ret.setFromBinary(value);
64 * Construct a MacAddress from a uint64_t in network byte order.
66 * The first two bytes are ignored, and the MAC address is taken from the
69 * This is a static method rather than a constructor to avoid confusion
70 * between host and network byte order constructors.
72 static MacAddress fromNBO(uint64_t value) {
73 return MacAddress(value);
77 * Construct a MacAddress from a uint64_t in host byte order.
79 * The most significant two bytes are ignored, and the MAC address is taken
80 * from the least significant 6 bytes.
82 * This is a static method rather than a constructor to avoid confusion
83 * between host and network byte order constructors.
85 static MacAddress fromHBO(uint64_t value) {
86 return MacAddress(Endian::big(value));
90 * Construct the multicast MacAddress for the specified multicast IPv6
93 static MacAddress createMulticast(IPAddressV6 addr);
96 * Get a pointer to the MAC address' binary value.
98 * The returned value points to internal storage inside the MacAddress
99 * object. It is only valid as long as the MacAddress, and its contents may
100 * change if the MacAddress is updated.
102 const uint8_t* bytes() const {
107 * Return the address as a uint64_t, in network byte order.
109 * The first two bytes will be 0, and the subsequent 6 bytes will contain
110 * the address in network byte order.
112 uint64_t u64NBO() const {
113 return packedBytes();
117 * Return the address as a uint64_t, in host byte order.
119 * The two most significant bytes will be 0, and the remaining 6 bytes will
120 * contain the address. The most significant of these 6 bytes will contain
121 * the first byte that appear on the wire, and the least significant byte
122 * will contain the last byte.
124 uint64_t u64HBO() const {
125 // Endian::big() does what we want here, even though we are converting
126 // from big-endian to host byte order. This swaps if and only if
127 // the host byte order is little endian.
128 return Endian::big(packedBytes());
132 * Return a human-readable representation of the MAC address.
134 std::string toString() const;
137 * Update the current MacAddress object from a human-readable string.
139 void parse(StringPiece str);
142 * Update the current MacAddress object from a 6-byte binary representation.
144 void setFromBinary(ByteRange value);
146 bool isBroadcast() const {
147 return *this == BROADCAST;
149 bool isMulticast() const {
150 return getByte(0) & 0x1;
152 bool isUnicast() const {
153 return !isMulticast();
157 * Return true if this MAC address is locally administered.
159 * Locally administered addresses are assigned by the local network
160 * administrator, and are not guaranteed to be globally unique. (It is
161 * similar to IPv4's private address space.)
163 * Note that isLocallyAdministered() will return true for the broadcast
164 * address, since it has the locally administered bit set.
166 bool isLocallyAdministered() const {
167 return getByte(0) & 0x2;
170 // Equality and less-than operators.
171 // boost::totally_ordered provides the other comparison operators.
173 bool operator==(const MacAddress& other) const {
174 // All constructors and modifying methods make sure padding is 0,
175 // so we don't need to mask these bytes out when comparing here.
176 return packedBytes() == other.packedBytes();
179 bool operator<(const MacAddress& other) const {
180 return u64HBO() < other.u64HBO();
184 explicit MacAddress(uint64_t valueNBO) {
185 memcpy(&bytes_, &valueNBO, 8);
186 // Set the pad bytes to 0.
187 // This allows us to easily compare two MacAddresses,
188 // without having to worry about differences in the padding.
193 /* We store the 6 bytes starting at bytes_[2] (most significant)
194 through bytes_[7] (least).
195 bytes_[0] and bytes_[1] are always equal to 0 to simplify comparisons.
197 unsigned char bytes_[8];
199 inline uint64_t getByte(size_t index) const {
200 return bytes_[index + 2];
203 uint64_t packedBytes() const {
205 memcpy(&u64, bytes_, 8);
210 /* Define toAppend() so to<string> will work */
212 typename std::enable_if<IsSomeString<Tgt>::value>::type
213 toAppend(MacAddress address, Tgt* result) {
214 toAppend(address.toString(), result);
217 std::ostream& operator<<(std::ostream& os, MacAddress address);