+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<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.samples</groupId>
- <artifactId>sal-samples</artifactId>
- <version>1.2.0-SNAPSHOT</version>
- <relativePath>../..</relativePath>
- </parent>
- <groupId>org.opendaylight.controller.samples.l2switch.md</groupId>
- <artifactId>l2switch-impl</artifactId>
- <packaging>bundle</packaging>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-service</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-inventory</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-topology</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.samples.l2switch.md</groupId>
- <artifactId>l2switch-model</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.thirdparty</groupId>
- <artifactId>net.sf.jung2</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-binding</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-common</artifactId>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
-
- <instructions>
- <Bundle-Activator>org.opendaylight.controller.sample.l2switch.md.L2SwitchProvider</Bundle-Activator>
- </instructions>
- <manifestLocation>${project.build.directory}/META-INF</manifestLocation>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
+++ /dev/null
-/*
- * Copyright (c) 2014 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.controller.sample.l2switch.md;
-
-import org.opendaylight.controller.sample.l2switch.md.addresstracker.AddressTracker;
-import org.opendaylight.controller.sample.l2switch.md.flow.FlowWriterService;
-import org.opendaylight.controller.sample.l2switch.md.flow.FlowWriterServiceImpl;
-import org.opendaylight.controller.sample.l2switch.md.inventory.InventoryService;
-import org.opendaylight.controller.sample.l2switch.md.packet.PacketHandler;
-import org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphDijkstra;
-import org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService;
-import org.opendaylight.controller.sample.l2switch.md.topology.TopologyLinkDataChangeHandler;
-import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareConsumer;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.binding.api.NotificationService;
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.NotificationListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * L2SwitchProvider serves as the Activator for our L2Switch OSGI bundle.
- */
-public class L2SwitchProvider extends AbstractBindingAwareConsumer
- implements AutoCloseable {
-
- private final static Logger _logger = LoggerFactory.getLogger(L2SwitchProvider.class);
-
- private ListenerRegistration<NotificationListener> listenerRegistration;
- private AddressTracker addressTracker;
- private TopologyLinkDataChangeHandler topologyLinkDataChangeHandler;
-
-
- /**
- * Setup the L2Switch.
- * @param consumerContext The context of the L2Switch.
- */
- @Override
- public void onSessionInitialized(BindingAwareBroker.ConsumerContext consumerContext) {
- DataBrokerService dataService = consumerContext.<DataBrokerService>getSALService(DataBrokerService.class);
- addressTracker = new AddressTracker(dataService);
-
- NetworkGraphService networkGraphService = new NetworkGraphDijkstra();
- FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataService, networkGraphService);
-
- NotificationService notificationService =
- consumerContext.<NotificationService>getSALService(NotificationService.class);
- PacketProcessingService packetProcessingService =
- consumerContext.<PacketProcessingService>getRpcService(PacketProcessingService.class);
- PacketHandler packetHandler = new PacketHandler();
- packetHandler.setAddressTracker(addressTracker);
- packetHandler.setFlowWriterService(flowWriterService);
- packetHandler.setPacketProcessingService(packetProcessingService);
- packetHandler.setInventoryService(new InventoryService(dataService));
-
- this.listenerRegistration = notificationService.registerNotificationListener(packetHandler);
- this.topologyLinkDataChangeHandler = new TopologyLinkDataChangeHandler(dataService, networkGraphService);
- topologyLinkDataChangeHandler.registerAsDataChangeListener();
- }
-
- /**
- * Cleanup the L2Switch.
- * @throws Exception occurs when the NotificationListener is closed
- */
- @Override
- public void close() throws Exception {
- if (listenerRegistration != null)
- listenerRegistration.close();
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.controller.sample.l2switch.md.addresstracker;
-
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.address.tracker.rev140402.L2Addresses;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.address.tracker.rev140402.l2.addresses.L2Address;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.address.tracker.rev140402.l2.addresses.L2AddressBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.address.tracker.rev140402.l2.addresses.L2AddressKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.Future;
-
-/**
- * AddressTracker manages the MD-SAL data tree for L2Address (mac, node connector pairings) information.
- */
-public class AddressTracker {
-
- private final static Logger _logger = LoggerFactory.getLogger(AddressTracker.class);
- private DataBrokerService dataService;
-
- /**
- * Construct an AddressTracker with the specified inputs
- * @param dataService The DataBrokerService for the AddressTracker
- */
- public AddressTracker(DataBrokerService dataService) {
- this.dataService = dataService;
- }
-
- /**
- * Get all the L2 Addresses in the MD-SAL data tree
- * @return All the L2 Addresses in the MD-SAL data tree
- */
- public L2Addresses getAddresses() {
- return (L2Addresses)dataService.readOperationalData(InstanceIdentifier.<L2Addresses>builder(L2Addresses.class).toInstance());
- }
-
- /**
- * Get a specific L2 Address in the MD-SAL data tree
- * @param macAddress A MacAddress associated with an L2 Address object
- * @return The L2 Address corresponding to the specified macAddress
- */
- public L2Address getAddress(MacAddress macAddress) {
- return (L2Address) dataService.readOperationalData(createPath(macAddress));
- }
-
- /**
- * Add L2 Address into the MD-SAL data tree
- * @param macAddress The MacAddress of the new L2Address object
- * @param nodeConnectorRef The NodeConnectorRef of the new L2Address object
- * @return Future containing the result of the add operation
- */
- public Future<RpcResult<TransactionStatus>> addAddress(MacAddress macAddress, NodeConnectorRef nodeConnectorRef) {
- if(macAddress == null || nodeConnectorRef == null) {
- return null;
- }
-
- // Create L2Address
- final L2AddressBuilder builder = new L2AddressBuilder();
- builder.setKey(new L2AddressKey(macAddress))
- .setMac(macAddress)
- .setNodeConnectorRef(nodeConnectorRef);
-
- // Add L2Address to MD-SAL data tree
- final DataModificationTransaction it = dataService.beginTransaction();
- it.putOperationalData(createPath(macAddress), builder.build());
- return it.commit();
- }
-
- /**
- * Remove L2Address from the MD-SAL data tree
- * @param macAddress The MacAddress of an L2Address object
- * @return Future containing the result of the remove operation
- */
- public Future<RpcResult<TransactionStatus>> removeHost(MacAddress macAddress) {
- final DataModificationTransaction it = dataService.beginTransaction();
- it.removeOperationalData(createPath(macAddress));
- return it.commit();
- }
-
- /**
- * Create InstanceIdentifier path for an L2Address in the MD-SAL data tree
- * @param macAddress The MacAddress of an L2Address object
- * @return InstanceIdentifier of the L2Address corresponding to the specified macAddress
- */
- private InstanceIdentifier<L2Address> createPath(MacAddress macAddress) {
- return InstanceIdentifier.<L2Addresses>builder(L2Addresses.class)
- .<L2Address, L2AddressKey>child(L2Address.class, new L2AddressKey(macAddress)).toInstance();
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (c) 2014 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.controller.sample.l2switch.md.flow;
-
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-
-/**
- * Service that adds packet forwarding flows to configuration data store.
- */
-public interface FlowWriterService {
-
- /**
- * Writes a flow that forwards packets to destPort if destination mac in packet is destMac and
- * source Mac in packet is sourceMac. If sourceMac is null then flow would not set any source mac,
- * resulting in all packets with destMac being forwarded to destPort.
- *
- * @param sourceMac
- * @param destMac
- * @param destNodeConnectorRef
- */
- public void addMacToMacFlow(MacAddress sourceMac, MacAddress destMac, NodeConnectorRef destNodeConnectorRef);
-
- /**
- * Writes mac-to-mac flow on all ports that are in the path between given source and destination ports.
- * It uses path provided by NetworkGraphService{@link org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService} to find a links{@link org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link}
- * between given ports. And then writes appropriate flow on each port that is covered in that path.
- *
- * @param sourceMac
- * @param sourceNodeConnectorRef
- * @param destMac
- * @param destNodeConnectorRef
- */
- public void addMacToMacFlowsUsingShortestPath(MacAddress sourceMac, NodeConnectorRef sourceNodeConnectorRef, MacAddress destMac, NodeConnectorRef destNodeConnectorRef);
-
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.controller.sample.l2switch.md.flow;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-
-import org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService;
-import org.opendaylight.controller.sample.l2switch.md.util.InstanceIdentifierUtils;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-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.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.math.BigInteger;
-import java.util.List;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Implementation of FlowWriterService{@link org.opendaylight.controller.sample.l2switch.md.flow.FlowWriterService},
- * that builds required flow and writes to configuration data store using provided DataBrokerService
- * {@link org.opendaylight.controller.sal.binding.api.data.DataBrokerService}
- */
-public class FlowWriterServiceImpl implements FlowWriterService {
- private static final Logger _logger = LoggerFactory.getLogger(FlowWriterServiceImpl.class);
- private final DataBrokerService dataBrokerService;
- private final NetworkGraphService networkGraphService;
- private AtomicLong flowIdInc = new AtomicLong();
- private AtomicLong flowCookieInc = new AtomicLong(0x2a00000000000000L);
-
-
- public FlowWriterServiceImpl(DataBrokerService dataBrokerService, NetworkGraphService networkGraphService) {
- Preconditions.checkNotNull(dataBrokerService, "dataBrokerService should not be null.");
- Preconditions.checkNotNull(networkGraphService, "networkGraphService should not be null.");
- this.dataBrokerService = dataBrokerService;
- this.networkGraphService = networkGraphService;
- }
-
- /**
- * Writes a flow that forwards packets to destPort if destination mac in packet is destMac and
- * source Mac in packet is sourceMac. If sourceMac is null then flow would not set any source mac,
- * resulting in all packets with destMac being forwarded to destPort.
- *
- * @param sourceMac
- * @param destMac
- * @param destNodeConnectorRef
- */
- @Override
- public void addMacToMacFlow(MacAddress sourceMac, MacAddress destMac, NodeConnectorRef destNodeConnectorRef) {
-
- Preconditions.checkNotNull(destMac, "Destination mac address should not be null.");
- Preconditions.checkNotNull(destNodeConnectorRef, "Destination port should not be null.");
-
-
- // do not add flow if both macs are same.
- if(sourceMac != null && destMac.equals(sourceMac)) {
- _logger.info("In addMacToMacFlow: No flows added. Source and Destination mac are same.");
- return;
- }
-
- // get flow table key
- TableKey flowTableKey = new TableKey((short) 0); //TODO: Hard coded Table Id 0, need to get it from Configuration data.
-
- //build a flow path based on node connector to program flow
- InstanceIdentifier<Flow> flowPath = buildFlowPath(destNodeConnectorRef, flowTableKey);
-
- // build a flow that target given mac id
- Flow flowBody = createMacToMacFlow(flowTableKey.getId(), 0, sourceMac, destMac, destNodeConnectorRef);
-
- // commit the flow in config data
- writeFlowToConfigData(flowPath, flowBody);
- }
-
- /**
- * Writes mac-to-mac flow on all ports that are in the path between given source and destination ports.
- * It uses path provided by NetworkGraphService
- * {@link org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService} to find a links
- * {@link org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link}
- * between given ports. And then writes appropriate flow on each port that is covered in that path.
- *
- * @param sourceMac
- * @param sourceNodeConnectorRef
- * @param destMac
- * @param destNodeConnectorRef
- */
- @Override
- public void addMacToMacFlowsUsingShortestPath(MacAddress sourceMac,
- NodeConnectorRef sourceNodeConnectorRef,
- MacAddress destMac,
- NodeConnectorRef destNodeConnectorRef) {
- Preconditions.checkNotNull(sourceMac, "Source mac address should not be null.");
- Preconditions.checkNotNull(sourceNodeConnectorRef, "Source port should not be null.");
- Preconditions.checkNotNull(destMac, "Destination mac address should not be null.");
- Preconditions.checkNotNull(destNodeConnectorRef, "Destination port should not be null.");
-
- if(sourceNodeConnectorRef.equals(destNodeConnectorRef)) {
- _logger.info("In addMacToMacFlowsUsingShortestPath: No flows added. Source and Destination ports are same.");
- return;
-
- }
- NodeId sourceNodeId = new NodeId(sourceNodeConnectorRef.getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
- NodeId destNodeId = new NodeId(destNodeConnectorRef.getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
-
- // add destMac-To-sourceMac flow on source port
- addMacToMacFlow(destMac, sourceMac, sourceNodeConnectorRef);
-
- // add sourceMac-To-destMac flow on destination port
- addMacToMacFlow(sourceMac, destMac, destNodeConnectorRef);
-
- if(!sourceNodeId.equals(destNodeId)) {
- List<Link> linksInBeween = networkGraphService.getPath(sourceNodeId, destNodeId);
-
- if(linksInBeween != null) {
- // assumes the list order is maintained and starts with link that has source as source node
- for(Link link : linksInBeween) {
- // add sourceMac-To-destMac flow on source port
- addMacToMacFlow(sourceMac, destMac, getSourceNodeConnectorRef(link));
-
- // add destMac-To-sourceMac flow on destination port
- addMacToMacFlow(destMac, sourceMac, getDestNodeConnectorRef(link));
- }
- }
- }
- }
-
- private NodeConnectorRef getSourceNodeConnectorRef(Link link) {
- InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier
- = InstanceIdentifierUtils.createNodeConnectorIdentifier(
- link.getSource().getSourceNode().getValue(),
- link.getSource().getSourceTp().getValue());
- return new NodeConnectorRef(nodeConnectorInstanceIdentifier);
- }
-
- private NodeConnectorRef getDestNodeConnectorRef(Link link) {
- InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier
- = InstanceIdentifierUtils.createNodeConnectorIdentifier(
- link.getDestination().getDestNode().getValue(),
- link.getDestination().getDestTp().getValue());
-
- return new NodeConnectorRef(nodeConnectorInstanceIdentifier);
- }
-
- /**
- * @param nodeConnectorRef
- * @return
- */
- private InstanceIdentifier<Flow> buildFlowPath(NodeConnectorRef nodeConnectorRef, TableKey flowTableKey) {
-
- // generate unique flow key
- FlowId flowId = new FlowId(String.valueOf(flowIdInc.getAndIncrement()));
- FlowKey flowKey = new FlowKey(flowId);
-
- return InstanceIdentifierUtils.generateFlowInstanceIdentifier(nodeConnectorRef, flowTableKey, flowKey);
- }
-
- /**
- * @param tableId
- * @param priority
- * @param sourceMac
- * @param destMac
- * @param destPort
- * @return {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder}
- * builds flow that forwards all packets with destMac to given port
- */
- private Flow createMacToMacFlow(Short tableId, int priority,
- MacAddress sourceMac, MacAddress destMac, NodeConnectorRef destPort) {
-
- // start building flow
- FlowBuilder macToMacFlow = new FlowBuilder() //
- .setTableId(tableId) //
- .setFlowName("mac2mac");
-
- // use its own hash code for id.
- macToMacFlow.setId(new FlowId(Long.toString(macToMacFlow.hashCode())));
-
- // create a match that has mac to mac ethernet match
- EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder() //
- .setEthernetDestination(new EthernetDestinationBuilder() //
- .setAddress(destMac) //
- .build());
- // set source in the match only if present
- if(sourceMac != null) {
- ethernetMatchBuilder.setEthernetSource(new EthernetSourceBuilder()
- .setAddress(sourceMac)
- .build());
- }
- EthernetMatch ethernetMatch = ethernetMatchBuilder.build();
- Match match = new MatchBuilder()
- .setEthernetMatch(ethernetMatch)
- .build();
-
-
- Uri destPortUri = destPort.getValue().firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
-
- Action outputToControllerAction = new ActionBuilder() //
- .setOrder(0)
- .setAction(new OutputActionCaseBuilder() //
- .setOutputAction(new OutputActionBuilder() //
- .setMaxLength(new Integer(0xffff)) //
- .setOutputNodeConnector(destPortUri) //
- .build()) //
- .build()) //
- .build();
-
- // Create an Apply Action
- ApplyActions applyActions = new ApplyActionsBuilder().setAction(ImmutableList.of(outputToControllerAction))
- .build();
-
- // Wrap our Apply Action in an Instruction
- Instruction applyActionsInstruction = new InstructionBuilder() //
- .setOrder(0)
- .setInstruction(new ApplyActionsCaseBuilder()//
- .setApplyActions(applyActions) //
- .build()) //
- .build();
-
- // Put our Instruction in a list of Instructions
- macToMacFlow
- .setMatch(match) //
- .setInstructions(new InstructionsBuilder() //
- .setInstruction(ImmutableList.of(applyActionsInstruction)) //
- .build()) //
- .setPriority(priority) //
- .setBufferId(0L) //
- .setHardTimeout(0) //
- .setIdleTimeout(0) //
- .setCookie(new FlowCookie(BigInteger.valueOf(flowCookieInc.getAndIncrement())))
- .setFlags(new FlowModFlags(false, false, false, false, false));
-
- return macToMacFlow.build();
- }
-
- /**
- * Starts and commits data change transaction which
- * modifies provided flow path with supplied body.
- *
- * @param flowPath
- * @param flowBody
- * @return transaction commit
- */
- private Future<RpcResult<TransactionStatus>> writeFlowToConfigData(InstanceIdentifier<Flow> flowPath,
- Flow flowBody) {
- DataModificationTransaction addFlowTransaction = dataBrokerService.beginTransaction();
- addFlowTransaction.putConfigurationData(flowPath, flowBody);
- return addFlowTransaction.commit();
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.controller.sample.l2switch.md.inventory;
-
-import org.opendaylight.controller.sample.l2switch.md.util.InstanceIdentifierUtils;
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-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.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * InventoryService provides functions related to Nodes & NodeConnectors.
- */
-public class InventoryService {
- private DataBrokerService dataService;
- // Key: SwitchId, Value: NodeConnectorRef that corresponds to NC between controller & switch
- private HashMap<String, NodeConnectorRef> controllerSwitchConnectors;
-
- /**
- * Construct an InventoryService object with the specified inputs.
- * @param dataService The DataBrokerService associated with the InventoryService.
- */
- public InventoryService(DataBrokerService dataService) {
- this.dataService = dataService;
- controllerSwitchConnectors = new HashMap<String, NodeConnectorRef>();
- }
-
- public HashMap<String, NodeConnectorRef> getControllerSwitchConnectors() {
- return controllerSwitchConnectors;
- }
-
- // ToDo: Improve performance for thousands of switch ports
- /**
- * Get the External NodeConnectors of the network, which are the NodeConnectors connected to hosts.
- * @return The list of external node connectors.
- */
- public List<NodeConnectorRef> getExternalNodeConnectors() {
- // External NodeConnectors = All - Internal
- ArrayList<NodeConnectorRef> externalNodeConnectors = new ArrayList<NodeConnectorRef>();
- Set<String> internalNodeConnectors = new HashSet<>();
-
- // Read Topology -- find list of switch-to-switch internal node connectors
- NetworkTopology networkTopology =
- (NetworkTopology)dataService.readOperationalData(
- InstanceIdentifier.<NetworkTopology>builder(NetworkTopology.class).toInstance());
-
- for (Topology topology : networkTopology.getTopology()) {
- Topology completeTopology =
- (Topology)dataService.readOperationalData(
- InstanceIdentifierUtils.generateTopologyInstanceIdentifier(
- topology.getTopologyId().getValue()));
-
- for (Link link : completeTopology.getLink()) {
- internalNodeConnectors.add(link.getDestination().getDestTp().getValue());
- internalNodeConnectors.add(link.getSource().getSourceTp().getValue());
- }
- }
-
- // Read Inventory -- contains list of all nodeConnectors
- InstanceIdentifier.InstanceIdentifierBuilder<Nodes> nodesInsIdBuilder = InstanceIdentifier.<Nodes>builder(Nodes.class);
- Nodes nodes = (Nodes)dataService.readOperationalData(nodesInsIdBuilder.toInstance());
- if (nodes != null) {
- for (Node node : nodes.getNode()) {
- Node completeNode = (Node)dataService.readOperationalData(InstanceIdentifierUtils.createNodePath(node.getId()));
- for (NodeConnector nodeConnector : completeNode.getNodeConnector()) {
- // NodeConnector isn't switch-to-switch, so it must be controller-to-switch (internal) or external
- if (!internalNodeConnectors.contains(nodeConnector.getId().getValue())) {
- NodeConnectorRef ncRef = new NodeConnectorRef(
- InstanceIdentifier.<Nodes>builder(Nodes.class).<Node, NodeKey>child(Node.class, node.getKey())
- .<NodeConnector, NodeConnectorKey>child(NodeConnector.class, nodeConnector.getKey()).toInstance());
-
- // External node connectors have "-" in their name for mininet, i.e. "s1-eth1"
- if (nodeConnector.getAugmentation(FlowCapableNodeConnector.class).getName().contains("-")) {
- externalNodeConnectors.add(ncRef);
- }
- // Controller-to-switch internal node connectors
- else {
- controllerSwitchConnectors.put(node.getId().getValue(), ncRef);
- }
- }
- }
- }
- }
-
- return externalNodeConnectors;
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (c) 2014 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.controller.sample.l2switch.md.packet;
-
-import org.opendaylight.controller.sample.l2switch.md.addresstracker.AddressTracker;
-import org.opendaylight.controller.sample.l2switch.md.flow.FlowWriterService;
-import org.opendaylight.controller.sample.l2switch.md.inventory.InventoryService;
-import org.opendaylight.controller.sample.l2switch.md.util.InstanceIdentifierUtils;
-import org.opendaylight.controller.sal.packet.Ethernet;
-import org.opendaylight.controller.sal.packet.LLDP;
-import org.opendaylight.controller.sal.packet.LinkEncap;
-import org.opendaylight.controller.sal.packet.Packet;
-import org.opendaylight.controller.sal.packet.RawPacket;
-import org.opendaylight.controller.sal.utils.HexEncode;
-import org.opendaylight.controller.sal.utils.NetUtils;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-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.yang.gen.v1.urn.opendaylight.l2.address.tracker.rev140402.l2.addresses.L2Address;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * PacketHandler examines Ethernet packets to find L2Addresses (mac, nodeConnector) pairings
- * of the sender and learns them.
- * It also forwards the data packets appropriately dependending upon whether it knows about the
- * target or not.
- */
-public class PacketHandler implements PacketProcessingListener {
-
- private final static Logger _logger = LoggerFactory.getLogger(PacketHandler.class);
-
- private PacketProcessingService packetProcessingService;
- private AddressTracker addressTracker;
- private FlowWriterService flowWriterService;
- private InventoryService inventoryService;
-
- public void setAddressTracker(AddressTracker addressTracker) {
- this.addressTracker = addressTracker;
- }
-
- public void setPacketProcessingService(PacketProcessingService packetProcessingService) {
- this.packetProcessingService = packetProcessingService;
- }
-
- public void setFlowWriterService(FlowWriterService flowWriterService) {
- this.flowWriterService = flowWriterService;
- }
-
- public void setInventoryService(InventoryService inventoryService) {
- this.inventoryService = inventoryService;
- }
-
- /**
- * The handler function for all incoming packets.
- * @param packetReceived The incoming packet.
- */
- @Override
- public void onPacketReceived(PacketReceived packetReceived) {
-
- if(packetReceived == null) return;
-
- try {
- byte[] payload = packetReceived.getPayload();
- RawPacket rawPacket = new RawPacket(payload);
- NodeConnectorRef ingress = packetReceived.getIngress();
-
- Packet packet = decodeDataPacket(rawPacket);
-
- if(!(packet instanceof Ethernet)) return;
-
- handleEthernetPacket(packet, ingress);
-
- } catch(Exception e) {
- _logger.error("Failed to handle packet {}", packetReceived, e);
- }
- }
-
- /**
- * The handler function for Ethernet packets.
- * @param packet The incoming Ethernet packet.
- * @param ingress The NodeConnector where the Ethernet packet came from.
- */
- private void handleEthernetPacket(Packet packet, NodeConnectorRef ingress) {
- byte[] srcMac = ((Ethernet) packet).getSourceMACAddress();
- byte[] destMac = ((Ethernet) packet).getDestinationMACAddress();
-
- if (srcMac == null || srcMac.length == 0) return;
-
- Object enclosedPacket = packet.getPayload();
-
- if (enclosedPacket instanceof LLDP)
- return; // LLDP packets are handled by OpenFlowPlugin
-
- // get l2address by src mac
- // if unknown, add l2address
- MacAddress srcMacAddress = toMacAddress(srcMac);
- L2Address src = addressTracker.getAddress(srcMacAddress);
- boolean isSrcKnown = (src != null);
- if (!isSrcKnown) {
- addressTracker.addAddress(srcMacAddress, ingress);
- }
-
- // get host by dest mac
- // if known set dest known to true
- MacAddress destMacAddress = toMacAddress(destMac);
- L2Address dest = addressTracker.getAddress(destMacAddress);
- boolean isDestKnown = (dest != null);
-
- byte[] payload = packet.getRawPayload();
- // if (src and dest known)
- // sendpacket to dest and add src<->dest flow
- if(isSrcKnown & isDestKnown) {
- flowWriterService.addMacToMacFlowsUsingShortestPath(srcMacAddress, src.getNodeConnectorRef(),
- destMacAddress, dest.getNodeConnectorRef());
- sendPacketOut(payload, getControllerNodeConnector(dest.getNodeConnectorRef()), dest.getNodeConnectorRef());
- } else {
- // if (dest unknown)
- // sendpacket to external links minus ingress
- floodExternalPorts(payload, ingress);
- }
- }
-
- /**
- * Floods the specified payload on external ports, which are ports not connected to switches.
- * @param payload The payload to be flooded.
- * @param ingress The NodeConnector where the payload came from.
- */
- private void floodExternalPorts(byte[] payload, NodeConnectorRef ingress) {
- List<NodeConnectorRef> externalPorts = inventoryService.getExternalNodeConnectors();
- externalPorts.remove(ingress);
-
- for (NodeConnectorRef egress : externalPorts) {
- sendPacketOut(payload, getControllerNodeConnector(egress), egress);
- }
- }
-
- /**
- * Sends the specified packet on the specified port.
- * @param payload The payload to be sent.
- * @param ingress The NodeConnector where the payload came from.
- * @param egress The NodeConnector where the payload will go.
- */
- private void sendPacketOut(byte[] payload, NodeConnectorRef ingress, NodeConnectorRef egress) {
- if (ingress == null || egress == null) return;
- InstanceIdentifier<Node> egressNodePath = InstanceIdentifierUtils.getNodePath(egress.getValue());
- TransmitPacketInput input = new TransmitPacketInputBuilder() //
- .setPayload(payload) //
- .setNode(new NodeRef(egressNodePath)) //
- .setEgress(egress) //
- .setIngress(ingress) //
- .build();
- packetProcessingService.transmitPacket(input);
- }
-
- /**
- * Decodes an incoming packet.
- * @param raw The raw packet to be decoded.
- * @return The decoded form of the raw packet.
- */
- private Packet decodeDataPacket(RawPacket raw) {
- if(raw == null) {
- return null;
- }
- byte[] data = raw.getPacketData();
- if(data.length <= 0) {
- return null;
- }
- if(raw.getEncap().equals(LinkEncap.ETHERNET)) {
- Ethernet res = new Ethernet();
- try {
- res.deserialize(data, 0, data.length * NetUtils.NumBitsInAByte);
- res.setRawPayload(raw.getPacketData());
- } catch(Exception e) {
- _logger.warn("Failed to decode packet: {}", e.getMessage());
- }
- return res;
- }
- return null;
- }
-
- /**
- * Creates a MacAddress object out of a byte array.
- * @param dataLinkAddress The byte-array form of a MacAddress
- * @return MacAddress of the specified dataLinkAddress.
- */
- private MacAddress toMacAddress(byte[] dataLinkAddress) {
- return new MacAddress(HexEncode.bytesToHexStringFormat(dataLinkAddress));
- }
-
- /**
- * Gets the NodeConnector that connects the controller & switch for a specified switch port/node connector.
- * @param nodeConnectorRef The nodeConnector of a switch.
- * @return The NodeConnector that that connects the controller & switch.
- */
- private NodeConnectorRef getControllerNodeConnector(NodeConnectorRef nodeConnectorRef) {
- NodeConnectorRef controllerSwitchNodeConnector = null;
- HashMap<String, NodeConnectorRef> controllerSwitchConnectors = inventoryService.getControllerSwitchConnectors();
- InstanceIdentifier<Node> nodePath = InstanceIdentifierUtils.getNodePath(nodeConnectorRef.getValue());
- if (nodePath != null) {
- NodeKey nodeKey = InstanceIdentifierUtils.getNodeKey(nodePath);
- if (nodeKey != null) {
- controllerSwitchNodeConnector = controllerSwitchConnectors.get(nodeKey.getId().getValue());
- }
- }
- return controllerSwitchNodeConnector;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.controller.sample.l2switch.md.topology;
-
-import com.google.common.base.Preconditions;
-import edu.uci.ics.jung.algorithms.shortestpath.DijkstraShortestPath;
-import edu.uci.ics.jung.graph.DirectedSparseGraph;
-import edu.uci.ics.jung.graph.Graph;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-
-/**
- * Implementation of NetworkGraphService{@link org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService}.
- * It uses Jung graph library internally to maintain a graph and optimum way to return shortest path using
- * Dijkstra algorithm.
- */
-public class NetworkGraphDijkstra implements NetworkGraphService {
-
- private static final Logger _logger = LoggerFactory.getLogger(NetworkGraphDijkstra.class);
-
- DijkstraShortestPath<NodeId, Link> shortestPath = null;
- Graph<NodeId, Link> networkGraph = null;
-
- /**
- * Adds links to existing graph or creates new directed graph with given links if graph was not initialized.
- * @param links
- */
- @Override
- public synchronized void addLinks(List<Link> links) {
- if(links == null || links.isEmpty()) {
- _logger.info("In addLinks: No link added as links is null or empty.");
- return;
- }
-
- if(networkGraph == null) {
- networkGraph = new DirectedSparseGraph<>();
- }
-
- for(Link link : links) {
- NodeId sourceNodeId = link.getSource().getSourceNode();
- NodeId destinationNodeId = link.getDestination().getDestNode();
- networkGraph.addVertex(sourceNodeId);
- networkGraph.addVertex(destinationNodeId);
- networkGraph.addEdge(link, sourceNodeId, destinationNodeId);
- }
- if(shortestPath == null) {
- shortestPath = new DijkstraShortestPath<>(networkGraph);
- } else {
- shortestPath.reset();
- }
- }
-
- /**
- * removes links from existing graph.
- * @param links
- */
- @Override
- public synchronized void removeLinks(List<Link> links) {
- Preconditions.checkNotNull(networkGraph, "Graph is not initialized, add links first.");
-
- if(links == null || links.isEmpty()) {
- _logger.info("In removeLinks: No link removed as links is null or empty.");
- return;
- }
-
- for(Link link : links) {
- networkGraph.removeEdge(link);
- }
-
- if(shortestPath == null) {
- shortestPath = new DijkstraShortestPath<>(networkGraph);
- } else {
- shortestPath.reset();
- }
- }
-
- /**
- * returns a path between 2 nodes. Uses Dijkstra's algorithm to return shortest path.
- * @param sourceNodeId
- * @param destinationNodeId
- * @return
- */
- @Override
- public synchronized List<Link> getPath(NodeId sourceNodeId, NodeId destinationNodeId) {
- Preconditions.checkNotNull(shortestPath, "Graph is not initialized, add links first.");
-
- if(sourceNodeId == null || destinationNodeId == null) {
- _logger.info("In getPath: returning null, as sourceNodeId or destinationNodeId is null.");
- return null;
- }
-
- return shortestPath.getPath(sourceNodeId, destinationNodeId);
- }
-
- /**
- * Clears the prebuilt graph, in case same service instance is required to process a new graph.
- */
- @Override
- public synchronized void clear() {
- networkGraph = null;
- shortestPath = null;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.controller.sample.l2switch.md.topology;
-
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-
-import java.util.List;
-
-/**
- * Service that allows to build a network graph using Topology links
- * {@link org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link}
- * and exposes operation that can be performed on such graph.
- */
-public interface NetworkGraphService {
-
- /**
- * Adds links to existing graph or creates new graph with given links if graph was not initialized.
- * @param links
- */
- public void addLinks(List<Link> links);
-
- /**
- * removes links from existing graph.
- * @param links
- */
- public void removeLinks(List<Link> links);
-
- /**
- * returns a path between 2 nodes. Implementation should ideally return shortest path.
- * @param sourceNodeId
- * @param destinationNodeId
- * @return
- */
- public List<Link> getPath(NodeId sourceNodeId, NodeId destinationNodeId);
-
- /**
- * Clears the prebuilt graph, in case same service instance is required to process a new graph.
- */
- public void clear();
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.controller.sample.l2switch.md.topology;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.sample.l2switch.md.util.InstanceIdentifierUtils;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Listens to data change events on topology links
- * {@link org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link}
- * and maintains a topology graph using provided NetworkGraphService
- * {@link org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService}.
- * It refreshes the graph after a delay(default 10 sec) to accommodate burst of change events if they come in bulk.
- * This is to avoid continuous refresh of graph on a series of change events in short time.
- */
-public class TopologyLinkDataChangeHandler implements DataChangeListener {
- private static final Logger _logger = LoggerFactory.getLogger(TopologyLinkDataChangeHandler.class);
- private static final String DEFAULT_TOPOLOGY_ID = "flow:1";
-
- private boolean networkGraphRefreshScheduled = false;
- private final ScheduledExecutorService networkGraphRefreshScheduler = Executors.newScheduledThreadPool(1);
- private final long DEFAULT_GRAPH_REFRESH_DELAY = 10;
- private final long graphRefreshDelayInSec;
-
- private final NetworkGraphService networkGraphService;
- private final DataBrokerService dataBrokerService;
-
- /**
- * Uses default delay to refresh topology graph if this constructor is used.
- * @param dataBrokerService
- * @param networkGraphService
- */
- public TopologyLinkDataChangeHandler(DataBrokerService dataBrokerService, NetworkGraphService networkGraphService) {
- Preconditions.checkNotNull(dataBrokerService, "dataBrokerService should not be null.");
- Preconditions.checkNotNull(networkGraphService, "networkGraphService should not be null.");
- this.dataBrokerService = dataBrokerService;
- this.networkGraphService = networkGraphService;
- this.graphRefreshDelayInSec = DEFAULT_GRAPH_REFRESH_DELAY;
- }
-
- /**
- *
- * @param dataBrokerService
- * @param networkGraphService
- * @param graphRefreshDelayInSec
- */
- public TopologyLinkDataChangeHandler(DataBrokerService dataBrokerService, NetworkGraphService networkGraphService,
- long graphRefreshDelayInSec) {
- Preconditions.checkNotNull(dataBrokerService, "dataBrokerService should not be null.");
- Preconditions.checkNotNull(networkGraphService, "networkGraphService should not be null.");
- this.dataBrokerService = dataBrokerService;
- this.networkGraphService = networkGraphService;
- this.graphRefreshDelayInSec = graphRefreshDelayInSec;
- }
-
- /**
- * Based on if links have been added or removed in topology data store, schedules a refresh of network graph.
- * @param dataChangeEvent
- */
- @Override
- public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> dataChangeEvent) {
- if(dataChangeEvent == null) {
- _logger.info("In onDataChanged: No Processing done as dataChangeEvent is null.");
- }
- Map<InstanceIdentifier<?>, DataObject> linkOriginalData = dataChangeEvent.getOriginalOperationalData();
- Map<InstanceIdentifier<?>, DataObject> linkUpdatedData = dataChangeEvent.getUpdatedOperationalData();
- // change this logic, once MD-SAL start populating DeletedOperationData Set
- if(linkOriginalData != null && linkUpdatedData != null
- && (linkOriginalData.size() != 0 || linkUpdatedData.size() != 0)
- && !networkGraphRefreshScheduled) {
- networkGraphRefreshScheduled = linkOriginalData.size() != linkUpdatedData.size();
- if(networkGraphRefreshScheduled) {
- networkGraphRefreshScheduler.schedule(new NetworkGraphRefresher(), graphRefreshDelayInSec, TimeUnit.SECONDS);
- }
- }
-
- }
-
- /**
- * Registers as a data listener to receive changes done to
- * {@link org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link}
- * under {@link org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology}
- * operation data root.
- */
-
- public void registerAsDataChangeListener() {
- InstanceIdentifier<Link> linkInstance = InstanceIdentifier.builder(NetworkTopology.class)
- .child(Topology.class, new TopologyKey(new TopologyId(DEFAULT_TOPOLOGY_ID))).child(Link.class).toInstance();
- dataBrokerService.registerDataChangeListener(linkInstance, this);
- }
-
- /**
- *
- */
- private class NetworkGraphRefresher implements Runnable {
- /**
- *
- */
- @Override
- public void run() {
- networkGraphRefreshScheduled = false;
- //TODO: it should refer to changed links only from DataChangeEvent above.
- List<Link> links = getLinksFromTopology(DEFAULT_TOPOLOGY_ID);
- networkGraphService.clear();// can remove this once changed links are addressed
- if(links != null && !links.isEmpty()) {
- networkGraphService.addLinks(links);
- }
- }
-
- /**
- * @param topologyId
- * @return
- */
- private List<Link> getLinksFromTopology(String topologyId) {
- InstanceIdentifier<Topology> topologyInstanceIdentifier = InstanceIdentifierUtils.generateTopologyInstanceIdentifier(topologyId);
- Topology topology = (Topology) dataBrokerService.readOperationalData(topologyInstanceIdentifier);
- return topology.getLink();
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.controller.sample.l2switch.md.util;
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
-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.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-/* InstanceIdentifierUtils provides utility functions related to InstanceIdentifiers.
- */
-public final class InstanceIdentifierUtils {
-
- private InstanceIdentifierUtils() {
- throw new UnsupportedOperationException("Utility class should never be instantiated");
- }
-
- /**
- * Creates an Instance Identifier (path) for node with specified id
- *
- * @param nodeId
- * @return
- */
- public static final InstanceIdentifier<Node> createNodePath(final NodeId nodeId) {
- return InstanceIdentifier.builder(Nodes.class) //
- .child(Node.class, new NodeKey(nodeId)) //
- .build();
- }
-
- /**
- * Shorten's node child path to node path.
- *
- * @param nodeChild child of node, from which we want node path.
- * @return
- */
- public static final InstanceIdentifier<Node> getNodePath(final InstanceIdentifier<?> nodeChild) {
- return nodeChild.firstIdentifierOf(Node.class);
- }
-
-
- /**
- * Creates a table path by appending table specific location to node path
- *
- * @param nodePath
- * @param tableKey
- * @return
- */
- public static final InstanceIdentifier<Table> createTablePath(final InstanceIdentifier<Node> nodePath, final TableKey tableKey) {
- return nodePath.builder()
- .augmentation(FlowCapableNode.class)
- .child(Table.class, tableKey)
- .build();
- }
-
- /**
- * Creates a path for particular flow, by appending flow-specific information
- * to table path.
- *
- * @param table
- * @param flowKey
- * @return
- */
- public static InstanceIdentifier<Flow> createFlowPath(final InstanceIdentifier<Table> table, final FlowKey flowKey) {
- return table.child(Flow.class, flowKey);
- }
-
- /**
- * Extract table id from table path.
- *
- * @param tablePath
- * @return
- */
- public static Short getTableId(final InstanceIdentifier<Table> tablePath) {
- return tablePath.firstKeyOf(Table.class, TableKey.class).getId();
- }
-
- /**
- * Extracts NodeConnectorKey from node connector path.
- */
- public static NodeConnectorKey getNodeConnectorKey(final InstanceIdentifier<?> nodeConnectorPath) {
- return nodeConnectorPath.firstKeyOf(NodeConnector.class, NodeConnectorKey.class);
- }
-
- /**
- * Extracts NodeKey from node path.
- */
- public static NodeKey getNodeKey(final InstanceIdentifier<?> nodePath) {
- return nodePath.firstKeyOf(Node.class, NodeKey.class);
- }
-
-
- //
- public static final InstanceIdentifier<NodeConnector> createNodeConnectorIdentifier(final String nodeIdValue,
- final String nodeConnectorIdValue) {
- return createNodePath(new NodeId(nodeIdValue))
- .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(nodeConnectorIdValue)));
- }
-
- /**
- * @param nodeConnectorRef
- * @return
- */
- public static InstanceIdentifier<Node> generateNodeInstanceIdentifier(final NodeConnectorRef nodeConnectorRef) {
- return nodeConnectorRef.getValue().firstIdentifierOf(Node.class);
- }
-
- /**
- * @param nodeConnectorRef
- * @param flowTableKey
- * @return
- */
- public static InstanceIdentifier<Table> generateFlowTableInstanceIdentifier(final NodeConnectorRef nodeConnectorRef, final TableKey flowTableKey) {
- return generateNodeInstanceIdentifier(nodeConnectorRef).builder()
- .augmentation(FlowCapableNode.class)
- .child(Table.class, flowTableKey)
- .build();
- }
-
- /**
- * @param nodeConnectorRef
- * @param flowTableKey
- * @param flowKey
- * @return
- */
- public static InstanceIdentifier<Flow> generateFlowInstanceIdentifier(final NodeConnectorRef nodeConnectorRef,
- final TableKey flowTableKey,
- final FlowKey flowKey) {
- return generateFlowTableInstanceIdentifier(nodeConnectorRef, flowTableKey).child(Flow.class, flowKey);
- }
-
- public static InstanceIdentifier<Topology> generateTopologyInstanceIdentifier(final String topologyId) {
- return InstanceIdentifier.builder(NetworkTopology.class)
- .child(Topology.class, new TopologyKey(new TopologyId(topologyId)))
- .build();
- }
-}
-
+++ /dev/null
-/**
- * Copyright (c) 2014 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.controller.sample.l2switch.md.flow;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-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;
-
-/**
- */
-public class FlowWriterServiceImplTest {
- private DataBrokerService dataBrokerService;
- private NodeConnectorRef srcNodeConnectorRef;
- private NodeConnectorRef destNodeConnectorRef;
- private MacAddress destMacAddress;
- private MacAddress srcMacAddress;
- private DataModificationTransaction dataModificationTransaction;
- private NetworkGraphService networkGraphService;
-
- @Before
- public void init() {
- dataBrokerService = mock(DataBrokerService.class);
- networkGraphService = mock(NetworkGraphService.class);
- //build source node connector ref
- InstanceIdentifier<Nodes> srcNodesInstanceIdentifier = InstanceIdentifier.create(Nodes.class);
- InstanceIdentifier<Node> srcNodeInstanceIdentifier = srcNodesInstanceIdentifier
- .child(Node.class, new NodeKey(new NodeId("openflow:1")));
- InstanceIdentifier<NodeConnector> srcNodeConnectorInstanceIdentifier = srcNodeInstanceIdentifier
- .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:1:2")));
- srcNodeConnectorRef = new NodeConnectorRef(srcNodeConnectorInstanceIdentifier);
-
- //build dest node connector ref
- InstanceIdentifier<Nodes> nodesInstanceIdentifier
- = InstanceIdentifier.builder(Nodes.class)
- .build();
- InstanceIdentifier<Node> nodeInstanceIdentifier =
- nodesInstanceIdentifier.child(Node.class, new NodeKey(new NodeId("openflow:2")));
- InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier =
- nodeInstanceIdentifier.child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:2:2")));
- destNodeConnectorRef = new NodeConnectorRef(nodeConnectorInstanceIdentifier);
- destMacAddress = new MacAddress("00:0a:95:9d:68:16");
- srcMacAddress = new MacAddress("00:0a:95:8c:97:24");
- dataModificationTransaction = mock(DataModificationTransaction.class);
- when(dataBrokerService.beginTransaction()).thenReturn(dataModificationTransaction);
- }
-
- @Test
- public void testFlowWriterServiceImpl_NPEWhenDataBrokerServiceIsNull() throws Exception {
- try {
- new FlowWriterServiceImpl(null, networkGraphService);
- fail("Expected null pointer exception.");
- } catch(NullPointerException npe) {
- assertEquals("dataBrokerService should not be null.", npe.getMessage());
- }
- }
-
- @Test
- public void testAddMacToMacFlow_NPEWhenNullSourceMacDestMacAndNodeConnectorRef() throws Exception {
- FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
- try {
- flowWriterService.addMacToMacFlow(null, null, null);
- fail("Expected null pointer exception.");
- } catch(NullPointerException npe) {
- assertEquals("Destination mac address should not be null.", npe.getMessage());
- }
- }
-
- @Test
- public void testAddMacToMacFlow_NPEWhenSourceMacNullMac() throws Exception {
- FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
- try {
- flowWriterService.addMacToMacFlow(null, null, destNodeConnectorRef);
- fail("Expected null pointer exception.");
- } catch(NullPointerException npe) {
- assertEquals("Destination mac address should not be null.", npe.getMessage());
- }
- }
-
- @Test
- public void testAddMacToMacFlow_NPEWhenNullSourceMacNodeConnectorRef() throws Exception {
- FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
- try {
- flowWriterService.addMacToMacFlow(null, destMacAddress, null);
- fail("Expected null pointer exception.");
- } catch(NullPointerException npe) {
- assertEquals("Destination port should not be null.", npe.getMessage());
- }
- }
-
- @Test
- public void testAddMacToMacFlow_WhenNullSourceMac() throws Exception {
- FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
- flowWriterService.addMacToMacFlow(null, destMacAddress, destNodeConnectorRef);
- verify(dataBrokerService, times(1)).beginTransaction();
- verify(dataModificationTransaction, times(1)).commit();
- }
-
- @Test
- public void testAddMacToMacFlow_WhenSrcAndDestMacAreSame() throws Exception {
- FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
- flowWriterService.addMacToMacFlow(new MacAddress(destMacAddress.getValue()), destMacAddress, destNodeConnectorRef);
- verify(dataBrokerService, never()).beginTransaction();
- verify(dataModificationTransaction, never()).commit();
-
- }
-
- @Test
- public void testAddMacToMacFlow_SunnyDay() throws Exception {
- FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
- flowWriterService.addMacToMacFlow(srcMacAddress, destMacAddress, destNodeConnectorRef);
- verify(dataBrokerService, times(1)).beginTransaction();
- verify(dataModificationTransaction, times(1)).commit();
- }
-
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 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.controller.sample.l2switch.md.topology;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.Destination;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.Source;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static junit.framework.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-/**
- */
-public class NetworkGraphDijkstraTest {
- Link link1, link2, link3, link4, link5, link6, link7, link8, link9, link10,link11,link12;
- Destination dest1, dest2, dest3, dest4, dest5, dest6,dest7,dest8,dest9,dest10,dest11,dest12;
- Source src1, src2, src3, src4, src5, src6,src7,src8,src9,src10,src11,src12;
- NodeId nodeId1 = new NodeId("openflow:1");
- NodeId nodeId2 = new NodeId("openflow:2");
- NodeId nodeId3 = new NodeId("openflow:3");
- NodeId nodeId4 = new NodeId("openflow:4");
- NodeId nodeId5 = new NodeId("openflow:5");
- NodeId nodeId6 = new NodeId("openflow:6");
- NodeId nodeId7 = new NodeId("openflow:7");
- List<Link> links = new ArrayList<>();
-
- @Before
- public void init() {
- link1 = mock(Link.class);
- link2 = mock(Link.class);
- link3 = mock(Link.class);
- link4 = mock(Link.class);
- link5 = mock(Link.class);
- link6 = mock(Link.class);
- link7 = mock(Link.class);
- link8 = mock(Link.class);
- link9 = mock(Link.class);
- link10 = mock(Link.class);
- link11 = mock(Link.class);
- link12 = mock(Link.class);
- dest1 = mock(Destination.class);
- dest2 = mock(Destination.class);
- dest3 = mock(Destination.class);
- dest4 = mock(Destination.class);
- dest5 = mock(Destination.class);
- dest6 = mock(Destination.class);
- dest7 = mock(Destination.class);
- dest8 = mock(Destination.class);
- dest9 = mock(Destination.class);
- dest10 = mock(Destination.class);
- dest11 = mock(Destination.class);
- dest12 = mock(Destination.class);
- src1 = mock(Source.class);
- src2 = mock(Source.class);
- src3 = mock(Source.class);
- src4 = mock(Source.class);
- src5 = mock(Source.class);
- src6 = mock(Source.class);
- src7 = mock(Source.class);
- src8 = mock(Source.class);
- src9 = mock(Source.class);
- src10 = mock(Source.class);
- src11 = mock(Source.class);
- src12 = mock(Source.class);
- when(link1.getSource()).thenReturn(src1);
- when(link2.getSource()).thenReturn(src2);
- when(link3.getSource()).thenReturn(src3);
- when(link4.getSource()).thenReturn(src4);
- when(link5.getSource()).thenReturn(src5);
- when(link6.getSource()).thenReturn(src6);
- when(link7.getSource()).thenReturn(src7);
- when(link8.getSource()).thenReturn(src8);
- when(link9.getSource()).thenReturn(src9);
- when(link10.getSource()).thenReturn(src10);
- when(link11.getSource()).thenReturn(src11);
- when(link12.getSource()).thenReturn(src12);
- when(link1.getDestination()).thenReturn(dest1);
- when(link2.getDestination()).thenReturn(dest2);
- when(link3.getDestination()).thenReturn(dest3);
- when(link4.getDestination()).thenReturn(dest4);
- when(link5.getDestination()).thenReturn(dest5);
- when(link6.getDestination()).thenReturn(dest6);
- when(link7.getDestination()).thenReturn(dest7);
- when(link8.getDestination()).thenReturn(dest8);
- when(link9.getDestination()).thenReturn(dest9);
- when(link10.getDestination()).thenReturn(dest10);
- when(link11.getDestination()).thenReturn(dest11);
- when(link12.getDestination()).thenReturn(dest12);
- when(src1.getSourceNode()).thenReturn(nodeId1);
- when(dest1.getDestNode()).thenReturn(nodeId2);
- when(src2.getSourceNode()).thenReturn(nodeId2);
- when(dest2.getDestNode()).thenReturn(nodeId1);
- when(src3.getSourceNode()).thenReturn(nodeId1);
- when(dest3.getDestNode()).thenReturn(nodeId3);
- when(src4.getSourceNode()).thenReturn(nodeId3);
- when(dest4.getDestNode()).thenReturn(nodeId1);
- when(src5.getSourceNode()).thenReturn(nodeId2);
- when(dest5.getDestNode()).thenReturn(nodeId4);
- when(src6.getSourceNode()).thenReturn(nodeId4);
- when(dest6.getDestNode()).thenReturn(nodeId2);
- when(src7.getSourceNode()).thenReturn(nodeId2);
- when(dest7.getDestNode()).thenReturn(nodeId5);
- when(src8.getSourceNode()).thenReturn(nodeId5);
- when(dest8.getDestNode()).thenReturn(nodeId2);
- when(src9.getSourceNode()).thenReturn(nodeId6);
- when(dest9.getDestNode()).thenReturn(nodeId3);
- when(src10.getSourceNode()).thenReturn(nodeId3);
- when(dest10.getDestNode()).thenReturn(nodeId6);
- when(src11.getSourceNode()).thenReturn(nodeId7);
- when(dest11.getDestNode()).thenReturn(nodeId3);
- when(src12.getSourceNode()).thenReturn(nodeId3);
- when(dest12.getDestNode()).thenReturn(nodeId7);
- links.add(link1);
- links.add(link2);
- links.add(link3);
- links.add(link4);
- links.add(link5);
- links.add(link6);
- links.add(link7);
- links.add(link8);
- links.add(link9);
- links.add(link10);
- links.add(link11);
- links.add(link12);
-
- }
-
- @Test
- public void testAddLinksAndGetPath() throws Exception {
- NetworkGraphService networkGraphService = new NetworkGraphDijkstra();
- networkGraphService.addLinks(links);
- List<Link> path = networkGraphService.getPath(nodeId2, nodeId3);
- assertEquals("path size is not as expected.", 2, path.size());
- assertEquals("link source is not as expected.", nodeId2, path.get(0).getSource().getSourceNode());
- assertEquals("link destination is not as expected.", nodeId1, path.get(0).getDestination().getDestNode());
- path = networkGraphService.getPath(nodeId3, nodeId2);
- assertEquals("path size is not as expected.", 2, path.size());
- assertEquals("link source is not as expected.", nodeId3, path.get(0).getSource().getSourceNode());
- assertEquals("link destination is not as expected.", nodeId1, path.get(0).getDestination().getDestNode());
-
- path = networkGraphService.getPath(nodeId4, nodeId6);
- assertEquals("path size is not as expected.", 4, path.size());
- assertEquals("link source is not as expected.", nodeId4, path.get(0).getSource().getSourceNode());
- assertEquals("link destination is not as expected.", nodeId2, path.get(0).getDestination().getDestNode());
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 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.controller.sample.l2switch.md.topology;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.sample.l2switch.md.util.InstanceIdentifierUtils;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-/**
- */
-public class TopologyLinkDataChangeHandlerTest {
- NetworkGraphService networkGraphService;
- DataBrokerService dataBrokerService;
- DataChangeEvent dataChangeEvent;
- Topology topology;
- Link link;
-
- @Before
- public void init() {
- networkGraphService = mock(NetworkGraphService.class);
- dataBrokerService = mock(DataBrokerService.class);
- dataChangeEvent = mock(DataChangeEvent.class);
- link = mock(Link.class);
- topology = mock(Topology.class);
- }
-
- @Test
- public void testOnDataChange() throws Exception {
- TopologyLinkDataChangeHandler topologyLinkDataChangeHandler = new TopologyLinkDataChangeHandler(dataBrokerService, networkGraphService, 2);
- Map<InstanceIdentifier<?>, DataObject> original = new HashMap<InstanceIdentifier<?>, DataObject>();
- InstanceIdentifier<?> instanceIdentifier = InstanceIdentifierUtils.generateTopologyInstanceIdentifier("flow:1");
- DataObject dataObject = mock(DataObject.class);
- Map<InstanceIdentifier<?>, DataObject> updated = new HashMap<InstanceIdentifier<?>, DataObject>();
- updated.put(instanceIdentifier, dataObject);
- when(dataChangeEvent.getUpdatedOperationalData()).thenReturn(updated);
- when(dataChangeEvent.getOriginalOperationalData()).thenReturn(original);
- List<Link> links = new ArrayList<>();
- links.add(link);
- when(dataBrokerService.readOperationalData(instanceIdentifier)).thenReturn(topology);
- when(topology.getLink()).thenReturn(links);
-
- topologyLinkDataChangeHandler.onDataChanged(dataChangeEvent);
- Thread.sleep(2100);
- verify(networkGraphService, times(1)).addLinks(links);
- }
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<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.samples</groupId>
- <artifactId>sal-samples</artifactId>
- <version>1.2.0-SNAPSHOT</version>
- <relativePath>../..</relativePath>
- </parent>
- <groupId>org.opendaylight.controller.samples.l2switch.md</groupId>
- <artifactId>l2switch-model</artifactId>
- <packaging>bundle</packaging>
-
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-inventory</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-binding</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-common</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools.model</groupId>
- <artifactId>ietf-yang-types</artifactId>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
- <Import-Package>org.opendaylight.yangtools.yang.binding.annotations, *</Import-Package>
- <manifestLocation>${project.basedir}/META-INF</manifestLocation>
- </instructions>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-maven-plugin</artifactId>
- <version>${yangtools.version}</version>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>${yangtools.version}</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-binding</artifactId>
- <version>${yangtools.version}</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- <executions>
- <execution>
- <goals>
- <goal>generate-sources</goal>
- </goals>
- <configuration>
- <yangFilesRootDir>src/main/yang</yangFilesRootDir>
- <codeGenerators>
- <generator>
- <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
- <outputBaseDir>${salGeneratorPath}</outputBaseDir>
- </generator>
- <generator>
- <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
- <outputBaseDir>target/site/models</outputBaseDir>
- </generator>
- <generator>
- <codeGeneratorClass>org.opendaylight.yangtools.yang.wadl.generator.maven.WadlGenerator</codeGeneratorClass>
- <outputBaseDir>target/site/models</outputBaseDir>
- </generator>
- </codeGenerators>
- <inspectDependencies>true</inspectDependencies>
- </configuration>
- </execution>
- </executions>
-
- </plugin>
- </plugins>
- </build>
-</project>
+++ /dev/null
-module l2-address-tracker {
- yang-version 1;
- namespace "urn:opendaylight:l2-address-tracker";
- prefix l2-address-tracker;
-
- import ietf-yang-types {
- prefix yang;
- revision-date 2010-09-24;
- }
- import opendaylight-inventory {
- prefix inv;
- revision-date 2013-08-19;
- }
-
- organization "Cisco Systems Inc";
- contact
- "Alex Fan <alefan@cisco.com>";
- description
- "YANG version of the L2 Address Tracker Data Model";
-
- revision 2014-04-02 {
- description
- "L2 Address Tracker module draft.";
- }
-
- grouping l2-address {
- leaf mac {
- type yang:mac-address;
- mandatory true;
- description
- "the mac address of the host.";
- }
- leaf node-connector-ref {
- type inv:node-connector-ref;
- }
- }
-
- container l2-addresses {
- config false;
- list l2-address {
- key "mac";
- uses l2-address;
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<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.samples</groupId>
- <artifactId>sal-samples</artifactId>
- <version>1.2.0-SNAPSHOT</version>
- </parent>
-
- <artifactId>l2switch.aggregator</artifactId>
- <groupId>org.opendaylight.controller.samples.l2switch</groupId>
- <version>1.1.0-SNAPSHOT</version>
- <packaging>pom</packaging>
-
- <modules>
- <module>model</module>
- <module>implementation</module>
- </modules>
-
-</project>
<module>toaster-consumer</module>
<module>toaster-provider</module>
<module>toaster-config</module>
- <module>l2switch</module>
<module>clustering-test-app</module>
</modules>
<scm>