ovn: Avoid ARP responder for packets from localnet port
authorHan Zhou <zhouhan@gmail.com>
Fri, 26 Feb 2016 04:26:23 +0000 (20:26 -0800)
committerBen Pfaff <blp@ovn.org>
Sat, 27 Feb 2016 00:25:03 +0000 (16:25 -0800)
This is required by next commit that allows lswitch with localnet
port to be attached to multiple chassises. Without this patch, if
an ARP request comes from localnet port, on each chassis there will
be an ARP response, which is not desired.

An new stage ls_in_arp_rsp is introduced for ARP responder before
ls_in_l2_lkup.

Suggested-by: Russell Bryant <russell@ovn.org>
Signed-off-by: Han Zhou <zhouhan@gmail.com>
Acked-by: Russell Bryant <russell@ovn.org>
Signed-off-by: Ben Pfaff <blp@ovn.org>
ovn/northd/ovn-northd.8.xml
ovn/northd/ovn-northd.c

index 1b2912e..cacd760 100644 (file)
       </li>
     </ul>
 
-    <h3>Ingress Table 3: Destination Lookup</h3>
+    <h3>Ingress Table 3: ARP responder</h3>
 
     <p>
-      This table implements switching behavior.  It contains these logical
-      flows:
+      This table implements ARP responder for known IPs.  It contains these
+      logical flows:
     </p>
 
     <ul>
+      <li>
+        Priority-100 flows to skip ARP responder if inport is of type
+        <code>localnet</code>, and advances directly to table 3.
+      </li>
+
       <li>
         <p>
-          Priority-150 flows that matches ARP requests to each known IP address
+          Priority-50 flows that matches ARP requests to each known IP address
           <var>A</var> of logical port <var>P</var>, and respond with ARP
           replies directly with corresponding Ethernet address <var>E</var>:
         </p>
@@ -229,6 +234,20 @@ output;
         </p>
       </li>
 
+      <li>
+        One priority-0 fallback flow that matches all packets and advances to
+        table 4.
+      </li>
+    </ul>
+
+    <h3>Ingress Table 4: Destination Lookup</h3>
+
+    <p>
+      This table implements switching behavior.  It contains these logical
+      flows:
+    </p>
+
+    <ul>
       <li>
         A priority-100 flow that outputs all packets with an Ethernet broadcast
         or multicast <code>eth.dst</code> to the <code>MC_FLOOD</code>
index 63f3fcd..35ec267 100644 (file)
@@ -88,7 +88,8 @@ enum ovn_stage {
     PIPELINE_STAGE(SWITCH, IN,  PORT_SEC,    0, "ls_in_port_sec")     \
     PIPELINE_STAGE(SWITCH, IN,  PRE_ACL,     1, "ls_in_pre_acl")      \
     PIPELINE_STAGE(SWITCH, IN,  ACL,         2, "ls_in_acl")          \
-    PIPELINE_STAGE(SWITCH, IN,  L2_LKUP,     3, "ls_in_l2_lkup")      \
+    PIPELINE_STAGE(SWITCH, IN,  ARP_RSP,     3, "ls_in_arp_rsp")      \
+    PIPELINE_STAGE(SWITCH, IN,  L2_LKUP,     4, "ls_in_l2_lkup")      \
                                                                       \
     /* Logical switch egress stages. */                               \
     PIPELINE_STAGE(SWITCH, OUT, PRE_ACL,     0, "ls_out_pre_acl")     \
@@ -1280,8 +1281,23 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
         ds_destroy(&match);
     }
 
-    /* Ingress table 3: Destination lookup, ARP reply for known IPs.
-     * (priority 150). */
+    /* Ingress table 3: ARP responder, skip requests coming from localnet ports.
+     * (priority 100). */
+    HMAP_FOR_EACH (op, key_node, ports) {
+        if (!op->nbs) {
+            continue;
+        }
+
+        if (!strcmp(op->nbs->type, "localnet")) {
+            char *match = xasprintf("inport == %s", op->json_key);
+            ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_RSP, 100,
+                          match, "next;");
+            free(match);
+        }
+    }
+
+    /* Ingress table 3: ARP responder, reply for known IPs.
+     * (priority 50). */
     HMAP_FOR_EACH (op, key_node, ports) {
         if (!op->nbs) {
             continue;
@@ -1320,7 +1336,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
                     ETH_ADDR_ARGS(laddrs.ea),
                     ETH_ADDR_ARGS(laddrs.ea),
                     IP_ARGS(laddrs.ipv4_addrs[j].addr));
-                ovn_lflow_add(lflows, op->od, S_SWITCH_IN_L2_LKUP, 150,
+                ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_RSP, 50,
                               match, actions);
                 free(match);
                 free(actions);
@@ -1330,7 +1346,17 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
         }
     }
 
-    /* Ingress table 3: Destination lookup, broadcast and multicast handling
+    /* Ingress table 3: ARP responder, by default goto next.
+     * (priority 0)*/
+    HMAP_FOR_EACH (od, key_node, datapaths) {
+        if (!od->nbs) {
+            continue;
+        }
+
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_ARP_RSP, 0, "1", "next;");
+    }
+
+    /* Ingress table 4: Destination lookup, broadcast and multicast handling
      * (priority 100). */
     HMAP_FOR_EACH (op, key_node, ports) {
         if (!op->nbs) {
@@ -1350,7 +1376,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
                       "outport = \""MC_FLOOD"\"; output;");
     }
 
-    /* Ingress table 3: Destination lookup, unicast handling (priority 50), */
+    /* Ingress table 4: Destination lookup, unicast handling (priority 50), */
     HMAP_FOR_EACH (op, key_node, ports) {
         if (!op->nbs) {
             continue;
@@ -1387,7 +1413,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
         }
     }
 
-    /* Ingress table 3: Destination lookup for unknown MACs (priority 0). */
+    /* Ingress table 4: Destination lookup for unknown MACs (priority 0). */
     HMAP_FOR_EACH (od, key_node, datapaths) {
         if (!od->nbs) {
             continue;