Rate limiting for ARP packet punts 84/72084/7
authorRavindra Thakur <ravindra.nath.thakur@ericsson.com>
Fri, 18 May 2018 08:20:26 +0000 (13:50 +0530)
committerSam Hague <shague@redhat.com>
Wed, 20 Jun 2018 12:25:50 +0000 (12:25 +0000)
spec link:
http://docs.opendaylight.org/projects/netvirt/en/latest/specs/fluorine/controller-punt-protection.html

Issue: NETVIRT-1218

Depends-On: https://git.opendaylight.org/gerrit/#/c/72006/
Depends-On: https://git.opendaylight.org/gerrit/#/c/72007/

Change-Id: I726abd103a6a680b6548e0069b06c5e0a049e512
Signed-off-by: Ravindra Thakur <ravindra.nath.thakur@ericsson.com>
elanmanager/api/src/main/java/org/opendaylight/netvirt/elan/arp/responder/ArpResponderUtil.java
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanNodeListener.java
elanmanager/impl/src/main/resources/initial/netvirt-elanmanager-config.xml

index 946b643728292b03448c3bc4492b865d77557daf..2a51c58493a7c3483550294459e8e5e9a5b42596 100644 (file)
@@ -37,7 +37,6 @@ import org.opendaylight.genius.mdsalutil.actions.ActionMoveSourceDestinationEth;
 import org.opendaylight.genius.mdsalutil.actions.ActionMoveSpaToTpa;
 import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadInPort;
 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
-import org.opendaylight.genius.mdsalutil.actions.ActionPuntToController;
 import org.opendaylight.genius.mdsalutil.actions.ActionSetArpOp;
 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetSource;
 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
@@ -126,27 +125,20 @@ public final class ArpResponderUtil {
      * Get Bucket Actions for ARP Responder Group Flow.
      *
      * <p>
-     * Install Default Groups, Group has 3 Buckets
+     * Install Default Groups, Group has 1 Bucket
      * </p>
      * <ul>
-     * <li>Punt to controller</li>
-     * <li>Resubmit to Table {@link NwConstants#LPORT_DISPATCHER_TABLE}, for
-     * ELAN flooding
      * <li>Resubmit to Table {@link NwConstants#ARP_RESPONDER_TABLE}, for ARP
      * Auto response from DPN itself</li>
      * </ul>
      *
      * @param resubmitTableId
      *            Resubmit Flow Table Id
-     * @param resubmitTableId2
-     *            Resubmit Flow Table Id
      * @return List of bucket actions
      */
-    public static List<BucketInfo> getDefaultBucketInfos(short resubmitTableId, short resubmitTableId2) {
+    public static List<BucketInfo> getDefaultBucketInfos(short resubmitTableId) {
         return Arrays.asList(
-                new BucketInfo(Collections.singletonList(new ActionPuntToController())),
-                new BucketInfo(Collections.singletonList(new ActionNxResubmit(resubmitTableId))),
-                new BucketInfo(Collections.singletonList(new ActionNxResubmit(resubmitTableId2))));
+                new BucketInfo(Collections.singletonList(new ActionNxResubmit(resubmitTableId))));
     }
 
     /**
index 7b9db79103423f00bd64e4f0a58545a653d19452..2e068a23976865f51c4b966c37adc68890788f5d 100644 (file)
@@ -28,12 +28,18 @@ import org.opendaylight.genius.mdsalutil.InstructionInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MatchInfo;
 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
+import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.NwConstants.NxmOfFieldType;
 import org.opendaylight.genius.mdsalutil.actions.ActionDrop;
 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
 import org.opendaylight.genius.mdsalutil.actions.ActionLearn;
+import org.opendaylight.genius.mdsalutil.actions.ActionLearn.CopyFromValue;
+import org.opendaylight.genius.mdsalutil.actions.ActionLearn.MatchFromField;
+import org.opendaylight.genius.mdsalutil.actions.ActionLearn.MatchFromValue;
 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
 import org.opendaylight.genius.mdsalutil.actions.ActionPuntToController;
+import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
@@ -61,12 +67,17 @@ public class ElanNodeListener extends AsyncDataTreeChangeListenerBase<Node, Elan
 
     private static final Logger LOG = LoggerFactory.getLogger(ElanNodeListener.class);
     private static final int LEARN_MATCH_REG4_VALUE = 1;
+    private static final int ARP_LEARN_FLOW_PRIORITY = 10;
+    private static final int ARP_LEARN_MATCH_VALUE = 0x1;
+    private static final int GARP_LEARN_MATCH_VALUE = 0x101;
+    private static final long ARP_LEARN_MATCH_MASK = 0xFFFFL;
 
     private final DataBroker broker;
     private final ManagedNewTransactionRunner txRunner;
     private final IMdsalApiManager mdsalManager;
     private final IdManagerService idManagerService;
     private final int tempSmacLearnTimeout;
+    private final int arpPuntTimeout;
     private final boolean puntLldpToController;
     private final JobCoordinator jobCoordinator;
 
@@ -77,6 +88,7 @@ public class ElanNodeListener extends AsyncDataTreeChangeListenerBase<Node, Elan
         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.mdsalManager = mdsalManager;
         this.tempSmacLearnTimeout = elanConfig.getTempSmacLearnTimeout();
+        this.arpPuntTimeout = elanConfig.getArpPuntTimeout().intValue();
         this.puntLldpToController = elanConfig.isPuntLldpToController();
         this.idManagerService = idManagerService;
         this.jobCoordinator = jobCoordinator;
@@ -121,6 +133,9 @@ public class ElanNodeListener extends AsyncDataTreeChangeListenerBase<Node, Elan
                 LOG.debug("Received notification to install Arp Check Default entries for dpn {} ", dpId);
                 createArpRequestMatchFlows(dpId, tx);
                 createArpResponseMatchFlows(dpId, tx);
+                createArpPuntAndLearnFlow(dpId, tx);
+                addGarpLearnMatchFlow(dpId, tx);
+                addArpLearnMatchFlow(dpId, tx);
             })));
     }
 
@@ -298,26 +313,122 @@ public class ElanNodeListener extends AsyncDataTreeChangeListenerBase<Node, Elan
     private void createArpRequestMatchFlows(BigInteger dpId, WriteTransaction writeFlowTx) {
 
         long arpRequestGroupId = ArpResponderUtil.retrieveStandardArpResponderGroupId(idManagerService);
-        List<BucketInfo> buckets = ArpResponderUtil.getDefaultBucketInfos(NwConstants.ELAN_BASE_TABLE,
-                NwConstants.ARP_RESPONDER_TABLE);
+        List<BucketInfo> buckets = ArpResponderUtil.getDefaultBucketInfos(NwConstants.ARP_RESPONDER_TABLE);
         ArpResponderUtil.installGroup(mdsalManager, dpId, arpRequestGroupId,
                 ArpResponderConstant.GROUP_FLOW_NAME.value(), buckets);
 
         FlowEntity arpReqArpCheckTbl = ArpResponderUtil.createArpDefaultFlow(dpId, NwConstants.ARP_CHECK_TABLE,
-                NwConstants.ARP_REQUEST, () -> Arrays.asList(MatchEthernetType.ARP, MatchArpOp.REQUEST),
-            () -> Collections.singletonList(new ActionGroup(arpRequestGroupId)));
+                NwConstants.ARP_REQUEST, () -> Arrays.asList(MatchEthernetType.ARP, MatchArpOp.REQUEST), () ->
+                        Arrays.asList(new ActionGroup(arpRequestGroupId),
+                                new ActionNxResubmit(NwConstants.ARP_LEARN_TABLE_1),
+                                new ActionNxResubmit(NwConstants.ARP_LEARN_TABLE_2),
+                                new ActionNxResubmit(NwConstants.ELAN_BASE_TABLE)));
         LOG.trace("Invoking MDSAL to install Arp Rquest Match Flow for table {}", NwConstants.ARP_CHECK_TABLE);
         mdsalManager.addFlowToTx(arpReqArpCheckTbl, writeFlowTx);
-
     }
 
     private void createArpResponseMatchFlows(BigInteger dpId, WriteTransaction writeFlowTx) {
         FlowEntity arpRepArpCheckTbl = ArpResponderUtil.createArpDefaultFlow(dpId, NwConstants.ARP_CHECK_TABLE,
-                NwConstants.ARP_REPLY, () -> Arrays.asList(MatchEthernetType.ARP, MatchArpOp.REPLY),
-            () -> Arrays.asList(new ActionPuntToController(), new ActionNxResubmit(NwConstants.ELAN_BASE_TABLE)));
+                NwConstants.ARP_REPLY, () -> Arrays.asList(MatchEthernetType.ARP, MatchArpOp.REPLY), () ->
+                        Arrays.asList(new ActionNxResubmit(NwConstants.ARP_LEARN_TABLE_1),
+                                new ActionNxResubmit(NwConstants.ARP_LEARN_TABLE_2),
+                                new ActionNxResubmit(NwConstants.ELAN_BASE_TABLE)));
         LOG.trace("Invoking MDSAL to install  Arp Reply Match Flow for Table {} ", NwConstants.ARP_CHECK_TABLE);
         mdsalManager.addFlowToTx(arpRepArpCheckTbl, writeFlowTx);
+    }
+
+    private void createArpPuntAndLearnFlow(BigInteger dpId, WriteTransaction writeFlowTx) {
+        LOG.debug("adding arp punt and learn entry in table {}", NwConstants.ARP_LEARN_TABLE_1);
+
+        List<MatchInfo> matches = new ArrayList<>();
+        List<ActionInfo> actions = new ArrayList<>();
+        BigInteger cookie = new BigInteger("88880000", 16);
+
+        matches.add(MatchEthernetType.ARP);
+        actions.add(new ActionPuntToController());
+        if (arpPuntTimeout != 0) {
+            actions.add(new ActionLearn(0, arpPuntTimeout, ARP_LEARN_FLOW_PRIORITY, cookie, 0,
+                    NwConstants.ARP_LEARN_TABLE_1, 0, 0,
+                    Arrays.asList(
+                            new MatchFromValue(NwConstants.ETHTYPE_ARP, NxmOfFieldType.NXM_OF_ETH_TYPE.getType(),
+                                    NxmOfFieldType.NXM_OF_ETH_TYPE.getFlowModHeaderLenInt()),
+                            new MatchFromField(NxmOfFieldType.NXM_OF_ARP_SPA.getType(),
+                                    NxmOfFieldType.NXM_OF_ARP_SPA.getType(),
+                                    NxmOfFieldType.NXM_OF_ARP_SPA.getFlowModHeaderLenInt()),
+                            new MatchFromField(NxmOfFieldType.NXM_OF_ARP_TPA.getType(),
+                                    NxmOfFieldType.NXM_OF_ARP_TPA.getType(),
+                                    NxmOfFieldType.NXM_OF_ARP_TPA.getFlowModHeaderLenInt()),
+                            new ActionLearn.MatchFromField(NxmOfFieldType.OXM_OF_METADATA.getType(),
+                                    MetaDataUtil.METADATA_ELAN_TAG_OFFSET,
+                                    NxmOfFieldType.OXM_OF_METADATA.getType(), MetaDataUtil.METADATA_ELAN_TAG_OFFSET,
+                                    ElanConstants.ELAN_TAG_LENGTH),
+                            new CopyFromValue(1, NxmOfFieldType.NXM_NX_REG4.getType(), 8))));
+
+            actions.add(new ActionLearn(0, arpPuntTimeout, ARP_LEARN_FLOW_PRIORITY, cookie, 0,
+                    NwConstants.ARP_LEARN_TABLE_2, 0, 0,
+                    Arrays.asList(
+                            new MatchFromValue(NwConstants.ETHTYPE_ARP, NxmOfFieldType.NXM_OF_ETH_TYPE.getType(),
+                                    NxmOfFieldType.NXM_OF_ETH_TYPE.getFlowModHeaderLenInt()),
+                            new MatchFromField(NxmOfFieldType.NXM_OF_ARP_SPA.getType(),
+                                    NxmOfFieldType.NXM_OF_ARP_TPA.getType(),
+                                    NxmOfFieldType.NXM_OF_ARP_SPA.getFlowModHeaderLenInt()),
+                            new MatchFromField(NxmOfFieldType.NXM_OF_ARP_TPA.getType(),
+                                    NxmOfFieldType.NXM_OF_ARP_SPA.getType(),
+                                    NxmOfFieldType.NXM_OF_ARP_TPA.getFlowModHeaderLenInt()),
+                            new ActionLearn.MatchFromField(NxmOfFieldType.OXM_OF_METADATA.getType(),
+                                    MetaDataUtil.METADATA_ELAN_TAG_OFFSET, NxmOfFieldType.OXM_OF_METADATA.getType(),
+                                    MetaDataUtil.METADATA_ELAN_TAG_OFFSET, MetaDataUtil.METADATA_ELAN_TAG_BITLEN),
+                            new CopyFromValue(1, NxmOfFieldType.NXM_NX_REG4.getType(), 8, 8))));
+        }
+
+        List<InstructionInfo> instructions = new ArrayList<>();
+        instructions.add(new InstructionApplyActions(actions));
+        String flowid = String.valueOf(NwConstants.ARP_LEARN_TABLE_1) + NwConstants.FLOWID_SEPARATOR + "arp.punt";
+        FlowEntity flow = MDSALUtil.buildFlowEntity(dpId, NwConstants.ARP_LEARN_TABLE_1, flowid,
+                NwConstants.TABLE_MISS_PRIORITY, "arp punt/learn flow", 0,
+                0, cookie, matches, instructions);
+        mdsalManager.addFlowToTx(flow, writeFlowTx);
+    }
+
+    private void addGarpLearnMatchFlow(BigInteger dpId, WriteTransaction writeFlowTx) {
+        List<ActionInfo> actions = new ArrayList<>();
+        List<MatchInfoBase> matches = new ArrayList<>();
+
+        matches.add(MatchEthernetType.ARP);
+        matches.add(new NxMatchRegister(NxmNxReg4.class, GARP_LEARN_MATCH_VALUE, ARP_LEARN_MATCH_MASK));
+
+        actions.add(new ActionRegLoad(NxmNxReg4.class, 0, 31, 0));
+        actions.add(new ActionPuntToController());
+        actions.add(new ActionNxResubmit(NwConstants.ELAN_SMAC_LEARNED_TABLE));
+        actions.add(new ActionNxResubmit(NwConstants.ELAN_SMAC_TABLE));
+
+        List<InstructionInfo> instructions = new ArrayList<>();
+        instructions.add(new InstructionApplyActions(actions));
+        String flowid = String.valueOf(NwConstants.ELAN_BASE_TABLE) + NwConstants.FLOWID_SEPARATOR + "garp.match";
+        FlowEntity garpFlow = MDSALUtil.buildFlowEntity(dpId, NwConstants.ELAN_BASE_TABLE, flowid,
+                NwConstants.DEFAULT_ARP_FLOW_PRIORITY, "GARP learn match flow", 0, 0,
+                ElanConstants.COOKIE_ELAN_BASE_SMAC, matches, instructions);
+        mdsalManager.addFlowToTx(garpFlow, writeFlowTx);
+    }
+
+    private void addArpLearnMatchFlow(BigInteger dpId, WriteTransaction writeFlowTx) {
+        List<ActionInfo> actions = new ArrayList<>();
+        List<MatchInfoBase> matches = new ArrayList<>();
+
+        matches.add(MatchEthernetType.ARP);
+        matches.add(new NxMatchRegister(NxmNxReg4.class, ARP_LEARN_MATCH_VALUE, ARP_LEARN_MATCH_MASK));
+
+        actions.add(new ActionRegLoad(NxmNxReg4.class, 0, 31, 0));
+        actions.add(new ActionNxResubmit(NwConstants.ELAN_SMAC_LEARNED_TABLE));
+        actions.add(new ActionNxResubmit(NwConstants.ELAN_SMAC_TABLE));
 
+        List<InstructionInfo> instructions = new ArrayList<>();
+        instructions.add(new InstructionApplyActions(actions));
+        String flowid = String.valueOf(NwConstants.ELAN_BASE_TABLE) + NwConstants.FLOWID_SEPARATOR + "arp.match";
+        FlowEntity arpFlow = MDSALUtil.buildFlowEntity(dpId, NwConstants.ELAN_BASE_TABLE, flowid,
+                NwConstants.DEFAULT_ARP_FLOW_PRIORITY, "ARP learn match flow", 0, 0,
+                ElanConstants.COOKIE_ELAN_BASE_SMAC, matches, instructions);
+        mdsalManager.addFlowToTx(arpFlow, writeFlowTx);
     }
 
 }
index cf574c9060ffc9740b46ef2275f086dc1554d60a..3016c6bd2fe48b03f6d0c2b471479774e098e040 100644 (file)
@@ -2,6 +2,7 @@
   <auto-create-bridge>true</auto-create-bridge>
   <int-bridge-gen-mac>true</int-bridge-gen-mac>
   <temp-smac-learn-timeout>10</temp-smac-learn-timeout>
+  <arp-punt-timeout>5</arp-punt-timeout>
   <punt-lldp-to-controller>false</punt-lldp-to-controller>
   <!--
   <controller-max-backoff>5000</controller-max-backoff>