diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java index 86af84751a9f0e2cbddb16d41ed3b21fc38aab81..aa6382fad235ef324311c766dd13e7e5ceea6130 100644 --- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java +++ b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java @@ -50,6 +50,7 @@ import net.floodlightcontroller.core.module.IFloodlightModule; import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.core.util.SingletonTask; import net.floodlightcontroller.linkdiscovery.ILinkDiscovery; +import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LinkType; import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.SwitchType; import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LDUpdate; import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.UpdateOperation; @@ -130,6 +131,7 @@ public class LinkDiscoveryManager private static final String LINK_DST_PORT = "dst_port"; private static final String LINK_DST_PORT_STATE = "dst_port_state"; private static final String LINK_VALID_TIME = "valid_time"; + private static final String LINK_TYPE = "link_type"; private static final String SWITCH_TABLE_NAME = "controller_switch"; private static final String SWITCH_CORE_SWITCH = "core_switch"; @@ -141,7 +143,8 @@ public class LinkDiscoveryManager private static final String LLDP_STANDARD_DST_MAC_STRING = "01:80:c2:00:00:00"; // BigSwitch OUI is 5C:16:C7, so 5D:16:C7 is the multicast version - private static final String LLDP_BSN_DST_MAC_STRING = "5d:16:c7:00:00:01"; + // private static final String LLDP_BSN_DST_MAC_STRING = "5d:16:c7:00:00:01"; + private static final String LLDP_BSN_DST_MAC_STRING = "ff:ff:ff:ff:ff:ff"; /** * Map from link to the most recent time it was verified functioning @@ -217,17 +220,26 @@ public class LinkDiscoveryManager } while (updates.peek() != null); } - protected void sendLLDPs(IOFSwitch sw, OFPhysicalPort port, String dstMacAddress) { + protected void sendLLDPs(IOFSwitch sw, OFPhysicalPort port, boolean isStandard) { if (log.isTraceEnabled()) { log.trace("Sending LLDP packet out of swich: {}, port: {}", sw.getStringId(), port.getPortNumber()); } - Ethernet ethernet = new Ethernet() + Ethernet ethernet; + + if (isStandard) { + ethernet = new Ethernet() .setSourceMACAddress(port.getHardwareAddress()) - .setDestinationMACAddress(dstMacAddress) + .setDestinationMACAddress(LLDP_STANDARD_DST_MAC_STRING) .setEtherType(Ethernet.TYPE_LLDP); + } else { + ethernet = new Ethernet() + .setSourceMACAddress(port.getHardwareAddress()) + .setDestinationMACAddress(LLDP_BSN_DST_MAC_STRING) + .setEtherType(Ethernet.TYPE_BSN); + } // using "nearest customer bridge" MAC address for broadest possible propagation // through provider and TPMR bridges (see IEEE 802.1AB-2009 and 802.1Q-2011), // in particular the Linux bridge which behaves mostly like a provider bridge @@ -304,16 +316,16 @@ public class LinkDiscoveryManager OFPhysicalPort port = sw.getPort(swt.getPort()); if (port != null) { - sendLLDPs(sw, port, LLDP_STANDARD_DST_MAC_STRING); - sendLLDPs(sw, port, LLDP_BSN_DST_MAC_STRING); + sendLLDPs(sw, port, true); + sendLLDPs(sw, port, false); } } protected void sendLLDPs(IOFSwitch sw) { if (sw.getEnabledPorts() != null) { for (OFPhysicalPort port : sw.getEnabledPorts()) { - sendLLDPs(sw, port, LLDP_STANDARD_DST_MAC_STRING); - sendLLDPs(sw, port, LLDP_BSN_DST_MAC_STRING); + sendLLDPs(sw, port, true); + sendLLDPs(sw, port, false); } } sw.flush(); @@ -390,6 +402,10 @@ public class LinkDiscoveryManager Short remotePort = portBB.getShort(); IOFSwitch remoteSwitch = null; boolean myLLDP = false; + + if (isStandard == false) { + log.info("srini: getting bsn-specific packet."); + } // Verify this LLDP packet matches what we're looking for for (LLDPTLV lldptlv : lldp.getOptionalTLVList()) { @@ -421,12 +437,10 @@ public class LinkDiscoveryManager if (eth.isMulticast()) { if (log.isTraceEnabled()) log.trace("Received a multicast LLDP packet from a different controller, allowing the packet to follow normal processing chain."); - return Command.STOP; - } - if (log.isTraceEnabled()) { - log.trace("Received a unicast LLDP packet from a different controller, stop processing the packet here."); + if (isStandard) + return Command.STOP; + else return Command.CONTINUE; } - return Command.STOP; } if (remoteSwitch == null) { @@ -653,8 +667,6 @@ public class LinkDiscoveryManager if (this.portLinks.get(lt.getDst()).isEmpty()) this.portLinks.remove(lt.getDst()); - removeLinkFromBroadcastDomain(lt); - this.links.remove(lt); updates.add(new LDUpdate(lt, 0, 0, null, UpdateOperation.REMOVE)); @@ -665,7 +677,9 @@ public class LinkDiscoveryManager lt.getDst().getPort(), 0, 0, // Port states EvAction.LINK_DELETED, reason); - removeLink(lt); + + // remove link from + removeLinkFromStorage(lt); if (log.isTraceEnabled()) { @@ -830,36 +844,43 @@ public class LinkDiscoveryManager lock.writeLock().lock(); try { Iterator<Entry<LinkTuple, LinkInfo>> it = - this.links.entrySet().iterator(); + this.links.entrySet().iterator(); while (it.hasNext()) { Entry<LinkTuple, LinkInfo> entry = it.next(); LinkTuple lt = entry.getKey(); - Long uTime = entry.getValue().getUnicastValidTime(); - Long mTime = entry.getValue().getMulticastValidTime(); + LinkInfo info = entry.getValue(); // Timeout the unicast and multicast LLDP valid times // independently. - if ((uTime != null) && (uTime + this.lldpTimeout < curTime)){ - entry.getValue().setUnicastValidTime(null); - uTime = null; - if (mTime != null) + if ((info.getUnicastValidTime() != null) && + (info.getUnicastValidTime() + this.lldpTimeout < curTime)){ + info.setUnicastValidTime(null); + + if (info.getMulticastValidTime() != null) addLinkToBroadcastDomain(lt); // Note that even if mTime becomes null later on, // the link would be deleted, which would trigger updateClusters(). linkChanged = true; } - if ((mTime != null) && (mTime + this.lldpTimeout < curTime)) { - entry.getValue().setMulticastValidTime(null); - mTime = null; + if ((info.getMulticastValidTime()!= null) && + (info.getMulticastValidTime()+ this.lldpTimeout < curTime)) { + info.setMulticastValidTime(null); // if uTime is not null, then link will remain as openflow // link. If uTime is null, it will be deleted. So, we // don't care about linkChanged flag here. removeLinkFromBroadcastDomain(lt); + linkChanged = true; } - // Add to the erase list only if both the unicast and multicast - // times are null. - if (uTime == null && mTime == null){ + // Add to the erase list only if the unicast + // time is null. + if (info.getUnicastValidTime() == null && + info.getMulticastValidTime() == null){ eraseList.add(entry.getKey()); + } else if (linkChanged) { + updates.add(new LDUpdate(lt, info.getSrcPortState(), + info.getDstPortState(), + getLinkType(lt, info), + UpdateOperation.ADD_OR_UPDATE)); } } @@ -986,7 +1007,6 @@ public class LinkDiscoveryManager * @param linkInfo The LinkInfo to write */ void writeLink(LinkTuple lt, LinkInfo linkInfo) { - if (linkInfo.getUnicastValidTime() != null) { Map<String, Object> rowValues = new HashMap<String, Object>(); String id = getLinkId(lt); rowValues.put(LINK_ID, id); @@ -994,6 +1014,15 @@ public class LinkDiscoveryManager String srcDpid = lt.getSrc().getSw().getStringId(); rowValues.put(LINK_SRC_SWITCH, srcDpid); rowValues.put(LINK_SRC_PORT, lt.getSrc().getPort()); + + LinkType type = (this.getLinkType(lt, linkInfo)); + if (type == LinkType.DIRECT_LINK) + rowValues.put(LINK_TYPE, "internal"); + else if (type == LinkType.MULTIHOP_LINK) + rowValues.put(LINK_TYPE, "external"); + else if (type == LinkType.TUNNEL) + rowValues.put(LINK_TYPE, "tunnel"); + if (linkInfo.linkStpBlocked()) { if (log.isTraceEnabled()) { log.trace("writeLink, link {}, info {}, srcPortState Blocked", @@ -1026,7 +1055,6 @@ public class LinkDiscoveryManager rowValues.put(LINK_DST_PORT_STATE, linkInfo.getDstPortState()); } storageSource.updateRowAsync(LINK_TABLE_NAME, rowValues); - } } public Long readLinkValidTime(LinkTuple lt) { @@ -1101,7 +1129,7 @@ public class LinkDiscoveryManager * Removes a link from storage using an asynchronous call. * @param lt The LinkTuple to delete. */ - void removeLink(LinkTuple lt) { + void removeLinkFromStorage(LinkTuple lt) { String id = getLinkId(lt); storageSource.deleteRowAsync(LINK_TABLE_NAME, id); } diff --git a/src/main/java/net/floodlightcontroller/packet/Ethernet.java b/src/main/java/net/floodlightcontroller/packet/Ethernet.java index dfd4fbaca5e6f414609c9293eb5f0dda379a18dd..c32b9b10cb0eb6c09f70722466341434c37544c3 100644 --- a/src/main/java/net/floodlightcontroller/packet/Ethernet.java +++ b/src/main/java/net/floodlightcontroller/packet/Ethernet.java @@ -35,6 +35,7 @@ public class Ethernet extends BasePacket { public static final short TYPE_IPv4 = 0x0800; public static final short TYPE_LLDP = (short) 0x88cc; public static final short VLAN_UNTAGGED = (short)0xffff; + public static final short TYPE_BSN = (short) 0x01ab; public static Map<Short, Class<? extends IPacket>> etherTypeClassMap; static { @@ -42,6 +43,7 @@ public class Ethernet extends BasePacket { etherTypeClassMap.put(TYPE_ARP, ARP.class); etherTypeClassMap.put(TYPE_IPv4, IPv4.class); etherTypeClassMap.put(TYPE_LLDP, LLDP.class); + etherTypeClassMap.put(TYPE_BSN, LLDP.class); } protected MACAddress destinationMACAddress; diff --git a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java b/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java index 39fe013e726d6f22188485c349b4c5e946ebed9d..2c727a34599c1b6ec3687455349687626e14f17f 100644 --- a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java +++ b/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java @@ -266,10 +266,9 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { assertTrue(topology.portBroadcastDomainLinks.get(lt.getSrc()).contains(lt)); assertTrue(topology.portBroadcastDomainLinks.get(lt.getDst()).contains(lt)); - - // Set the multicastValidTime to be old and see if that also times out. - topology.links.get(lt).setMulticastValidTime(System.currentTimeMillis() - 40000); + info = new LinkInfo(null, System.currentTimeMillis() - 40000, 0, 0); + topology.addOrUpdateLink(lt, info); topology.timeoutLinks(); assertTrue(topology.links.get(lt) == null); assertTrue(topology.portBroadcastDomainLinks.get(lt.getSrc()) == null ||