@Override public IPacket deserialize(byte[] data, int offset, int length) throws PacketParsingException { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); this.hardwareType = bb.getShort(); this.protocolType = bb.getShort(); this.hardwareAddressLength = bb.get(); this.protocolAddressLength = bb.get(); if (this.hardwareAddressLength != 6) { String msg = "Incorrect ARP hardware address length: " + hardwareAddressLength; throw new PacketParsingException(msg); } if (this.protocolAddressLength != 4) { String msg = "Incorrect ARP protocol address length: " + protocolAddressLength; throw new PacketParsingException(msg); } this.opCode = ArpOpcode.of(bb.getShort()); byte[] tmpMac = new byte[0xff & this.hardwareAddressLength]; byte[] tmpIp = new byte[0xff & this.protocolAddressLength]; bb.get(tmpMac, 0, this.hardwareAddressLength); this.senderHardwareAddress = MacAddress.of(tmpMac); bb.get(tmpIp, 0, this.protocolAddressLength); this.senderProtocolAddress = IPv4Address.of(tmpIp); bb.get(tmpMac, 0, this.hardwareAddressLength); this.targetHardwareAddress = MacAddress.of(tmpMac); bb.get(tmpIp, 0, this.protocolAddressLength); this.targetProtocolAddress = IPv4Address.of(tmpIp); return this; }
private OFAction buildL2Modification(Instruction i) { L2ModificationInstruction l2m = (L2ModificationInstruction) i; ModEtherInstruction eth; OFOxm<?> oxm = null; switch (l2m.subtype()) { case ETH_DST: eth = (ModEtherInstruction) l2m; oxm = factory().oxms().ethDst(MacAddress.of(eth.mac().toLong())); break; case ETH_SRC: eth = (ModEtherInstruction) l2m; oxm = factory().oxms().ethSrc(MacAddress.of(eth.mac().toLong())); break; case VLAN_ID: ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m; oxm = factory().oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort())); break; case VLAN_PCP: ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m; oxm = factory().oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp())); break; case MPLS_PUSH: PushHeaderInstructions pushHeaderInstructions = (PushHeaderInstructions) l2m; return factory() .actions() .pushMpls(EthType.of(pushHeaderInstructions.ethernetType().toShort())); case MPLS_POP: PushHeaderInstructions popHeaderInstructions = (PushHeaderInstructions) l2m; return factory() .actions() .popMpls(EthType.of(popHeaderInstructions.ethernetType().toShort())); case MPLS_LABEL: ModMplsLabelInstruction mplsLabel = (ModMplsLabelInstruction) l2m; oxm = factory().oxms().mplsLabel(U32.of(mplsLabel.label().longValue())); break; case DEC_MPLS_TTL: return factory().actions().decMplsTtl(); case VLAN_POP: return factory().actions().popVlan(); case VLAN_PUSH: PushHeaderInstructions pushVlanInstruction = (PushHeaderInstructions) l2m; return factory() .actions() .pushVlan(EthType.of(pushVlanInstruction.ethernetType().toShort())); default: log.warn("Unimplemented action type {}.", l2m.subtype()); break; } if (oxm != null) { return factory().actions().buildSetField().setField(oxm).build(); } return null; }
@Test public void emit() { MacAddress mac1 = MacAddress.of("00:00:00:11:00:01"); MacAddress mac2 = MacAddress.of("00:00:00:22:00:02"); ARP arp = new ARP(); arp.setSenderProtocolAddress(ANY) .setSenderHardwareAddress(mac1.getBytes()) .setTargetHardwareAddress(mac2.getBytes()) .setTargetProtocolAddress(ANY) .setHardwareType((short) 0) .setProtocolType((short) 0) .setHardwareAddressLength((byte) 6) .setProtocolAddressLength((byte) 4) .setOpCode((byte) 0); Ethernet eth = new Ethernet(); eth.setVlanID(VLANID) .setEtherType(Ethernet.TYPE_ARP) .setSourceMACAddress("00:00:00:11:00:01") .setDestinationMACAddress("00:00:00:22:00:02") .setPayload(arp); // the should-be working setup. OutboundPacket passPkt = outPacket(DID, TR, eth); sw.setRole(RoleState.MASTER); provider.emit(passPkt); assertEquals("invalid switch", sw, controller.current); assertEquals("message not sent", PLIST.size(), sw.sent.size()); sw.sent.clear(); // wrong Role // sw.setRole(RoleState.SLAVE); // provider.emit(passPkt); // assertEquals("invalid switch", sw, controller.current); // assertEquals("message sent incorrectly", 0, sw.sent.size()); // sw.setRole(RoleState.MASTER); // missing switch OutboundPacket swFailPkt = outPacket(DID_MISSING, TR, eth); provider.emit(swFailPkt); assertNull("invalid switch", controller.current); assertEquals("message sent incorrectly", 0, sw.sent.size()); // to missing port // OutboundPacket portFailPkt = outPacket(DID, TR_MISSING, eth); // provider.emit(portFailPkt); // assertEquals("extra message sent", 1, sw.sent.size()); }
/** * Parse a mac adress from the canonical string representation as 6 hex bytes separated by colons * (01:02:03:04:05:06). * * @param macString - a mac address in canonical string representation * @return the parsed MacAddress * @throws IllegalArgumentException if macString is not a valid mac adddress */ @Nonnull public static MacAddress of(@Nonnull final String macString) throws IllegalArgumentException { if (macString == null) { throw new NullPointerException("macString must not be null"); } int index = 0; int shift = 40; long raw = 0; if (macString.length() != MAC_STRING_LENGTH) { throw new IllegalArgumentException(FORMAT_ERROR + macString); } while (shift >= 0) { int digit1 = Character.digit(macString.charAt(index++), 16); int digit2 = Character.digit(macString.charAt(index++), 16); if ((digit1 < 0) || (digit2 < 0)) throw new IllegalArgumentException(FORMAT_ERROR + macString); raw |= ((long) (digit1 << 4 | digit2)) << shift; if (shift == 0) break; if (macString.charAt(index++) != ':') throw new IllegalArgumentException(FORMAT_ERROR + macString); shift -= 8; } return MacAddress.of(raw); }
public static MacAddress of(final byte[] address) { if (address.length != MacAddrLen) throw new IllegalArgumentException( "Mac address byte array must be exactly 6 bytes long; length = " + address.length); long raw = (address[0] & 0xFFL) << 40 | (address[1] & 0xFFL) << 32 | (address[2] & 0xFFL) << 24 | (address[3] & 0xFFL) << 16 | (address[4] & 0xFFL) << 8 | (address[5] & 0xFFL); return MacAddress.of(raw); }
/* * Parse an IPv4 Multicast address and return the macAddress * corresponding to the multicast IPv4 address. * * For multicast forwarding, the mac addresses in the range * 01-00-5E-00-00-00 to 01-00-5E-7F-FF-FF have been reserved. * The most significant 25 bits of the above 48-bit mac address * are fixed while the lower 23 bits are variable. * These lower 23 bits are derived from the lower 23 bits * of the multicast IP address. * * AND ipv4 address with 0x07FFFFF to extract the last 23 bits * OR with 01:00:5E:00:00:00 MAC (first 25 bits) * * @param ipv4 - ipv4 multicast address * @return the MacAddress corresponding to the multicast address * @throws IllegalArgumentException if ipv4 is not a valid multicast address */ @Nonnull public static MacAddress forIPv4MulticastAddress(IPv4Address ipv4) throws IllegalArgumentException { if (!ipv4.isMulticast()) throw new IllegalArgumentException("Not a Multicast IPAddress\"" + ipv4 + "\""); long ipLong = ipv4.getInt(); int ipMask = 0x007FFFFF; ipLong = ipLong & ipMask; long macLong = MULTICAST_BASE_ADDRESS.getLong(); // 01:00:5E:00:00:00 macLong = macLong | ipLong; MacAddress returnMac = MacAddress.of(macLong); return returnMac; }
@Test public void testWrite() { OFBsnGentableEntryDelete.Builder builder = factory.buildBsnGentableEntryDelete(); builder .setXid(0x12345678) .setTableId(GenTableId.of(20)) .setKey( ImmutableList.<OFBsnTlv>of( factory.bsnTlvs().port(OFPort.of(5)), factory.bsnTlvs().mac(MacAddress.of("01:23:45:67:89:ab")))); OFBsnGentableEntryDelete bsnGentableEntryDelete = builder.build(); ByteBuf bb = Unpooled.buffer(); bsnGentableEntryDelete.writeTo(bb); byte[] written = new byte[bb.readableBytes()]; bb.readBytes(written); assertThat(written, CoreMatchers.equalTo(BSN_GENTABLE_ENTRY_DELETE_SERIALIZED)); }
@Test public void testRead() throws Exception { OFBsnGentableEntryDelete.Builder builder = factory.buildBsnGentableEntryDelete(); builder .setXid(0x12345678) .setTableId(GenTableId.of(20)) .setKey( ImmutableList.<OFBsnTlv>of( factory.bsnTlvs().port(OFPort.of(5)), factory.bsnTlvs().mac(MacAddress.of("01:23:45:67:89:ab")))); OFBsnGentableEntryDelete bsnGentableEntryDeleteBuilt = builder.build(); ByteBuf input = Unpooled.copiedBuffer(BSN_GENTABLE_ENTRY_DELETE_SERIALIZED); // FIXME should invoke the overall reader once implemented OFBsnGentableEntryDelete bsnGentableEntryDeleteRead = OFBsnGentableEntryDeleteVer13.READER.readFrom(input); assertEquals(BSN_GENTABLE_ENTRY_DELETE_SERIALIZED.length, input.readerIndex()); assertEquals(bsnGentableEntryDeleteBuilt, bsnGentableEntryDeleteRead); }
@Override public MacAddress applyMask(MacAddress mask) { return MacAddress.of(this.rawValue & mask.rawValue); }
public static MacAddress read6Bytes(ChannelBuffer c) throws OFParseError { long raw = c.readUnsignedInt() << 16 | c.readUnsignedShort(); return MacAddress.of(raw); }
/** * Wrapper around a 6 byte mac address. * * @author Andreas Wundsam {@literal <}[email protected]{@literal >} */ public class MacAddress implements OFValueType<MacAddress> { static final int MacAddrLen = 6; private final long rawValue; private static final long NONE_VAL = 0x0L; public static final MacAddress NONE = new MacAddress(NONE_VAL); private static final long BROADCAST_VAL = 0x0000FFFFFFFFFFFFL; public static final MacAddress BROADCAST = new MacAddress(BROADCAST_VAL); public static final MacAddress NO_MASK = MacAddress.of(0xFFFFFFFFFFFFFFFFl); public static final MacAddress FULL_MASK = MacAddress.of(0x0); private static final long LLDP_MAC_ADDRESS_MASK = 0xfffffffffff0L; private static final long LLDP_MAC_ADDRESS_VALUE = 0x0180c2000000L; private static final MacAddress MULTICAST_BASE_ADDRESS = MacAddress.of("01:00:5E:00:00:00"); private static final String FORMAT_ERROR = "Mac address is not well-formed. " + "It must consist of 6 hex digit pairs separated by colons: "; private static final int MAC_STRING_LENGTH = 6 * 2 + 5; private MacAddress(final long rawValue) { this.rawValue = rawValue; } public static MacAddress of(final byte[] address) { if (address.length != MacAddrLen) throw new IllegalArgumentException( "Mac address byte array must be exactly 6 bytes long; length = " + address.length); long raw = (address[0] & 0xFFL) << 40 | (address[1] & 0xFFL) << 32 | (address[2] & 0xFFL) << 24 | (address[3] & 0xFFL) << 16 | (address[4] & 0xFFL) << 8 | (address[5] & 0xFFL); return MacAddress.of(raw); } public static MacAddress of(long raw) { raw &= BROADCAST_VAL; if (raw == NONE_VAL) return NONE; if (raw == BROADCAST_VAL) return BROADCAST; return new MacAddress(raw); } /** * Parse a mac adress from the canonical string representation as 6 hex bytes separated by colons * (01:02:03:04:05:06). * * @param macString - a mac address in canonical string representation * @return the parsed MacAddress * @throws IllegalArgumentException if macString is not a valid mac adddress */ @Nonnull public static MacAddress of(@Nonnull final String macString) throws IllegalArgumentException { if (macString == null) { throw new NullPointerException("macString must not be null"); } int index = 0; int shift = 40; long raw = 0; if (macString.length() != MAC_STRING_LENGTH) { throw new IllegalArgumentException(FORMAT_ERROR + macString); } while (shift >= 0) { int digit1 = Character.digit(macString.charAt(index++), 16); int digit2 = Character.digit(macString.charAt(index++), 16); if ((digit1 < 0) || (digit2 < 0)) throw new IllegalArgumentException(FORMAT_ERROR + macString); raw |= ((long) (digit1 << 4 | digit2)) << shift; if (shift == 0) break; if (macString.charAt(index++) != ':') throw new IllegalArgumentException(FORMAT_ERROR + macString); shift -= 8; } return MacAddress.of(raw); } /** * Creates a {@link MacAddress} from a {@link DatapathId}. This factory method assumes that the * first two bytes of the {@link DatapathId} are 0 bytes. * * @param dpid the {@link DatapathId} to create the {@link MacAddress} from * @return a {@link MacAddress} derived from the supplied {@link DatapathId} */ public static MacAddress of(@Nonnull DatapathId dpid) { Preconditions.checkNotNull(dpid, "dpid must not be null"); long raw = dpid.getLong(); // Mask out valid bytes if ((raw & ~BROADCAST_VAL) != 0L) { throw new IllegalArgumentException("First two bytes of supplied " + "Datapathid must be 0"); } return of(raw); } private volatile byte[] bytesCache = null; public byte[] getBytes() { if (bytesCache == null) { synchronized (this) { if (bytesCache == null) { bytesCache = new byte[] { (byte) ((rawValue >> 40) & 0xFF), (byte) ((rawValue >> 32) & 0xFF), (byte) ((rawValue >> 24) & 0xFF), (byte) ((rawValue >> 16) & 0xFF), (byte) ((rawValue >> 8) & 0xFF), (byte) ((rawValue >> 0) & 0xFF) }; } } } return Arrays.copyOf(bytesCache, bytesCache.length); } /** * 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() { return this == BROADCAST; } /** * Returns {@code true} if the MAC address is a multicast address. * * @return {@code true} if the MAC address is a multicast address. */ public boolean isMulticast() { if (isBroadcast()) { return false; } return (rawValue & (0x01L << 40)) != 0; } /** * Returns {@code true} if the MAC address is an LLDP mac address. * * @return {@code true} if the MAC address is an LLDP mac address. */ public boolean isLLDPAddress() { return (rawValue & LLDP_MAC_ADDRESS_MASK) == LLDP_MAC_ADDRESS_VALUE; } @Override public int getLength() { return MacAddrLen; } @Override public String toString() { return HexString.toHexString(rawValue, 6); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (int) (rawValue ^ (rawValue >>> 32)); return result; } @Override public boolean equals(final Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; MacAddress other = (MacAddress) obj; if (rawValue != other.rawValue) return false; return true; } public long getLong() { return rawValue; } public void write6Bytes(ChannelBuffer c) { c.writeInt((int) (this.rawValue >> 16)); c.writeShort((int) this.rawValue & 0xFFFF); } public static MacAddress read6Bytes(ChannelBuffer c) throws OFParseError { long raw = c.readUnsignedInt() << 16 | c.readUnsignedShort(); return MacAddress.of(raw); } @Override public MacAddress applyMask(MacAddress mask) { return MacAddress.of(this.rawValue & mask.rawValue); } @Override public int compareTo(MacAddress o) { return Longs.compare(rawValue, o.rawValue); } @Override public void putTo(PrimitiveSink sink) { sink.putInt((int) (this.rawValue >> 16)); sink.putShort((short) (this.rawValue & 0xFFFF)); } /* * Parse an IPv4 Multicast address and return the macAddress * corresponding to the multicast IPv4 address. * * For multicast forwarding, the mac addresses in the range * 01-00-5E-00-00-00 to 01-00-5E-7F-FF-FF have been reserved. * The most significant 25 bits of the above 48-bit mac address * are fixed while the lower 23 bits are variable. * These lower 23 bits are derived from the lower 23 bits * of the multicast IP address. * * AND ipv4 address with 0x07FFFFF to extract the last 23 bits * OR with 01:00:5E:00:00:00 MAC (first 25 bits) * * @param ipv4 - ipv4 multicast address * @return the MacAddress corresponding to the multicast address * @throws IllegalArgumentException if ipv4 is not a valid multicast address */ @Nonnull public static MacAddress forIPv4MulticastAddress(IPv4Address ipv4) throws IllegalArgumentException { if (!ipv4.isMulticast()) throw new IllegalArgumentException("Not a Multicast IPAddress\"" + ipv4 + "\""); long ipLong = ipv4.getInt(); int ipMask = 0x007FFFFF; ipLong = ipLong & ipMask; long macLong = MULTICAST_BASE_ADDRESS.getLong(); // 01:00:5E:00:00:00 macLong = macLong | ipLong; MacAddress returnMac = MacAddress.of(macLong); return returnMac; } }