Do not prefer empty MAC address

Motivation:

When comparing MAC addresses searching for the best MAC address, if
locally-administered address (e.g., from a Docker container) is compared
against an empty MAC address, the empty MAC address will be marked as
preferred. In cases this is the only available MAC address, this leaves
Netty using a random machine ID instead of using a perfectly valid
machine ID from the locally-adminstered address.

Modifications:

This commit modifies the MAC address logic so that the empty MAC address
is not preferred over a locally-administered address. This commit also
simplifies the comparison logic here.

Result:

Empty MAC addresses will not be preferred over locally-administered
addresses thus permitting the default machine ID to be the
locally-adminstered MAC address if it is the only available MAC address.
This commit is contained in:
Jason Tedor 2017-02-02 21:14:07 -05:00 committed by Scott Mitchell
parent 661ff2538e
commit 42c0359820
2 changed files with 59 additions and 8 deletions

View File

@ -203,7 +203,8 @@ public final class MacAddressUtil {
/** /**
* @return positive - current is better, 0 - cannot tell from MAC addr, negative - candidate is better. * @return positive - current is better, 0 - cannot tell from MAC addr, negative - candidate is better.
*/ */
private static int compareAddresses(byte[] current, byte[] candidate) { // visible for testing
static int compareAddresses(byte[] current, byte[] candidate) {
if (candidate == null || candidate.length < EUI48_MAC_ADDRESS_LENGTH) { if (candidate == null || candidate.length < EUI48_MAC_ADDRESS_LENGTH) {
return 1; return 1;
} }
@ -227,20 +228,23 @@ public final class MacAddressUtil {
} }
// Prefer globally unique address. // Prefer globally unique address.
if (current.length == 0 || (current[0] & 2) == 0) { if ((candidate[0] & 2) == 0) {
if ((candidate[0] & 2) == 0) { if (current.length != 0 && (current[0] & 2) == 0) {
// Both current and candidate are globally unique addresses. // Both current and candidate are globally unique addresses.
return 0; return 0;
} else { } else {
// Only candidate is globally unique.
return -1;
}
} else {
if (current.length != 0 && (current[0] & 2) == 0) {
// Only current is globally unique. // Only current is globally unique.
return 1; return 1;
} else {
// Both current and candidate are non-unique.
return 0;
} }
} else if ((candidate[0] & 2) == 0) {
// Only candidate is globally unique.
return -1;
} }
// Both current and candidate are non-unique.
return 0;
} }
/** /**

View File

@ -17,10 +17,57 @@ package io.netty.util.internal;
import org.junit.Test; import org.junit.Test;
import static io.netty.util.internal.EmptyArrays.EMPTY_BYTES;
import static io.netty.util.internal.MacAddressUtil.parseMAC; import static io.netty.util.internal.MacAddressUtil.parseMAC;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
public class MacAddressUtilTest { public class MacAddressUtilTest {
@Test
public void testCompareAddresses() {
// should not prefer empty address when candidate is not globally unique
assertEquals(
0,
MacAddressUtil.compareAddresses(
EMPTY_BYTES,
new byte[]{(byte) 0x52, (byte) 0x54, (byte) 0x00, (byte) 0xf9, (byte) 0x32, (byte) 0xbd}));
// only candidate is globally unique
assertEquals(
-1,
MacAddressUtil.compareAddresses(
EMPTY_BYTES,
new byte[]{(byte) 0x50, (byte) 0x54, (byte) 0x00, (byte) 0xf9, (byte) 0x32, (byte) 0xbd}));
// only candidate is globally unique
assertEquals(
-1,
MacAddressUtil.compareAddresses(
new byte[]{(byte) 0x52, (byte) 0x54, (byte) 0x00, (byte) 0xf9, (byte) 0x32, (byte) 0xbd},
new byte[]{(byte) 0x50, (byte) 0x54, (byte) 0x00, (byte) 0xf9, (byte) 0x32, (byte) 0xbd}));
// only current is globally unique
assertEquals(
1,
MacAddressUtil.compareAddresses(
new byte[]{(byte) 0x52, (byte) 0x54, (byte) 0x00, (byte) 0xf9, (byte) 0x32, (byte) 0xbd},
EMPTY_BYTES));
// only current is globally unique
assertEquals(
1,
MacAddressUtil.compareAddresses(
new byte[]{(byte) 0x50, (byte) 0x54, (byte) 0x00, (byte) 0xf9, (byte) 0x32, (byte) 0xbd},
new byte[]{(byte) 0x52, (byte) 0x54, (byte) 0x00, (byte) 0xf9, (byte) 0x32, (byte) 0xbd}));
// both are globally unique
assertEquals(
0,
MacAddressUtil.compareAddresses(
new byte[]{(byte) 0x50, (byte) 0x54, (byte) 0x00, (byte) 0xf9, (byte) 0x32, (byte) 0xbd},
new byte[]{(byte) 0x50, (byte) 0x55, (byte) 0x01, (byte) 0xfa, (byte) 0x33, (byte) 0xbe}));
}
@Test @Test
public void testParseMacEUI48() { public void testParseMacEUI48() {
assertArrayEquals(new byte[]{0, (byte) 0xaa, 0x11, (byte) 0xbb, 0x22, (byte) 0xcc}, assertArrayEquals(new byte[]{0, (byte) 0xaa, 0x11, (byte) 0xbb, 0x22, (byte) 0xcc},