Skip to content
Snippets Groups Projects
Commit 51aa40f9 authored by Alex Reimers's avatar Alex Reimers
Browse files

Merge into master from pull request #5:

Adding a class representing MAC address (https://github.com/floodlight/floodlight/pull/5)
parents 2935cc6e ee798330
No related branches found
No related tags found
No related merge requests found
......@@ -22,6 +22,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import net.floodlightcontroller.util.MACAddress;
import org.openflow.util.HexString;
/**
......@@ -29,7 +30,6 @@ import org.openflow.util.HexString;
* @author David Erickson (daviderickson@cs.stanford.edu)
*/
public class Ethernet extends BasePacket {
private static String HEXES = "0123456789ABCDEF";
public static final short TYPE_ARP = 0x0806;
public static final short TYPE_IPv4 = 0x0800;
public static final short TYPE_LLDP = (short) 0x88cc;
......@@ -43,8 +43,8 @@ public class Ethernet extends BasePacket {
etherTypeClassMap.put(TYPE_LLDP, LLDP.class);
}
protected byte[] destinationMACAddress;
protected byte[] sourceMACAddress;
protected MACAddress destinationMACAddress;
protected MACAddress sourceMACAddress;
protected byte priorityCode;
protected short vlanID;
protected short etherType;
......@@ -62,14 +62,14 @@ public class Ethernet extends BasePacket {
* @return the destinationMACAddress
*/
public byte[] getDestinationMACAddress() {
return destinationMACAddress;
return destinationMACAddress.toBytes();
}
/**
* @param destinationMACAddress the destinationMACAddress to set
*/
public Ethernet setDestinationMACAddress(byte[] destinationMACAddress) {
this.destinationMACAddress = destinationMACAddress;
this.destinationMACAddress = MACAddress.valueOf(destinationMACAddress);
return this;
}
......@@ -77,8 +77,7 @@ public class Ethernet extends BasePacket {
* @param destinationMACAddress the destinationMACAddress to set
*/
public Ethernet setDestinationMACAddress(String destinationMACAddress) {
this.destinationMACAddress = Ethernet
.toMACAddress(destinationMACAddress);
this.destinationMACAddress = MACAddress.valueOf(destinationMACAddress);
return this;
}
......@@ -86,14 +85,14 @@ public class Ethernet extends BasePacket {
* @return the sourceMACAddress
*/
public byte[] getSourceMACAddress() {
return sourceMACAddress;
return sourceMACAddress.toBytes();
}
/**
* @param sourceMACAddress the sourceMACAddress to set
*/
public Ethernet setSourceMACAddress(byte[] sourceMACAddress) {
this.sourceMACAddress = sourceMACAddress;
this.sourceMACAddress = MACAddress.valueOf(sourceMACAddress);
return this;
}
......@@ -101,7 +100,7 @@ public class Ethernet extends BasePacket {
* @param sourceMACAddress the sourceMACAddress to set
*/
public Ethernet setSourceMACAddress(String sourceMACAddress) {
this.sourceMACAddress = Ethernet.toMACAddress(sourceMACAddress);
this.sourceMACAddress = MACAddress.valueOf(sourceMACAddress);
return this;
}
......@@ -154,22 +153,15 @@ public class Ethernet extends BasePacket {
* @return True if the Ethernet frame is broadcast, false otherwise
*/
public boolean isBroadcast() {
assert(destinationMACAddress.length == 6);
for (byte b : destinationMACAddress) {
if (b != -1) // checks if equal to 0xff
return false;
}
return true;
assert(destinationMACAddress.length() == 6);
return destinationMACAddress.isBroadcast();
}
/**
* @return True is the Ethernet frame is multicast, False otherwise
*/
public boolean isMulticast() {
if (this.isBroadcast()) {
return false;
}
return (destinationMACAddress[0] & 0x01) != 0;
return destinationMACAddress.isMulticast();
}
/**
* Pad this packet to 60 bytes minimum, filling with zeros?
......@@ -201,8 +193,8 @@ public class Ethernet extends BasePacket {
}
byte[] data = new byte[length];
ByteBuffer bb = ByteBuffer.wrap(data);
bb.put(destinationMACAddress);
bb.put(sourceMACAddress);
bb.put(destinationMACAddress.toBytes());
bb.put(sourceMACAddress.toBytes());
if (vlanID != VLAN_UNTAGGED) {
bb.putShort((short) 0x8100);
bb.putShort((short) ((priorityCode << 13) | (vlanID & 0x0fff)));
......@@ -220,12 +212,16 @@ public class Ethernet extends BasePacket {
public IPacket deserialize(byte[] data, int offset, int length) {
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
if (this.destinationMACAddress == null)
this.destinationMACAddress = new byte[6];
bb.get(this.destinationMACAddress);
this.destinationMACAddress = MACAddress.valueOf(new byte[6]);
byte[] dstAddr = new byte[MACAddress.MAC_ADDRESS_LENGTH];
bb.get(dstAddr);
this.destinationMACAddress = MACAddress.valueOf(dstAddr);
if (this.sourceMACAddress == null)
this.sourceMACAddress = new byte[6];
bb.get(this.sourceMACAddress);
this.sourceMACAddress = MACAddress.valueOf(new byte[6]);
byte[] srcAddr = new byte[MACAddress.MAC_ADDRESS_LENGTH];
bb.get(srcAddr);
this.sourceMACAddress = MACAddress.valueOf(srcAddr);
short etherType = bb.getShort();
if (etherType == (short) 0x8100) {
......@@ -254,20 +250,6 @@ public class Ethernet extends BasePacket {
return this;
}
public static boolean isMACAddress(String macAddress) {
String[] macBytes = macAddress.split(":");
if (macBytes.length != 6)
return false;
for (int i = 0; i < 6; ++i) {
if (HEXES.indexOf(macBytes[i].toUpperCase().charAt(0)) == -1 ||
HEXES.indexOf(macBytes[i].toUpperCase().charAt(1)) == -1) {
return false;
}
}
return true;
}
/**
* Accepts a MAC address of the form 00:aa:11:bb:22:cc, case does not
* matter, and returns a corresponding byte[].
......@@ -275,24 +257,10 @@ public class Ethernet extends BasePacket {
* @return
*/
public static byte[] toMACAddress(String macAddress) {
byte[] address = new byte[6];
if (!Ethernet.isMACAddress(macAddress)) {
throw new IllegalArgumentException(
"Specified MAC Address must contain 12 hex digits" +
" separated pairwise by :'s.");
}
String[] macBytes = macAddress.split(":");
for (int i = 0; i < 6; ++i) {
address[i] = (byte) ((HEXES.indexOf(macBytes[i].toUpperCase()
.charAt(0)) << 4) | HEXES.indexOf(macBytes[i].toUpperCase()
.charAt(1)));
}
return address;
return MACAddress.valueOf(macAddress).toBytes();
}
/**
* Accepts a MAC address and returns the corresponding long, where the
* MAC bytes are set on the lower order bytes of the long.
......@@ -300,28 +268,16 @@ public class Ethernet extends BasePacket {
* @return a long containing the mac address bytes
*/
public static long toLong(byte[] macAddress) {
long mac = 0;
for (int i = 0; i < 6; i++) {
long t = (macAddress[i] & 0xffL) << ((5-i)*8);
mac |= t;
}
return mac;
return MACAddress.valueOf(macAddress).toLong();
}
/**
* Convert a long MAC address to a byte array
* @param macAddress
* @return the bytes of the mac address
*/
public static byte[] toByteArray(long macAddress) {
return new byte[] {
(byte)((macAddress >> 40) & 0xff),
(byte)((macAddress >> 32) & 0xff),
(byte)((macAddress >> 24) & 0xff),
(byte)((macAddress >> 16) & 0xff),
(byte)((macAddress >> 8 ) & 0xff),
(byte)((macAddress >> 0) & 0xff)
};
return MACAddress.valueOf(macAddress).toBytes();
}
/* (non-Javadoc)
......@@ -331,10 +287,10 @@ public class Ethernet extends BasePacket {
public int hashCode() {
final int prime = 7867;
int result = super.hashCode();
result = prime * result + Arrays.hashCode(destinationMACAddress);
result = prime * result + destinationMACAddress.hashCode();
result = prime * result + etherType;
result = prime * result + (pad ? 1231 : 1237);
result = prime * result + Arrays.hashCode(sourceMACAddress);
result = prime * result + sourceMACAddress.hashCode();
return result;
}
......@@ -350,7 +306,7 @@ public class Ethernet extends BasePacket {
if (!(obj instanceof Ethernet))
return false;
Ethernet other = (Ethernet) obj;
if (!Arrays.equals(destinationMACAddress, other.destinationMACAddress))
if (!destinationMACAddress.equals(other.destinationMACAddress))
return false;
if (priorityCode != other.priorityCode)
return false;
......@@ -360,7 +316,7 @@ public class Ethernet extends BasePacket {
return false;
if (pad != other.pad)
return false;
if (!Arrays.equals(sourceMACAddress, other.sourceMACAddress))
if (!sourceMACAddress.equals(other.sourceMACAddress))
return false;
return true;
}
......
package net.floodlightcontroller.util;
import java.util.Arrays;
/**
* The class representing MAC address.
*
* @author Sho Shimizu (sho.shimizu@gmail.com)
*/
public class MACAddress {
public static final int MAC_ADDRESS_LENGTH = 6;
private byte[] address = new byte[MAC_ADDRESS_LENGTH];
private MACAddress(byte[] address) {
this.address = Arrays.copyOf(address, MAC_ADDRESS_LENGTH);
}
/**
* Returns a MAC address instance representing the value of the specified {@code String}.
* @param address the String representation of the MAC Address to be parsed.
* @return a MAC Address instance representing the value of the specified {@code String}.
* @throws IllegalArgumentException if the string cannot be parsed as a MAC address.
*/
public static MACAddress valueOf(String address) {
String[] elements = address.split(":");
if (elements.length != MAC_ADDRESS_LENGTH) {
throw new IllegalArgumentException(
"Specified MAC Address must contain 12 hex digits" +
" separated pairwise by :'s.");
}
byte[] addressInBytes = new byte[MAC_ADDRESS_LENGTH];
for (int i = 0; i < MAC_ADDRESS_LENGTH; i++) {
String element = elements[i];
addressInBytes[i] = (byte)Integer.parseInt(element, 16);
}
return new MACAddress(addressInBytes);
}
/**
* Returns a MAC address instance representing the specified {@code byte} array.
* @param address the byte array to be parsed.
* @return a MAC address instance representing the specified {@code byte} array.
* @throws IllegalArgumentException if the byte array cannot be parsed as a MAC address.
*/
public static MACAddress valueOf(byte[] address) {
if (address.length != MAC_ADDRESS_LENGTH) {
throw new IllegalArgumentException("the length is not " + MAC_ADDRESS_LENGTH);
}
return new MACAddress(address);
}
/**
* Returns a MAC address instance representing the specified {@code long} value.
* The lower 48 bits of the long value are used to parse as a MAC address.
* @param address the long value to be parsed. The lower 48 bits are used for a MAC address.
* @return a MAC address instance representing the specified {@code long} value.
* @throws IllegalArgumentException if the long value cannot be parsed as a MAC address.
*/
public static MACAddress valueOf(long address) {
byte[] addressInBytes = new byte[] {
(byte)((address >> 40) & 0xff),
(byte)((address >> 32) & 0xff),
(byte)((address >> 24) & 0xff),
(byte)((address >> 16) & 0xff),
(byte)((address >> 8 ) & 0xff),
(byte)((address >> 0) & 0xff)
};
return new MACAddress(addressInBytes);
}
/**
* Returns the length of the {@code MACAddress}.
* @return the length of the {@code MACAddress}.
*/
public int length() {
return address.length;
}
/**
* Returns the value of the {@code MACAddress} as a {@code byte} array.
* @return the numeric value represented by this object after conversion to type {@code byte} array.
*/
public byte[] toBytes() {
return Arrays.copyOf(address, address.length);
}
/**
* Returns the value of the {@code MACAddress} as a {@code long}.
* @return the numeric value represented by this object after conversion to type {@code long}.
*/
public long toLong() {
long mac = 0;
for (int i = 0; i < 6; i++) {
long t = (address[i] & 0xffL) << ((5 - i) * 8);
mac |= t;
}
return mac;
}
/**
* Returns {@code true} if the MAC address is the broadcast address.
* @return {@code true} if the MAC address is the broadcast address.
*/
public boolean isBroadcast() {
for (byte b : address) {
if (b != -1) // checks if equal to 0xff
return false;
}
return true;
}
/**
* Returns {@code true} if the MAC address is the multicast address.
* @return {@code true} if the MAC address is the multicast address.
*/
public boolean isMulticast() {
if (isBroadcast()) {
return false;
}
return (address[0] & 0x01) != 0;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof MACAddress)) {
return false;
}
MACAddress other = (MACAddress)o;
return Arrays.equals(this.address, other.address);
}
@Override
public int hashCode() {
return Arrays.hashCode(this.address);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (byte b: address) {
if (builder.length() > 0) {
builder.append(":");
}
builder.append(String.format("%02X", b & 0xFF));
}
return builder.toString();
}
}
package net.floodlightcontroller.util;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author Sho Shimizu (sho.shimizu@gmail.com)
*/
public class MACAddressTest {
@Test
public void testValueOf() {
MACAddress address = MACAddress.valueOf("00:01:02:03:04:05");
assertEquals(address,
MACAddress.valueOf(new byte[]{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}));
assertEquals("00:01:02:03:04:05", address.toString());
address = MACAddress.valueOf("FF:FE:FD:10:20:30");
assertEquals(address,
MACAddress.valueOf(new byte[]{(byte) 0xFF, (byte) 0xFE, (byte) 0xFD, 0x10, 0x20, 0x30}));
assertEquals("FF:FE:FD:10:20:30", address.toString());
address = MACAddress.valueOf("00:11:22:aa:bb:cc");
assertEquals(address,
MACAddress.valueOf(new byte[]{0x00, 0x11, 0x22, (byte)0xaa, (byte)0xbb, (byte)0xcc}));
}
@Test(expected=NumberFormatException.class)
public void testIllegalFormat() {
MACAddress address = MACAddress.valueOf("0T:00:01:02:03:04");
}
@Test(expected=IllegalArgumentException.class)
public void testLongStringFields() {
MACAddress address = MACAddress.valueOf("00:01:02:03:04:05:06");
}
@Test(expected=IllegalArgumentException.class)
public void testShortStringFields() {
MACAddress address = MACAddress.valueOf("00:01:02:03:04");
}
@Test(expected=IllegalArgumentException.class)
public void testLongByteFields() {
MACAddress address = MACAddress.valueOf(new byte[]{0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06});
}
@Test(expected=IllegalArgumentException.class)
public void testShortByteField() {
MACAddress address = MACAddress.valueOf(new byte[]{0x01, 0x01, 0x02, 0x03, 0x04});
}
// Test data is imported from net.floodlightcontroller.packet.EthernetTest
@Test
public void testToLong() {
assertEquals(
281474976710655L,
MACAddress.valueOf(new byte[]{(byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}).toLong());
assertEquals(
1103823438081L,
MACAddress.valueOf(new byte[] { (byte) 0x01, (byte) 0x01,
(byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01 }).toLong());
assertEquals(
141289400074368L,
MACAddress.valueOf(new byte[] { (byte) 0x80, (byte) 0x80,
(byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80 }).toLong());
}
@Test
public void testIsBroadcast() {
assertTrue(MACAddress.valueOf("FF:FF:FF:FF:FF:FF").isBroadcast());
assertFalse(MACAddress.valueOf("11:22:33:44:55:66").isBroadcast());
}
@Test
public void testIsMulticast() {
assertTrue(MACAddress.valueOf("01:80:C2:00:00:00").isMulticast());
assertFalse(MACAddress.valueOf("FF:FF:FF:FF:FF:FF").isMulticast());
assertFalse(MACAddress.valueOf("11:22:33:44:55:66").isBroadcast());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment