BUG-5110 Enable pinging any router
authorJosh <jhershbe@redhat.com>
Wed, 27 Jan 2016 16:08:12 +0000 (18:08 +0200)
committerJosh <jhershbe@redhat.com>
Sun, 31 Jan 2016 16:07:41 +0000 (18:07 +0200)
Works like this:
In table 60, routed packets have their src MACs
saved to reg4 and reg5

In table 70:
ICMP echos are responded to, for routed packets
and for pings to routers on the same LAN

Change-Id: I23e3a6ef5397aa687e14745841efeccc3f7a5301
Signed-off-by: Josh <jhershbe@redhat.com>
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/Service.java
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IcmpEchoResponderService.java
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/RoutingService.java
utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/ActionUtils.java

index 1ba5b82d9df2064ff89ce93fe31ac9909ff057dc..cb6e0f5e77f1787a1893c5c776b0466feaabbbe0 100644 (file)
@@ -17,11 +17,11 @@ public enum Service {
     DIRECTOR ((short) 10, "Director"),
     SFC_CLASSIFIER ((short) 10, "SFC Classifier"),
     ARP_RESPONDER ((short) 20, "Distributed ARP Responder"),
-    ICMP_ECHO ((short) 20, "Distributed ICMP Echo Responder"),
     INBOUND_NAT ((short) 30, "DNAT for inbound floating-ip traffic"),
     EGRESS_ACL ((short) 40, "Egress Acces-control"),
     LOAD_BALANCER ((short) 50, "Distributed LBaaS"),
     ROUTING ((short) 60, "Distributed Virtual Routing (DVR)"),
+    ICMP_ECHO ((short) 70, "Distributed ICMP Echo Responder"),
     L3_FORWARDING ((short) 70, "Layer 3 forwarding/lookup service"),
     L2_REWRITE ((short) 80, "Layer2 rewrite service"),
     INGRESS_ACL ((short) 90, "Ingress Acces-control"),
index 708eecb43d717e9bbf514d08fe8dcefda8f1fc0f..174a81baa5661e81f8c830979f7fbaeff41cc275 100644 (file)
@@ -11,7 +11,6 @@ import com.google.common.collect.Lists;
 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;
@@ -30,6 +29,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 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;
@@ -45,6 +49,8 @@ import java.util.List;
  */
 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);
@@ -56,28 +62,8 @@ public class IcmpEchoResponderService extends AbstractServiceInstance implements
 
     @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
@@ -87,61 +73,118 @@ public class IcmpEchoResponderService extends AbstractServiceInstance implements
             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);
index 5006e7fd3e475b6b2dae75ca7183c2bdc76f9b70..fbc2e8d0162c7846ec7a457482a66ba2220df751 100644 (file)
@@ -40,6 +40,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 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;
@@ -73,8 +77,9 @@ public class RoutingService extends AbstractServiceInstance implements RoutingPr
         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,
@@ -96,22 +101,41 @@ public class RoutingService extends AbstractServiceInstance implements RoutingPr
             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
index 40411d103855c0962d1057bd3ffb82c29abf28e2..dfaed3a3ac8a806ba45229a49623ae93aea46867 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015 Red Hat, Inc. and others. All rights reserved.
+ * Copyright (c) 2014 - 2016 Red Hat, 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,
@@ -268,16 +268,24 @@ public final class ActionUtils {
                                          DstChoice dstChoice,
                                          int endOffset,
                                          boolean groupBucket) {
+        return nxMoveRegAction(srcChoice, dstChoice, 0, 0, endOffset, groupBucket);
+    }
+
+    public static Action nxMoveRegAction(SrcChoice srcChoice,
+                                         DstChoice dstChoice,
+                                         int srcStartOffset,
+                                         int dstStartOffset,
+                                         int dstEndOffset,
+                                         boolean groupBucket) {
         NxRegMove r = new NxRegMoveBuilder()
             .setSrc(new SrcBuilder()
                 .setSrcChoice(srcChoice)
-                .setStart(0)
-                .setEnd(endOffset)
+                .setStart(srcStartOffset)
                 .build())
             .setDst(new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.nx.reg.move.DstBuilder()
                 .setDstChoice(dstChoice)
-                .setStart(0)
-                .setEnd(endOffset)
+                .setStart(dstStartOffset)
+                .setEnd(dstEndOffset)
                 .build())
             .build();
         if (groupBucket) {