<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>topology-manager</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-topology</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-topology</artifactId>
+ <version>2013.07.12.2-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-util</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller.md</groupId>
<artifactId>statistics-manager</artifactId>
@Property
IPluginOutTopologyService topologyPublisher;
-
- @Property
- IDiscoveryService discoveryPublisher;
@Property
FlowTopologyDiscoveryService topologyDiscovery;
override onLinkDiscovered(LinkDiscovered notification) {
val update = new TopoEdgeUpdate(notification.toADEdge,Collections.emptySet(),UpdateType.ADDED);
- discoveryPublisher.notifyEdge(notification.toADEdge,UpdateType.ADDED,Collections.emptySet());
topologyPublisher.edgeUpdate(Collections.singletonList(update))
}
augment "/topo:network-topology/topo:topology/topo:node" {
ext:augment-identifier "inventory-node";
- uses inv:node-context-ref;
+ leaf inventory-node-ref {
+ type inv:node-ref;
+ }
}
augment "/topo:network-topology/topo:topology/topo:node/topo:termination-point" {
ext:augment-identifier "inventory-node-connector";
- leaf node-connector {
+ leaf inventory-node-connector-ref {
ext:context-reference "inv:node-connector-context";
type inv:node-connector-ref;
}
<module>inventory-manager</module>
<module>statistics-manager</module>
+ <module>topology-manager</module>
<module>forwardingrules-manager</module>
+ <module>topology-lldp-discovery</module>
<!-- Compability Packages -->
<module>compatibility</module>
public final class TypeSafeDataReader {
- private final DataReader<InstanceIdentifier<?>,DataObject> delegate;
+ private final DataReader<InstanceIdentifier<? extends DataObject>,DataObject> delegate;
}
- public TypeSafeDataReader(DataReader<InstanceIdentifier<?>, DataObject> delegate) {
+ public TypeSafeDataReader(DataReader<InstanceIdentifier<? extends DataObject>, DataObject> delegate) {
this.delegate = delegate;
}
return (D) delegate.readOperationalData(path);
}
- public static TypeSafeDataReader forReader(DataReader<InstanceIdentifier<?>, DataObject> delegate) {
+ public static TypeSafeDataReader forReader(DataReader<InstanceIdentifier<? extends DataObject>, DataObject> delegate) {
return new TypeSafeDataReader(delegate);
}
}
--- /dev/null
+<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>
--- /dev/null
+/*
+ * 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();
+ }
+
+}
--- /dev/null
+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);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
+
+
--- /dev/null
+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);
+ }
+ }
+ }
+
+ }
+
+ }
+}
+
--- /dev/null
+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;
+ }
+}
</dependency>
<dependency>
<groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-topology-view</artifactId>
+ <artifactId>model-topology</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Bundle-Activator>org.opendaylight.controller.md.inventory.manager.InventoryActivator</Bundle-Activator>
- <Private-Package>org.opendaylight.controller.md.inventory.manager</Private-Package>
+ <Bundle-Activator>org.opendaylight.md.controller.topology.manager.FlowCapableTopologyProvider</Bundle-Activator>
+ <Private-Package>org.opendaylight.md.controller.topology.manager</Private-Package>
</instructions>
</configuration>
</plugin>
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnector
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TpId
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NodeId
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.NodeBuilder
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.link.attributes.SourceBuilder
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.link.attributes.DestinationBuilder
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.LinkBuilder
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.LinkKey
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.LinkId
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNodeBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNode
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNodeConnector
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNodeConnectorBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
class FlowCapableNodeMapping {
(ref?.value?.path?.get(2) as IdentifiableItem<NodeConnector,NodeConnectorKey>).key
}
- static def TerminationPoint toTerminationPoint(NodeConnectorUpdated updated) {
- val it = new TerminationPointBuilder
- key = new TerminationPointKey(new TpId(updated.id));
- return it.build()
- }
-
static def NodeId toToplogyNodeId(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId nodeId) {
return new NodeId(nodeId);
}
static def toTerminationPointId(NodeConnectorId id) {
return new TpId(id);
}
+
+ static def toTopologyNode(NodeId nodeId,NodeRef invNodeRef) {
+ val nb = new NodeBuilder();
+ nb.setNodeId(nodeId)
+ val inb = new InventoryNodeBuilder
+ inb.setInventoryNodeRef(invNodeRef)
+ nb.addAugmentation(InventoryNode,inb.build)
+ return nb.build();
+ }
+
+ static def toTerminationPoint(TpId id, NodeConnectorRef invNodeConnectorRef) {
+ val tpb = new TerminationPointBuilder
+ tpb.setTpId(id);
+ val incb = new InventoryNodeConnectorBuilder
+ incb.setInventoryNodeConnectorRef(invNodeConnectorRef)
+ tpb.addAugmentation(InventoryNodeConnector,incb.build())
+ return tpb.build();
+ }
+
+ static def toTopologyLink(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.Link link) {
+ val sb = new SourceBuilder();
+ sb.setSourceNode(link.source.nodeKey.id.toToplogyNodeId)
+ sb.setSourceTp(link.source.nodeConnectorKey.id.toTerminationPointId)
+ val db = new DestinationBuilder();
+ db.setDestNode(link.destination.nodeKey.id.toToplogyNodeId)
+ db.setDestTp(link.destination.nodeConnectorKey.id.toTerminationPointId)
+ val lb = new LinkBuilder();
+ lb.setSource(sb.build())
+ lb.setDestination(db.build());
+ lb.setLinkId(new LinkId(lb.source.sourceTp.value))
+ return lb.build();
+ }
}
package org.opendaylight.md.controller.topology.manager
+import com.google.common.collect.FluentIterable
+import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryListener
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.LinkOverutilized
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkRemoved
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkUtilizationNormal
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NetworkTopology
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NodeId
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TopologyId
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TpId
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.Topology
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.TopologyBuilder
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.TopologyKey
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NetworkTopology
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Link
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Node
-
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.NodeKey
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NodeId
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPointKey
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TpId
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+
import static extension org.opendaylight.md.controller.topology.manager.FlowCapableNodeMapping.*
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
-import com.google.common.collect.FluentIterable
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Link
class FlowCapableTopologyExporter implements //
FlowTopologyDiscoveryListener, //
OpendaylightInventoryListener //
{
- var TopologyKey topology;
+ var TopologyKey topology = new TopologyKey(new TopologyId("flow:1"));
@Property
var DataProviderService dataService;
+
+ def start() {
+ val tb = new TopologyBuilder();
+ tb.setKey(topology);
+ val path = InstanceIdentifier.builder(NetworkTopology).child(Topology,topology).toInstance;
+ val top = tb.build();
+ val it = dataService.beginTransaction
+ putOperationalData(path,top);
+ commit()
+ }
override onNodeRemoved(NodeRemoved notification) {
- val invNodeKey = notification.nodeRef.nodeKey
- val tpNodeId = invNodeKey.id.toToplogyNodeId()
- val tpNodeInstance = notification.nodeRef.toNodeIdentifier()
+ val nodeId = notification.nodeRef.nodeKey.id.toToplogyNodeId()
+ val nodeInstance = notification.nodeRef.toNodeIdentifier()
val it = dataService.beginTransaction
- removeRuntimeData(tpNodeInstance);
- removeAffectedLinks(tpNodeId)
+ removeOperationalData(nodeInstance);
+ removeAffectedLinks(it,nodeId)
commit()
}
override onNodeUpdated(NodeUpdated notification) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ val fcnu = notification.getAugmentation(FlowCapableNodeUpdated)
+ if(fcnu != null) {
+ val node = notification.id.toToplogyNodeId.toTopologyNode(notification.nodeRef)
+ val path = notification.id.toToplogyNodeId.nodePath;
+ val it = dataService.beginTransaction
+ putOperationalData(path, node);
+ commit()
+ }
}
override onNodeConnectorRemoved(NodeConnectorRemoved notification) {
- val tpRef = notification.nodeConnectorRef.toTerminationPointIdentifier();
+ val tpInstance = notification.nodeConnectorRef.toTerminationPointIdentifier;
+ val tpId = notification.nodeConnectorRef.nodeConnectorKey.id.toTerminationPointId;
val it = dataService.beginTransaction
- removeRuntimeData(tpRef);
+ removeOperationalData(tpInstance);
+ removeAffectedLinks(it,tpId)
commit()
}
override onNodeConnectorUpdated(NodeConnectorUpdated notification) {
- val nodeId = notification.nodeConnectorRef.nodeKey.id.toToplogyNodeId();
- val TerminationPoint point = notification.toTerminationPoint();
- val path = tpPath(nodeId, point.key.tpId);
-
- val it = dataService.beginTransaction
- putRuntimeData(path, point);
- commit()
+ val fcncu = notification.getAugmentation(FlowCapableNodeConnectorUpdated)
+ if(fcncu != null) {
+ val nodeId = notification.nodeConnectorRef.nodeKey.id.toToplogyNodeId;
+ val TerminationPoint point = notification.id.toTerminationPointId.toTerminationPoint(notification.nodeConnectorRef);
+ val path = tpPath(nodeId, point.key.tpId);
+
+ val it = dataService.beginTransaction
+ putOperationalData(path, point);
+ commit()
+ }
}
override onLinkDiscovered(LinkDiscovered notification) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ val link = notification.toTopologyLink;
+ val path = link.linkPath;
+ val it = dataService.beginTransaction
+ putOperationalData(path, link);
+ commit()
}
override onLinkOverutilized(LinkOverutilized notification) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ // NOOP
}
override onLinkRemoved(LinkRemoved notification) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
-
+ val path = notification.toTopologyLink.linkPath
+ val it = dataService.beginTransaction
+ removeOperationalData(path);
+ commit()
}
override onLinkUtilizationNormal(LinkUtilizationNormal notification) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ // NOOP
}
def InstanceIdentifier<Node> toNodeIdentifier(NodeRef ref) {
val invNodeKey = ref.nodeKey
val nodeKey = new NodeKey(invNodeKey.id.toToplogyNodeId);
- return InstanceIdentifier.builder.node(NetworkTopology).child(Topology, topology).child(Node, nodeKey).
+ return InstanceIdentifier.builder(NetworkTopology).child(Topology, topology).child(Node, nodeKey).
toInstance;
}
private def void removeAffectedLinks(DataModificationTransaction transaction, NodeId id) {
val reader = TypeSafeDataReader.forReader(transaction)
- val topologyPath = InstanceIdentifier.builder().node(NetworkTopology).child(Topology, topology).toInstance;
+ val topologyPath = InstanceIdentifier.builder(NetworkTopology).child(Topology, topology).toInstance;
val topologyData = reader.readOperationalData(topologyPath);
if (topologyData === null) {
return;
val affectedLinkInstances = FluentIterable.from(topologyData.link).filter[
source.sourceNode == id || destination.destNode == id].transform [
//
- InstanceIdentifier.builder().node(NetworkTopology).child(Topology, topology).child(Link, key).toInstance
+ InstanceIdentifier.builder(NetworkTopology).child(Topology, topology).child(Link, key).toInstance
//
]
for(affectedLink : affectedLinkInstances) {
- transaction.removeRuntimeData(affectedLink);
+ transaction.removeOperationalData(affectedLink);
}
}
+ private def void removeAffectedLinks(DataModificationTransaction transaction, TpId id) {
+ val reader = TypeSafeDataReader.forReader(transaction)
+ val topologyPath = InstanceIdentifier.builder(NetworkTopology).child(Topology, topology).toInstance;
+ val topologyData = reader.readOperationalData(topologyPath);
+ if (topologyData === null) {
+ return;
+ }
+ val affectedLinkInstances = FluentIterable.from(topologyData.link).filter[
+ source.sourceTp == id || destination.destTp == id].transform [
+ //
+ InstanceIdentifier.builder(NetworkTopology).child(Topology, topology).child(Link, key).toInstance
+ //
+ ]
+ for(affectedLink : affectedLinkInstances) {
+ transaction.removeOperationalData(affectedLink);
+ }
+ }
+
+ private def InstanceIdentifier<Node> nodePath(NodeId nodeId) {
+ val nodeKey = new NodeKey(nodeId);
+ return InstanceIdentifier.builder(NetworkTopology)
+ .child(Topology, topology)
+ .child(Node, nodeKey)
+ .toInstance;
+ }
+
private def InstanceIdentifier<TerminationPoint> tpPath(NodeId nodeId, TpId tpId) {
val nodeKey = new NodeKey(nodeId);
val tpKey = new TerminationPointKey(tpId)
- return InstanceIdentifier.builder.node(NetworkTopology).child(Topology, topology).child(Node, nodeKey).
+ return InstanceIdentifier.builder(NetworkTopology).child(Topology, topology).child(Node, nodeKey).
child(TerminationPoint, tpKey).toInstance;
}
+
+ private def InstanceIdentifier<Link> linkPath(Link link) {
+ val linkInstanceId = InstanceIdentifier.builder(NetworkTopology)
+ .child(Topology, topology)
+ .child(Link, link.key)
+ .toInstance;
+ return linkInstanceId;
+ }
}
--- /dev/null
+/*
+ * 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.manager
+
+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
+import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
+
+class FlowCapableTopologyProvider extends AbstractBindingAwareProvider implements AutoCloseable {
+
+
+
+ static val LOG = LoggerFactory.getLogger(FlowCapableTopologyProvider);
+
+ @Property
+ DataProviderService dataService;
+
+ @Property
+ NotificationProviderService notificationService;
+
+ val FlowCapableTopologyExporter exporter = new FlowCapableTopologyExporter();
+
+ Registration<NotificationListener> listenerRegistration
+
+ override close() {
+ LOG.info("FlowCapableTopologyProvider stopped.");
+ listenerRegistration?.close();
+ }
+
+ override onSessionInitiated(ProviderContext session) {
+ dataService = session.getSALService(DataProviderService)
+ notificationService = session.getSALService(NotificationProviderService)
+ exporter.setDataService(dataService);
+ exporter.start();
+ listenerRegistration = notificationService.registerNotificationListener(exporter);
+ }
+
+}
+
+