Added topology-lldp-discovery module 26/3926/2
authorEd Warnicke <eaw@cisco.com>
Wed, 25 Dec 2013 22:41:35 +0000 (14:41 -0800)
committerEd Warnicke <eaw@cisco.com>
Mon, 30 Dec 2013 22:43:50 +0000 (14:43 -0800)
Change-Id: I512af91128aeeed096b80690c4f1fc181d585457
Signed-off-by: Ed Warnicke <eaw@cisco.com>
opendaylight/distribution/opendaylight/pom.xml
opendaylight/md-sal/pom.xml
opendaylight/md-sal/topology-lldp-discovery/pom.xml [new file with mode: 0644]
opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPActivator.xtend [new file with mode: 0644]
opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPDiscoveryListener.java [new file with mode: 0644]
opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPDiscoveryProvider.xtend [new file with mode: 0644]
opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/LLDPLinkAger.java [new file with mode: 0644]
opendaylight/md-sal/topology-lldp-discovery/src/main/java/org/opendaylight/md/controller/topology/lldp/utils/LLDPDiscoveryUtils.java [new file with mode: 0644]

index b0f7ad89a4b81694c889c52e51f5cc00947c8c4f..4feeff873b63a9c13da71ba4f5ff45d6b03b8f7d 100644 (file)
           <artifactId>forwardingrules-manager</artifactId>
           <version>${mdsal.version}</version>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller.md</groupId>
+          <artifactId>topology-lldp-discovery</artifactId>
+          <version>${mdsal.version}</version>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller.md</groupId>
           <artifactId>statistics-manager</artifactId>
index 0d6523bc0bbb38dd059e9c978be147cab7a4b7e8..1bd06037702bd757f7443445ed379e93b3b2abab 100644 (file)
@@ -51,6 +51,7 @@
         <module>inventory-manager</module>
         <module>statistics-manager</module>
         <module>forwardingrules-manager</module>
+        <module>topology-lldp-discovery</module>
 
         <!-- Compability Packages -->
         <module>compatibility</module>
diff --git a/opendaylight/md-sal/topology-lldp-discovery/pom.xml b/opendaylight/md-sal/topology-lldp-discovery/pom.xml
new file mode 100644 (file)
index 0000000..ed94c8d
--- /dev/null
@@ -0,0 +1,129 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-parent</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+    <groupId>org.opendaylight.controller.md</groupId>
+    <artifactId>topology-lldp-discovery</artifactId>
+    <packaging>bundle</packaging>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    </scm>
+    <properties>
+        <guava.version>14.0.1</guava.version>
+        <xtend.version>2.4.3</xtend.version>
+        <bundle.plugin.version>2.4.0</bundle.plugin.version>
+        <maven.clean.plugin.version>2.5</maven.clean.plugin.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-service</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>    
+           <dependency>
+             <groupId>org.opendaylight.controller.model</groupId>
+             <artifactId>model-flow-base</artifactId>
+             <version>1.0-SNAPSHOT</version>
+           </dependency>
+          <dependency>
+             <groupId>org.opendaylight.controller.model</groupId>
+             <artifactId>model-flow-management</artifactId>
+             <version>1.0-SNAPSHOT</version>
+           </dependency>    
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-inventory</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+        </dependency>
+         <dependency>
+               <groupId>equinoxSDK381</groupId>
+               <artifactId>org.eclipse.osgi</artifactId>
+               <version>3.8.1.v20120830-144521</version>
+             </dependency>
+             <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.6</version>
+          </dependency>
+          <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+          </dependency>
+          <dependency>
+                   <groupId>commons-codec</groupId>
+                   <artifactId>commons-codec</artifactId>
+                   <version>1.8</version>
+                 </dependency>
+    <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal</artifactId>
+            <version>0.7.0-SNAPSHOT</version>
+        </dependency>
+             
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>org.opendaylight.md.controller.topology.lldp.LLDPActivator</Bundle-Activator>
+                        <Export-Package>org.opendaylight.md.controller.topology.lldp.utils</Export-Package>
+                        <Embed-Dependency>commons-lang</Embed-Dependency>>
+                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                    </instructions>
+                    <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+                <executions>
+                  <execution>
+                      <goals>
+                          <goal>compile</goal>
+                      </goals>
+                      <configuration>
+                          <outputDirectory>${basedir}/src/main/xtend-gen</outputDirectory>
+                      </configuration>
+                  </execution>
+              </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>${basedir}/src/main/xtend-gen</directory>
+                            <includes>
+                                <include>**</include>
+                            </includes>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
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 (file)
index 0000000..674e919
--- /dev/null
@@ -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 (file)
index 0000000..095d12e
--- /dev/null
@@ -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 (file)
index 0000000..fc724ac
--- /dev/null
@@ -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<NotificationListener> 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 (file)
index 0000000..171783b
--- /dev/null
@@ -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<LinkDiscovered,Date> linkToDate = new ConcurrentHashMap<LinkDiscovered,Date>();
+    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<LinkDiscovered,Date> 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 (file)
index 0000000..d5dee32
--- /dev/null
@@ -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<LLDPTLV> 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<NodeConnector> 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;
+    }
+}