From 9a19d9b2951fb82676f74a24c7a36902acc7627f Mon Sep 17 00:00:00 2001 From: Ed Warnicke Date: Wed, 25 Dec 2013 14:41:35 -0800 Subject: [PATCH] Added topology-lldp-discovery module Change-Id: I512af91128aeeed096b80690c4f1fc181d585457 Signed-off-by: Ed Warnicke --- .../distribution/opendaylight/pom.xml | 5 + opendaylight/md-sal/pom.xml | 1 + .../md-sal/topology-lldp-discovery/pom.xml | 129 ++++++++++++++++++ .../topology/lldp/LLDPActivator.xtend | 30 ++++ .../topology/lldp/LLDPDiscoveryListener.java | 34 +++++ .../topology/lldp/LLDPDiscoveryProvider.xtend | 46 +++++++ .../topology/lldp/LLDPLinkAger.java | 65 +++++++++ .../lldp/utils/LLDPDiscoveryUtils.java | 76 +++++++++++ 8 files changed, 386 insertions(+) create mode 100644 opendaylight/md-sal/topology-lldp-discovery/pom.xml create mode 100644 opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPActivator.xtend create mode 100644 opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPDiscoveryListener.java create mode 100644 opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPDiscoveryProvider.xtend create mode 100644 opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPLinkAger.java create mode 100644 opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/utils/LLDPDiscoveryUtils.java diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index b0f7ad89a4..4feeff873b 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -134,6 +134,11 @@ forwardingrules-manager ${mdsal.version} + + org.opendaylight.controller.md + topology-lldp-discovery + ${mdsal.version} + org.opendaylight.controller.md statistics-manager diff --git a/opendaylight/md-sal/pom.xml b/opendaylight/md-sal/pom.xml index 0d6523bc0b..1bd0603770 100644 --- a/opendaylight/md-sal/pom.xml +++ b/opendaylight/md-sal/pom.xml @@ -51,6 +51,7 @@ inventory-manager statistics-manager forwardingrules-manager + topology-lldp-discovery compatibility diff --git a/opendaylight/md-sal/topology-lldp-discovery/pom.xml b/opendaylight/md-sal/topology-lldp-discovery/pom.xml new file mode 100644 index 0000000000..ed94c8dfb7 --- /dev/null +++ b/opendaylight/md-sal/topology-lldp-discovery/pom.xml @@ -0,0 +1,129 @@ + + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.0-SNAPSHOT + ../ + + org.opendaylight.controller.md + topology-lldp-discovery + bundle + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + + + 14.0.1 + 2.4.3 + 2.4.0 + 2.5 + + + + com.google.guava + guava + + + org.opendaylight.controller + sal-binding-api + 1.0-SNAPSHOT + + + org.opendaylight.controller.model + model-flow-service + 1.0-SNAPSHOT + + + org.opendaylight.controller.model + model-flow-base + 1.0-SNAPSHOT + + + org.opendaylight.controller.model + model-flow-management + 1.0-SNAPSHOT + + + org.opendaylight.controller.model + model-inventory + 1.0-SNAPSHOT + + + org.eclipse.xtend + org.eclipse.xtend.lib + + + equinoxSDK381 + org.eclipse.osgi + 3.8.1.v20120830-144521 + + + commons-lang + commons-lang + 2.6 + + + com.google.guava + guava + + + commons-codec + commons-codec + 1.8 + + + org.opendaylight.controller + sal + 0.7.0-SNAPSHOT + + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + org.opendaylight.md.controller.topology.lldp.LLDPActivator + org.opendaylight.md.controller.topology.lldp.utils + commons-lang> + ${project.groupId}.${project.artifactId} + + ${project.basedir}/META-INF + + + + org.eclipse.xtend + xtend-maven-plugin + + + + compile + + + ${basedir}/src/main/xtend-gen + + + + + + maven-clean-plugin + + + + ${basedir}/src/main/xtend-gen + + ** + + + + + + + + diff --git a/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPActivator.xtend b/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPActivator.xtend new file mode 100644 index 0000000000..674e919cd7 --- /dev/null +++ b/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPActivator.xtend @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.md.controller.topology.lldp + +import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext +import org.opendaylight.controller.sal.binding.api.NotificationProviderService +import org.opendaylight.controller.sal.binding.api.data.DataProviderService +import org.osgi.framework.BundleContext + +class LLDPActivator extends AbstractBindingAwareProvider { + + static var LLDPDiscoveryProvider provider = new LLDPDiscoveryProvider(); + + override onSessionInitiated(ProviderContext session) { + provider.dataService = session.getSALService(DataProviderService) + provider.notificationService = session.getSALService(NotificationProviderService) + provider.start(); + } + + override protected stopImpl(BundleContext context) { + provider.close(); + } + +} diff --git a/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPDiscoveryListener.java b/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPDiscoveryListener.java new file mode 100644 index 0000000000..095d12e6ef --- /dev/null +++ b/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPDiscoveryListener.java @@ -0,0 +1,34 @@ +package org.opendaylight.md.controller.topology.lldp; + +import org.opendaylight.md.controller.topology.lldp.utils.LLDPDiscoveryUtils; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkDiscovered; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkDiscoveredBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class LLDPDiscoveryListener implements PacketProcessingListener { + static Logger LOG = LoggerFactory.getLogger(LLDPDiscoveryListener.class); + + private LLDPDiscoveryProvider manager; + + LLDPDiscoveryListener(LLDPDiscoveryProvider manager) { + this.manager = manager; + } + + public void onPacketReceived(PacketReceived lldp) { + NodeConnectorRef src = LLDPDiscoveryUtils.lldpToNodeConnectorRef(lldp.getPayload()); + if(src != null) { + LinkDiscoveredBuilder ldb = new LinkDiscoveredBuilder(); + ldb.setDestination(lldp.getIngress()); + ldb.setSource(new NodeConnectorRef(src)); + LinkDiscovered ld = ldb.build(); + + manager.getNotificationService().publish(ld); + LLDPLinkAger.getInstance().put(ld); + } + } + +} diff --git a/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPDiscoveryProvider.xtend b/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPDiscoveryProvider.xtend new file mode 100644 index 0000000000..fc724ac680 --- /dev/null +++ b/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPDiscoveryProvider.xtend @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.md.controller.topology.lldp + +import org.opendaylight.controller.sal.binding.api.NotificationProviderService +import org.opendaylight.controller.sal.binding.api.data.DataProviderService +import org.opendaylight.yangtools.concepts.Registration +import org.opendaylight.yangtools.yang.binding.NotificationListener +import org.slf4j.LoggerFactory + +class LLDPDiscoveryProvider implements AutoCloseable { + + + static val LOG = LoggerFactory.getLogger(LLDPDiscoveryProvider); + + @Property + DataProviderService dataService; + + @Property + NotificationProviderService notificationService; + + val LLDPDiscoveryListener commiter = new LLDPDiscoveryListener(this); + + Registration listenerRegistration + + def void start() { + listenerRegistration = notificationService.registerNotificationListener(commiter); + LLDPLinkAger.instance.manager = this; + LOG.info("LLDPDiscoveryListener Started."); + + } + + override close() { + LOG.info("LLDPDiscoveryListener stopped."); + listenerRegistration?.close(); + LLDPLinkAger.instance.close(); + } + +} + + diff --git a/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPLinkAger.java b/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPLinkAger.java new file mode 100644 index 0000000000..171783b0a2 --- /dev/null +++ b/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPLinkAger.java @@ -0,0 +1,65 @@ +package org.opendaylight.md.controller.topology.lldp; + +import java.util.Date; +import java.util.Map; +import java.util.Timer; +import java.util.Map.Entry; +import java.util.TimerTask; +import java.util.concurrent.ConcurrentHashMap; + +import org.opendaylight.md.controller.topology.lldp.utils.LLDPDiscoveryUtils; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkDiscovered; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkRemovedBuilder; + + +public class LLDPLinkAger { + private static final LLDPLinkAger instance = new LLDPLinkAger(); + private Map linkToDate = new ConcurrentHashMap(); + private LLDPDiscoveryProvider manager; + private Timer timer = new Timer(); + + public LLDPDiscoveryProvider getManager() { + return manager; + } + public void setManager(LLDPDiscoveryProvider manager) { + this.manager = manager; + } + private LLDPLinkAger() { + timer.schedule(new LLDPAgingTask(), 0,LLDPDiscoveryUtils.LLDP_INTERVAL); + } + public static LLDPLinkAger getInstance() { + return instance; + } + + public void put(LinkDiscovered link) { + Date expires = new Date(); + expires.setTime(expires.getTime() + LLDPDiscoveryUtils.LLDP_EXPIRATION_TIME); + linkToDate.put(link, expires); + } + + public void close() { + timer.cancel(); + } + + private class LLDPAgingTask extends TimerTask { + + @Override + public void run() { + for (Entry entry : linkToDate.entrySet()) { + LinkDiscovered link = entry.getKey(); + Date expires = entry.getValue(); + Date now = new Date(); + if(now.after(expires)) { + if(getInstance().getManager() != null) { + LinkRemovedBuilder lrb = new LinkRemovedBuilder(link); + getInstance().getManager().getNotificationService().publish(lrb.build()); + linkToDate.remove(link); + } + } + } + + } + + } +} + diff --git a/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/utils/LLDPDiscoveryUtils.java b/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/utils/LLDPDiscoveryUtils.java new file mode 100644 index 0000000000..d5dee32e40 --- /dev/null +++ b/opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/utils/LLDPDiscoveryUtils.java @@ -0,0 +1,76 @@ +package org.opendaylight.md.controller.topology.lldp.utils; + +import java.nio.charset.Charset; +import java.util.List; + +import org.opendaylight.controller.sal.packet.Ethernet; +import org.opendaylight.controller.sal.packet.LLDP; +import org.opendaylight.controller.sal.packet.LLDPTLV; +import org.opendaylight.controller.sal.utils.NetUtils; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LLDPDiscoveryUtils { + static Logger LOG = LoggerFactory.getLogger(LLDPDiscoveryUtils.class); + + public static final Long LLDP_INTERVAL = (long) (1000*5); // Send LLDP every five seconds + public static final Long LLDP_EXPIRATION_TIME = LLDP_INTERVAL*3; // Let up to three intervals pass before we decide we are expired. + + public static String macToString(byte[] mac) { + StringBuilder b = new StringBuilder(); + for (int i = 0; i < mac.length; i++) { + b.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? ":" : "")); + } + + return b.toString(); + } + + public static NodeConnectorRef lldpToNodeConnectorRef(byte[] payload) { + Ethernet ethPkt = new Ethernet(); + try { + ethPkt.deserialize(payload, 0,payload.length * NetUtils.NumBitsInAByte); + } catch (Exception e) { + LOG.warn("Failed to decode LLDP packet {}", e); + } + + if (ethPkt.getPayload() instanceof LLDP) { + LLDP lldp = (LLDP) ethPkt.getPayload(); + + try { + List optionalTLVList = lldp.getOptionalTLVList(); + if (optionalTLVList == null) { + return null; + } + NodeId srcNodeId = null; + NodeConnectorId srcNodeConnectorId = null; + for (LLDPTLV lldptlv : lldp.getOptionalTLVList()) { + if (lldptlv.getType() == LLDPTLV.TLVType.Custom.getValue()) { + srcNodeConnectorId = new NodeConnectorId(LLDPTLV.getCustomString(lldptlv.getValue(), lldptlv.getLength())); + } + if (lldptlv.getType() == LLDPTLV.TLVType.SystemName.getValue()) { + String srcNodeIdString = new String(lldptlv.getValue(),Charset.defaultCharset()); + srcNodeId = new NodeId(srcNodeIdString); + } + } + + InstanceIdentifier srcInstanceId = InstanceIdentifier.builder(Nodes.class) + .child(Node.class,new NodeKey(srcNodeId)) + .child(NodeConnector.class, new NodeConnectorKey(srcNodeConnectorId)) + .toInstance(); + return new NodeConnectorRef(srcInstanceId); + } catch (Exception e) { + LOG.warn("Caught exception ", e); + } + } + return null; + } +} -- 2.36.6