This commit adds programming of L3 services.
In addition, we add a deleteFlow method to the AbstractServiceInstance
class
Change-Id: I4d9fe8c93e6a93732660f3895df7885cda015b7e
Signed-off-by: Dave Tucker <djt@redhat.com>
import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
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.AsyncTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
logger.debug("Transaction success for write of Flow "+flowBuilder.getFlowName());
} catch (InterruptedException|ExecutionException e) {
logger.error(e.getMessage(), e);
+
+ }
+ }
+
+ 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);
+
+ 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);
}
}
}
}
- private NodeBuilder createNodeBuilder(String nodeId) {
+ public static NodeBuilder createNodeBuilder(String nodeId) {
NodeBuilder builder = new NodeBuilder();
builder.setId(new NodeId(nodeId));
builder.setKey(new NodeKey(builder.getId()));
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
import org.opendaylight.ovsdb.openstack.netvirt.api.ArpProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.OF13Provider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
+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.flow.inventory.rev130819.FlowId;
+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.flow.InstructionsBuilder;
+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.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+import com.google.common.collect.Lists;
+
+import java.math.BigInteger;
import java.net.InetAddress;
+import java.util.List;
public class ArpResponderService extends AbstractServiceInstance implements ArpProvider {
public ArpResponderService() {
@Override
public Status programStaticArpEntry(Node node, Long dpid, String segmentationId, String macAddress,
InetAddress ipAddress, Action action) {
- return new Status(StatusCode.NOTIMPLEMENTED);
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName);
+
+ // Instructions List Stores Individual Instructions
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionBuilder ib = new InstructionBuilder();
+
+ MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+ MatchUtils.createEtherTypeMatch(matchBuilder, new EtherType(Constants.ARP_ETHERTYPE));
+
+ // Move Eth Src to Eth Dst
+ InstructionUtils.applyActionIns(ActionUtils.nxMoveEthSrcToEthDstAction());
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ // Set Eth Src
+ InstructionUtils.createDlSrcInstructions(ib, new MacAddress(macAddress));
+ ib.setOrder(1);
+ ib.setKey(new InstructionKey(1));
+ instructions.add(ib.build());
+
+ // Set ARP OP
+ InstructionUtils.applyActionIns(ActionUtils.nxLoadArpOpAction(BigInteger.valueOf(0x02L)));
+ ib.setOrder(2);
+ ib.setKey(new InstructionKey(2));
+ instructions.add(ib.build());
+
+ // Move ARP SHA to ARP THA
+ InstructionUtils.applyActionIns(ActionUtils.nxMoveArpShaToArpThaAction());
+ ib.setOrder(3);
+ ib.setKey(new InstructionKey(3));
+ instructions.add(ib.build());
+
+ // Move ARP SPA to ARP TPA
+ InstructionUtils.applyActionIns(ActionUtils.nxMoveArpSpaToArpTpaAction());
+ ib.setOrder(4);
+ ib.setKey(new InstructionKey(4));
+ instructions.add(ib.build());
+
+ // Load Mac to ARP SHA
+ InstructionUtils.applyActionIns(ActionUtils.nxLoadArpShaAction(new BigInteger(macAddress)));
+ ib.setOrder(5);
+ ib.setKey(new InstructionKey(5));
+ instructions.add(ib.build());
+
+ // Load IP to ARP SPA
+ InstructionUtils.applyActionIns(ActionUtils.nxLoadArpSpaAction(ipAddress.getHostAddress()));
+ ib.setOrder(6);
+ ib.setKey(new InstructionKey(6));
+ instructions.add(ib.build());
+
+ // Output of InPort
+ InstructionUtils.applyActionIns(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":INPORT")));
+ ib.setOrder(7);
+ ib.setKey(new InstructionKey(7));
+ instructions.add(ib.build());
+
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ flowBuilder.setInstructions(isb.setInstruction(instructions).build());
+
+ String flowId = "ArpResponder_" + ipAddress.getHostAddress();
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setPriority(1024);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ writeFlow(flowBuilder, nodeBuilder);
+
+ if (action.equals(Action.ADD)) {
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+
+ // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
+ return new Status(StatusCode.SUCCESS);
}
}
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
import org.opendaylight.ovsdb.openstack.netvirt.api.InboundNatProvider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.OF13Provider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+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.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.flow.InstructionsBuilder;
+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.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import com.google.common.collect.Lists;
+
+import java.math.BigInteger;
import java.net.InetAddress;
+import java.util.List;
public class InboundNatService extends AbstractServiceInstance implements InboundNatProvider {
public InboundNatService() {
@Override
public Status programIpRewriteRule(Node node, Long dpid, String segmentationId, InetAddress matchAddress,
InetAddress rewriteAddress, Action action) {
- return new Status(StatusCode.NOTIMPLEMENTED);
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName);
+
+ // Instructions List Stores Individual Instructions
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionBuilder ib = new InstructionBuilder();
+
+ MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+ MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(matchAddress.getHostAddress()));
+
+ // Set Dest IP address
+ InstructionUtils.createNwDstInstructions(ib, new Ipv4Prefix(rewriteAddress.getHostAddress()));
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ // Goto Next Table
+ ib = getMutablePipelineInstructionBuilder();
+ ib.setOrder(1);
+ ib.setKey(new InstructionKey(1));
+ instructions.add(ib.build());
+
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ flowBuilder.setInstructions(isb.setInstruction(instructions).build());
+
+ String flowId = "InboundNAT_" + rewriteAddress.getHostAddress();
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setPriority(1024);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ writeFlow(flowBuilder, nodeBuilder);
+
+ if (action.equals(Action.ADD)) {
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+
+ // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
+ return new Status(StatusCode.SUCCESS);
}
@Override
public Status programIpRewriteExclusion(Node node, Long dpid, String segmentationId, String excludedCidr,
Action action) {
- return new Status(StatusCode.NOTIMPLEMENTED);
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName);
+
+ // Instructions List Stores Individual Instructions
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionBuilder ib;
+
+ MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+ MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(excludedCidr));
+
+ // Goto Next Table
+ ib = getMutablePipelineInstructionBuilder();
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ flowBuilder.setInstructions(isb.setInstruction(instructions).build());
+
+ String flowId = "InboundNATExclusion_" + excludedCidr;
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setPriority(1024);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ writeFlow(flowBuilder, nodeBuilder);
+
+ if (action.equals(Action.ADD)) {
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+
+ // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
+ return new Status(StatusCode.SUCCESS);
}
}
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
import org.opendaylight.ovsdb.openstack.netvirt.api.L3ForwardingProvider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.OF13Provider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+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.flow.inventory.rev130819.FlowId;
+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.flow.InstructionsBuilder;
+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.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import com.google.common.collect.Lists;
+
+import java.math.BigInteger;
import java.net.InetAddress;
+import java.util.List;
public class L3ForwardingService extends AbstractServiceInstance implements L3ForwardingProvider {
public L3ForwardingService() {
@Override
public Status programForwardingTableEntry(Node node, Long dpid, String segmentationId, InetAddress ipAddress,
String macAddress, Action action) {
- return null;
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName);
+
+ // Instructions List Stores Individual Instructions
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionBuilder ib = new InstructionBuilder();
+
+ MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+ MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(ipAddress.getHostAddress()));
+
+ // Set Dest Mac address
+ InstructionUtils.createDlDstInstructions(ib, new MacAddress(macAddress));
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ // Goto Next Table
+ ib = getMutablePipelineInstructionBuilder();
+ ib.setOrder(1);
+ ib.setKey(new InstructionKey(1));
+ instructions.add(ib.build());
+
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ flowBuilder.setInstructions(isb.setInstruction(instructions).build());
+
+ String flowId = "L3Forwarding_" + ipAddress.getHostAddress();
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setPriority(1024);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ writeFlow(flowBuilder, nodeBuilder);
+
+ if (action.equals(Action.ADD)) {
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+
+ // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
+ return new Status(StatusCode.SUCCESS);
}
}
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
import org.opendaylight.ovsdb.openstack.netvirt.api.OutboundNatProvider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.OF13Provider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+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.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.flow.InstructionsBuilder;
+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.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import com.google.common.collect.Lists;
+
+import java.math.BigInteger;
import java.net.InetAddress;
+import java.util.List;
public class OutboundNatService extends AbstractServiceInstance implements OutboundNatProvider {
public OutboundNatService() {
@Override
public Status programIpRewriteRule(Node node, Long dpid, String segmentationId, InetAddress matchAddress,
InetAddress rewriteAddress, Action action) {
- return new Status(StatusCode.NOTIMPLEMENTED);
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName);
+
+ // Instructions List Stores Individual Instructions
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionBuilder ib = new InstructionBuilder();
+
+ MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+ MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(matchAddress.getHostAddress()));
+
+ // Set Dest IP address
+ InstructionUtils.createNwDstInstructions(ib, new Ipv4Prefix(rewriteAddress.getHostAddress()));
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ // Goto Next Table
+ ib = getMutablePipelineInstructionBuilder();
+ ib.setOrder(1);
+ ib.setKey(new InstructionKey(1));
+ instructions.add(ib.build());
+
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ flowBuilder.setInstructions(isb.setInstruction(instructions).build());
+
+ String flowId = "OutboundNAT_" + rewriteAddress.getHostAddress();
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setPriority(1024);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ writeFlow(flowBuilder, nodeBuilder);
+
+ if (action.equals(Action.ADD)) {
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+
+ // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
+ return new Status(StatusCode.SUCCESS);
}
@Override
public Status programIpRewriteExclusion(Node node, Long dpid, String segmentationId, String excludedCidr,
Action action) {
- return new Status(StatusCode.NOTIMPLEMENTED);
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName);
+
+ // Instructions List Stores Individual Instructions
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionBuilder ib;
+
+ MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+ MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(excludedCidr));
+
+ // Goto Next Table
+ ib = getMutablePipelineInstructionBuilder();
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ flowBuilder.setInstructions(isb.setInstruction(instructions).build());
+
+ String flowId = "OutboundNATExclusion_" + excludedCidr;
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setPriority(1024);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ writeFlow(flowBuilder, nodeBuilder);
+
+ if (action.equals(Action.ADD)) {
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+
+ // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
+ return new Status(StatusCode.SUCCESS);
}
}
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
import org.opendaylight.ovsdb.openstack.netvirt.api.RoutingProvider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.OF13Provider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+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.flow.inventory.rev130819.FlowId;
+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.flow.InstructionsBuilder;
+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.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import com.google.common.collect.Lists;
+
+import java.math.BigInteger;
import java.net.InetAddress;
+import java.util.List;
public class RoutingService extends AbstractServiceInstance implements RoutingProvider {
public RoutingService() {
@Override
public Status programRouterInterface(Node node, Long dpid, String segmentationId, String macAddress,
InetAddress address, int mask, Action action) {
- return new Status(StatusCode.NOTIMPLEMENTED);
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName);
+
+ // Instructions List Stores Individual Instructions
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionBuilder ib = new InstructionBuilder();
+
+ String prefixString = address.getHostAddress() + "/" + mask;
+ MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+ MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(prefixString));
+
+ // Set source Mac address
+ InstructionUtils.createDlSrcInstructions(ib, new MacAddress(macAddress));
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ // DecTTL
+ InstructionUtils.createDecNwTtlInstructions(ib);
+ ib.setOrder(1);
+ ib.setKey(new InstructionKey(1));
+ instructions.add(ib.build());
+
+ // Goto Next Table
+ ib = getMutablePipelineInstructionBuilder();
+ ib.setOrder(2);
+ ib.setKey(new InstructionKey(2));
+ instructions.add(ib.build());
+
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ flowBuilder.setInstructions(isb.setInstruction(instructions).build());
+
+ String flowId = "Routing_" + prefixString;
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setPriority(2048);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ writeFlow(flowBuilder, nodeBuilder);
+
+ if (action.equals(Action.ADD)) {
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+
+ // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
+ return new Status(StatusCode.SUCCESS);
}
@Override
public Status programDefaultRouteEntry(Node node, Long dpid, String segmentationId, String macAddress,
InetAddress nextHop, Action action) {
- return new Status(StatusCode.NOTIMPLEMENTED);
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName);
+
+ MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+
+ // Instructions List Stores Individual Instructions
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionBuilder ib = new InstructionBuilder();
+
+ // Set source Mac address
+ InstructionUtils.createDlSrcInstructions(ib, new MacAddress(macAddress));
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ // DecTTL
+ InstructionUtils.createDecNwTtlInstructions(ib);
+ ib.setOrder(1);
+ ib.setKey(new InstructionKey(1));
+ instructions.add(ib.build());
+
+ // Goto Next Table
+ ib = getMutablePipelineInstructionBuilder();
+ ib.setOrder(2);
+ ib.setKey(new InstructionKey(2));
+ instructions.add(ib.build());
+
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ flowBuilder.setInstructions(isb.setInstruction(instructions).build());
+
+ String flowId = "DefaultRoute_" + nextHop.getHostAddress();
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setPriority(1024);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (action.equals(Action.ADD)) {
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+
+ // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
+ return new Status(StatusCode.SUCCESS);
}
}
public static final String EVENT_HANDLER_TYPE_PROPERTY = "eventHandlerType";
public static final String PROVIDER_NAME_PROPERTY = "providerName";
public static final String NAT_PROVIDER_DIRECTION = "natDirection";
+
+ /*
+ * MD-SAL
+ */
+
+ public static final String OPENFLOW_NODE_PREFIX = "openflow:";
+
+ /*
+ * Ethertypes
+ */
+ public static final long ARP_ETHERTYPE = 0x0806L;
}
package org.opendaylight.ovsdb.utils.mdsal.openflow;
-import java.math.BigInteger;
-
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;
import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.action.rev140421.OfjNxMpAlgorithm;
import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionMultipathNodesNodeTableFlowApplyActionsCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionResubmitNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNsiNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNspNodesNodeTableFlowApplyActionsCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.multipath.grouping.NxMultipath;
import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.multipath.grouping.NxMultipathBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.resubmit.grouping.NxResubmit;
import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.resubmit.grouping.NxResubmitBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNspNodesNodeTableFlowApplyActionsCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.set.nsp.grouping.NxSetNsp;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.set.nsp.grouping.NxSetNspBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNsiNodesNodeTableFlowApplyActionsCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.set.nsi.grouping.NxSetNsi;
import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.set.nsi.grouping.NxSetNsiBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.set.nsp.grouping.NxSetNsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.set.nsp.grouping.NxSetNspBuilder;
import com.google.common.net.InetAddresses;
+import java.math.BigInteger;
+
public final class ActionUtils {
public static Action dropAction() {
return new DropActionCaseBuilder()
import static org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils.dropAction;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
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.PopVlanActionCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCaseBuilder;
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.action.pop.vlan.action._case.PopVlanActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.dst.action._case.SetDlDstActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.src.action._case.SetDlSrcActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
+
+import com.google.common.collect.Lists;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.collect.Lists;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
public class InstructionUtils {
private static final Logger logger = LoggerFactory.getLogger(InstructionUtils.class);
return ib;
}
+ public static InstructionBuilder createDlSrcInstructions(InstructionBuilder ib, MacAddress macAddress) {
+
+ List<Action> actionList = Lists.newArrayList();
+ ActionBuilder ab = new ActionBuilder();
+
+ SetDlSrcActionBuilder dlSrcActionBuilder= new SetDlSrcActionBuilder();
+
+ dlSrcActionBuilder.setAddress(macAddress);
+
+ ab.setAction(new SetDlSrcActionCaseBuilder().setSetDlSrcAction(dlSrcActionBuilder.build()).build());
+ actionList.add(ab.build());
+
+ // Create an Apply Action
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+
+ // Wrap our Apply Action in an Instruction
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+
+ return ib;
+ }
+
+ public static InstructionBuilder createDlDstInstructions(InstructionBuilder ib, MacAddress macAddress) {
+
+ List<Action> actionList = Lists.newArrayList();
+ ActionBuilder ab = new ActionBuilder();
+
+ SetDlDstActionBuilder dlDstActionBuilder= new SetDlDstActionBuilder();
+
+ dlDstActionBuilder.setAddress(macAddress);
+
+ ab.setAction(new SetDlDstActionCaseBuilder().setSetDlDstAction(dlDstActionBuilder.build()).build());
+ actionList.add(ab.build());
+
+ // Create an Apply Action
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+
+ // Wrap our Apply Action in an Instruction
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+
+ return ib;
+ }
+
public static ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action>
actionList (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action... actions) {
}
return ins;
}
-}
\ No newline at end of file
+}