diff mbox

[ovs-dev,v4,2/2] ovn: add lflows for 'na' action for ND

Message ID 1465960204-17141-1-git-send-email-zealokii@gmail.com
State Superseded
Headers show

Commit Message

Zong Kai LI June 15, 2016, 3:10 a.m. UTC
This patch adds some lflows for 'na' action to support ND versus ARP.

For ovn-northd, it will generate lflows per each lport with its IPv6
addresses and mac addresss, with 'na' action.

e.g. match=(icmp6 && icmp6.type == 135 &&
            (nd.target == fd81:ce49:a948:0:f816:3eff:fe46:8a42 ||
             nd.target == fd81:ce49:b123:0:f816:3eff:fe46:8a42)),
     action=(na { eth.src = fa:16:3e:46:8a:42; nd.tll = fa:16:3e:46:8a:42;
                  outport = inport;
                  inport = ""; /* Allow sending out inport. */ output; };)

And new lflows will be set in tabel ls_in_arp_nd_rsp, which is renamed
from previous ls_in_arp_rsp.

This patch also modified current ACL lflows for ND, not to do conntrack
on ND packets in following tables:
 - S_SWITCH_IN_PRE_ACL
 - S_SWITCH_OUT_PRE_ACL
 - S_SWITCH_IN_ACL
 - S_SWITCH_OUT_ACL

Signed-off-by: Zong Kai LI <zealokii@gmail.com>
---
 ovn/northd/ovn-northd.c  | 57 +++++++++++++++++++++++++++++++++++++++++-------
 tutorial/OVN-Tutorial.md |  6 ++---
 2 files changed, 52 insertions(+), 11 deletions(-)
diff mbox

Patch

diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index d53fca9..20d8c98 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -93,7 +93,7 @@  enum ovn_stage {
     PIPELINE_STAGE(SWITCH, IN,  PORT_SEC_ND,    2, "ls_in_port_sec_nd")     \
     PIPELINE_STAGE(SWITCH, IN,  PRE_ACL,        3, "ls_in_pre_acl")      \
     PIPELINE_STAGE(SWITCH, IN,  ACL,            4, "ls_in_acl")          \
-    PIPELINE_STAGE(SWITCH, IN,  ARP_RSP,        5, "ls_in_arp_rsp")      \
+    PIPELINE_STAGE(SWITCH, IN,  ARP_ND_RSP,     5, "ls_in_arp_nd_rsp")      \
     PIPELINE_STAGE(SWITCH, IN,  L2_LKUP,        6, "ls_in_l2_lkup")      \
                                                                       \
     /* Logical switch egress stages. */                               \
@@ -1383,6 +1383,12 @@  build_acls(struct ovn_datapath *od, struct hmap *lflows, struct hmap *ports)
         ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_ACL, 100, "ip", "ct_next;");
         ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_ACL, 100, "ip", "ct_next;");
 
+        /* Ingress and Egress Pre-ACL Table (Priority 110).
+         *
+         * Not to do conntrack on ND packets. */
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_ACL, 110, "nd", "next;");
+        ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_ACL, 110, "nd", "next;");
+
         /* Ingress and Egress ACL Table (Priority 1).
          *
          * By default, traffic is allowed.  This is partially handled by
@@ -1433,6 +1439,12 @@  build_acls(struct ovn_datapath *od, struct hmap *lflows, struct hmap *ports)
         ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX,
                       "!ct.est && ct.rel && !ct.new && !ct.inv",
                       "next;");
+
+        /* Ingress and Egress ACL Table (Priority 65535).
+         *
+         * Not to do conntrack on ND packets. */
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, 65535, "nd", "next;");
+        ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, 65535, "nd", "next;");
     }
 
     /* Ingress or Egress ACL Table (Various priorities). */
@@ -1566,13 +1578,13 @@  build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
 
         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,
+            ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 100,
                           match, "next;");
             free(match);
         }
     }
 
-    /* Ingress table 5: ARP responder, reply for known IPs.
+    /* Ingress table 5: ARP/ND responder, reply for known IPs.
      * (priority 50). */
     HMAP_FOR_EACH (op, key_node, ports) {
         if (!op->nbs) {
@@ -1580,7 +1592,7 @@  build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
         }
 
         /*
-         * Add ARP reply flows if either the
+         * Add ARP/ND reply flows if either the
          *  - port is up or
          *  - port type is router
          */
@@ -1591,7 +1603,7 @@  build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
         for (size_t i = 0; i < op->nbs->n_addresses; i++) {
             struct lport_addresses laddrs;
             if (!extract_lsp_addresses(op->nbs->addresses[i], &laddrs,
-                                       false)) {
+                                       true)) {
                 continue;
             }
             for (size_t j = 0; j < laddrs.n_ipv4_addrs; j++) {
@@ -1612,24 +1624,53 @@  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_ARP_RSP, 50,
+                ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 50,
                               match, actions);
                 free(match);
                 free(actions);
             }
 
+            if (laddrs.n_ipv6_addrs > 0) {
+                char ip6_str[INET6_ADDRSTRLEN + 1];
+                struct ds match = DS_EMPTY_INITIALIZER;
+                ds_put_cstr(&match, "icmp6 && icmp6.type == 135 && (");
+                for (size_t j = 0; j < laddrs.n_ipv6_addrs; j++) {
+                    ipv6_string_mapped(ip6_str, &(laddrs.ipv6_addrs[j].addr));
+                    ds_put_format(&match, "nd.target == %s || ", ip6_str);
+                }
+                ds_chomp(&match, ' ');
+                ds_chomp(&match, '|');
+                ds_chomp(&match, '|');
+                ds_chomp(&match, ' ');
+                ds_put_cstr(&match, ")");
+                char *actions = xasprintf(
+                    "na { eth.src = "ETH_ADDR_FMT"; "
+                    "nd.tll = "ETH_ADDR_FMT"; "
+                    "outport = inport; "
+                    "inport = \"\"; /* Allow sending out inport. */ "
+                    "output; };",
+                    ETH_ADDR_ARGS(laddrs.ea),
+                    ETH_ADDR_ARGS(laddrs.ea));
+
+                ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 50,
+                              ds_cstr(&match), actions);
+
+                ds_destroy(&match);
+            }
+
             free(laddrs.ipv4_addrs);
+            free(laddrs.ipv6_addrs);
         }
     }
 
-    /* Ingress table 5: ARP responder, by default goto next.
+    /* Ingress table 5: ARP/ND 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;");
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_ARP_ND_RSP, 0, "1", "next;");
     }
 
     /* Ingress table 6: Destination lookup, broadcast and multicast handling
diff --git a/tutorial/OVN-Tutorial.md b/tutorial/OVN-Tutorial.md
index c4bcbae..811224d 100644
--- a/tutorial/OVN-Tutorial.md
+++ b/tutorial/OVN-Tutorial.md
@@ -104,7 +104,7 @@  show the logical flows.
       table=2(ls_in_port_sec_nd), priority=    0, match=(1), action=(next;)
       table=3(   ls_in_pre_acl), priority=    0, match=(1), action=(next;)
       table=4(       ls_in_acl), priority=    0, match=(1), action=(next;)
-      table=5(   ls_in_arp_rsp), priority=    0, match=(1), action=(next;)
+      table=5(ls_in_arp_nd_rsp), priority=    0, match=(1), action=(next;)
       table=6(   ls_in_l2_lkup), priority=  100, match=(eth.mcast), action=(outport = "_MC_flood"; output;)
       table=6(   ls_in_l2_lkup), priority=   50, match=(eth.dst == 00:00:00:00:00:01), action=(outport = "sw0-port1"; output;)
       table=6(   ls_in_l2_lkup), priority=   50, match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0-port2"; output;)
@@ -277,7 +277,7 @@  OVN creates separate logical flows for each logical switch.
       table=2(ls_in_port_sec_nd), priority=    0, match=(1), action=(next;)
       table=3(   ls_in_pre_acl), priority=    0, match=(1), action=(next;)
       table=4(       ls_in_acl), priority=    0, match=(1), action=(next;)
-      table=5(   ls_in_arp_rsp), priority=    0, match=(1), action=(next;)
+      table=5(ls_in_arp_nd_rsp), priority=    0, match=(1), action=(next;)
       table=6(   ls_in_l2_lkup), priority=  100, match=(eth.mcast), action=(outport = "_MC_flood"; output;)
       table=6(   ls_in_l2_lkup), priority=   50, match=(eth.dst == 00:00:00:00:00:03), action=(outport = "sw1-port1"; output;)
       table=6(   ls_in_l2_lkup), priority=   50, match=(eth.dst == 00:00:00:00:00:04), action=(outport = "sw1-port2"; output;)
@@ -303,7 +303,7 @@  OVN creates separate logical flows for each logical switch.
       table=2(ls_in_port_sec_nd), priority=    0, match=(1), action=(next;)
       table=3(   ls_in_pre_acl), priority=    0, match=(1), action=(next;)
       table=4(       ls_in_acl), priority=    0, match=(1), action=(next;)
-      table=5(   ls_in_arp_rsp), priority=    0, match=(1), action=(next;)
+      table=5(ls_in_arp_nd_rsp), priority=    0, match=(1), action=(next;)
       table=6(   ls_in_l2_lkup), priority=  100, match=(eth.mcast), action=(outport = "_MC_flood"; output;)
       table=6(   ls_in_l2_lkup), priority=   50, match=(eth.dst == 00:00:00:00:00:01), action=(outport = "sw0-port1"; output;)
       table=6(   ls_in_l2_lkup), priority=   50, match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0-port2"; output;)