@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; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; ARP other = (ARP) obj; if (hardwareAddressLength != other.hardwareAddressLength) return false; if (hardwareType != other.hardwareType) return false; if (opCode == null) { if (other.opCode != null) return false; } else if (!opCode.equals(other.opCode)) return false; if (protocolAddressLength != other.protocolAddressLength) return false; if (protocolType != other.protocolType) return false; if (senderHardwareAddress == null) { if (other.senderHardwareAddress != null) return false; } else if (!senderHardwareAddress.equals(other.senderHardwareAddress)) return false; if (senderProtocolAddress == null) { if (other.senderProtocolAddress != null) return false; } else if (!senderProtocolAddress.equals(other.senderProtocolAddress)) return false; if (targetHardwareAddress == null) { if (other.targetHardwareAddress != null) return false; } else if (!targetHardwareAddress.equals(other.targetHardwareAddress)) return false; if (targetProtocolAddress == null) { if (other.targetProtocolAddress != null) return false; } else if (!targetProtocolAddress.equals(other.targetProtocolAddress)) return false; return true; }
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; }
/** * 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); }
@Override public OFPortDesc readFrom(ByteBuf bb) throws OFParseError { OFPort portNo = OFPort.read4Bytes(bb); // pad: 4 bytes bb.skipBytes(4); MacAddress hwAddr = MacAddress.read6Bytes(bb); // pad: 2 bytes bb.skipBytes(2); String name = ChannelUtils.readFixedLengthString(bb, 16); Set<OFPortConfig> config = OFPortConfigSerializerVer12.readFrom(bb); Set<OFPortState> state = OFPortStateSerializerVer12.readFrom(bb); Set<OFPortFeatures> curr = OFPortFeaturesSerializerVer12.readFrom(bb); Set<OFPortFeatures> advertised = OFPortFeaturesSerializerVer12.readFrom(bb); Set<OFPortFeatures> supported = OFPortFeaturesSerializerVer12.readFrom(bb); Set<OFPortFeatures> peer = OFPortFeaturesSerializerVer12.readFrom(bb); long currSpeed = U32.f(bb.readInt()); long maxSpeed = U32.f(bb.readInt()); OFPortDescVer12 portDescVer12 = new OFPortDescVer12( portNo, hwAddr, name, config, state, curr, advertised, supported, peer, currSpeed, maxSpeed); if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", portDescVer12); return portDescVer12; }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((value == null) ? 0 : value.hashCode()); return result; }
/* * 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; }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((dlAddr == null) ? 0 : dlAddr.hashCode()); return result; }
@Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + hardwareAddressLength; result = prime * result + hardwareType; result = prime * result + ((opCode == null) ? 0 : opCode.hashCode()); result = prime * result + protocolAddressLength; result = prime * result + protocolType; result = prime * result + ((senderHardwareAddress == null) ? 0 : senderHardwareAddress.hashCode()); result = prime * result + ((senderProtocolAddress == null) ? 0 : senderProtocolAddress.hashCode()); result = prime * result + ((targetHardwareAddress == null) ? 0 : targetHardwareAddress.hashCode()); result = prime * result + ((targetProtocolAddress == null) ? 0 : targetProtocolAddress.hashCode()); return result; }
@Override public OFOxmArpTha readFrom(ChannelBuffer bb) throws OFParseError { // fixed value property typeLen == 0x80003206L int typeLen = bb.readInt(); if (typeLen != (int) 0x80003206) throw new OFParseError("Wrong typeLen: Expected=0x80003206L(0x80003206L), got=" + typeLen); MacAddress value = MacAddress.read6Bytes(bb); OFOxmArpThaVer13 oxmArpThaVer13 = new OFOxmArpThaVer13(value); if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", oxmArpThaVer13); return oxmArpThaVer13; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; OFActionSetDlSrcVer10 other = (OFActionSetDlSrcVer10) obj; if (dlAddr == null) { if (other.dlAddr != null) return false; } else if (!dlAddr.equals(other.dlAddr)) return false; return true; }
@Override public OFOxmEthSrc readFrom(ByteBuf bb) throws OFParseError { // fixed value property typeLen == 0x80000806L int typeLen = bb.readInt(); if (typeLen != (int) 0x80000806) throw new OFParseError("Wrong typeLen: Expected=0x80000806L(0x80000806L), got=" + typeLen); MacAddress value = MacAddress.read6Bytes(bb); OFOxmEthSrcVer12 oxmEthSrcVer12 = new OFOxmEthSrcVer12(value); if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", oxmEthSrcVer12); return oxmEthSrcVer12; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; OFOxmBsnInnerEthDstVer14 other = (OFOxmBsnInnerEthDstVer14) obj; if (value == null) { if (other.value != null) return false; } else if (!value.equals(other.value)) return false; return true; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; OFBsnTlvActorSystemMacVer14 other = (OFBsnTlvActorSystemMacVer14) obj; if (value == null) { if (other.value != null) return false; } else if (!value.equals(other.value)) return false; return true; }
@Override public OFOxmBsnInnerEthDst readFrom(ByteBuf bb) throws OFParseError { // fixed value property typeLen == 0x32c06L int typeLen = bb.readInt(); if (typeLen != 0x32c06) throw new OFParseError("Wrong typeLen: Expected=0x32c06L(0x32c06L), got=" + typeLen); MacAddress value = MacAddress.read6Bytes(bb); OFOxmBsnInnerEthDstVer14 oxmBsnInnerEthDstVer14 = new OFOxmBsnInnerEthDstVer14(value); if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", oxmBsnInnerEthDstVer14); return oxmBsnInnerEthDstVer14; }
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); }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((portNo == null) ? 0 : portNo.hashCode()); result = prime * result + ((hwAddr == null) ? 0 : hwAddr.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((config == null) ? 0 : config.hashCode()); result = prime * result + ((state == null) ? 0 : state.hashCode()); result = prime * result + ((curr == null) ? 0 : curr.hashCode()); result = prime * result + ((advertised == null) ? 0 : advertised.hashCode()); result = prime * result + ((supported == null) ? 0 : supported.hashCode()); result = prime * result + ((peer == null) ? 0 : peer.hashCode()); result = prime * (int) (currSpeed ^ (currSpeed >>> 32)); result = prime * (int) (maxSpeed ^ (maxSpeed >>> 32)); return result; }
@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 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()); }
/** * Returns a specific available IP address binding for lease. The MAC and IP will be queried * against the DHCP pool. (1) If the MAC is found in an available, fixed binding, and that binding * is not for the provided IP, the fixed binding associated with the MAC will be returned. (2) If * the IP is found in an available, fixed binding, and that binding also contains the MAC address * provided, then the binding will be returned -- this is true only if the IP and MAC result in * the same available, fixed binding. (3) If the IP is found in the pool and it is available and * not fixed, then its binding will be returned. (4) If the IP provided does not match any * available entries or is invalid, null will be returned. If this is the case, run * getAnyAvailableLease(mac) to resolve. * * @param {@code byte[]}: The IP address on which to try and obtain a lease * @param {@code byte[]}: The MAC address on which to try and obtain a lease. * @return {@code DHCPBinding}: Reference to the DHCPBinding object if successful, null if * unsuccessful. */ public DHCPBinding getSpecificAvailableLease(IPv4Address ip, MacAddress mac) { if (ip == null || mac == null || isPoolFull()) return null; DHCPBinding binding = this.getDHCPbindingFromIPv4(ip); DHCPBinding binding2 = this.getDHCPbindingFromMAC(mac); // For all of the following, the binding is also determined to be inactive: // If configured, we must return a fixed binding for a MAC address even if it's requesting // another IP if (binding2 != null && !binding2.isActiveLease() && binding2.isStaticIPLease() && binding != binding2) { if (log != null) log.info("Fixed DHCP entry for MAC trumps requested IP. Returning binding for MAC"); return binding2; // If configured, we must return a fixed binding for an IP if the binding is fixed to the // provided MAC (ideal static request case) } else if (binding != null && !binding.isActiveLease() && binding.isStaticIPLease() && mac.equals(binding.getMACAddress())) { if (log != null) log.info( "Found matching fixed DHCP entry for IP with MAC. Returning binding for IP with MAC"); return binding; // The IP and MAC are not a part of a fixed binding, so return the binding of the requested IP } else if (binding != null && !binding.isActiveLease() && !binding.isStaticIPLease()) { if (log != null) log.info("No fixed DHCP entry for IP or MAC found. Returning dynamic binding for IP."); return binding; // Otherwise, the binding is fixed for both MAC and IP and this MAC does not match either, so // we can't return it as available } else { if (log != null) log.debug( "Invalid IP address request or IP is actively leased...check for any available lease to resolve"); return null; } }
@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 OFBsnTlvActorSystemMac readFrom(ChannelBuffer bb) throws OFParseError { int start = bb.readerIndex(); // fixed value property type == 0x29 short type = bb.readShort(); if (type != (short) 0x29) throw new OFParseError("Wrong type: Expected=0x29(0x29), got=" + type); int length = U16.f(bb.readShort()); if (length != 10) throw new OFParseError("Wrong length: Expected=10(10), got=" + length); if (bb.readableBytes() + (bb.readerIndex() - start) < length) { // Buffer does not have all data yet bb.readerIndex(start); return null; } if (logger.isTraceEnabled()) logger.trace("readFrom - length={}", length); MacAddress value = MacAddress.read6Bytes(bb); OFBsnTlvActorSystemMacVer14 bsnTlvActorSystemMacVer14 = new OFBsnTlvActorSystemMacVer14(value); if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", bsnTlvActorSystemMacVer14); return bsnTlvActorSystemMacVer14; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; OFPortDescVer12 other = (OFPortDescVer12) obj; if (portNo == null) { if (other.portNo != null) return false; } else if (!portNo.equals(other.portNo)) return false; if (hwAddr == null) { if (other.hwAddr != null) return false; } else if (!hwAddr.equals(other.hwAddr)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (config == null) { if (other.config != null) return false; } else if (!config.equals(other.config)) return false; if (state == null) { if (other.state != null) return false; } else if (!state.equals(other.state)) return false; if (curr == null) { if (other.curr != null) return false; } else if (!curr.equals(other.curr)) return false; if (advertised == null) { if (other.advertised != null) return false; } else if (!advertised.equals(other.advertised)) return false; if (supported == null) { if (other.supported != null) return false; } else if (!supported.equals(other.supported)) return false; if (peer == null) { if (other.peer != null) return false; } else if (!peer.equals(other.peer)) return false; if (currSpeed != other.currSpeed) return false; if (maxSpeed != other.maxSpeed) return false; return true; }
@Override public OFActionSetDlSrc readFrom(ByteBuf bb) throws OFParseError { int start = bb.readerIndex(); // fixed value property type == 4 short type = bb.readShort(); if (type != (short) 0x4) throw new OFParseError("Wrong type: Expected=OFActionType.SET_DL_SRC(4), got=" + type); int length = U16.f(bb.readShort()); if (length != 16) throw new OFParseError("Wrong length: Expected=16(16), got=" + length); if (bb.readableBytes() + (bb.readerIndex() - start) < length) { // Buffer does not have all data yet bb.readerIndex(start); return null; } if (logger.isTraceEnabled()) logger.trace("readFrom - length={}", length); MacAddress dlAddr = MacAddress.read6Bytes(bb); // pad: 6 bytes bb.skipBytes(6); OFActionSetDlSrcVer10 actionSetDlSrcVer10 = new OFActionSetDlSrcVer10(dlAddr); if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", actionSetDlSrcVer10); return actionSetDlSrcVer10; }
/** * 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; } }
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); }