*/
package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.NetvirtProvidersProvider;
import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
+import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
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.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.CheckedFuture;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* Any ServiceInstance class that extends AbstractServiceInstance to be a part of the pipeline
* have 2 basic requirements : <br>
*/
public abstract class AbstractServiceInstance {
public static final String SERVICE_PROPERTY ="serviceProperty";
- private static final Logger logger = LoggerFactory.getLogger(AbstractServiceInstance.class);
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractServiceInstance.class);
public static final String OPENFLOW = "openflow:";
+ private DataBroker dataBroker = null;
// OSGi Services that we are dependent on.
- private volatile MdsalConsumer mdsalConsumer;
private volatile PipelineOrchestrator orchestrator;
+ private volatile Southbound southbound;
- // Concrete Service that this AbstractServiceInstance represent
+ // Concrete Service that this AbstractServiceInstance represents
private Service service;
public AbstractServiceInstance (Service service) {
this.service = service;
+ this.dataBroker = NetvirtProvidersProvider.getDataBroker();
+ }
+
+ protected void setDependencies(final ServiceReference ref, AbstractServiceInstance serviceInstance) {
+ this.orchestrator =
+ (PipelineOrchestrator) ServiceHelper.getGlobalInstance(PipelineOrchestrator.class, serviceInstance);
+ orchestrator.registerService(ref, serviceInstance);
+ this.southbound =
+ (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, serviceInstance);
}
- // Let the Concrete service instance class decide if a Bride is part of the pipeline or not.
- public abstract boolean isBridgeInPipeline (String nodeId);
+ public boolean isBridgeInPipeline (Node node){
+ String bridgeName = southbound.getBridgeName(node);
+ return bridgeName != null && Constants.INTEGRATION_BRIDGE.equals(bridgeName);
+ }
public short getTable() {
return service.getTable();
return builder;
}
+ private static InstanceIdentifier<Flow> createFlowPath(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
+ return InstanceIdentifier.builder(Nodes.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
+ nodeBuilder.getKey())
+ .augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(flowBuilder.getTableId()))
+ .child(Flow.class, flowBuilder.getKey()).build();
+ }
+
+ private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node>
+ createNodePath(NodeBuilder nodeBuilder) {
+ return InstanceIdentifier.builder(Nodes.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
+ nodeBuilder.getKey()).build();
+ }
+
/**
- * This method returns the required Pipeline Instructions to by used by any matching flows that needs
+ * This method returns the required Pipeline Instructions to by used by any matching flows that need
* to be further processed by next service in the pipeline.
*
* Important to note that this is a convenience method which returns a mutable instructionBuilder which
}
protected void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
- Preconditions.checkNotNull(mdsalConsumer);
- if (mdsalConsumer == null) {
- logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
- return;
- }
-
- DataBroker dataBroker = mdsalConsumer.getDataBroker();
- if (dataBroker == null) {
- logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
- return;
- }
-
- ReadWriteTransaction modification = dataBroker.newReadWriteTransaction();
- InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
- .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
- new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
-
- //modification.put(LogicalDatastoreType.OPERATIONAL, path1, flowBuilder.build());
- modification.put(LogicalDatastoreType.CONFIGURATION, path1, flowBuilder.build(), true /*createMissingParents*/);
-
+ LOG.debug("writeFlow: flowBuilder: {}, nodeBuilder: {}",
+ flowBuilder.build(), nodeBuilder.build());
+ WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
+ modification.put(LogicalDatastoreType.CONFIGURATION, createNodePath(nodeBuilder),
+ nodeBuilder.build(), true /*createMissingParents*/);
+ modification.put(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder),
+ flowBuilder.build(), true /*createMissingParents*/);
CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
try {
commitFuture.get(); // TODO: Make it async (See bug 1362)
- logger.debug("Transaction success for write of Flow "+flowBuilder.getFlowName());
- } catch (InterruptedException|ExecutionException e) {
- logger.error(e.getMessage(), e);
-
+ LOG.debug("Transaction success for write of Flow {}", flowBuilder.getFlowName());
+ } catch (Exception e) {
+ LOG.error(e.getMessage(), e);
+ modification.cancel();
}
}
protected void removeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
- Preconditions.checkNotNull(mdsalConsumer);
- if (mdsalConsumer == null) {
- logger.error("ERROR finding MDSAL Service.");
- return;
- }
-
- DataBroker dataBroker = mdsalConsumer.getDataBroker();
- if (dataBroker == null) {
- logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
- return;
- }
-
WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
- InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class)
- .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
- .rev130819.nodes.Node.class, nodeBuilder.getKey())
- .augmentation(FlowCapableNode.class).child(Table.class,
- new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
- //modification.delete(LogicalDatastoreType.OPERATIONAL, nodeBuilderToInstanceId(nodeBuilder));
- //modification.delete(LogicalDatastoreType.OPERATIONAL, path1);
- //modification.delete(LogicalDatastoreType.CONFIGURATION, nodeBuilderToInstanceId(nodeBuilder));
- modification.delete(LogicalDatastoreType.CONFIGURATION, path1);
+ modification.delete(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder));
CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
try {
commitFuture.get(); // TODO: Make it async (See bug 1362)
- logger.debug("Transaction success for deletion of Flow "+flowBuilder.getFlowName());
- } catch (InterruptedException|ExecutionException e) {
- logger.error(e.getMessage(), e);
+ LOG.debug("Transaction success for deletion of Flow {}", flowBuilder.getFlowName());
+ } catch (Exception e) {
+ LOG.error(e.getMessage(), e);
+ modification.cancel();
}
}
public Flow getFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
- Preconditions.checkNotNull(mdsalConsumer);
- if (mdsalConsumer == null) {
- logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
- return null;
+ ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
+ try {
+ Optional<Flow> data =
+ readTx.read(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder)).get();
+ if (data.isPresent()) {
+ return data.get();
+ }
+ } catch (InterruptedException|ExecutionException e) {
+ LOG.error(e.getMessage(), e);
}
- DataBroker dataBroker = mdsalConsumer.getDataBroker();
- if (dataBroker == null) {
- logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
- return null;
- }
+ LOG.debug("Cannot find data for Flow {}", flowBuilder.getFlowName());
+ return null;
+ }
- InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
- .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
- new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
+ public org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+ getOpenFlowNode(String nodeId) {
ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
try {
- Optional<Flow> data = readTx.read(LogicalDatastoreType.CONFIGURATION, path1).get();
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> data =
+ readTx.read(LogicalDatastoreType.OPERATIONAL, createNodePath(createNodeBuilder(nodeId))).get();
if (data.isPresent()) {
return data.get();
}
} catch (InterruptedException|ExecutionException e) {
- logger.error(e.getMessage(), e);
+ LOG.error(e.getMessage(), e);
}
- logger.debug("Cannot find data for Flow " + flowBuilder.getFlowName());
+ LOG.debug("Cannot find data for Node {}", nodeId);
return null;
}
+ private long getDpid(Node node) {
+ long dpid = southbound.getDataPathId(node);
+ if (dpid == 0) {
+ LOG.warn("getDpid: dpid not found: {}", node);
+ }
+ return dpid;
+ }
+
/**
* Program Default Pipeline Flow.
*
- * @param nodeId Node on which the default pipeline flow is programmed.
+ * @param node on which the default pipeline flow is programmed.
*/
- protected void programDefaultPipelineRule(String nodeId) {
+ protected void programDefaultPipelineRule(Node node) {
+ if (!isBridgeInPipeline(node)) {
+ //LOG.trace("Bridge is not in pipeline {} ", node);
+ return;
+ }
MatchBuilder matchBuilder = new MatchBuilder();
FlowBuilder flowBuilder = new FlowBuilder();
- NodeBuilder nodeBuilder = createNodeBuilder(nodeId);
+ long dpid = getDpid(node);
+ if (dpid == 0L) {
+ LOG.info("could not find dpid: {}", node.getNodeId());
+ return;
+ }
+ String nodeName = OPENFLOW + getDpid(node);
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
// Create the OF Actions and Instructions
InstructionsBuilder isb = new InstructionsBuilder();
// Add InstructionsBuilder to FlowBuilder
flowBuilder.setInstructions(isb.build());
- String flowId = "DEFAULT_PIPELINE_FLOW";
+ String flowId = "DEFAULT_PIPELINE_FLOW_"+service.getTable();
flowBuilder.setId(new FlowId(flowId));
FlowKey key = new FlowKey(new FlowId(flowId));
flowBuilder.setMatch(matchBuilder.build());