@Override public OFOxm<?> mapSelector(OFFactory factory, ExtensionSelector extensionSelector) { ExtensionSelectorType type = extensionSelector.type(); if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.OFDPA_MATCH_VLAN_VID.type())) { VlanId vlanId = ((OfdpaMatchVlanVid) extensionSelector).vlanId(); // Special VLAN 0x0000/0x1FFF required by OFDPA if (vlanId.equals(VlanId.NONE)) { OFVlanVidMatch vid = OFVlanVidMatch.ofRawVid((short) 0x0000); OFVlanVidMatch mask = OFVlanVidMatch.ofRawVid((short) 0x1FFF); return factory.oxms().vlanVidMasked(vid, mask); // Normal case } else if (vlanId.equals(VlanId.ANY)) { return factory.oxms().vlanVidMasked(OFVlanVidMatch.PRESENT, OFVlanVidMatch.PRESENT); } else { return factory.oxms().vlanVid(OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vlanId.toShort()))); } } throw new UnsupportedOperationException( "Unexpected ExtensionSelector: " + extensionSelector.toString()); }
private void generateDeviceEvent(IDevice device, String reason) { List<IPv4Address> ipv4Addresses = new ArrayList<IPv4Address>(Arrays.asList(device.getIPv4Addresses())); List<IPv6Address> ipv6Addresses = new ArrayList<IPv6Address>(Arrays.asList(device.getIPv6Addresses())); List<SwitchPort> oldAps = new ArrayList<SwitchPort>(Arrays.asList(device.getOldAP())); List<SwitchPort> currentAps = new ArrayList<SwitchPort>(Arrays.asList(device.getAttachmentPoints())); List<VlanVid> vlanIds = new ArrayList<VlanVid>(Arrays.asList(device.getVlanId())); debugEventCategory.newEventNoFlush(new DeviceEvent(device.getMACAddress(), ipv4Addresses, ipv6Addresses, oldAps, currentAps, vlanIds, reason)); }
/** * Parse an entity from an {@link Ethernet} packet. * @param eth the packet to parse * @param sw the switch on which the packet arrived * @param pi the original packetin * @return the entity from the packet */ protected Entity getSourceEntityFromPacket(Ethernet eth, DatapathId swdpid, OFPort port) { MacAddress dlAddr = eth.getSourceMACAddress(); // Ignore broadcast/multicast source if (dlAddr.isBroadcast() || dlAddr.isMulticast()) return null; // Ignore 0 source mac if (dlAddr.getLong() == 0) return null; VlanVid vlan = VlanVid.ofVlan(eth.getVlanID()); IPv4Address ipv4Src = getSrcIPv4AddrFromARP(eth, dlAddr); IPv6Address ipv6Src = ipv4Src.equals(IPv4Address.NONE) ? getSrcIPv6Addr(eth) : IPv6Address.NONE; return new Entity(dlAddr, vlan, ipv4Src, ipv6Src, swdpid, port, new Date()); }
/** * Construct a new device iterator over the key fields * @param subIterator an iterator over the full data structure to scan * @param entityClasses the entity classes to search for * @param macAddress The MAC address * @param vlan the VLAN * @param ipv4Address the ipv4 address * @param ipv6Address the ipv6 address * @param switchDPID the switch DPID * @param switchPort the switch port */ public DeviceIterator(Iterator<Device> subIterator, IEntityClass[] entityClasses, MacAddress macAddress, VlanVid vlan, IPv4Address ipv4Address, IPv6Address ipv6Address, DatapathId switchDPID, OFPort switchPort) { super(subIterator); this.entityClasses = entityClasses; this.subIterator = subIterator; this.macAddress = macAddress; this.vlan = vlan; this.ipv4Address = ipv4Address; this.ipv6Address = ipv6Address; this.switchDPID = switchDPID; this.switchPort = switchPort; }
protected Match createMatchFromPacket(IOFSwitch sw, OFPort inPort, FloodlightContext cntx) { // The packet in match will only contain the port number. // We need to add in specifics for the hosts we're routing between. Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); VlanVid vlan = VlanVid.ofVlan(eth.getVlanID()); MacAddress srcMac = eth.getSourceMACAddress(); MacAddress dstMac = eth.getDestinationMACAddress(); Match.Builder mb = sw.getOFFactory().buildMatch(); mb.setExact(MatchField.IN_PORT, inPort) .setExact(MatchField.ETH_SRC, srcMac) .setExact(MatchField.ETH_DST, dstMac); if (!vlan.equals(VlanVid.ZERO)) { mb.setExact(MatchField.VLAN_VID, OFVlanVidMatch.ofVlanVid(vlan)); } return mb.build(); }
/** * Parse set_vlan_id actions. * The key and delimiter for the action should be omitted, and only the * data should be presented to this decoder. Data with a leading 0x is permitted. * * @param actionToDecode; The action as a string to decode * @param version; The OF version to create the action for * @param log * @return */ private static OFActionSetVlanVid decode_set_vlan_id(String actionToDecode, OFVersion version, Logger log) { Matcher n = Pattern.compile("((?:0x)?\\d+)").matcher(actionToDecode); if (n.matches()) { if (n.group(1) != null) { try { VlanVid vlanid = VlanVid.ofVlan(get_short(n.group(1))); OFActionSetVlanVid.Builder ab = OFFactories.getFactory(version).actions().buildSetVlanVid(); ab.setVlanVid(vlanid); log.debug("action {}", ab.build()); return ab.build(); } catch (NumberFormatException e) { log.debug("Invalid VLAN in: {} (error ignored)", actionToDecode); return null; } } } else { log.debug("Invalid action: '{}'", actionToDecode); return null; } return null; }
@Test public void testLastSeen() throws Exception { Calendar c = Calendar.getInstance(); Date d1 = c.getTime(); Entity entity1 = new Entity(MacAddress.of(1L), VlanVid.ZERO /* untagged*/, IPv4Address.NONE, IPv6Address.NONE, DatapathId.NONE, OFPort.ZERO, d1); c.add(Calendar.SECOND, 1); Entity entity2 = new Entity(MacAddress.of(1L), VlanVid.ZERO /* untagged*/, IPv4Address.of(1), IPv6Address.NONE, DatapathId.NONE, OFPort.ZERO, c.getTime()); IDevice d = deviceManager.learnDeviceByEntity(entity2); assertEquals(c.getTime(), d.getLastSeen()); d = deviceManager.learnDeviceByEntity(entity1); assertEquals(c.getTime(), d.getLastSeen()); deviceManager.startUp(null); d = deviceManager.learnDeviceByEntity(entity1); assertEquals(d1, d.getLastSeen()); d = deviceManager.learnDeviceByEntity(entity2); assertEquals(c.getTime(), d.getLastSeen()); }
/** * Verify that the given device exactly matches the given fields. E.g., * if ip is not null we expect the device to have exactly one IP address. * swId and port are the attachment point port. * Vlan and ip are optional all other fields must be specified. * @return */ private static void verifyDevice(IDevice d, MacAddress mac, VlanVid vlan, IPv4Address ipv4, IPv6Address ipv6, DatapathId swId, OFPort port) { assertNotNull(d); if (!mac.equals(MacAddress.NONE)) { assertEquals(mac, d.getMACAddress()); } if (vlan != null) { assertArrayEquals(new VlanVid[] { vlan }, d.getVlanId()); } if (!ipv4.equals(IPv4Address.NONE)) { assertArrayEquals(new IPv4Address[] { ipv4 }, d.getIPv4Addresses()); } if (!ipv6.equals(IPv6Address.NONE)) { assertArrayEquals(new IPv6Address[] { ipv6 }, d.getIPv6Addresses()); } if (!swId.equals(DatapathId.NONE) && !port.equals(OFPort.ZERO)) { SwitchPort expectedAp = new SwitchPort(swId, port); assertArrayEquals(new SwitchPort[] { expectedAp }, d.getAttachmentPoints()); } }
@Test public void testGetSwitchPortVlanId() { Entity entity1 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(1), IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(10L), OFPort.of(1), new Date()); Entity entity2 = new Entity(MacAddress.of(1L), VlanVid.ZERO, IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(10L), OFPort.of(1), new Date()); Entity entity3 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(3), IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(1L), OFPort.of(1), new Date()); Entity entity4 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(42), IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(1L), OFPort.of(1), new Date()); Entity[] entities = new Entity[] { entity1, entity2, entity3, entity4 }; Device d = new Device(null,1L, null, null, null, Arrays.asList(entities), null); SwitchPort swp1x1 = new SwitchPort(DatapathId.of(1L), OFPort.of(1)); SwitchPort swp1x2 = new SwitchPort(DatapathId.of(1L), OFPort.of(2)); SwitchPort swp2x1 = new SwitchPort(DatapathId.of(2L), OFPort.of(1)); SwitchPort swp10x1 = new SwitchPort(DatapathId.of(10L), OFPort.of(1)); assertArrayEquals(new VlanVid[] { VlanVid.ZERO, VlanVid.ofVlan(1)}, d.getSwitchPortVlanIds(swp10x1)); assertArrayEquals(new VlanVid[] { VlanVid.ofVlan(3), VlanVid.ofVlan(42)}, d.getSwitchPortVlanIds(swp1x1)); assertArrayEquals(new VlanVid[0], d.getSwitchPortVlanIds(swp1x2)); assertArrayEquals(new VlanVid[0], d.getSwitchPortVlanIds(swp2x1)); }
@Override protected void setUp() throws Exception { super.setUp(); e1a = new Entity(MacAddress.of(1L), VlanVid.ofVlan(1), IPv4Address.of(1), IPv6Address.of(1, 1), DatapathId.of(1L), OFPort.of(1), new Date()); e1b = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(1), IPv6Address.of(1, 1), DatapathId.of(1L), OFPort.of(1), new Date()); List<Entity> d1Entities = new ArrayList<Entity>(2); d1Entities.add(e1a); d1Entities.add(e1b); d1 = new Device(null, Long.valueOf(1), null, null, null, d1Entities, null); // e2 and e2 alt match in MAC and VLAN e2 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.of(2), IPv6Address.of(2, 2), DatapathId.of(2L), OFPort.of(2), new Date()); e2alt = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.NONE, IPv6Address.NONE, DatapathId.NONE, OFPort.ZERO, Entity.NO_DATE); // IP is null e3 = new Entity(MacAddress.of(3L), VlanVid.ofVlan(3), IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(3L), OFPort.of(3), new Date()); // IP and switch and port are null e4 = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), IPv4Address.NONE, IPv6Address.NONE, DatapathId.NONE, OFPort.ZERO, new Date()); }
/** * Learn a device using the given characteristics. * @param macAddress the MAC * @param vlan the VLAN (can be VlanVid.ZERO for untagged) * @param ipv4Address the IPv4 (can be IPv4Address.NONE) * @param ipv6Address the IPv6 (can be IPv6Address.NONE) * @param switchDPID the attachment point switch DPID (can be DatapathId.NONE) * @param switchPort the attachment point switch port (can be OFPort.ZERO) * @param processUpdates if false, will not send updates. Note that this * method is not thread safe if this is false * @return the device, either new or not */ public IDevice learnEntity(MacAddress macAddress, VlanVid vlan, IPv4Address ipv4Address, IPv6Address ipv6Address, DatapathId switchDPID, OFPort switchPort, boolean processUpdates) { List<IDeviceListener> listeners = deviceListeners.getOrderedListeners(); if (!processUpdates) { deviceListeners.clearListeners(); } /* Entity will enforce all but VLAN be non-null */ IDevice res = learnDeviceByEntity(new Entity(macAddress, vlan, ipv4Address, ipv6Address, switchDPID, switchPort, new Date())); // Restore listeners if (listeners != null) { for (IDeviceListener listener : listeners) { deviceListeners.addListener("device", listener); } } return res; }
private VlanVid[] computeVlandIds() { if (entities.length == 1) { if (entities[0].getVlan() != null) { return new VlanVid[]{ entities[0].getVlan() }; } else { return new VlanVid[] { VlanVid.ofVlan(-1) }; } } TreeSet<VlanVid> vals = new TreeSet<VlanVid>(); for (Entity e : entities) { if (e.getVlan() == null) vals.add(VlanVid.ofVlan(-1)); else vals.add(e.getVlan()); } return vals.toArray(new VlanVid[vals.size()]); }
@Override public IDevice findDevice(MacAddress macAddress, VlanVid vlan, IPv4Address ipv4Address, DatapathId switchDPID, OFPort switchPort) throws IllegalArgumentException { if (vlan != null && vlan.getVlan() <= 0) vlan = null; if (ipv4Address != null && ipv4Address.getInt() == 0) ipv4Address = null; Entity e = new Entity(macAddress, vlan, ipv4Address, switchDPID, switchPort, null); if (!allKeyFieldsPresent(e, entityClassifier.getKeyFields())) { throw new IllegalArgumentException("Not all key fields specified." + " Required fields: " + entityClassifier.getKeyFields()); } return findDeviceByEntity(e); }
@Override public IDevice findClassDevice(IEntityClass entityClass, MacAddress macAddress, VlanVid vlan, IPv4Address ipv4Address) throws IllegalArgumentException { if (vlan != null && vlan.getVlan() <= 0) vlan = null; if (ipv4Address != null && ipv4Address.getInt() == 0) ipv4Address = null; Entity e = new Entity(macAddress, vlan, ipv4Address, null, null, null); if (entityClass == null || !allKeyFieldsPresent(e, entityClass.getKeyFields())) { throw new IllegalArgumentException("Not all key fields and/or " + " no source device specified. Required fields: " + entityClassifier.getKeyFields()); } return findDestByEntity(entityClass, e); }
/** * Verify that the given device exactly matches the given fields. E.g., * if ip is not null we expect the device to have exactly one IP address. * swId and port are the attachment point port. * Vlan and ip are optional all other fields must be specified. * @return */ private static void verifyDevice(IDevice d, long mac, Short vlan, Integer ip, long swId, int port) { assertNotNull(d); assertEquals(MacAddress.of(mac), d.getMACAddress()); if (vlan == null) assertArrayEquals(new VlanVid[] { VlanVid.ofVlan(-1) }, d.getVlanId()); else assertArrayEquals(new VlanVid[] { VlanVid.ofVlan(vlan) }, d.getVlanId()); if (ip == null) assertArrayEquals(new IPv4Address[] { IPv4Address.of(0) }, d.getIPv4Addresses()); else assertArrayEquals(new IPv4Address[] { IPv4Address.of(ip) }, d.getIPv4Addresses()); SwitchPort expectedAp = new SwitchPort(DatapathId.of(swId), OFPort.of(port)); assertArrayEquals(new SwitchPort[] { expectedAp }, d.getAttachmentPoints()); }
private void generateDeviceEvent(IDevice device, String reason) { List<IPv4Address> ipv4Addresses = new ArrayList<IPv4Address>(Arrays.asList(device.getIPv4Addresses())); List<SwitchPort> oldAps = new ArrayList<SwitchPort>(Arrays.asList(device.getOldAP())); List<SwitchPort> currentAps = new ArrayList<SwitchPort>(Arrays.asList(device.getAttachmentPoints())); List<VlanVid> vlanIds = new ArrayList<VlanVid>(Arrays.asList(device.getVlanId())); debugEventCategory.newEventNoFlush(new DeviceEvent(device.getMACAddress(), ipv4Addresses, oldAps, currentAps, vlanIds, reason)); }
/** * Parse an entity from an {@link Ethernet} packet. * @param eth the packet to parse * @param sw the switch on which the packet arrived * @param pi the original packetin * @return the entity from the packet */ protected Entity getSourceEntityFromPacket(Ethernet eth, DatapathId swdpid, OFPort port) { MacAddress dlAddr = eth.getSourceMACAddress(); // Ignore broadcast/multicast source if (dlAddr.isBroadcast() || dlAddr.isMulticast()) return null; // Ignore 0 source mac if (dlAddr.getLong() == 0) return null; VlanVid vlan = VlanVid.ofVlan(eth.getVlanID()); IPv4Address nwSrc = getSrcNwAddr(eth, dlAddr); return new Entity(dlAddr, vlan, nwSrc, swdpid, port, new Date()); }
@Test public void testGetSwitchPortVlanId() { Entity entity1 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(1), null, DatapathId.of(10L), OFPort.of(1), new Date()); Entity entity2 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(10L), OFPort.of(1), new Date()); Entity entity3 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(3), null, DatapathId.of(1L), OFPort.of(1), new Date()); Entity entity4 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(42), null, DatapathId.of(1L), OFPort.of(1), new Date()); Entity[] entities = new Entity[] { entity1, entity2, entity3, entity4 }; Device d = new Device(null,1L, null, null, null, Arrays.asList(entities), null); SwitchPort swp1x1 = new SwitchPort(DatapathId.of(1L), OFPort.of(1)); SwitchPort swp1x2 = new SwitchPort(DatapathId.of(1L), OFPort.of(2)); SwitchPort swp2x1 = new SwitchPort(DatapathId.of(2L), OFPort.of(1)); SwitchPort swp10x1 = new SwitchPort(DatapathId.of(10L), OFPort.of(1)); assertArrayEquals(new VlanVid[] { VlanVid.ofVlan(-1), VlanVid.ofVlan(1)}, d.getSwitchPortVlanIds(swp10x1)); assertArrayEquals(new VlanVid[] { VlanVid.ofVlan(3), VlanVid.ofVlan(42)}, d.getSwitchPortVlanIds(swp1x1)); assertArrayEquals(new VlanVid[0], d.getSwitchPortVlanIds(swp1x2)); assertArrayEquals(new VlanVid[0], d.getSwitchPortVlanIds(swp2x1)); }
/** * Get a (partial) entity for the destination from the packet. * @param eth * @return */ protected Entity getDestEntityFromPacket(Ethernet eth) { MacAddress dlAddr = eth.getDestinationMACAddress(); VlanVid vlan = VlanVid.ofVlan(eth.getVlanID()); IPv4Address nwDst = IPv4Address.NONE; // Ignore broadcast/multicast destination if (dlAddr.isBroadcast() || dlAddr.isMulticast()) return null; // Ignore zero dest mac if (dlAddr.getLong() == 0) return null; if (eth.getPayload() instanceof IPv4) { IPv4 ipv4 = (IPv4) eth.getPayload(); nwDst = ipv4.getDestinationAddress(); } return new Entity(dlAddr, vlan, nwDst, null, null, null); }
private EnumSet<DeviceField> getEntityKeys(MacAddress macAddress, VlanVid vlan, IPv4Address ipv4Address, DatapathId switchDPID, OFPort switchPort) { // FIXME: vlan==null is a valid search. Need to handle this // case correctly. Note that the code will still work correctly. // But we might do a full device search instead of using an index. EnumSet<DeviceField> keys = EnumSet.noneOf(DeviceField.class); if (macAddress != null) keys.add(DeviceField.MAC); if (vlan != null) keys.add(DeviceField.VLAN); if (ipv4Address != null) keys.add(DeviceField.IPV4); if (switchDPID != null) keys.add(DeviceField.SWITCH); if (switchPort != null) keys.add(DeviceField.PORT); return keys; }
@Override protected void setUp() throws Exception { super.setUp(); e1a = new Entity(MacAddress.of(1L), VlanVid.ofVlan(1), IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), new Date()); e1b = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), new Date()); List<Entity> d1Entities = new ArrayList<Entity>(2); d1Entities.add(e1a); d1Entities.add(e1b); d1 = new Device(null, Long.valueOf(1), null, null, null, d1Entities, null); // e2 and e2 alt match in MAC and VLAN e2 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.of(2), DatapathId.of(2L), OFPort.of(2), new Date()); e2alt = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), null, null, null, null); // IP is null e3 = new Entity(MacAddress.of(3L), VlanVid.ofVlan(3), null, DatapathId.of(3L), OFPort.of(3), new Date()); // IP and switch and port are null e4 = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), null, null, null, new Date()); }
/** * Construct a new device iterator over the key fields * @param subIterator an iterator over the full data structure to scan * @param entityClasses the entity classes to search for * @param macAddress The MAC address * @param vlan the VLAN * @param ipv4Address the ipv4 address * @param switchDPID the switch DPID * @param switchPort the switch port */ public DeviceIterator(Iterator<Device> subIterator, IEntityClass[] entityClasses, MacAddress macAddress, VlanVid vlan, IPv4Address ipv4Address, DatapathId switchDPID, OFPort switchPort) { super(subIterator); this.entityClasses = entityClasses; this.subIterator = subIterator; this.macAddress = macAddress; this.vlan = vlan; this.ipv4Address = ipv4Address; this.switchDPID = switchDPID; this.switchPort = switchPort; }
private VlanVid[] computeVlandIds() { if (entities.length == 1) { return new VlanVid[] { entities[0].getVlan() }; } TreeSet<VlanVid> vals = new TreeSet<VlanVid>(); for (Entity e : entities) { vals.add(e.getVlan()); } return vals.toArray(new VlanVid[vals.size()]); }
@Override public VlanVid[] getSwitchPortVlanIds(SwitchPort swp) { TreeSet<VlanVid> vals = new TreeSet<VlanVid>(); for (Entity e : entities) { if (e.switchDPID.equals(swp.getSwitchDPID()) && e.switchPort.equals(swp.getPort())) { if (e.getVlan() == null) vals.add(VlanVid.ZERO); else vals.add(e.getVlan()); } } return vals.toArray(new VlanVid[vals.size()]); }
@Override public IDevice findDevice(@Nonnull MacAddress macAddress, VlanVid vlan, @Nonnull IPv4Address ipv4Address, @Nonnull IPv6Address ipv6Address, @Nonnull DatapathId switchDPID, @Nonnull OFPort switchPort) throws IllegalArgumentException { if (macAddress == null) { throw new IllegalArgumentException("MAC address cannot be null. Try MacAddress.NONE if intention is 'no MAC'"); } if (ipv4Address == null) { throw new IllegalArgumentException("IPv4 address cannot be null. Try IPv4Address.NONE if intention is 'no IPv4'"); } if (ipv6Address == null) { throw new IllegalArgumentException("IPv6 address cannot be null. Try IPv6Address.NONE if intention is 'no IPv6'"); } if (vlan == null) { throw new IllegalArgumentException("VLAN cannot be null. Try VlanVid.ZERO if intention is 'no VLAN / untagged'"); } if (switchDPID == null) { throw new IllegalArgumentException("Switch DPID cannot be null. Try DatapathId.NONE if intention is 'no DPID'"); } if (switchPort == null) { throw new IllegalArgumentException("Switch port cannot be null. Try OFPort.ZERO if intention is 'no port'"); } Entity e = new Entity(macAddress, vlan, ipv4Address, ipv6Address, switchDPID, switchPort, Entity.NO_DATE); /* * allKeyFieldsPresent() will check if the entity key fields (e.g. MAC and VLAN) * have non-"zero" values i.e. are not set to e.g. MacAddress.NONE and VlanVid.ZERO */ if (!allKeyFieldsPresent(e, entityClassifier.getKeyFields())) { throw new IllegalArgumentException("Not all key fields specified." + " Required fields: " + entityClassifier.getKeyFields()); } return findDeviceByEntity(e); }
@Override public IDevice findClassDevice(@Nonnull IEntityClass entityClass, @Nonnull MacAddress macAddress, @Nonnull VlanVid vlan, @Nonnull IPv4Address ipv4Address, @Nonnull IPv6Address ipv6Address) throws IllegalArgumentException { if (entityClass == null) { throw new IllegalArgumentException("Entity class cannot be null."); } if (macAddress == null) { throw new IllegalArgumentException("MAC address cannot be null. Try MacAddress.NONE if intention is 'no MAC'"); } if (ipv4Address == null) { throw new IllegalArgumentException("IPv4 address cannot be null. Try IPv4Address.NONE if intention is 'no IPv4'"); } if (ipv6Address == null) { throw new IllegalArgumentException("IPv6 address cannot be null. Try IPv6Address.NONE if intention is 'no IPv6'"); } if (vlan == null) { throw new IllegalArgumentException("VLAN cannot be null. Try VlanVid.ZERO if intention is 'no VLAN / untagged'"); } Entity e = new Entity(macAddress, vlan, ipv4Address, ipv6Address, DatapathId.NONE, OFPort.ZERO, Entity.NO_DATE); if (!allKeyFieldsPresent(e, entityClass.getKeyFields())) { throw new IllegalArgumentException("Not all key fields and/or " + " no source device specified. Required fields: " + entityClassifier.getKeyFields()); } return findDestByEntity(entityClass, e); }
/** * Get a (partial) entity for the destination from the packet. * @param eth * @return */ protected Entity getDestEntityFromPacket(Ethernet eth) { MacAddress dlAddr = eth.getDestinationMACAddress(); VlanVid vlan = VlanVid.ofVlan(eth.getVlanID()); IPv4Address ipv4Dst = IPv4Address.NONE; IPv6Address ipv6Dst = IPv6Address.NONE; // Ignore broadcast/multicast destination if (dlAddr.isBroadcast() || dlAddr.isMulticast()) return null; // Ignore zero dest mac if (dlAddr.equals(MacAddress.of(0))) return null; if (eth.getPayload() instanceof IPv4) { IPv4 ipv4 = (IPv4) eth.getPayload(); ipv4Dst = ipv4.getDestinationAddress(); } else if (eth.getPayload() instanceof IPv6) { IPv6 ipv6 = (IPv6) eth.getPayload(); ipv6Dst = ipv6.getDestinationAddress(); } return new Entity(dlAddr, vlan, ipv4Dst, ipv6Dst, DatapathId.NONE, OFPort.ZERO, Entity.NO_DATE); }
private EnumSet<DeviceField> getEntityKeys(@Nonnull MacAddress macAddress, VlanVid vlan, /* A null VLAN means 'don't care'; VlanVid.ZERO means 'untagged' */ @Nonnull IPv4Address ipv4Address, @Nonnull IPv6Address ipv6Address, @Nonnull DatapathId switchDPID, @Nonnull OFPort switchPort) { EnumSet<DeviceField> keys = EnumSet.noneOf(DeviceField.class); if (!macAddress.equals(MacAddress.NONE)) keys.add(DeviceField.MAC); if (vlan != null) keys.add(DeviceField.VLAN); /* TODO verify fix. null means 'don't care' and will conduct full search; VlanVid.ZERO means 'untagged' and only uses untagged index */ if (!ipv4Address.equals(IPv4Address.NONE)) keys.add(DeviceField.IPv4); if (!ipv6Address.equals(IPv6Address.NONE)) keys.add(DeviceField.IPv6); if (!switchDPID.equals(DatapathId.NONE)) keys.add(DeviceField.SWITCH); if (!switchPort.equals(OFPort.ZERO)) keys.add(DeviceField.PORT); return keys; }
public DeviceEvent(MacAddress macAddress, List<IPv4Address> ipv4Addresses, List<IPv6Address> ipv6Addresses, List<SwitchPort> oldAttachmentPoints, List<SwitchPort> currentAttachmentPoints, List<VlanVid> vlanIds, String reason) { super(); this.macAddress = macAddress; this.ipv4Addresses = ipv4Addresses; this.ipv6Addresses = ipv6Addresses; this.oldAttachmentPoints = oldAttachmentPoints; this.currentAttachmentPoints = currentAttachmentPoints; this.vlanIds = vlanIds; this.reason = reason; }
/** * Create a new entity * * @param macAddress * @param vlan * @param ipv4Address * @param ipv6Address * @param switchDPID * @param switchPort * @param lastSeenTimestamp */ public Entity(@Nonnull MacAddress macAddress, VlanVid vlan, @Nonnull IPv4Address ipv4Address, @Nonnull IPv6Address ipv6Address, @Nonnull DatapathId switchDPID, @Nonnull OFPort switchPort, @Nonnull Date lastSeenTimestamp) { if (macAddress == null) { throw new IllegalArgumentException("MAC address cannot be null. Try MacAddress.NONE if intention is 'no MAC'"); } if (ipv4Address == null) { throw new IllegalArgumentException("IPv4 address cannot be null. Try IPv4Address.NONE if intention is 'no IPv4'"); } if (ipv6Address == null) { throw new IllegalArgumentException("IPv6 address cannot be null. Try IPv6Address.NONE if intention is 'no IPv6'"); } /* VLAN can be null for 'don't care' in query searches */ if (switchDPID == null) { throw new IllegalArgumentException("Switch DPID cannot be null. Try DatapathId.NONE if intention is 'no DPID'"); } if (switchPort == null) { throw new IllegalArgumentException("Switch port cannot be null. Try OFPort.ZERO if intention is 'no port'"); } if (lastSeenTimestamp == null) { throw new IllegalArgumentException("Last seen time stamp cannot be null. Try Entity.NO_DATE if intention is 'no time'"); } this.macAddress = macAddress; this.ipv4Address = ipv4Address; this.ipv6Address = ipv6Address; this.vlan = vlan; this.switchDPID = switchDPID; this.switchPort = switchPort; this.lastSeenTimestamp = lastSeenTimestamp; this.activeSince = lastSeenTimestamp; }
public Entity asEntity() { Entity e = new Entity(MacAddress.of(macAddress), VlanVid.ofVlan(vlan), IPv4Address.of(ipv4Address), IPv6Address.NONE, DatapathId.of(switchDPID), OFPort.of(switchPort), lastSeenTimestamp); e.setActiveSince(activeSince); return e; }
@Override public void switchActivated(DatapathId switchId) { IOFSwitch sw = switchService.getSwitch(switchId); if (sw == null) { log.warn("Switch {} was activated but had no switch object in the switch service. Perhaps it quickly disconnected", switchId); return; } if (OFDPAUtils.isOFDPASwitch(sw)) { sw.write(sw.getOFFactory().buildFlowDelete() .setTableId(TableId.ALL) .build() ); sw.write(sw.getOFFactory().buildGroupDelete() .setGroup(OFGroup.ANY) .setGroupType(OFGroupType.ALL) .build() ); sw.write(sw.getOFFactory().buildGroupDelete() .setGroup(OFGroup.ANY) .setGroupType(OFGroupType.INDIRECT) .build() ); sw.write(sw.getOFFactory().buildBarrierRequest().build()); List<OFPortModeTuple> portModes = new ArrayList<OFPortModeTuple>(); for (OFPortDesc p : sw.getPorts()) { portModes.add(OFPortModeTuple.of(p.getPortNo(), OFPortMode.ACCESS)); } if (log.isWarnEnabled()) { log.warn("For OF-DPA switch {}, initializing VLAN {} on ports {}", new Object[] { switchId, VlanVid.ZERO, portModes}); } OFDPAUtils.addLearningSwitchPrereqs(sw, VlanVid.ZERO, portModes); } }
/** * Removes a host from the MAC/VLAN->SwitchPort mapping * @param sw The switch to remove the mapping from * @param mac The MAC address of the host to remove * @param vlan The VLAN that the host is on */ protected void removeFromPortMap(IOFSwitch sw, MacAddress mac, VlanVid vlan) { if (vlan == VlanVid.FULL_MASK) { vlan = VlanVid.ofVlan(0); } Map<MacVlanPair, OFPort> swMap = macVlanToSwitchPortMap.get(sw); if (swMap != null) { swMap.remove(new MacVlanPair(mac, vlan)); } }
/** * Get the port that a MAC/VLAN pair is associated with * @param sw The switch to get the mapping from * @param mac The MAC address to get * @param vlan The VLAN number to get * @return The port the host is on */ public OFPort getFromPortMap(IOFSwitch sw, MacAddress mac, VlanVid vlan) { if (vlan == VlanVid.FULL_MASK || vlan == null) { vlan = VlanVid.ofVlan(0); } Map<MacVlanPair, OFPort> swMap = macVlanToSwitchPortMap.get(sw); if (swMap != null) { return swMap.get(new MacVlanPair(mac, vlan)); } // if none found return null; }
/** * Processes a flow removed message. We will delete the learned MAC/VLAN mapping from * the switch's table. * @param sw The switch that sent the flow removed message. * @param flowRemovedMessage The flow removed message. * @return Whether to continue processing this message or stop. */ private Command processFlowRemovedMessage(IOFSwitch sw, OFFlowRemoved flowRemovedMessage) { if (!flowRemovedMessage.getCookie().equals(U64.of(LearningSwitch.LEARNING_SWITCH_COOKIE))) { return Command.CONTINUE; } if (log.isTraceEnabled()) { log.trace("{} flow entry removed {}", sw, flowRemovedMessage); } Match match = flowRemovedMessage.getMatch(); // When a flow entry expires, it means the device with the matching source // MAC address and VLAN either stopped sending packets or moved to a different // port. If the device moved, we can't know where it went until it sends // another packet, allowing us to re-learn its port. Meanwhile we remove // it from the macVlanToPortMap to revert to flooding packets to this device. this.removeFromPortMap(sw, match.get(MatchField.ETH_SRC), match.get(MatchField.VLAN_VID) == null ? VlanVid.ZERO : match.get(MatchField.VLAN_VID).getVlanVid()); // Also, if packets keep coming from another device (e.g. from ping), the // corresponding reverse flow entry will never expire on its own and will // send the packets to the wrong port (the matching input port of the // expired flow entry), so we must delete the reverse entry explicitly. Match.Builder mb = sw.getOFFactory().buildMatch(); mb.setExact(MatchField.ETH_SRC, match.get(MatchField.ETH_DST)) .setExact(MatchField.ETH_DST, match.get(MatchField.ETH_SRC)); if (match.get(MatchField.VLAN_VID) != null) { mb.setExact(MatchField.VLAN_VID, match.get(MatchField.VLAN_VID)); } this.writeFlowMod(sw, OFFlowModCommand.DELETE, OFBufferId.NO_BUFFER, mb.build(), match.get(MatchField.IN_PORT)); return Command.CONTINUE; }
@Test public void testSyncEntity() { Date d1 = new Date(); Date d2 = new Date(0); Entity e1 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(3), DatapathId.of(4L), OFPort.of(5), d1); e1.setActiveSince(d2); SyncEntity se1 = new SyncEntity(e1); assertEntityEquals(e1, se1); assertEquals(1L, se1.macAddress); assertEquals(2, se1.vlan); assertEquals(3, se1.ipv4Address); assertEquals(4L, se1.switchDPID); assertEquals(5, se1.switchPort); assertEquals(d1, se1.lastSeenTimestamp); assertEquals(d2, se1.activeSince); assertNotSame(d1, se1.lastSeenTimestamp); assertNotSame(d2, se1.activeSince); Entity e2 = new Entity(MacAddress.of(42L), null, null, null, null, null); SyncEntity se2 = new SyncEntity(e2); assertEntityEquals(e2, se2); SyncEntity se3 = new SyncEntity(); SyncEntity se4 = new SyncEntity(); se3.lastSeenTimestamp = new Date(1000); se4.lastSeenTimestamp = new Date(2000); assertTrue("", se3.compareTo(se4) < 0); assertTrue("", se4.compareTo(se3) > 0); se4.lastSeenTimestamp = new Date(1000); assertTrue("", se3.compareTo(se4) == 0); assertTrue("", se4.compareTo(se3) == 0); se4.lastSeenTimestamp = new Date(500); assertTrue("", se3.compareTo(se4) > 0); assertTrue("", se4.compareTo(se3) < 0); }
private void doTestEntityOrdering(boolean computeInsertionPoint) throws Exception { Entity e = new Entity(MacAddress.of(10L), VlanVid.ZERO, IPv4Address.NONE, IPv6Address.NONE, DatapathId.NONE, OFPort.ZERO, Entity.NO_DATE); IEntityClass ec = createNiceMock(IEntityClass.class); Device d = new Device(deviceManager, 1L, e, ec); int expectedLength = 1; Long[] macs = new Long[] { 5L, // new first element 15L, // new last element 7L, // insert in middle 12L, // insert in middle 6L, // insert at idx 1 14L, // insert at idx length-2 1L, 20L }; for (Long mac: macs) { e = new Entity(MacAddress.of(mac), VlanVid.ZERO, IPv4Address.NONE, IPv6Address.NONE, DatapathId.NONE, OFPort.ZERO, Entity.NO_DATE); int insertionPoint; if (computeInsertionPoint) { insertionPoint = -(Arrays.binarySearch(d.entities, e)+1); } else { insertionPoint = -1; } d = deviceManager.allocateDevice(d, e, insertionPoint); expectedLength++; assertEquals(expectedLength, d.entities.length); for (int i = 0; i < d.entities.length-1; i++) assertEquals(-1, d.entities[i].compareTo(d.entities[i+1])); } }
@Override public Collection<Device> values() { // Get the values from the real map and copy them since // the collection returned by values can reflect changed Collection<Device> devs = new ArrayList<Device>(super.values()); for (Device d: devs) { if (remove) { // We remove the device from the underlying map super.remove(d.getDeviceKey()); } else { super.remove(d.getDeviceKey()); // We add a different Device instance with the same // key to the map. We'll do some hackery so the device // is different enough to compare differently in equals // but otherwise looks the same. // It's ugly but it works. // clone entities Device newDevice = d; for (Entity e: d.getEntities()) { Entity newEntity = new Entity (e.macAddress, e.vlan, e.ipv4Address, e.ipv6Address, e.switchDPID, e.switchPort, e.lastSeenTimestamp); if (newEntity.vlan.equals(VlanVid.ZERO)) { newEntity.vlan = VlanVid.ofVlan(1); } else { newEntity.vlan = VlanVid.ofVlan((e.vlan.getVlan() + 1 % 4095) + 1); } newDevice = new Device(newDevice, newEntity, -1); } assertEquals(false, newDevice.equals(d)); super.put(newDevice.getDeviceKey(), newDevice); } } return devs; }
@Test public void testDeviceSyncRepresentationBasics() { DeviceSyncRepresentation dsr = new DeviceSyncRepresentation(); assertNull(dsr.getKey()); assertNull(dsr.getEntities()); dsr.setKey("MyKey"); assertEquals("MyKey", dsr.getKey()); assertEquals("MyKey", dsr.toString()); List<SyncEntity> entities = new ArrayList<SyncEntity>(); Entity e1a = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(3), IPv6Address.NONE, DatapathId.of(4L), OFPort.of(5), new Date(1000)); Entity e1b = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(4L), OFPort.of(5), new Date(1)); entities.add(new SyncEntity(e1a)); entities.add(new SyncEntity(e1b)); // e1b comes before e1 (lastSeen) but we add it after it to test // sorting dsr.setEntities(entities); assertEquals(2, dsr.getEntities().size()); // e1b has earlier time assertEquals(e1b, dsr.getEntities().get(0).asEntity()); assertEquals(e1a, dsr.getEntities().get(1).asEntity()); dsr.setKey(null); dsr.setEntities(null); assertNull(dsr.getKey()); assertNull(dsr.getEntities()); }