Currently, the only use of stateful services in conntrack is
OVN ACLs. In table pre-ACL, we send the packet to conntrack
to track it (to get its status) via the ct_next action.

As we introduce more stateful services, the ACL feature will
have to share the conntrack module with others. As
preparation for more stateful features like NAT and
loadbalancing, this commit introduces a new pre-stateful
table that is responsible to send packets through conntrack
via ct_next action. If pre-ACL table needs to send a packet
through conntrack, it just sets the 'reg0' as 1.
Pre-stateful table in-turn will send the packet to conntrack
if 'reg0' is 1.

Signed-off-by: Gurucharan Shetty <g...@ovn.org>
---
 ovn/northd/ovn-northd.8.xml | 37 +++++++++++++++++-------
 ovn/northd/ovn-northd.c     | 68 ++++++++++++++++++++++++++++++---------------
 2 files changed, 73 insertions(+), 32 deletions(-)

diff --git a/ovn/northd/ovn-northd.8.xml b/ovn/northd/ovn-northd.8.xml
index fa7675b..eb80cc0 100644
--- a/ovn/northd/ovn-northd.8.xml
+++ b/ovn/northd/ovn-northd.8.xml
@@ -143,13 +143,24 @@
 
     <p>
       Ingress table 1 prepares flows for possible stateful ACL processing
-      in table 2.  It contains a priority-0 flow that simply moves
+      in table 3.  It contains a priority-0 flow that simply moves
       traffic to table 2.  If stateful ACLs are used in the logical
-      datapath, a priority-100 flow is added that sends IP packets to
-      the connection tracker before advancing to table 2.
+      datapath, a priority-100 flow is added that sets a hint (with reg0 = 1)
+      for table 2 to send IP packets to the connection tracker before
+      advancing to table 3.
     </p>
 
-    <h3>Ingress table 2: <code>from-lport</code> ACLs</h3>
+    <h3>Ingress Table 2: Pre-STATEFUL</h3>
+
+    <p>
+      Ingress table 2 prepares flows for all possible stateful processing
+      in next tables.  It contains a priority-0 flow that simply moves
+      traffic to table 3.  A priority-100 flow sends the packets to connection
+      tracker based on a hint provided by the previous tables (with a match
+      for reg0 == 1).
+    </p>
+
+    <h3>Ingress table 3: <code>from-lport</code> ACLs</h3>
 
     <p>
       Logical flows in this table closely reproduce those in the
@@ -163,9 +174,9 @@
     </p>
 
     <p>
-      Ingress table 2 also contains a priority 0 flow with action
+      Ingress table 3 also contains a priority 0 flow with action
       <code>next;</code>, so that ACLs allow packets by default.  If the
-      logical datapath has a statetful ACL, the following flows will
+      logical datapath has a stateful ACL, the following flows will
       also be added:
     </p>
 
@@ -195,7 +206,7 @@
       </li>
     </ul>
 
-    <h3>Ingress Table 3: Destination Lookup</h3>
+    <h3>Ingress Table 4: Destination Lookup</h3>
 
     <p>
       This table implements switching behavior.  It contains these logical
@@ -251,13 +262,19 @@ output;
       traffic.
     </p>
 
-    <h3>Egress Table 1: <code>to-lport</code> ACLs</h3>
+    <h3>Egress Table 1: Pre-STATEFUL</h3>
+
+    <p>
+      This is similar to ingress table 2.
+    </p>
+
+    <h3>Egress Table 2: <code>to-lport</code> ACLs</h3>
 
     <p>
-      This is similar to ingress table 2 except for <code>to-lport</code> ACLs.
+      This is similar to ingress table 3 except for <code>to-lport</code> ACLs.
     </p>
 
-    <h3>Egress Table 2: Egress Port Security</h3>
+    <h3>Egress Table 4: Egress Port Security</h3>
 
     <p>
       This is similar to the ingress port security logic in ingress table 0,
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 4b2ac64..ed7852a 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -83,25 +83,27 @@ enum ovn_datapath_type {
  * form the stage's full name, e.g. S_SWITCH_IN_PORT_SEC,
  * S_ROUTER_OUT_DELIVERY. */
 enum ovn_stage {
-#define PIPELINE_STAGES                                               \
-    /* Logical switch ingress stages. */                              \
-    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")      \
-                                                                      \
-    /* Logical switch egress stages. */                               \
-    PIPELINE_STAGE(SWITCH, OUT, PRE_ACL,     0, "ls_out_pre_acl")     \
-    PIPELINE_STAGE(SWITCH, OUT, ACL,         1, "ls_out_acl")         \
-    PIPELINE_STAGE(SWITCH, OUT, PORT_SEC,    2, "ls_out_port_sec")    \
-                                                                      \
-    /* Logical router ingress stages. */                              \
-    PIPELINE_STAGE(ROUTER, IN,  ADMISSION,   0, "lr_in_admission")    \
-    PIPELINE_STAGE(ROUTER, IN,  IP_INPUT,    1, "lr_in_ip_input")     \
-    PIPELINE_STAGE(ROUTER, IN,  IP_ROUTING,  2, "lr_in_ip_routing")   \
-    PIPELINE_STAGE(ROUTER, IN,  ARP,         3, "lr_in_arp")          \
-                                                                      \
-    /* Logical router egress stages. */                               \
+#define PIPELINE_STAGES                                                 \
+    /* Logical switch ingress stages. */                                \
+    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,  PRE_STATEFUL, 2, "ls_in_pre_stateful")  \
+    PIPELINE_STAGE(SWITCH, IN,  ACL,          3, "ls_in_acl")           \
+    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")      \
+    PIPELINE_STAGE(SWITCH, OUT, PRE_STATEFUL, 1, "ls_out_pre_stateful") \
+    PIPELINE_STAGE(SWITCH, OUT, ACL,          2, "ls_out_acl")          \
+    PIPELINE_STAGE(SWITCH, OUT, PORT_SEC,     3, "ls_out_port_sec")     \
+                                                                        \
+    /* Logical router ingress stages. */                                \
+    PIPELINE_STAGE(ROUTER, IN,  ADMISSION,   0, "lr_in_admission")      \
+    PIPELINE_STAGE(ROUTER, IN,  IP_INPUT,    1, "lr_in_ip_input")       \
+    PIPELINE_STAGE(ROUTER, IN,  IP_ROUTING,  2, "lr_in_ip_routing")     \
+    PIPELINE_STAGE(ROUTER, IN,  ARP,         3, "lr_in_arp")            \
+                                                                        \
+    /* Logical router egress stages. */                                 \
     PIPELINE_STAGE(ROUTER, OUT, DELIVERY,    0, "lr_out_delivery")
 
 #define PIPELINE_STAGE(DP_TYPE, PIPELINE, STAGE, TABLE, NAME)   \
@@ -1008,13 +1010,34 @@ build_pre_acls(struct ovn_datapath *od, struct hmap 
*lflows,
          *
          * Regardless of whether the ACL is "from-lport" or "to-lport",
          * we need rules in both the ingress and egress table, because
-         * the return traffic needs to be followed. */
-        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;");
+         * the return traffic needs to be followed.
+         *
+         * 'reg0' is set to let the pre-STATEFUL table send
+         * it to conntrack for tracking. */
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_ACL, 100, "ip",
+                      "reg0 = 1; next;");
+        ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_ACL, 100, "ip",
+                      "reg0 = 1; next;");
     }
 }
 
 static void
+build_pre_stateful(struct ovn_datapath *od, struct hmap *lflows)
+{
+    /* Ingress and Egress Pre-STATEFUL Table (Priority 0): Packets are
+     * allowed by default. */
+    ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_STATEFUL, 0, "1", "next;");
+    ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_STATEFUL, 0, "1", "next;");
+
+    /* If reg0 is set as 1, then the packets should be sent to conntrack for
+     * tracking. */
+    ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_STATEFUL, 100, "reg0 == 1",
+                  "ct_next;");
+    ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_STATEFUL, 100, "reg0 == 1",
+                  "ct_next;");
+}
+
+static void
 build_acls(struct ovn_datapath *od, struct hmap *lflows)
 {
     bool has_stateful = has_stateful_acl(od);
@@ -1136,6 +1159,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap 
*ports,
         }
 
         build_pre_acls(od, lflows, ports);
+        build_pre_stateful(od, lflows);
         build_acls(od, lflows);
     }
 
-- 
1.9.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to