diff mbox series

[ovs-dev,v2] northd: drop traffic to disabled LSPs in ingress pipeline

Message ID 20220908140644.2647859-1-odivlad@gmail.com
State Superseded
Headers show
Series [ovs-dev,v2] northd: drop traffic to disabled LSPs in ingress pipeline | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_ovn-kubernetes success github build: passed
ovsrobot/github-robot-_Build_and_Test fail github build: failed

Commit Message

Vladislav Odintsov Sept. 8, 2022, 2:06 p.m. UTC
Prior to this patch traffic to LSPs, which are disabled with
`ovn-nbctl lsp-set-enabled <LSP> disabled` was dropped in the end of
lswitch egress pipeline.  This means that traffic is processed in vain:
- traffic, which should be dropped, first travels from one chassis to
  another (if source/dest LSPs reside on different nodes) and dropped on
  the destination chassis;
- when such traffic reaches destination chassis, if stateful services are
  enabled within logical switch, first traffic is sent to conntrack and
  is dropped after that.

So it is costly to drop traffic in such manner especially in case LSP is
disabled to prevent chassis and/or VM attack by any harmful traffic.

This patch changes "to-lport" drop behaviour.  Now it is dropped in
lswitch ingress pipeline to avoid sending traffic to disabled LSP from
one chassis to another.
Traffic doesn't reach conntrack in destination LSP's zone now as well.

Signed-off-by: Vladislav Odintsov <odivlad@gmail.com>
---
 northd/northd.c         |  18 ++--
 northd/ovn-northd.8.xml |  21 ++---
 tests/ovn-northd.at     | 184 +++++++++++++++++++++++++---------------
 3 files changed, 135 insertions(+), 88 deletions(-)
diff mbox series

Patch

diff --git a/northd/northd.c b/northd/northd.c
index 4a40ec9b0..1eb190dc1 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -5475,9 +5475,8 @@  build_lswitch_port_sec_op(struct ovn_port *op, struct hmap *lflows,
         ds_clear(match);
         ds_put_format(match, "outport == %s", op->json_key);
         ovn_lflow_add_with_lport_and_hint(
-            lflows, op->od, S_SWITCH_OUT_CHECK_PORT_SEC, 150,
-            ds_cstr(match), REGBIT_PORT_SEC_DROP" = 1; next;",
-            op->key, &op->nbsp->header_);
+            lflows, op->od, S_SWITCH_IN_L2_UNKNOWN, 50, ds_cstr(match),
+            "drop;", op->key, &op->nbsp->header_);
         return;
     }
 
@@ -8466,6 +8465,8 @@  build_lswitch_ip_unicast_lookup(struct ovn_port *op,
              * Ethernet address followed by zero or more IPv4
              * or IPv6 addresses (or both). */
             struct eth_addr mac;
+            bool lsp_enabled = lsp_is_enabled(op->nbsp);
+            char *action = lsp_enabled ? "outport = %s; output;" : "drop;";
             if (ovs_scan(op->nbsp->addresses[i],
                         ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) {
                 ds_clear(match);
@@ -8473,13 +8474,13 @@  build_lswitch_ip_unicast_lookup(struct ovn_port *op,
                               ETH_ADDR_ARGS(mac));
 
                 ds_clear(actions);
-                ds_put_format(actions, "outport = %s; output;", op->json_key);
+                ds_put_format(actions, action, op->json_key);
                 ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_L2_LKUP,
                                         50, ds_cstr(match),
                                         ds_cstr(actions),
                                         &op->nbsp->header_);
             } else if (!strcmp(op->nbsp->addresses[i], "unknown")) {
-                if (lsp_is_enabled(op->nbsp)) {
+                if (lsp_enabled) {
                     ovs_mutex_lock(&mcgroup_mutex);
                     ovn_multicast_add(mcgroups, &mc_unknown, op);
                     ovs_mutex_unlock(&mcgroup_mutex);
@@ -8496,7 +8497,7 @@  build_lswitch_ip_unicast_lookup(struct ovn_port *op,
                               ETH_ADDR_ARGS(mac));
 
                 ds_clear(actions);
-                ds_put_format(actions, "outport = %s; output;", op->json_key);
+                ds_put_format(actions, action, op->json_key);
                 ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_L2_LKUP,
                                         50, ds_cstr(match),
                                         ds_cstr(actions),
@@ -8544,7 +8545,7 @@  build_lswitch_ip_unicast_lookup(struct ovn_port *op,
                 }
 
                 ds_clear(actions);
-                ds_put_format(actions, "outport = %s; output;", op->json_key);
+                ds_put_format(actions, action, op->json_key);
                 ovn_lflow_add_with_hint(lflows, op->od,
                                         S_SWITCH_IN_L2_LKUP, 50,
                                         ds_cstr(match), ds_cstr(actions),
@@ -8567,8 +8568,7 @@  build_lswitch_ip_unicast_lookup(struct ovn_port *op,
                                           nat->logical_port);
 
                             ds_clear(actions);
-                            ds_put_format(actions, "outport = %s; output;",
-                                          op->json_key);
+                            ds_put_format(actions, action, op->json_key);
                             ovn_lflow_add_with_hint(lflows, op->od,
                                                     S_SWITCH_IN_L2_LKUP, 50,
                                                     ds_cstr(match),
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index f4eceb0ec..dae961c87 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -1737,8 +1737,9 @@  output;
       <li>
         <p>
           One priority-50 flow that matches each known Ethernet address against
-          <code>eth.dst</code> and outputs the packet to the single associated
-          output port.
+          <code>eth.dst</code>.  Action of this flow outputs the packet to the
+          single associated output port if it is enabled. <code>drop;</code>
+          action is applied if LSP is disabled.
         </p>
 
         <p>
@@ -1814,6 +1815,13 @@  output;
     </p>
 
     <ul>
+      <li>
+        <p>
+          Priority 50 flow with the match <code>outport == <var>P</var></code>
+          is added for each disabled Logical Switch Port <code>P</code>.  This
+          flow has action <code>drop;</code>.
+        </p>
+      </li>
       <li>
         <p>
           If the logical switch has logical ports with 'unknown' addresses set,
@@ -1822,7 +1830,7 @@  output;
 
         <ul>
           <li>
-            Priority 50 flow with the match <code>outport == none</code> then
+            Priority 50 flow with the match <code>outport == "none"</code> then
             outputs them to the <code>MC_UNKNOWN</code> multicast group, which
             <code>ovn-northd</code> populates with all enabled logical ports
             that accept unknown destination packets.  As a small optimization,
@@ -2011,13 +2019,6 @@  output;
         the out port security checks.
       </li>
 
-      <li>
-        For each disabled logical port, a priority 150 flow is added which
-        matches on all packets and applies the action
-        <code>REGBIT_PORT_SEC_DROP" = 1; next;"</code> so that the packets are
-        dropped in the next stage.
-      </li>
-
       <li>
         A priority 0 logical flow is added which matches on all the packets
         and applies the action
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index d5136ac6d..da83bce7c 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -7425,16 +7425,22 @@  check ovn-nbctl --wait=sb ls-add sw0
 ovn-sbctl dump-flows sw0 > sw0flows
 AT_CAPTURE_FILE([sw0flows])
 
-AT_CHECK([cat sw0flows | grep -e port_sec | sort | sed 's/table=./table=?/' ], [0], [dnl
-  table=? (ls_in_check_port_sec), priority=100  , match=(eth.src[[40]]), action=(drop;)
-  table=? (ls_in_check_port_sec), priority=100  , match=(vlan.present), action=(drop;)
-  table=? (ls_in_check_port_sec), priority=50   , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;)
-  table=? (ls_in_apply_port_sec), priority=0    , match=(1), action=(next;)
-  table=? (ls_in_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
-  table=? (ls_out_check_port_sec), priority=0    , match=(1), action=(reg0[[15]] = check_out_port_sec(); next;)
-  table=? (ls_out_check_port_sec), priority=100  , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
-  table=? (ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
-  table=? (ls_out_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
+AT_CHECK([cat sw0flows | grep -e port_sec -e ls_in_l2_lkup -e ls_in_l2_unknown | \
+sort | sed 's/table=../table=??/' ], [0], [dnl
+  table=??(ls_in_check_port_sec), priority=100  , match=(eth.src[[40]]), action=(drop;)
+  table=??(ls_in_check_port_sec), priority=100  , match=(vlan.present), action=(drop;)
+  table=??(ls_in_check_port_sec), priority=50   , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;)
+  table=??(ls_in_apply_port_sec), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
+  table=??(ls_in_l2_lkup      ), priority=0    , match=(1), action=(outport = get_fdb(eth.dst); next;)
+  table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(handle_svc_check(inport);)
+  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
+  table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), action=(drop;)
+  table=??(ls_out_check_port_sec), priority=0    , match=(1), action=(reg0[[15]] = check_out_port_sec(); next;)
+  table=??(ls_out_check_port_sec), priority=100  , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
+  table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
+  table=??(ls_out_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
 ])
 
 check ovn-nbctl lsp-add sw0 sw0p1 -- lsp-set-addresses sw0p1 "00:00:00:00:00:01"
@@ -7444,16 +7450,24 @@  check ovn-nbctl --wait=sb lsp-add sw0 localnetport -- lsp-set-type localnetport
 ovn-sbctl dump-flows sw0 > sw0flows
 AT_CAPTURE_FILE([sw0flows])
 
-AT_CHECK([cat sw0flows | grep -e port_sec | sort | sed 's/table=./table=?/' ], [0], [dnl
-  table=? (ls_in_check_port_sec), priority=100  , match=(eth.src[[40]]), action=(drop;)
-  table=? (ls_in_check_port_sec), priority=100  , match=(vlan.present), action=(drop;)
-  table=? (ls_in_check_port_sec), priority=50   , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;)
-  table=? (ls_in_apply_port_sec), priority=0    , match=(1), action=(next;)
-  table=? (ls_in_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
-  table=? (ls_out_check_port_sec), priority=0    , match=(1), action=(reg0[[15]] = check_out_port_sec(); next;)
-  table=? (ls_out_check_port_sec), priority=100  , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
-  table=? (ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
-  table=? (ls_out_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
+AT_CHECK([cat sw0flows | grep -e port_sec -e ls_in_l2_lkup -e ls_in_l2_unknown | \
+sort | sed 's/table=../table=??/' ], [0], [dnl
+  table=??(ls_in_check_port_sec), priority=100  , match=(eth.src[[40]]), action=(drop;)
+  table=??(ls_in_check_port_sec), priority=100  , match=(vlan.present), action=(drop;)
+  table=??(ls_in_check_port_sec), priority=50   , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;)
+  table=??(ls_in_apply_port_sec), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
+  table=??(ls_in_l2_lkup      ), priority=0    , match=(1), action=(outport = get_fdb(eth.dst); next;)
+  table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(handle_svc_check(inport);)
+  table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:01), action=(outport = "sw0p1"; output;)
+  table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
+  table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), action=(drop;)
+  table=??(ls_out_check_port_sec), priority=0    , match=(1), action=(reg0[[15]] = check_out_port_sec(); next;)
+  table=??(ls_out_check_port_sec), priority=100  , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
+  table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
+  table=??(ls_out_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
 ])
 
 check ovn-nbctl lsp-set-port-security sw0p1 "00:00:00:00:00:01 10.0.0.3 1000::3"
@@ -7462,16 +7476,24 @@  check ovn-nbctl --wait=sb lsp-set-port-security sw0p2 "00:00:00:00:00:02 10.0.0.
 ovn-sbctl dump-flows sw0 > sw0flows
 AT_CAPTURE_FILE([sw0flows])
 
-AT_CHECK([cat sw0flows | grep -e port_sec | sort | sed 's/table=./table=?/' ], [0], [dnl
-  table=? (ls_in_check_port_sec), priority=100  , match=(eth.src[[40]]), action=(drop;)
-  table=? (ls_in_check_port_sec), priority=100  , match=(vlan.present), action=(drop;)
-  table=? (ls_in_check_port_sec), priority=50   , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;)
-  table=? (ls_in_apply_port_sec), priority=0    , match=(1), action=(next;)
-  table=? (ls_in_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
-  table=? (ls_out_check_port_sec), priority=0    , match=(1), action=(reg0[[15]] = check_out_port_sec(); next;)
-  table=? (ls_out_check_port_sec), priority=100  , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
-  table=? (ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
-  table=? (ls_out_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
+AT_CHECK([cat sw0flows | grep -e port_sec -e ls_in_l2_lkup -e ls_in_l2_unknown | \
+sort | sed 's/table=../table=??/' ], [0], [dnl
+  table=??(ls_in_check_port_sec), priority=100  , match=(eth.src[[40]]), action=(drop;)
+  table=??(ls_in_check_port_sec), priority=100  , match=(vlan.present), action=(drop;)
+  table=??(ls_in_check_port_sec), priority=50   , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;)
+  table=??(ls_in_apply_port_sec), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
+  table=??(ls_in_l2_lkup      ), priority=0    , match=(1), action=(outport = get_fdb(eth.dst); next;)
+  table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(handle_svc_check(inport);)
+  table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:01), action=(outport = "sw0p1"; output;)
+  table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
+  table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), action=(drop;)
+  table=??(ls_out_check_port_sec), priority=0    , match=(1), action=(reg0[[15]] = check_out_port_sec(); next;)
+  table=??(ls_out_check_port_sec), priority=100  , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
+  table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
+  table=??(ls_out_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
 ])
 
 # Disable sw0p1
@@ -7480,37 +7502,53 @@  check ovn-nbctl --wait=sb set logical_switch_port sw0p1 enabled=false
 ovn-sbctl dump-flows sw0 > sw0flows
 AT_CAPTURE_FILE([sw0flows])
 
-AT_CHECK([cat sw0flows | grep -e port_sec | sort | sed 's/table=./table=?/' ], [0], [dnl
-  table=? (ls_in_check_port_sec), priority=100  , match=(eth.src[[40]]), action=(drop;)
-  table=? (ls_in_check_port_sec), priority=100  , match=(inport == "sw0p1"), action=(reg0[[15]] = 1; next;)
-  table=? (ls_in_check_port_sec), priority=100  , match=(vlan.present), action=(drop;)
-  table=? (ls_in_check_port_sec), priority=50   , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;)
-  table=? (ls_in_apply_port_sec), priority=0    , match=(1), action=(next;)
-  table=? (ls_in_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
-  table=? (ls_out_check_port_sec), priority=0    , match=(1), action=(reg0[[15]] = check_out_port_sec(); next;)
-  table=? (ls_out_check_port_sec), priority=100  , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
-  table=? (ls_out_check_port_sec), priority=150  , match=(outport == "sw0p1"), action=(reg0[[15]] = 1; next;)
-  table=? (ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
-  table=? (ls_out_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
+AT_CHECK([cat sw0flows | grep -e port_sec -e ls_in_l2_lkup -e ls_in_l2_unknown | \
+sort | sed 's/table=../table=??/' ], [0], [dnl
+  table=??(ls_in_check_port_sec), priority=100  , match=(eth.src[[40]]), action=(drop;)
+  table=??(ls_in_check_port_sec), priority=100  , match=(inport == "sw0p1"), action=(reg0[[15]] = 1; next;)
+  table=??(ls_in_check_port_sec), priority=100  , match=(vlan.present), action=(drop;)
+  table=??(ls_in_check_port_sec), priority=50   , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;)
+  table=??(ls_in_apply_port_sec), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
+  table=??(ls_in_l2_lkup      ), priority=0    , match=(1), action=(outport = get_fdb(eth.dst); next;)
+  table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(handle_svc_check(inport);)
+  table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:01), action=(drop;)
+  table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
+  table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), action=(drop;)
+  table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "sw0p1"), action=(drop;)
+  table=??(ls_out_check_port_sec), priority=0    , match=(1), action=(reg0[[15]] = check_out_port_sec(); next;)
+  table=??(ls_out_check_port_sec), priority=100  , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
+  table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
+  table=??(ls_out_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
 ])
 
 check ovn-nbctl --wait=sb lsp-set-options sw0p2 qdisc_queue_id=10
 ovn-sbctl dump-flows sw0 > sw0flows
 AT_CAPTURE_FILE([sw0flows])
 
-AT_CHECK([cat sw0flows | grep -e port_sec | sort | sed 's/table=./table=?/' ], [0], [dnl
-  table=? (ls_in_check_port_sec), priority=100  , match=(eth.src[[40]]), action=(drop;)
-  table=? (ls_in_check_port_sec), priority=100  , match=(inport == "sw0p1"), action=(reg0[[15]] = 1; next;)
-  table=? (ls_in_check_port_sec), priority=100  , match=(vlan.present), action=(drop;)
-  table=? (ls_in_check_port_sec), priority=50   , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;)
-  table=? (ls_in_check_port_sec), priority=70   , match=(inport == "sw0p2"), action=(set_queue(10); reg0[[15]] = check_in_port_sec(); next;)
-  table=? (ls_in_apply_port_sec), priority=0    , match=(1), action=(next;)
-  table=? (ls_in_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
-  table=? (ls_out_check_port_sec), priority=0    , match=(1), action=(reg0[[15]] = check_out_port_sec(); next;)
-  table=? (ls_out_check_port_sec), priority=100  , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
-  table=? (ls_out_check_port_sec), priority=150  , match=(outport == "sw0p1"), action=(reg0[[15]] = 1; next;)
-  table=? (ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
-  table=? (ls_out_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
+AT_CHECK([cat sw0flows | grep -e port_sec -e ls_in_l2_lkup -e ls_in_l2_unknown | \
+sort | sed 's/table=../table=??/' ], [0], [dnl
+  table=??(ls_in_check_port_sec), priority=100  , match=(eth.src[[40]]), action=(drop;)
+  table=??(ls_in_check_port_sec), priority=100  , match=(inport == "sw0p1"), action=(reg0[[15]] = 1; next;)
+  table=??(ls_in_check_port_sec), priority=100  , match=(vlan.present), action=(drop;)
+  table=??(ls_in_check_port_sec), priority=50   , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;)
+  table=??(ls_in_check_port_sec), priority=70   , match=(inport == "sw0p2"), action=(set_queue(10); reg0[[15]] = check_in_port_sec(); next;)
+  table=??(ls_in_apply_port_sec), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
+  table=??(ls_in_l2_lkup      ), priority=0    , match=(1), action=(outport = get_fdb(eth.dst); next;)
+  table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(handle_svc_check(inport);)
+  table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:01), action=(drop;)
+  table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
+  table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), action=(drop;)
+  table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "sw0p1"), action=(drop;)
+  table=??(ls_out_check_port_sec), priority=0    , match=(1), action=(reg0[[15]] = check_out_port_sec(); next;)
+  table=??(ls_out_check_port_sec), priority=100  , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
+  table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
+  table=??(ls_out_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
 ])
 
 check ovn-nbctl set logical_switch_port sw0p1 enabled=true
@@ -7519,20 +7557,28 @@  check ovn-nbctl --wait=sb lsp-set-options localnetport qdisc_queue_id=10
 ovn-sbctl dump-flows sw0 > sw0flows
 AT_CAPTURE_FILE([sw0flows])
 
-AT_CHECK([cat sw0flows | grep -e port_sec | sort | sed 's/table=./table=?/' ], [0], [dnl
-  table=? (ls_in_check_port_sec), priority=100  , match=(eth.src[[40]]), action=(drop;)
-  table=? (ls_in_check_port_sec), priority=100  , match=(vlan.present), action=(drop;)
-  table=? (ls_in_check_port_sec), priority=50   , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;)
-  table=? (ls_in_check_port_sec), priority=70   , match=(inport == "localnetport"), action=(set_queue(10); reg0[[15]] = check_in_port_sec(); next;)
-  table=? (ls_in_check_port_sec), priority=70   , match=(inport == "sw0p1"), action=(reg0[[14]] = 1; next(pipeline=ingress, table=16);)
-  table=? (ls_in_check_port_sec), priority=70   , match=(inport == "sw0p2"), action=(set_queue(10); reg0[[15]] = check_in_port_sec(); next;)
-  table=? (ls_in_apply_port_sec), priority=0    , match=(1), action=(next;)
-  table=? (ls_in_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
-  table=? (ls_out_check_port_sec), priority=0    , match=(1), action=(reg0[[15]] = check_out_port_sec(); next;)
-  table=? (ls_out_check_port_sec), priority=100  , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
-  table=? (ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
-  table=? (ls_out_apply_port_sec), priority=100  , match=(outport == "localnetport"), action=(set_queue(10); output;)
-  table=? (ls_out_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
+AT_CHECK([cat sw0flows | grep -e port_sec -e ls_in_l2_lkup -e ls_in_l2_unknown | \
+sort | sed 's/table=../table=??/' ], [0], [dnl
+  table=??(ls_in_check_port_sec), priority=100  , match=(eth.src[[40]]), action=(drop;)
+  table=??(ls_in_check_port_sec), priority=100  , match=(vlan.present), action=(drop;)
+  table=??(ls_in_check_port_sec), priority=50   , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;)
+  table=??(ls_in_check_port_sec), priority=70   , match=(inport == "localnetport"), action=(set_queue(10); reg0[[15]] = check_in_port_sec(); next;)
+  table=??(ls_in_check_port_sec), priority=70   , match=(inport == "sw0p1"), action=(reg0[[14]] = 1; next(pipeline=ingress, table=16);)
+  table=??(ls_in_check_port_sec), priority=70   , match=(inport == "sw0p2"), action=(set_queue(10); reg0[[15]] = check_in_port_sec(); next;)
+  table=??(ls_in_apply_port_sec), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
+  table=??(ls_in_l2_lkup      ), priority=0    , match=(1), action=(outport = get_fdb(eth.dst); next;)
+  table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(handle_svc_check(inport);)
+  table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:01), action=(outport = "sw0p1"; output;)
+  table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
+  table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), action=(drop;)
+  table=??(ls_out_check_port_sec), priority=0    , match=(1), action=(reg0[[15]] = check_out_port_sec(); next;)
+  table=??(ls_out_check_port_sec), priority=100  , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
+  table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
+  table=??(ls_out_apply_port_sec), priority=100  , match=(outport == "localnetport"), action=(set_queue(10); output;)
+  table=??(ls_out_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
 ])
 
 AT_CLEANUP