Adds utility functions related to the link local addresses
Change-Id: I26045542d4f9d60a0d7d0905087136b995f8c03e
diff --git a/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java b/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
index 66b5fa5..7375105 100644
--- a/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
+++ b/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
@@ -221,13 +221,13 @@
* we should use the solicitation node address as IPv6 destination
* and the multicast mac address as Ethernet destination.
*/
- byte[] destIp = IPv6.solicitationNodeAddress(targetIp.toOctets());
+ byte[] destIp = IPv6.getSolicitNodeAddress(targetIp.toOctets());
probePacket = NeighborSolicitation.buildNdpSolicit(
targetIp.toOctets(),
sourceIp.toOctets(),
destIp,
sourceMac.toBytes(),
- IPv6.multicastMacAddress(destIp),
+ IPv6.getMCastMacAddress(destIp),
vlan
);
}
diff --git a/utils/misc/src/main/java/org/onlab/packet/IPv6.java b/utils/misc/src/main/java/org/onlab/packet/IPv6.java
index f466ca4..e88998d 100644
--- a/utils/misc/src/main/java/org/onlab/packet/IPv6.java
+++ b/utils/misc/src/main/java/org/onlab/packet/IPv6.java
@@ -30,6 +30,7 @@
import java.util.Map;
import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
import static org.onlab.packet.PacketUtils.checkInput;
/**
@@ -48,6 +49,8 @@
public static final byte PROTOCOL_AH = 0x33;
public static final byte PROTOCOL_DSTOPT = 0x3C;
+ public static final byte LINK_LOCAL_0 = (byte) 0xfe;
+ public static final byte LINK_LOCAL_1 = (byte) 0x80;
public static final Map<Byte, Deserializer<? extends IPacket>> PROTOCOL_DESERIALIZER_MAP =
new HashMap<>();
@@ -396,8 +399,9 @@
* @param targetIp the unicast or anycast address
* @return the computed solicitation node address
*/
- public static byte[] solicitationNodeAddress(byte[] targetIp) {
- return targetIp.length != Ip6Address.BYTE_LENGTH ? null : new byte[] {
+ public static byte[] getSolicitNodeAddress(byte[] targetIp) {
+ checkArgument(targetIp.length == Ip6Address.BYTE_LENGTH);
+ return new byte[] {
(byte) 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, (byte) 0xff,
targetIp[targetIp.length - 3],
@@ -424,8 +428,9 @@
* @param targetIp the multicast address.
* @return the multicast mac address
*/
- public static byte[] multicastMacAddress(byte[] targetIp) {
- return targetIp.length != Ip6Address.BYTE_LENGTH ? null : new byte[] {
+ public static byte[] getMCastMacAddress(byte[] targetIp) {
+ checkArgument(targetIp.length == Ip6Address.BYTE_LENGTH);
+ return new byte[] {
0x33, 0x33,
targetIp[targetIp.length - 4],
targetIp[targetIp.length - 3],
@@ -433,4 +438,70 @@
targetIp[targetIp.length - 1],
};
}
+
+ /**
+ * According to the RFC 4291, an IPv6 link local address is an IPv6
+ * unicast address that can be automatically configured on any interface
+ * using the link-local prefix FE80::/10 (1111 1110 10) and the interface
+ * identifier in the modified EUI-64 format.
+ *
+ * +----------------------------------------------------------------+
+ * | 10 bits | 54 bits | 64 bits |
+ * +----------- +-------------------------+-------------------------+
+ * | 1111111010 | 0 | interface ID |
+ * +----------- +-------------------------+-------------------------+
+ *
+ * @param targetIp the ip address to verify
+ * @return true if the ipv6 address is link local,
+ * false otherwise
+ */
+ public static boolean isLinkLocalAddress(byte[] targetIp) {
+ checkArgument(targetIp.length == Ip6Address.BYTE_LENGTH);
+ return (targetIp[0] & 0xff) == 0xfe && (targetIp[1] & 0xc0) == 0x80;
+ }
+
+ /**
+ * Returns the auto-generated link local address using the
+ * mac address as parameter.
+ *
+ * @param macAddress the mac address to use
+ * @return the ipv6 link local address
+ */
+ public static byte[] getLinkLocalAddress(byte[] macAddress) {
+ checkArgument(macAddress.length == MacAddress.MAC_ADDRESS_LENGTH);
+ return new byte[] {
+ LINK_LOCAL_0,
+ LINK_LOCAL_1,
+ 0, 0, 0, 0, 0, 0,
+ (byte) (macAddress[0] ^ (1 << 1)),
+ macAddress[1],
+ macAddress[2],
+ (byte) 0xff,
+ (byte) 0xfe,
+ macAddress[3],
+ macAddress[4],
+ macAddress[5],
+ };
+ }
+
+ /**
+ * Returns the mac address from the auto-generated
+ * link local address.
+ *
+ * @param linkLocalAddress the ipv6 to use
+ * @return the mac address
+ */
+ public static byte[] getMacAddress(byte[] linkLocalAddress) {
+ return !isLinkLocalAddress(linkLocalAddress) ? null : new byte[] {
+ (byte) (linkLocalAddress[8] ^ (1 << 1)),
+ linkLocalAddress[9],
+ linkLocalAddress[10],
+ linkLocalAddress[13],
+ linkLocalAddress[14],
+ linkLocalAddress[15],
+ };
+ }
+
+
+
}
diff --git a/utils/misc/src/test/java/org/onlab/packet/IPv6Test.java b/utils/misc/src/test/java/org/onlab/packet/IPv6Test.java
index b1b555d..fef26ed 100644
--- a/utils/misc/src/test/java/org/onlab/packet/IPv6Test.java
+++ b/utils/misc/src/test/java/org/onlab/packet/IPv6Test.java
@@ -24,10 +24,10 @@
import org.junit.Test;
import java.nio.ByteBuffer;
-import java.util.Arrays;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;
+import static org.onlab.packet.IPv6.*;
/**
* Tests for class {@link IPv6}.
@@ -48,6 +48,21 @@
private static final byte[] MULTICAST_ADDRESS = {
(byte) 0x33, (byte) 0x33, (byte) 0xfe, (byte) 0x54, (byte) 0x37, (byte) 0xc8
};
+ private static final byte[] LINK_LOCAL_ADDRESS_1 = {
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x50, (byte) 0x74, (byte) 0xf2, (byte) 0xff, (byte) 0xfe, (byte) 0xb1, (byte) 0xa8, (byte) 0x7f
+ };
+ private static final byte[] MAC_ADDRESS_1 = {
+ (byte) 0x52, (byte) 0x74, (byte) 0xf2, (byte) 0xb1, (byte) 0xa8, (byte) 0x7f
+ };
+ private static final byte[] LINK_LOCAL_ADDRESS_2 = {
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x02, (byte) 0x0c, (byte) 0x29, (byte) 0xff, (byte) 0xfe, (byte) 0x8f, (byte) 0x99, (byte) 0xd2
+ };
+ private static final byte[] MAC_ADDRESS_2 = {
+ (byte) 0x00, (byte) 0x0c, (byte) 0x29, (byte) 0x8f, (byte) 0x99, (byte) 0xd2
+ };
+
private static Data data;
private static UDP udp;
private static byte[] bytePacket;
@@ -78,7 +93,7 @@
@Before
public void setUp() {
- deserializer = IPv6.deserializer();
+ deserializer = deserializer();
}
/**
@@ -91,7 +106,7 @@
ipv6.setVersion((byte) 6);
ipv6.setTrafficClass((byte) 0x93);
ipv6.setFlowLabel(0x13579);
- ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
+ ipv6.setNextHeader(PROTOCOL_UDP);
ipv6.setHopLimit((byte) 32);
ipv6.setSourceAddress(SOURCE_ADDRESS);
ipv6.setDestinationAddress(DESTINATION_ADDRESS);
@@ -107,7 +122,7 @@
@Test
public void testDeserializeTruncated() throws Exception {
// Run the truncation test only on the IPv6 header
- byte[] ipv6Header = new byte[IPv6.FIXED_HEADER_LENGTH];
+ byte[] ipv6Header = new byte[FIXED_HEADER_LENGTH];
ByteBuffer.wrap(bytePacket).get(ipv6Header);
PacketTestUtils.testDeserializeTruncated(deserializer, ipv6Header);
@@ -123,7 +138,7 @@
assertThat(ipv6.getVersion(), is((byte) 6));
assertThat(ipv6.getTrafficClass(), is((byte) 0x93));
assertThat(ipv6.getFlowLabel(), is(0x13579));
- assertThat(ipv6.getNextHeader(), is(IPv6.PROTOCOL_UDP));
+ assertThat(ipv6.getNextHeader(), is(PROTOCOL_UDP));
assertThat(ipv6.getHopLimit(), is((byte) 32));
assertArrayEquals(ipv6.getSourceAddress(), SOURCE_ADDRESS);
assertArrayEquals(ipv6.getDestinationAddress(), DESTINATION_ADDRESS);
@@ -139,7 +154,7 @@
packet1.setVersion((byte) 6);
packet1.setTrafficClass((byte) 0x93);
packet1.setFlowLabel(0x13579);
- packet1.setNextHeader(IPv6.PROTOCOL_UDP);
+ packet1.setNextHeader(PROTOCOL_UDP);
packet1.setHopLimit((byte) 32);
packet1.setSourceAddress(SOURCE_ADDRESS);
packet1.setDestinationAddress(DESTINATION_ADDRESS);
@@ -149,7 +164,7 @@
packet2.setVersion((byte) 6);
packet2.setTrafficClass((byte) 0x93);
packet2.setFlowLabel(0x13579);
- packet2.setNextHeader(IPv6.PROTOCOL_UDP);
+ packet2.setNextHeader(PROTOCOL_UDP);
packet2.setHopLimit((byte) 32);
packet2.setSourceAddress(DESTINATION_ADDRESS);
packet2.setDestinationAddress(SOURCE_ADDRESS);
@@ -169,7 +184,7 @@
assertTrue(StringUtils.contains(str, "version=" + (byte) 6));
assertTrue(StringUtils.contains(str, "trafficClass=" + (byte) 0x93));
assertTrue(StringUtils.contains(str, "flowLabel=" + 0x13579));
- assertTrue(StringUtils.contains(str, "nextHeader=" + IPv6.PROTOCOL_UDP));
+ assertTrue(StringUtils.contains(str, "nextHeader=" + PROTOCOL_UDP));
assertTrue(StringUtils.contains(str, "hopLimit=" + (byte) 32));
// TODO: test IPv6 source and destination address
}
@@ -179,7 +194,7 @@
*/
@Test
public void testSolicitationNodeAddress() {
- assertTrue(Arrays.equals(SOLICITATION_NODE_ADDRESS, IPv6.solicitationNodeAddress(DESTINATION_ADDRESS)));
+ assertArrayEquals(SOLICITATION_NODE_ADDRESS, getSolicitNodeAddress(DESTINATION_ADDRESS));
}
/**
@@ -187,6 +202,36 @@
*/
@Test
public void testMulticastAddress() {
- assertTrue(Arrays.equals(MULTICAST_ADDRESS, IPv6.multicastMacAddress(DESTINATION_ADDRESS)));
+ assertArrayEquals(MULTICAST_ADDRESS, getMCastMacAddress(DESTINATION_ADDRESS));
+ }
+
+ /**
+ * Tests the proper operation of the isLinkLocalAddress function.
+ */
+ @Test
+ public void testIsLinkLocalAddress() {
+ assertFalse(isLinkLocalAddress(SOURCE_ADDRESS));
+ assertFalse(isLinkLocalAddress(DESTINATION_ADDRESS));
+ assertFalse(isLinkLocalAddress(SOLICITATION_NODE_ADDRESS));
+ assertTrue(isLinkLocalAddress(LINK_LOCAL_ADDRESS_1));
+ assertTrue(isLinkLocalAddress(LINK_LOCAL_ADDRESS_2));
+ }
+
+ /**
+ * Tests the proper operation of the linkLocalAddress function.
+ */
+ @Test
+ public void testLinkLocalAddress() {
+ assertArrayEquals(getLinkLocalAddress(MAC_ADDRESS_1), LINK_LOCAL_ADDRESS_1);
+ assertArrayEquals(getLinkLocalAddress(MAC_ADDRESS_2), LINK_LOCAL_ADDRESS_2);
+ }
+
+ /**
+ * Tests the proper operation of the macAddress function.
+ */
+ @Test
+ public void testMacAddress() {
+ assertArrayEquals(getMacAddress(LINK_LOCAL_ADDRESS_1), MAC_ADDRESS_1);
+ assertArrayEquals(getMacAddress(LINK_LOCAL_ADDRESS_2), MAC_ADDRESS_2);
}
}