import org.opendaylight.ovsdb.openstack.netvirt.api.*;
import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
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.FlowUtils;
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.openflowjava.nx.match.rev140421.NxmNxReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfEthDstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxRegCaseBuilder;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
*/
public class IcmpEchoResponderService extends AbstractServiceInstance implements IcmpEchoProvider, ConfigInterface {
private static final Logger LOG = LoggerFactory.getLogger(IcmpEchoResponderService.class);
+ public static final Class<? extends NxmNxReg> SRC_MAC_4_HIGH_BYTES_FIELD = NxmNxReg4.class;
+ public static final Class<? extends NxmNxReg> SRC_MAC_2_LOW_BYTES_FIELD = NxmNxReg5.class;
public IcmpEchoResponderService() {
super(Service.ICMP_ECHO);
@Override
public Status programIcmpEchoEntry(Long dpid, String segmentationId, String macAddressStr, InetAddress ipAddress, Action action) {
- String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
- MacAddress macAddress = new MacAddress(macAddressStr);
- 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();
- ApplyActionsBuilder aab = new ApplyActionsBuilder();
- ActionBuilder ab = new ActionBuilder();
- List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actionList = Lists.newArrayList();
-
- if (segmentationId != null) {
- final Long inPort = MatchUtils.parseExplicitOFPort(segmentationId);
- if (inPort != null) {
- MatchUtils.createInPortMatch(matchBuilder, dpid, inPort);
- } else {
- MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
- }
- }
+ if (segmentationId == null) return new Status(StatusCode.BADREQUEST);
if (ipAddress instanceof Inet6Address) {
// WORKAROUND: For now ipv6 is not supported
return new Status(StatusCode.NOTIMPLEMENTED);
}
+ MacAddress macAddress = new MacAddress(macAddressStr);
+
+ programEntry(dpid, segmentationId, macAddress, ipAddress, true, action);
+ programEntry(dpid, segmentationId, macAddress, ipAddress, false, action);
+
+ // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
+ return new Status(StatusCode.SUCCESS);
+ }
+
+ private Status programEntry(long dpid, String segmentationId, MacAddress macAddress, InetAddress ipAddress, boolean isRouted, Action action) {
+ FlowBuilder flowBuilder = new FlowBuilder();
+ String flowName = (isRouted ? "RoutedIcmpEchoResponder_" : "LanIcmpEchoResponder_")
+ + segmentationId + "_" + ipAddress.getHostAddress();
+
+ //The non-routed flow has an extra match condition and it must therefor be of a higher
+ //prio to make sure we get a "best match" kind of logic between the two
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(isRouted ? 2048 : 2049);
+
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid);
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+
+ MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+
// Match ICMP echo requests, type=8, code=0
- MatchUtils.createICMPv4Match(matchBuilder, (short)8, (short)0);
+ MatchUtils.createICMPv4Match(matchBuilder, (short) 8, (short) 0);
MatchUtils.createDstL3IPv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(ipAddress.getHostAddress()));
- // Move Eth Src to Eth Dst
- ab.setAction(ActionUtils.nxMoveEthSrcToEthDstAction());
- ab.setOrder(0);
- ab.setKey(new ActionKey(0));
- actionList.add(ab.build());
-
- // Set Eth Src
- ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress)));
- ab.setOrder(1);
- ab.setKey(new ActionKey(1));
- actionList.add(ab.build());
-
- // Move Ip Src to Ip Dst
- ab.setAction(ActionUtils.nxMoveIpSrcToIpDstAction());
- ab.setOrder(2);
- ab.setKey(new ActionKey(2));
- actionList.add(ab.build());
-
- // Set Ip Src
- ab.setAction(ActionUtils.setNwSrcAction(new Ipv4Builder().setIpv4Address(
- MatchUtils.iPv4PrefixFromIPv4Address(ipAddress.getHostAddress())).build()));
- ab.setOrder(3);
- ab.setKey(new ActionKey(3));
- actionList.add(ab.build());
-
- // Set the ICMP type to 0 (echo reply)
- ab.setAction(ActionUtils.setIcmpTypeAction((byte)0));
- ab.setOrder(4);
- ab.setKey(new ActionKey(4));
- actionList.add(ab.build());
-
- // Output of InPort
- ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":INPORT")));
- ab.setOrder(5);
- ab.setKey(new ActionKey(5));
- actionList.add(ab.build());
-
- // Create Apply Actions Instruction
- aab.setAction(actionList);
- ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
- ib.setOrder(0);
- ib.setKey(new InstructionKey(0));
- instructions.add(ib.build());
+ if (!isRouted) {
+ //packets that have been "routed" in table 60 (DVR) will have their src MAC in nxm_nx_reg4 and nxm_nx_reg5
+ //here we check that nxm_nx_reg4 is empty to check whether the packet has *not* been router since its
+ //destination is on the same LAN
+ MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(SRC_MAC_4_HIGH_BYTES_FIELD, 0x0L));
+ }
- FlowBuilder flowBuilder = new FlowBuilder();
- String flowName = "IcmpEchoResponder_" + segmentationId + "_" + ipAddress.getHostAddress();
- FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(1024);
flowBuilder.setMatch(matchBuilder.build());
- flowBuilder.setInstructions(isb.setInstruction(instructions).build());
if (action.equals(Action.ADD)) {
+ // Instructions List Stores Individual Instructions
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionBuilder ib = new InstructionBuilder();
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ ActionBuilder ab = new ActionBuilder();
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actionList = Lists.newArrayList();
+
+ if (isRouted) {
+ ab.setAction(
+ ActionUtils.nxMoveRegAction(
+ new SrcNxRegCaseBuilder().setNxReg(SRC_MAC_4_HIGH_BYTES_FIELD).build(),
+ new DstOfEthDstCaseBuilder().setOfEthDst(true).build(),
+ 0, 0, 31, false));
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
+ actionList.add(ab.build());
+
+ ab.setAction(
+ ActionUtils.nxMoveRegAction(
+ new SrcNxRegCaseBuilder().setNxReg(SRC_MAC_2_LOW_BYTES_FIELD).build(),
+ new DstOfEthDstCaseBuilder().setOfEthDst(true).build(),
+ 0, 32, 47, false));
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
+ actionList.add(ab.build());
+ } else {
+ ab.setAction(ActionUtils.nxMoveEthSrcToEthDstAction());
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
+ actionList.add(ab.build());
+ }
+
+ // Set Eth Src
+ ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress)));
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
+ actionList.add(ab.build());
+
+ // Move Ip Src to Ip Dst
+ ab.setAction(ActionUtils.nxMoveIpSrcToIpDstAction());
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
+ actionList.add(ab.build());
+
+ // Set Ip Src
+ ab.setAction(ActionUtils.setNwSrcAction(new Ipv4Builder().setIpv4Address(
+ MatchUtils.iPv4PrefixFromIPv4Address(ipAddress.getHostAddress())).build()));
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
+ actionList.add(ab.build());
+
+ // Set the ICMP type to 0 (echo reply)
+ ab.setAction(ActionUtils.setIcmpTypeAction((byte)0));
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
+ actionList.add(ab.build());
+
+ // Output of InPort
+ ab.setAction(ActionUtils.outputAction(new NodeConnectorId(
+ nodeBuilder.getId().getValue() + ":INPORT")));
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
+ actionList.add(ab.build());
+
+ // Create Apply Actions Instruction
+ aab.setAction(actionList);
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ flowBuilder.setInstructions(isb.setInstruction(instructions).build());
+
writeFlow(flowBuilder, nodeBuilder);
} else {
removeFlow(flowBuilder, nodeBuilder);
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
import com.google.common.collect.Lists;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfEthSrcCaseBuilder;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
String flowName = "Routing_" + sourceSegId + "_" + destSegId + "_" + prefixString;
FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(2048);
+ boolean isExternalNet = sourceSegId.equals(Constants.EXTERNAL_NETWORK);
MatchBuilder matchBuilder = new MatchBuilder();
- if (sourceSegId.equals(Constants.EXTERNAL_NETWORK)) {
+ if (isExternalNet) {
// If matching on external network, use register reserved for InboundNatService to ensure that
// ip rewrite is meant to be consumed by this destination tunnel id.
MatchUtils.addNxRegMatch(matchBuilder,
List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actionList
= Lists.newArrayList();
+ //if this is an east<->west route, save the src mac in case this is an ICMP echo request
+ if(!isExternalNet) {
+ ab.setAction(ActionUtils.nxMoveRegAction(
+ new SrcOfEthSrcCaseBuilder().setOfEthSrc(Boolean.TRUE).build(),
+ new DstNxRegCaseBuilder().setNxReg(IcmpEchoResponderService.SRC_MAC_4_HIGH_BYTES_FIELD).build(),
+ 0,0,31, false));
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
+ actionList.add(ab.build());
+
+ ab.setAction(ActionUtils.nxMoveRegAction(
+ new SrcOfEthSrcCaseBuilder().setOfEthSrc(Boolean.TRUE).build(),
+ new DstNxRegCaseBuilder().setNxReg(IcmpEchoResponderService.SRC_MAC_2_LOW_BYTES_FIELD).build(),
+ 32,0,15, false));
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
+ actionList.add(ab.build());
+ }
+
// Set source Mac address
ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress)));
- ab.setOrder(0);
- ab.setKey(new ActionKey(0));
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
actionList.add(ab.build());
// DecTTL
ab.setAction(ActionUtils.decNwTtlAction());
- ab.setOrder(1);
- ab.setKey(new ActionKey(1));
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
actionList.add(ab.build());
// Set Destination Tunnel ID
ab.setAction(ActionUtils.setTunnelIdAction(new BigInteger(destSegId)));
- ab.setOrder(2);
- ab.setKey(new ActionKey(2));
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
actionList.add(ab.build());
// Create Apply Actions Instruction