From b4d45961651e5de2e62fb64e941d10e8959da6db Mon Sep 17 00:00:00 2001 From: yatinkarel Date: Jul 10 2023 13:56:53 +0000 Subject: Import ovn23.03-23.03.0-69.el9fdp.src.rpm from FDP --- diff --git a/SOURCES/ovn23.03.patch b/SOURCES/ovn23.03.patch index c66abc6..9478c3b 100644 --- a/SOURCES/ovn23.03.patch +++ b/SOURCES/ovn23.03.patch @@ -1,3 +1,26 @@ +diff --git a/.github/workflows/ovn-kubernetes.yml b/.github/workflows/ovn-kubernetes.yml +index c82b23a1f..1d554cd03 100644 +--- a/.github/workflows/ovn-kubernetes.yml ++++ b/.github/workflows/ovn-kubernetes.yml +@@ -56,7 +56,7 @@ jobs: + name: e2e + if: github.event_name != 'schedule' + runs-on: ubuntu-20.04 +- timeout-minutes: 120 ++ timeout-minutes: 220 + strategy: + fail-fast: false + matrix: +@@ -137,6 +137,9 @@ jobs: + working-directory: src/github.com/ovn-org/ovn-kubernetes + + - name: Run Tests ++ # e2e tests take ~60 minutes normally, 120 should be more than enough ++ # set 180 for control-plane tests as these might take a while ++ timeout-minutes: ${{ matrix.target == 'control-plane' && 180 || 120 }} + run: | + make -C test ${{ matrix.target }} + working-directory: src/github.com/ovn-org/ovn-kubernetes diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0f8d9d193..edf4fb2fd 100644 --- a/.github/workflows/test.yml @@ -13,10 +36,10 @@ index 0f8d9d193..edf4fb2fd 100644 ARCH: ${{ matrix.cfg.arch }} CC: ${{ matrix.cfg.compiler }} diff --git a/NEWS b/NEWS -index 5e8aed06d..60c460a05 100644 +index 5e8aed06d..d7ba71ef5 100644 --- a/NEWS +++ b/NEWS -@@ -1,3 +1,11 @@ +@@ -1,3 +1,17 @@ +OVN v23.03.1 - xx xxx xxxx +-------------------------- + - CT entries are not flushed by default anymore whenever a load balancer @@ -24,6 +47,12 @@ index 5e8aed06d..60c460a05 100644 + restore the previous behavior. Disabled by default. + - Always allow IPv6 Router Discovery, Neighbor Discovery, and Multicast + Listener Discovery protocols, regardless of ACLs defined. ++ - Send ICMP Fragmentation Needed packets back to offending ports when ++ communicating with multichassis ports using frames that don't fit through a ++ tunnel. This is done only for logical switches that are attached to a ++ physical network via a localnet port, in which case multichassis ports may ++ have an effective MTU different from regular ports and hence may need this ++ mechanism to maintain connectivity with other peers in the network. + OVN v23.03.0 - 03 Mar 2023 -------------------------- @@ -42,10 +71,21 @@ index b51d0f01e..0ba9e8d7e 100644 AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) diff --git a/controller/binding.c b/controller/binding.c -index 5df62baef..bd810f669 100644 +index 5df62baef..8fce6fc3f 100644 --- a/controller/binding.c +++ b/controller/binding.c -@@ -746,6 +746,19 @@ local_binding_get_lport_ofport(const struct shash *local_bindings, +@@ -57,6 +57,10 @@ struct claimed_port { + static struct shash _claimed_ports = SHASH_INITIALIZER(&_claimed_ports); + static struct sset _postponed_ports = SSET_INITIALIZER(&_postponed_ports); + ++static void ++remove_additional_chassis(const struct sbrec_port_binding *pb, ++ const struct sbrec_chassis *chassis_rec); ++ + struct sset * + get_postponed_ports(void) + { +@@ -746,6 +750,19 @@ local_binding_get_lport_ofport(const struct shash *local_bindings, u16_to_ofp(lbinding->iface->ofport[0]) : 0; } @@ -65,7 +105,7 @@ index 5df62baef..bd810f669 100644 bool local_binding_is_up(struct shash *local_bindings, const char *pb_name, const struct sbrec_chassis *chassis_rec) -@@ -783,6 +796,7 @@ local_binding_is_down(struct shash *local_bindings, const char *pb_name, +@@ -783,6 +800,7 @@ local_binding_is_down(struct shash *local_bindings, const char *pb_name, } else if (b_lport->pb->chassis) { VLOG_DBG("lport %s already claimed by other chassis", b_lport->pb->logical_port); @@ -73,7 +113,7 @@ index 5df62baef..bd810f669 100644 } } -@@ -834,6 +848,38 @@ local_binding_set_up(struct shash *local_bindings, const char *pb_name, +@@ -834,6 +852,38 @@ local_binding_set_up(struct shash *local_bindings, const char *pb_name, } } @@ -112,7 +152,7 @@ index 5df62baef..bd810f669 100644 void local_binding_set_down(struct shash *local_bindings, const char *pb_name, const struct sbrec_chassis *chassis_rec, -@@ -853,7 +899,6 @@ local_binding_set_down(struct shash *local_bindings, const char *pb_name, +@@ -853,7 +903,6 @@ local_binding_set_down(struct shash *local_bindings, const char *pb_name, if (!sb_readonly && b_lport && b_lport->pb->n_up && b_lport->pb->up[0] && (!b_lport->pb->chassis || b_lport->pb->chassis == chassis_rec)) { @@ -120,7 +160,45 @@ index 5df62baef..bd810f669 100644 binding_lport_set_down(b_lport, sb_readonly); LIST_FOR_EACH (b_lport, list_node, &lbinding->binding_lports) { binding_lport_set_down(b_lport, sb_readonly); -@@ -1239,7 +1284,9 @@ claim_lport(const struct sbrec_port_binding *pb, +@@ -1028,6 +1077,26 @@ set_pb_chassis_in_sbrec(const struct sbrec_port_binding *pb, + } + } + ++void ++set_pb_additional_chassis_in_sbrec(const struct sbrec_port_binding *pb, ++ const struct sbrec_chassis *chassis_rec, ++ bool is_set) ++{ ++ if (!is_additional_chassis(pb, chassis_rec)) { ++ VLOG_INFO("Claiming lport %s for this additional chassis.", ++ pb->logical_port); ++ for (size_t i = 0; i < pb->n_mac; i++) { ++ VLOG_INFO("%s: Claiming %s", pb->logical_port, pb->mac[i]); ++ } ++ sbrec_port_binding_update_additional_chassis_addvalue(pb, chassis_rec); ++ if (pb->chassis == chassis_rec) { ++ sbrec_port_binding_set_chassis(pb, NULL); ++ } ++ } else if (!is_set) { ++ remove_additional_chassis(pb, chassis_rec); ++ } ++} ++ + bool + local_bindings_pb_chassis_is_set(struct shash *local_bindings, + const char *pb_name, +@@ -1228,8 +1297,8 @@ claim_lport(const struct sbrec_port_binding *pb, + } + set_pb_chassis_in_sbrec(pb, chassis_rec, true); + } else { +- if_status_mgr_claim_iface(if_mgr, pb, chassis_rec, +- sb_readonly); ++ if_status_mgr_claim_iface(if_mgr, pb, chassis_rec, iface_rec, ++ sb_readonly, can_bind); + } + register_claim_timestamp(pb->logical_port, now); + sset_find_and_delete(postponed_ports, pb->logical_port); +@@ -1239,29 +1308,19 @@ claim_lport(const struct sbrec_port_binding *pb, return false; } } else { @@ -129,9 +207,35 @@ index 5df62baef..bd810f669 100644 + !smap_get_bool(&iface_rec->external_ids, + OVN_INSTALLED_EXT_ID, false)) { if_status_mgr_claim_iface(if_mgr, pb, chassis_rec, - sb_readonly); +- sb_readonly); ++ iface_rec, sb_readonly, ++ can_bind); } -@@ -1464,9 +1511,11 @@ consider_vif_lport_(const struct sbrec_port_binding *pb, + } + } + } else if (can_bind == CAN_BIND_AS_ADDITIONAL) { + if (!is_additional_chassis(pb, chassis_rec)) { +- if (sb_readonly) { +- return false; +- } +- +- VLOG_INFO("Claiming lport %s for this additional chassis.", +- pb->logical_port); +- for (size_t i = 0; i < pb->n_mac; i++) { +- VLOG_INFO("%s: Claiming %s", pb->logical_port, pb->mac[i]); +- } +- +- sbrec_port_binding_update_additional_chassis_addvalue(pb, +- chassis_rec); +- if (pb->chassis == chassis_rec) { +- sbrec_port_binding_set_chassis(pb, NULL); +- } ++ if_status_mgr_claim_iface(if_mgr, pb, chassis_rec, iface_rec, ++ sb_readonly, can_bind); + update_tracked = true; + } + } +@@ -1464,9 +1523,11 @@ consider_vif_lport_(const struct sbrec_port_binding *pb, const char *requested_chassis_option = smap_get( &pb->options, "requested-chassis"); VLOG_INFO_RL(&rl, @@ -145,7 +249,25 @@ index 5df62baef..bd810f669 100644 } } -@@ -2288,6 +2337,11 @@ consider_iface_release(const struct ovsrec_interface *iface_rec, +@@ -2030,7 +2091,7 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) + free(lnet_lport); + } + +- /* Run through external lport list to see if these are external ports ++ /* Run through external lport list to see if there are external ports + * on local datapaths discovered from above loop, and update the + * corresponding local datapath accordingly. */ + struct lport *ext_lport; +@@ -2039,7 +2100,7 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) + free(ext_lport); + } + +- /* Run through multichassis lport list to see if these are ports ++ /* Run through multichassis lport list to see if there are ports + * on local datapaths discovered from above loop, and update the + * corresponding local datapath accordingly. */ + struct lport *multichassis_lport; +@@ -2288,6 +2349,11 @@ consider_iface_release(const struct ovsrec_interface *iface_rec, return false; } } @@ -157,7 +279,7 @@ index 5df62baef..bd810f669 100644 } else if (lbinding && b_lport && b_lport->type == LP_LOCALPORT) { /* lbinding is associated with a localport. Remove it from the -@@ -2558,6 +2612,7 @@ handle_deleted_lport(const struct sbrec_port_binding *pb, +@@ -2558,6 +2624,7 @@ handle_deleted_lport(const struct sbrec_port_binding *pb, if (ld) { remove_pb_from_local_datapath(pb, b_ctx_out, ld); @@ -165,7 +287,7 @@ index 5df62baef..bd810f669 100644 return; } -@@ -2581,6 +2636,7 @@ handle_deleted_lport(const struct sbrec_port_binding *pb, +@@ -2581,6 +2648,7 @@ handle_deleted_lport(const struct sbrec_port_binding *pb, remove_pb_from_local_datapath(pb, b_ctx_out, ld); } @@ -173,7 +295,7 @@ index 5df62baef..bd810f669 100644 } } -@@ -2627,6 +2683,11 @@ handle_deleted_vif_lport(const struct sbrec_port_binding *pb, +@@ -2627,6 +2695,11 @@ handle_deleted_vif_lport(const struct sbrec_port_binding *pb, } handle_deleted_lport(pb, b_ctx_in, b_ctx_out); @@ -185,7 +307,7 @@ index 5df62baef..bd810f669 100644 return true; } -@@ -3314,6 +3375,24 @@ binding_lport_delete(struct shash *binding_lports, +@@ -3314,6 +3387,24 @@ binding_lport_delete(struct shash *binding_lports, binding_lport_destroy(b_lport); } @@ -210,7 +332,7 @@ index 5df62baef..bd810f669 100644 static void binding_lport_set_up(struct binding_lport *b_lport, bool sb_readonly) { -@@ -3331,6 +3410,7 @@ binding_lport_set_down(struct binding_lport *b_lport, bool sb_readonly) +@@ -3331,6 +3422,7 @@ binding_lport_set_down(struct binding_lport *b_lport, bool sb_readonly) if (sb_readonly || !b_lport || !b_lport->pb->n_up || !b_lport->pb->up[0]) { return; } @@ -219,7 +341,7 @@ index 5df62baef..bd810f669 100644 bool up = false; sbrec_port_binding_set_up(b_lport->pb, &up, 1); diff --git a/controller/binding.h b/controller/binding.h -index 6c3a98b02..5b73c6a4b 100644 +index 6c3a98b02..46e618b97 100644 --- a/controller/binding.h +++ b/controller/binding.h @@ -159,6 +159,14 @@ bool local_binding_is_up(struct shash *local_bindings, const char *pb_name, @@ -237,10 +359,15 @@ index 6c3a98b02..5b73c6a4b 100644 void local_binding_set_up(struct shash *local_bindings, const char *pb_name, const struct sbrec_chassis *chassis_rec, const char *ts_now_str, bool sb_readonly, -@@ -195,6 +203,14 @@ void set_pb_chassis_in_sbrec(const struct sbrec_port_binding *pb, +@@ -194,6 +202,18 @@ bool is_additional_chassis(const struct sbrec_port_binding *pb, + void set_pb_chassis_in_sbrec(const struct sbrec_port_binding *pb, const struct sbrec_chassis *chassis_rec, bool is_set); - ++void ++set_pb_additional_chassis_in_sbrec(const struct sbrec_port_binding *pb, ++ const struct sbrec_chassis *chassis_rec, ++ bool is_set); ++ +void remove_ovn_installed_for_uuid(const struct ovsrec_interface_table *, + const struct uuid *); + @@ -248,10 +375,9 @@ index 6c3a98b02..5b73c6a4b 100644 + const struct sbrec_port_binding_table *pb_table, + const char *iface_id, + const struct uuid *pb_uuid); -+ + /* Corresponds to each Port_Binding.type. */ enum en_lport_type { - LP_UNKNOWN, diff --git a/controller/encaps.c b/controller/encaps.c index 2662eaf98..b69d72584 100644 --- a/controller/encaps.c @@ -363,10 +489,25 @@ index 867c6f28c..3e58b3c82 100644 + #endif /* controller/encaps.h */ diff --git a/controller/if-status.c b/controller/if-status.c -index d1c14ac30..8503e5daa 100644 +index d1c14ac30..2b2eb1679 100644 --- a/controller/if-status.c +++ b/controller/if-status.c -@@ -54,44 +54,54 @@ VLOG_DEFINE_THIS_MODULE(if_status); +@@ -18,12 +18,14 @@ + #include "binding.h" + #include "if-status.h" + #include "ofctrl-seqno.h" ++#include "ovsport.h" + #include "simap.h" + + #include "lib/hmapx.h" + #include "lib/util.h" + #include "timeval.h" + #include "openvswitch/vlog.h" ++#include "lib/vswitch-idl.h" + #include "lib/ovn-sb-idl.h" + + VLOG_DEFINE_THIS_MODULE(if_status); +@@ -54,44 +56,54 @@ VLOG_DEFINE_THIS_MODULE(if_status); */ enum if_state { @@ -450,7 +591,7 @@ index d1c14ac30..8503e5daa 100644 * | | +----------------------+ | | | * | | | V ^ | | | * | | | | | handle_claims() | | | -@@ -109,38 +119,63 @@ static const char *if_state_names[] = { +@@ -109,43 +121,69 @@ static const char *if_state_names[] = { * | | | - remove ovn-installed from ovsdb | | | * | | | mgr_update() | | | * | +----------------------+ - sbrec_update_chassis if needed | | | @@ -538,7 +679,13 @@ index d1c14ac30..8503e5daa 100644 enum if_state state; /* State of the interface in the state machine. */ uint32_t install_seqno; /* Seqno at which this interface is expected to * be fully programmed in OVS. Only used in state -@@ -155,6 +190,9 @@ struct if_status_mgr { + * OIF_INSTALL_FLOWS. + */ ++ uint16_t mtu; /* Extracted from OVS interface.mtu field. */ + }; + + static uint64_t ifaces_usage; +@@ -155,6 +193,9 @@ struct if_status_mgr { /* All local interfaces, mapping from 'iface-id' to 'struct ovs_iface'. */ struct shash ifaces; @@ -548,10 +695,17 @@ index d1c14ac30..8503e5daa 100644 /* All local interfaces, stored per state. */ struct hmapx ifaces_per_state[OIF_MAX]; -@@ -170,15 +208,20 @@ struct if_status_mgr { - static struct ovs_iface *ovs_iface_create(struct if_status_mgr *, - const char *iface_id, - enum if_state ); +@@ -167,18 +208,24 @@ struct if_status_mgr { + uint32_t iface_seqno; + }; + +-static struct ovs_iface *ovs_iface_create(struct if_status_mgr *, +- const char *iface_id, +- enum if_state ); ++static struct ovs_iface * ++ovs_iface_create(struct if_status_mgr *, const char *iface_id, ++ const struct ovsrec_interface *iface_rec, ++ enum if_state); +static void add_to_ovn_uninstall_hash(struct if_status_mgr *, const char *, + const struct uuid *); static void ovs_iface_destroy(struct if_status_mgr *, struct ovs_iface *); @@ -569,7 +723,7 @@ index d1c14ac30..8503e5daa 100644 struct if_status_mgr * if_status_mgr_create(void) { -@@ -189,6 +232,7 @@ if_status_mgr_create(void) +@@ -189,6 +236,7 @@ if_status_mgr_create(void) hmapx_init(&mgr->ifaces_per_state[i]); } shash_init(&mgr->ifaces); @@ -577,7 +731,7 @@ index d1c14ac30..8503e5daa 100644 return mgr; } -@@ -202,6 +246,11 @@ if_status_mgr_clear(struct if_status_mgr *mgr) +@@ -202,6 +250,11 @@ if_status_mgr_clear(struct if_status_mgr *mgr) } ovs_assert(shash_is_empty(&mgr->ifaces)); @@ -589,7 +743,7 @@ index d1c14ac30..8503e5daa 100644 for (size_t i = 0; i < ARRAY_SIZE(mgr->ifaces_per_state); i++) { ovs_assert(hmapx_is_empty(&mgr->ifaces_per_state[i])); } -@@ -212,6 +261,7 @@ if_status_mgr_destroy(struct if_status_mgr *mgr) +@@ -212,6 +265,7 @@ if_status_mgr_destroy(struct if_status_mgr *mgr) { if_status_mgr_clear(mgr); shash_destroy(&mgr->ifaces); @@ -597,15 +751,32 @@ index d1c14ac30..8503e5daa 100644 for (size_t i = 0; i < ARRAY_SIZE(mgr->ifaces_per_state); i++) { hmapx_destroy(&mgr->ifaces_per_state[i]); } -@@ -231,6 +281,7 @@ if_status_mgr_claim_iface(struct if_status_mgr *mgr, - iface = ovs_iface_create(mgr, iface_id, OIF_CLAIMED); +@@ -222,27 +276,35 @@ void + if_status_mgr_claim_iface(struct if_status_mgr *mgr, + const struct sbrec_port_binding *pb, + const struct sbrec_chassis *chassis_rec, +- bool sb_readonly) ++ const struct ovsrec_interface *iface_rec, ++ bool sb_readonly, enum can_bind bind_type) + { + const char *iface_id = pb->logical_port; + struct ovs_iface *iface = shash_find_data(&mgr->ifaces, iface_id); + + if (!iface) { +- iface = ovs_iface_create(mgr, iface_id, OIF_CLAIMED); ++ iface = ovs_iface_create(mgr, iface_id, iface_rec, OIF_CLAIMED); } + memcpy(&iface->pb_uuid, &pb->header_.uuid, sizeof(iface->pb_uuid)); if (!sb_readonly) { - set_pb_chassis_in_sbrec(pb, chassis_rec, true); +- set_pb_chassis_in_sbrec(pb, chassis_rec, true); ++ if (bind_type == CAN_BIND_AS_MAIN) { ++ set_pb_chassis_in_sbrec(pb, chassis_rec, true); ++ } else if (bind_type == CAN_BIND_AS_ADDITIONAL) { ++ set_pb_additional_chassis_in_sbrec(pb, chassis_rec, true); ++ } } -@@ -238,11 +289,13 @@ if_status_mgr_claim_iface(struct if_status_mgr *mgr, + switch (iface->state) { case OIF_CLAIMED: case OIF_INSTALL_FLOWS: @@ -619,7 +790,7 @@ index d1c14ac30..8503e5daa 100644 ovs_iface_set_state(mgr, iface, OIF_CLAIMED); break; case OIF_MAX: -@@ -271,9 +324,10 @@ if_status_mgr_release_iface(struct if_status_mgr *mgr, const char *iface_id) +@@ -271,9 +333,10 @@ if_status_mgr_release_iface(struct if_status_mgr *mgr, const char *iface_id) switch (iface->state) { case OIF_CLAIMED: case OIF_INSTALL_FLOWS: @@ -633,7 +804,7 @@ index d1c14ac30..8503e5daa 100644 case OIF_MARK_UP: case OIF_INSTALLED: /* Properly mark interfaces "down" if their flows were already -@@ -282,6 +336,7 @@ if_status_mgr_release_iface(struct if_status_mgr *mgr, const char *iface_id) +@@ -282,6 +345,7 @@ if_status_mgr_release_iface(struct if_status_mgr *mgr, const char *iface_id) ovs_iface_set_state(mgr, iface, OIF_MARK_DOWN); break; case OIF_MARK_DOWN: @@ -641,7 +812,7 @@ index d1c14ac30..8503e5daa 100644 /* Nothing to do here. */ break; case OIF_MAX: -@@ -302,9 +357,10 @@ if_status_mgr_delete_iface(struct if_status_mgr *mgr, const char *iface_id) +@@ -302,9 +366,10 @@ if_status_mgr_delete_iface(struct if_status_mgr *mgr, const char *iface_id) switch (iface->state) { case OIF_CLAIMED: case OIF_INSTALL_FLOWS: @@ -655,7 +826,7 @@ index d1c14ac30..8503e5daa 100644 case OIF_MARK_UP: case OIF_INSTALLED: /* Properly mark interfaces "down" if their flows were already -@@ -313,6 +369,7 @@ if_status_mgr_delete_iface(struct if_status_mgr *mgr, const char *iface_id) +@@ -313,6 +378,7 @@ if_status_mgr_delete_iface(struct if_status_mgr *mgr, const char *iface_id) ovs_iface_set_state(mgr, iface, OIF_MARK_DOWN); break; case OIF_MARK_DOWN: @@ -663,7 +834,7 @@ index d1c14ac30..8503e5daa 100644 /* Nothing to do here. */ break; case OIF_MAX: -@@ -346,12 +403,34 @@ if_status_handle_claims(struct if_status_mgr *mgr, +@@ -346,12 +412,34 @@ if_status_handle_claims(struct if_status_mgr *mgr, return rc; } @@ -698,7 +869,7 @@ index d1c14ac30..8503e5daa 100644 if (!binding_data) { return; } -@@ -359,6 +438,17 @@ if_status_mgr_update(struct if_status_mgr *mgr, +@@ -359,6 +447,17 @@ if_status_mgr_update(struct if_status_mgr *mgr, struct shash *bindings = &binding_data->bindings; struct hmapx_node *node; @@ -716,7 +887,7 @@ index d1c14ac30..8503e5daa 100644 /* Interfaces in OIF_MARK_UP/INSTALL_FLOWS state have already set their * pb->chassis. However, the update might still be in fly (confirmation * not received yet) or pb->chassis was overwitten by another chassis. -@@ -390,6 +480,10 @@ if_status_mgr_update(struct if_status_mgr *mgr, +@@ -390,6 +489,10 @@ if_status_mgr_update(struct if_status_mgr *mgr, HMAPX_FOR_EACH_SAFE (node, &mgr->ifaces_per_state[OIF_MARK_DOWN]) { struct ovs_iface *iface = node->data; @@ -727,7 +898,7 @@ index d1c14ac30..8503e5daa 100644 if (!sb_readonly) { local_binding_set_pb(bindings, iface->id, chassis_rec, NULL, false); -@@ -437,6 +531,21 @@ if_status_mgr_update(struct if_status_mgr *mgr, +@@ -437,6 +540,21 @@ if_status_mgr_update(struct if_status_mgr *mgr, } } @@ -749,7 +920,7 @@ index d1c14ac30..8503e5daa 100644 /* Register for a notification about flows being installed in OVS for all * newly claimed interfaces for which pb->chassis has been updated. * Request a seqno update when the flows for new interfaces have been -@@ -450,10 +559,23 @@ if_status_mgr_update(struct if_status_mgr *mgr, +@@ -450,10 +568,23 @@ if_status_mgr_update(struct if_status_mgr *mgr, } } @@ -773,7 +944,7 @@ index d1c14ac30..8503e5daa 100644 bool sb_readonly, bool ovs_readonly) { struct ofctrl_acked_seqnos *acked_seqnos = -@@ -471,12 +593,25 @@ if_status_mgr_run(struct if_status_mgr *mgr, +@@ -471,12 +602,25 @@ if_status_mgr_run(struct if_status_mgr *mgr, iface->install_seqno)) { continue; } @@ -800,7 +971,7 @@ index d1c14ac30..8503e5daa 100644 sb_readonly, ovs_readonly); } -@@ -492,6 +627,18 @@ ovs_iface_account_mem(const char *iface_id, bool erase) +@@ -492,8 +636,46 @@ ovs_iface_account_mem(const char *iface_id, bool erase) } } @@ -816,10 +987,42 @@ index d1c14ac30..8503e5daa 100644 + } +} + ++uint16_t ++if_status_mgr_iface_get_mtu(const struct if_status_mgr *mgr, ++ const char *iface_id) ++{ ++ const struct ovs_iface *iface = shash_find_data(&mgr->ifaces, iface_id); ++ return iface ? iface->mtu : 0; ++} ++ ++bool ++if_status_mgr_iface_update(const struct if_status_mgr *mgr, ++ const struct ovsrec_interface *iface_rec) ++{ ++ const char *iface_id = smap_get(&iface_rec->external_ids, "iface-id"); ++ if (!iface_id) { ++ return false; ++ } ++ uint16_t mtu = get_iface_mtu(iface_rec); ++ struct ovs_iface *iface = shash_find_data(&mgr->ifaces, iface_id); ++ if (iface && iface->mtu != mtu) { ++ iface->mtu = mtu; ++ return true; ++ } ++ return false; ++} ++ static struct ovs_iface * ovs_iface_create(struct if_status_mgr *mgr, const char *iface_id, ++ const struct ovsrec_interface *iface_rec, enum if_state state) -@@ -506,6 +653,16 @@ ovs_iface_create(struct if_status_mgr *mgr, const char *iface_id, + { + struct ovs_iface *iface = xzalloc(sizeof *iface); +@@ -503,9 +685,20 @@ ovs_iface_create(struct if_status_mgr *mgr, const char *iface_id, + shash_add_nocopy(&mgr->ifaces, iface->id, iface); + ovs_iface_set_state(mgr, iface, state); + ovs_iface_account_mem(iface_id, false); ++ if_status_mgr_iface_update(mgr, iface_rec); return iface; } @@ -836,7 +1039,7 @@ index d1c14ac30..8503e5daa 100644 static void ovs_iface_destroy(struct if_status_mgr *mgr, struct ovs_iface *iface) { -@@ -521,6 +678,23 @@ ovs_iface_destroy(struct if_status_mgr *mgr, struct ovs_iface *iface) +@@ -521,6 +714,23 @@ ovs_iface_destroy(struct if_status_mgr *mgr, struct ovs_iface *iface) free(iface); } @@ -860,7 +1063,7 @@ index d1c14ac30..8503e5daa 100644 static void ovs_iface_set_state(struct if_status_mgr *mgr, struct ovs_iface *iface, enum if_state state) -@@ -539,6 +713,7 @@ static void +@@ -539,6 +749,7 @@ static void if_status_mgr_update_bindings(struct if_status_mgr *mgr, struct local_binding_data *binding_data, const struct sbrec_chassis *chassis_rec, @@ -868,7 +1071,7 @@ index d1c14ac30..8503e5daa 100644 bool sb_readonly, bool ovs_readonly) { if (!binding_data) { -@@ -558,7 +733,17 @@ if_status_mgr_update_bindings(struct if_status_mgr *mgr, +@@ -558,7 +769,17 @@ if_status_mgr_update_bindings(struct if_status_mgr *mgr, sb_readonly, ovs_readonly); } @@ -888,18 +1091,29 @@ index d1c14ac30..8503e5daa 100644 * module. */ diff --git a/controller/if-status.h b/controller/if-status.h -index 5bd187a25..8ba80acd9 100644 +index 5bd187a25..15624bcfa 100644 --- a/controller/if-status.h +++ b/controller/if-status.h -@@ -17,6 +17,7 @@ +@@ -17,8 +17,10 @@ #define IF_STATUS_H 1 #include "openvswitch/shash.h" +#include "lib/vswitch-idl.h" #include "binding.h" - -@@ -35,9 +36,13 @@ void if_status_mgr_delete_iface(struct if_status_mgr *, const char *iface_id); ++#include "lport.h" + + struct if_status_mgr; + struct simap; +@@ -29,15 +31,20 @@ void if_status_mgr_destroy(struct if_status_mgr *); + void if_status_mgr_claim_iface(struct if_status_mgr *, + const struct sbrec_port_binding *pb, + const struct sbrec_chassis *chassis_rec, +- bool sb_readonly); ++ const struct ovsrec_interface *iface_rec, ++ bool sb_readonly, enum can_bind bind_type); + void if_status_mgr_release_iface(struct if_status_mgr *, const char *iface_id); + void if_status_mgr_delete_iface(struct if_status_mgr *, const char *iface_id); void if_status_mgr_update(struct if_status_mgr *, struct local_binding_data *, const struct sbrec_chassis *chassis, @@ -913,19 +1127,41 @@ index 5bd187a25..8ba80acd9 100644 bool sb_readonly, bool ovs_readonly); void if_status_mgr_get_memory_usage(struct if_status_mgr *mgr, struct simap *usage); -@@ -48,5 +53,8 @@ bool if_status_handle_claims(struct if_status_mgr *mgr, +@@ -48,5 +55,12 @@ bool if_status_handle_claims(struct if_status_mgr *mgr, const struct sbrec_chassis *chassis_rec, struct hmap *tracked_datapath, bool sb_readonly); +void if_status_mgr_remove_ovn_installed(struct if_status_mgr *mgr, + const char *name, + const struct uuid *uuid); ++uint16_t if_status_mgr_iface_get_mtu(const struct if_status_mgr *mgr, ++ const char *iface_id); ++bool if_status_mgr_iface_update(const struct if_status_mgr *mgr, ++ const struct ovsrec_interface *iface_rec); # endif /* controller/if-status.h */ diff --git a/controller/lflow.c b/controller/lflow.c -index 6a98b19e1..0b071138d 100644 +index 6a98b19e1..22faaf013 100644 --- a/controller/lflow.c +++ b/controller/lflow.c +@@ -397,7 +397,7 @@ consider_lflow_for_added_as_ips__( + : OFTABLE_LOG_EGRESS_PIPELINE); + uint8_t ptable = first_ptable + lflow->table_id; + uint8_t output_ptable = (ingress +- ? OFTABLE_REMOTE_OUTPUT ++ ? OFTABLE_OUTPUT_INIT + : OFTABLE_SAVE_INPORT); + + uint64_t ovnacts_stub[1024 / 8]; +@@ -1067,7 +1067,7 @@ consider_logical_flow__(const struct sbrec_logical_flow *lflow, + : OFTABLE_LOG_EGRESS_PIPELINE); + uint8_t ptable = first_ptable + lflow->table_id; + uint8_t output_ptable = (ingress +- ? OFTABLE_REMOTE_OUTPUT ++ ? OFTABLE_OUTPUT_INIT + : OFTABLE_SAVE_INPORT); + + /* Parse OVN logical actions. @@ -1729,6 +1729,7 @@ add_lb_vip_hairpin_flows(const struct ovn_controller_lb *lb, static void @@ -997,6 +1233,100 @@ index 6a98b19e1..0b071138d 100644 local_datapaths, &match, &ofpacts, flow_table); } } +diff --git a/controller/lflow.h b/controller/lflow.h +index dd742257b..2472dec29 100644 +--- a/controller/lflow.h ++++ b/controller/lflow.h +@@ -63,27 +63,36 @@ struct uuid; + * + * These are heavily documented in ovn-architecture(7), please update it if + * you make any changes. */ +-#define OFTABLE_PHY_TO_LOG 0 +-#define OFTABLE_LOG_INGRESS_PIPELINE 8 /* First of LOG_PIPELINE_LEN tables. */ +-#define OFTABLE_REMOTE_OUTPUT 37 +-#define OFTABLE_LOCAL_OUTPUT 38 +-#define OFTABLE_CHECK_LOOPBACK 39 +-#define OFTABLE_LOG_EGRESS_PIPELINE 40 /* First of LOG_PIPELINE_LEN tables. */ +-#define OFTABLE_SAVE_INPORT 64 +-#define OFTABLE_LOG_TO_PHY 65 +-#define OFTABLE_MAC_BINDING 66 +-#define OFTABLE_MAC_LOOKUP 67 +-#define OFTABLE_CHK_LB_HAIRPIN 68 +-#define OFTABLE_CHK_LB_HAIRPIN_REPLY 69 +-#define OFTABLE_CT_SNAT_HAIRPIN 70 +-#define OFTABLE_GET_FDB 71 +-#define OFTABLE_LOOKUP_FDB 72 +-#define OFTABLE_CHK_IN_PORT_SEC 73 +-#define OFTABLE_CHK_IN_PORT_SEC_ND 74 +-#define OFTABLE_CHK_OUT_PORT_SEC 75 +-#define OFTABLE_ECMP_NH_MAC 76 +-#define OFTABLE_ECMP_NH 77 +-#define OFTABLE_CHK_LB_AFFINITY 78 ++#define OFTABLE_PHY_TO_LOG 0 ++ ++/* Start of LOG_PIPELINE_LEN tables. */ ++#define OFTABLE_LOG_INGRESS_PIPELINE 8 ++#define OFTABLE_OUTPUT_LARGE_PKT_DETECT 37 ++#define OFTABLE_OUTPUT_LARGE_PKT_PROCESS 38 ++#define OFTABLE_REMOTE_OUTPUT 39 ++#define OFTABLE_LOCAL_OUTPUT 40 ++#define OFTABLE_CHECK_LOOPBACK 41 ++ ++/* Start of the OUTPUT section of the pipeline. */ ++#define OFTABLE_OUTPUT_INIT OFTABLE_OUTPUT_LARGE_PKT_DETECT ++ ++/* Start of LOG_PIPELINE_LEN tables. */ ++#define OFTABLE_LOG_EGRESS_PIPELINE 42 ++#define OFTABLE_SAVE_INPORT 64 ++#define OFTABLE_LOG_TO_PHY 65 ++#define OFTABLE_MAC_BINDING 66 ++#define OFTABLE_MAC_LOOKUP 67 ++#define OFTABLE_CHK_LB_HAIRPIN 68 ++#define OFTABLE_CHK_LB_HAIRPIN_REPLY 69 ++#define OFTABLE_CT_SNAT_HAIRPIN 70 ++#define OFTABLE_GET_FDB 71 ++#define OFTABLE_LOOKUP_FDB 72 ++#define OFTABLE_CHK_IN_PORT_SEC 73 ++#define OFTABLE_CHK_IN_PORT_SEC_ND 74 ++#define OFTABLE_CHK_OUT_PORT_SEC 75 ++#define OFTABLE_ECMP_NH_MAC 76 ++#define OFTABLE_ECMP_NH 77 ++#define OFTABLE_CHK_LB_AFFINITY 78 + + struct lflow_ctx_in { + struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath; +diff --git a/controller/local_data.c b/controller/local_data.c +index acaf1de6d..cf0b21bb1 100644 +--- a/controller/local_data.c ++++ b/controller/local_data.c +@@ -22,6 +22,7 @@ + #include "lib/util.h" + #include "lib/vswitch-idl.h" + #include "openvswitch/vlog.h" ++#include "socket-util.h" + + /* OVN includes. */ + #include "encaps.h" +@@ -447,6 +448,7 @@ local_nonvif_data_run(const struct ovsrec_bridge *br_int, + tun->chassis_id = xstrdup(tunnel_id); + tun->ofport = u16_to_ofp(ofport); + tun->type = tunnel_type; ++ tun->is_ipv6 = ip ? addr_is_ipv6(ip) : false; + + free(hash_id); + free(ip); +diff --git a/controller/local_data.h b/controller/local_data.h +index 748f009aa..ad0fa7f94 100644 +--- a/controller/local_data.h ++++ b/controller/local_data.h +@@ -133,6 +133,7 @@ struct chassis_tunnel { + char *chassis_id; + ofp_port_t ofport; + enum chassis_tunnel_type type; ++ bool is_ipv6; + }; + + void local_nonvif_data_run(const struct ovsrec_bridge *br_int, diff --git a/controller/mirror.c b/controller/mirror.c index 665736966..0e5885e9b 100644 --- a/controller/mirror.c @@ -1069,6 +1399,75 @@ index 665736966..0e5885e9b 100644 struct ovsrec_port *port = ovsrec_port_insert(ovs_idl_txn); ovsrec_port_set_name(port, port_name); +diff --git a/controller/ofctrl.c b/controller/ofctrl.c +index b1ba1c743..64a444ff6 100644 +--- a/controller/ofctrl.c ++++ b/controller/ofctrl.c +@@ -766,13 +766,18 @@ ofctrl_get_mf_field_id(void) + + /* Runs the OpenFlow state machine against 'br_int', which is local to the + * hypervisor on which we are running. Attempts to negotiate a Geneve option +- * field for class OVN_GENEVE_CLASS, type OVN_GENEVE_TYPE. */ +-void ++ * field for class OVN_GENEVE_CLASS, type OVN_GENEVE_TYPE. ++ * ++ * Returns 'true' if an OpenFlow reconnect happened; 'false' otherwise. ++ */ ++bool + ofctrl_run(const struct ovsrec_bridge *br_int, + const struct ovsrec_open_vswitch_table *ovs_table, + struct shash *pending_ct_zones) + { + char *target = xasprintf("unix:%s/%s.mgmt", ovs_rundir(), br_int->name); ++ bool reconnected = false; ++ + if (strcmp(target, rconn_get_target(swconn))) { + VLOG_INFO("%s: connecting to switch", target); + rconn_connect(swconn, target, target); +@@ -782,10 +787,12 @@ ofctrl_run(const struct ovsrec_bridge *br_int, + rconn_run(swconn); + + if (!rconn_is_connected(swconn)) { +- return; ++ return reconnected; + } ++ + if (seqno != rconn_get_connection_seqno(swconn)) { + seqno = rconn_get_connection_seqno(swconn); ++ reconnected = true; + state = S_NEW; + + /* Reset the state of any outstanding ct flushes to resend them. */ +@@ -855,6 +862,8 @@ ofctrl_run(const struct ovsrec_bridge *br_int, + * point, so ensure that we come back again without waiting. */ + poll_immediate_wake(); + } ++ ++ return reconnected; + } + + void +@@ -909,6 +918,7 @@ ofctrl_recv(const struct ofp_header *oh, enum ofptype type) + } else if (type == OFPTYPE_ERROR) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300); + log_openflow_rl(&rl, VLL_INFO, oh, "OpenFlow error"); ++ rconn_reconnect(swconn); + } else { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300); + log_openflow_rl(&rl, VLL_DBG, oh, "OpenFlow packet ignored"); +diff --git a/controller/ofctrl.h b/controller/ofctrl.h +index f5751e3ee..105f9370b 100644 +--- a/controller/ofctrl.h ++++ b/controller/ofctrl.h +@@ -51,7 +51,7 @@ struct ovn_desired_flow_table { + void ofctrl_init(struct ovn_extend_table *group_table, + struct ovn_extend_table *meter_table, + int inactivity_probe_interval); +-void ofctrl_run(const struct ovsrec_bridge *br_int, ++bool ofctrl_run(const struct ovsrec_bridge *br_int, + const struct ovsrec_open_vswitch_table *, + struct shash *pending_ct_zones); + enum mf_field_id ofctrl_get_mf_field_id(void); diff --git a/controller/ovn-controller.8.xml b/controller/ovn-controller.8.xml index ab52e2d34..f61f43008 100644 --- a/controller/ovn-controller.8.xml @@ -1112,10 +1511,18 @@ index ab52e2d34..f61f43008 100644 diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c -index 2d18bbfca..44a4518b9 100644 +index 2d18bbfca..ead789fb9 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c -@@ -712,7 +712,7 @@ get_snat_ct_zone(const struct sbrec_datapath_binding *dp) +@@ -60,6 +60,7 @@ + #include "lib/ovn-dirs.h" + #include "lib/ovn-sb-idl.h" + #include "lib/ovn-util.h" ++#include "ovsport.h" + #include "patch.h" + #include "vif-plug.h" + #include "vif-plug-provider.h" +@@ -712,7 +713,7 @@ get_snat_ct_zone(const struct sbrec_datapath_binding *dp) } static void @@ -1124,7 +1531,7 @@ index 2d18bbfca..44a4518b9 100644 const struct hmap *local_datapaths, struct simap *ct_zones, unsigned long *ct_zone_bitmap, struct shash *pending_ct_zones) -@@ -725,9 +725,9 @@ update_ct_zones(const struct shash *binding_lports, +@@ -725,9 +726,9 @@ update_ct_zones(const struct shash *binding_lports, unsigned long unreq_snat_zones_map[BITMAP_N_LONGS(MAX_CT_ZONES)]; struct simap unreq_snat_zones = SIMAP_INITIALIZER(&unreq_snat_zones); @@ -1137,7 +1544,72 @@ index 2d18bbfca..44a4518b9 100644 } /* Local patched datapath (gateway routers) need zones assigned. */ -@@ -2010,7 +2010,11 @@ addr_sets_update(const struct sbrec_address_set_table *address_set_table, +@@ -1060,6 +1061,7 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_name); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_bfd); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_bfd_status); ++ ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_mtu); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_type); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_options); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_ofport); +@@ -1158,6 +1160,56 @@ en_ofctrl_is_connected_run(struct engine_node *node, void *data) + engine_set_node_state(node, EN_UNCHANGED); + } + ++struct ed_type_if_status_mgr { ++ const struct if_status_mgr *manager; ++ const struct ovsrec_interface_table *iface_table; ++}; ++ ++static void * ++en_if_status_mgr_init(struct engine_node *node OVS_UNUSED, ++ struct engine_arg *arg OVS_UNUSED) ++{ ++ struct ed_type_if_status_mgr *data = xzalloc(sizeof *data); ++ return data; ++} ++ ++static void ++en_if_status_mgr_cleanup(void *data OVS_UNUSED) ++{ ++} ++ ++static void ++en_if_status_mgr_run(struct engine_node *node, void *data_) ++{ ++ enum engine_node_state state = EN_UNCHANGED; ++ struct ed_type_if_status_mgr *data = data_; ++ struct controller_engine_ctx *ctrl_ctx = engine_get_context()->client_ctx; ++ data->manager = ctrl_ctx->if_mgr; ++ data->iface_table = EN_OVSDB_GET(engine_get_input("OVS_interface", node)); ++ ++ const struct ovsrec_interface *iface; ++ OVSREC_INTERFACE_TABLE_FOR_EACH (iface, data->iface_table) { ++ if (if_status_mgr_iface_update(data->manager, iface)) { ++ state = EN_UPDATED; ++ } ++ } ++ engine_set_node_state(node, state); ++} ++ ++static bool ++if_status_mgr_ovs_interface_handler(struct engine_node *node, void *data) ++{ ++ struct ed_type_if_status_mgr *data_ = data; ++ ++ const struct ovsrec_interface *iface; ++ OVSREC_INTERFACE_TABLE_FOR_EACH_TRACKED (iface, data_->iface_table) { ++ if (if_status_mgr_iface_update(data_->manager, iface)) { ++ engine_set_node_state(node, EN_UPDATED); ++ } ++ } ++ return true; ++} ++ + /* This engine node is to wrap the OVS_interface input and maintain a copy of + * the old version of data for the column external_ids. + * +@@ -2010,7 +2062,11 @@ addr_sets_update(const struct sbrec_address_set_table *address_set_table, if (sbrec_address_set_is_deleted(as)) { expr_const_sets_remove(addr_sets, as->name); sset_add(deleted, as->name); @@ -1150,7 +1622,7 @@ index 2d18bbfca..44a4518b9 100644 struct expr_constant_set *cs_old = shash_find_data(addr_sets, as->name); if (!cs_old) { -@@ -2381,7 +2385,7 @@ en_ct_zones_run(struct engine_node *node, void *data) +@@ -2381,7 +2437,7 @@ en_ct_zones_run(struct engine_node *node, void *data) EN_OVSDB_GET(engine_get_input("OVS_bridge", node)); restore_ct_zones(bridge_table, ovs_table, ct_zones_data); @@ -1159,7 +1631,7 @@ index 2d18bbfca..44a4518b9 100644 &ct_zones_data->current, ct_zones_data->bitmap, &ct_zones_data->pending); -@@ -2471,8 +2475,10 @@ ct_zones_runtime_data_handler(struct engine_node *node, void *data) +@@ -2471,8 +2527,10 @@ ct_zones_runtime_data_handler(struct engine_node *node, void *data) SHASH_FOR_EACH (shash_node, &tdp->lports) { struct tracked_lport *t_lport = shash_node->data; if (strcmp(t_lport->pb->type, "") @@ -1172,7 +1644,7 @@ index 2d18bbfca..44a4518b9 100644 continue; } -@@ -2697,7 +2703,8 @@ static void +@@ -2697,7 +2755,8 @@ static void lb_data_removed_five_tuples_add(struct ed_type_lb_data *lb_data, const struct ovn_controller_lb *lb) { @@ -1182,7 +1654,7 @@ index 2d18bbfca..44a4518b9 100644 return; } -@@ -2716,7 +2723,8 @@ static void +@@ -2716,7 +2775,8 @@ static void lb_data_removed_five_tuples_remove(struct ed_type_lb_data *lb_data, const struct ovn_controller_lb *lb) { @@ -1192,7 +1664,143 @@ index 2d18bbfca..44a4518b9 100644 return; } -@@ -5071,7 +5079,8 @@ main(int argc, char *argv[]) +@@ -4048,6 +4108,9 @@ static void init_physical_ctx(struct engine_node *node, + const struct ed_type_mff_ovn_geneve *ed_mff_ovn_geneve = + engine_get_input_data("mff_ovn_geneve", node); + ++ const struct ovsrec_interface_table *ovs_interface_table = ++ EN_OVSDB_GET(engine_get_input("if_status_mgr", node)); ++ + const struct ovsrec_open_vswitch_table *ovs_table = + EN_OVSDB_GET(engine_get_input("OVS_open_vswitch", node)); + const struct ovsrec_bridge_table *bridge_table = +@@ -4072,6 +4135,7 @@ static void init_physical_ctx(struct engine_node *node, + p_ctx->sbrec_port_binding_by_name = sbrec_port_binding_by_name; + p_ctx->sbrec_port_binding_by_datapath = sbrec_port_binding_by_datapath; + p_ctx->port_binding_table = port_binding_table; ++ p_ctx->ovs_interface_table = ovs_interface_table; + p_ctx->mc_group_table = multicast_group_table; + p_ctx->br_int = br_int; + p_ctx->chassis_table = chassis_table; +@@ -4085,6 +4149,9 @@ static void init_physical_ctx(struct engine_node *node, + p_ctx->patch_ofports = &non_vif_data->patch_ofports; + p_ctx->chassis_tunnels = &non_vif_data->chassis_tunnels; + ++ struct controller_engine_ctx *ctrl_ctx = engine_get_context()->client_ctx; ++ p_ctx->if_mgr = ctrl_ctx->if_mgr; ++ + pflow_output_get_debug(node, &p_ctx->debug); + } + +@@ -4128,6 +4195,63 @@ en_pflow_output_run(struct engine_node *node, void *data) + engine_set_node_state(node, EN_UPDATED); + } + ++static bool ++pflow_output_if_status_mgr_handler(struct engine_node *node, ++ void *data) ++{ ++ struct ed_type_pflow_output *pfo = data; ++ struct ed_type_runtime_data *rt_data = ++ engine_get_input_data("runtime_data", node); ++ struct ed_type_non_vif_data *non_vif_data = ++ engine_get_input_data("non_vif_data", node); ++ struct ed_type_if_status_mgr *if_mgr_data = ++ engine_get_input_data("if_status_mgr", node); ++ ++ struct physical_ctx p_ctx; ++ init_physical_ctx(node, rt_data, non_vif_data, &p_ctx); ++ ++ const struct ovsrec_interface *iface; ++ OVSREC_INTERFACE_TABLE_FOR_EACH_TRACKED (iface, if_mgr_data->iface_table) { ++ const char *iface_id = smap_get(&iface->external_ids, "iface-id"); ++ if (!iface_id) { ++ continue; ++ } ++ ++ const struct sbrec_port_binding *pb = lport_lookup_by_name( ++ p_ctx.sbrec_port_binding_by_name, iface_id); ++ if (!pb) { ++ continue; ++ } ++ if (pb->n_additional_chassis) { ++ /* Update flows for all ports in datapath. */ ++ struct sbrec_port_binding *target = ++ sbrec_port_binding_index_init_row( ++ p_ctx.sbrec_port_binding_by_datapath); ++ sbrec_port_binding_index_set_datapath(target, pb->datapath); ++ ++ const struct sbrec_port_binding *binding; ++ SBREC_PORT_BINDING_FOR_EACH_EQUAL ( ++ binding, target, p_ctx.sbrec_port_binding_by_datapath) { ++ bool removed = sbrec_port_binding_is_deleted(binding); ++ if (!physical_handle_flows_for_lport(binding, removed, &p_ctx, ++ &pfo->flow_table)) { ++ return false; ++ } ++ } ++ sbrec_port_binding_index_destroy_row(target); ++ } else { ++ /* If any multichassis ports, update flows for the port. */ ++ bool removed = sbrec_port_binding_is_deleted(pb); ++ if (!physical_handle_flows_for_lport(pb, removed, &p_ctx, ++ &pfo->flow_table)) { ++ return false; ++ } ++ } ++ engine_set_node_state(node, EN_UPDATED); ++ } ++ return true; ++} ++ + static bool + pflow_output_sb_port_binding_handler(struct engine_node *node, + void *data) +@@ -4611,6 +4735,7 @@ main(int argc, char *argv[]) + ENGINE_NODE_WITH_CLEAR_TRACK_DATA(port_groups, "port_groups"); + ENGINE_NODE(northd_options, "northd_options"); + ENGINE_NODE(dhcp_options, "dhcp_options"); ++ ENGINE_NODE(if_status_mgr, "if_status_mgr"); + ENGINE_NODE_WITH_CLEAR_TRACK_DATA(lb_data, "lb_data"); + + #define SB_NODE(NAME, NAME_STR) ENGINE_NODE_SB(NAME, NAME_STR); +@@ -4649,6 +4774,9 @@ main(int argc, char *argv[]) + engine_add_input(&en_non_vif_data, &en_ovs_interface, + non_vif_data_ovs_iface_handler); + ++ engine_add_input(&en_if_status_mgr, &en_ovs_interface, ++ if_status_mgr_ovs_interface_handler); ++ + /* Note: The order of inputs is important, all OVS interface changes must + * be handled before any ct_zone changes. + */ +@@ -4659,6 +4787,8 @@ main(int argc, char *argv[]) + engine_add_input(&en_pflow_output, &en_sb_chassis, + pflow_lflow_output_sb_chassis_handler); + ++ engine_add_input(&en_pflow_output, &en_if_status_mgr, ++ pflow_output_if_status_mgr_handler); + engine_add_input(&en_pflow_output, &en_sb_port_binding, + pflow_output_sb_port_binding_handler); + engine_add_input(&en_pflow_output, &en_sb_multicast_group, +@@ -5061,8 +5191,14 @@ main(int argc, char *argv[]) + + if (br_int) { + ct_zones_data = engine_get_data(&en_ct_zones); +- if (ct_zones_data) { +- ofctrl_run(br_int, ovs_table, &ct_zones_data->pending); ++ if (ct_zones_data && ofctrl_run(br_int, ovs_table, ++ &ct_zones_data->pending)) { ++ static struct vlog_rate_limit rl ++ = VLOG_RATE_LIMIT_INIT(1, 1); ++ ++ VLOG_INFO_RL(&rl, "OVS OpenFlow connection reconnected," ++ "force recompute."); ++ engine_set_force_recompute(true); + } + + if (chassis) { +@@ -5071,7 +5207,8 @@ main(int argc, char *argv[]) chassis, sbrec_sb_global_first(ovnsb_idl_loop.idl), ovs_table, @@ -1202,7 +1810,7 @@ index 2d18bbfca..44a4518b9 100644 stopwatch_start(CONTROLLER_LOOP_STOPWATCH_NAME, time_msec()); -@@ -5225,6 +5234,11 @@ main(int argc, char *argv[]) +@@ -5225,6 +5362,11 @@ main(int argc, char *argv[]) stopwatch_start(IF_STATUS_MGR_UPDATE_STOPWATCH_NAME, time_msec()); if_status_mgr_update(if_mgr, binding_data, chassis, @@ -1214,7 +1822,7 @@ index 2d18bbfca..44a4518b9 100644 !ovnsb_idl_txn); stopwatch_stop(IF_STATUS_MGR_UPDATE_STOPWATCH_NAME, time_msec()); -@@ -5254,11 +5268,12 @@ main(int argc, char *argv[]) +@@ -5254,11 +5396,12 @@ main(int argc, char *argv[]) stopwatch_start(IF_STATUS_MGR_RUN_STOPWATCH_NAME, time_msec()); if_status_mgr_run(if_mgr, binding_data, chassis, @@ -1228,7 +1836,7 @@ index 2d18bbfca..44a4518b9 100644 } if (!engine_has_run()) { -@@ -5449,6 +5464,7 @@ loop_done: +@@ -5449,6 +5592,7 @@ loop_done: binding_destroy(); patch_destroy(); mirror_destroy(); @@ -1236,10 +1844,651 @@ index 2d18bbfca..44a4518b9 100644 if_status_mgr_destroy(if_mgr); shash_destroy(&vif_plug_deleted_iface_ids); shash_destroy(&vif_plug_changed_iface_ids); +@@ -5466,6 +5610,7 @@ loop_done: + free(cli_system_id); + } + service_stop(); ++ ovsrcu_exit(); + + exit(retval); + } +diff --git a/controller/ovsport.c b/controller/ovsport.c +index ec38c3fca..ebcb9cb6d 100644 +--- a/controller/ovsport.c ++++ b/controller/ovsport.c +@@ -264,3 +264,12 @@ maintain_interface_smap_column( + } + } + } ++ ++uint16_t ++get_iface_mtu(const struct ovsrec_interface *iface) ++{ ++ if (!iface || !iface->n_mtu || iface->mtu[0] <= 0) { ++ return 0; ++ } ++ return (uint16_t) iface->mtu[0]; ++} +diff --git a/controller/ovsport.h b/controller/ovsport.h +index e355ff7ff..c40c1855a 100644 +--- a/controller/ovsport.h ++++ b/controller/ovsport.h +@@ -57,4 +57,6 @@ const struct ovsrec_port * ovsport_lookup_by_interfaces( + const struct ovsrec_port * ovsport_lookup_by_interface( + struct ovsdb_idl_index *, struct ovsrec_interface *); + ++uint16_t get_iface_mtu(const struct ovsrec_interface *); ++ + #endif /* lib/ovsport.h */ +diff --git a/controller/physical.c b/controller/physical.c +index ec861f49c..d19eb9200 100644 +--- a/controller/physical.c ++++ b/controller/physical.c +@@ -41,6 +41,7 @@ + #include "lib/ovn-sb-idl.h" + #include "lib/ovn-util.h" + #include "ovn/actions.h" ++#include "if-status.h" + #include "physical.h" + #include "pinctrl.h" + #include "openvswitch/shash.h" +@@ -91,6 +92,7 @@ physical_register_ovs_idl(struct ovsdb_idl *ovs_idl) + + ovsdb_idl_add_table(ovs_idl, &ovsrec_table_interface); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_name); ++ ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_mtu); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_ofport); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_external_ids); + } +@@ -876,12 +878,12 @@ put_local_common_flows(uint32_t dp_key, + + uint32_t port_key = pb->tunnel_key; + +- /* Table 38, priority 100. ++ /* Table 40, priority 100. + * ======================= + * + * Implements output to local hypervisor. Each flow matches a + * logical output port on the local hypervisor, and resubmits to +- * table 39. ++ * table 41. + */ + + ofpbuf_clear(ofpacts_p); +@@ -891,13 +893,13 @@ put_local_common_flows(uint32_t dp_key, + + put_zones_ofpacts(zone_ids, ofpacts_p); + +- /* Resubmit to table 39. */ ++ /* Resubmit to table 41. */ + put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p); + ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, + pb->header_.uuid.parts[0], &match, ofpacts_p, + &pb->header_.uuid); + +- /* Table 39, Priority 100. ++ /* Table 41, Priority 100. + * ======================= + * + * Drop packets whose logical inport and outport are the same +@@ -1104,6 +1106,240 @@ setup_activation_strategy(const struct sbrec_port_binding *binding, + } + } + ++/* ++ * Insert a flow to determine if an IP packet is too big for the corresponding ++ * egress interface. ++ */ ++static void ++determine_if_pkt_too_big(struct ovn_desired_flow_table *flow_table, ++ const struct sbrec_port_binding *binding, ++ const struct sbrec_port_binding *mcp, ++ uint16_t mtu, bool is_ipv6, int direction) ++{ ++ struct ofpbuf ofpacts; ++ ofpbuf_init(&ofpacts, 0); ++ ++ /* Store packet too large flag in reg9[1]. */ ++ struct match match; ++ match_init_catchall(&match); ++ match_set_dl_type(&match, htons(is_ipv6 ? ETH_TYPE_IPV6 : ETH_TYPE_IP)); ++ match_set_metadata(&match, htonll(binding->datapath->tunnel_key)); ++ match_set_reg(&match, direction - MFF_REG0, mcp->tunnel_key); ++ ++ /* reg9[1] is REGBIT_PKT_LARGER as defined by northd */ ++ struct ofpact_check_pkt_larger *pkt_larger = ++ ofpact_put_CHECK_PKT_LARGER(&ofpacts); ++ pkt_larger->pkt_len = mtu; ++ pkt_larger->dst.field = mf_from_id(MFF_REG9); ++ pkt_larger->dst.ofs = 1; ++ ++ put_resubmit(OFTABLE_OUTPUT_LARGE_PKT_PROCESS, &ofpacts); ++ ofctrl_add_flow(flow_table, OFTABLE_OUTPUT_LARGE_PKT_DETECT, 100, ++ binding->header_.uuid.parts[0], &match, &ofpacts, ++ &binding->header_.uuid); ++ ofpbuf_uninit(&ofpacts); ++} ++ ++/* ++ * Insert a flow to reply with ICMP error for IP packets that are too big for ++ * the corresponding egress interface. ++ */ ++/* ++ * NOTE(ihrachys) This reimplements icmp_error as found in ++ * build_icmperr_pkt_big_flows. We may look into reusing the existing OVN ++ * action for this flow in the future. ++ */ ++static void ++reply_imcp_error_if_pkt_too_big(struct ovn_desired_flow_table *flow_table, ++ const struct sbrec_port_binding *binding, ++ const struct sbrec_port_binding *mcp, ++ uint16_t mtu, bool is_ipv6, int direction) ++{ ++ struct match match; ++ match_init_catchall(&match); ++ match_set_dl_type(&match, htons(is_ipv6 ? ETH_TYPE_IPV6 : ETH_TYPE_IP)); ++ match_set_metadata(&match, htonll(binding->datapath->tunnel_key)); ++ match_set_reg(&match, direction - MFF_REG0, mcp->tunnel_key); ++ match_set_reg_masked(&match, MFF_REG9 - MFF_REG0, 1 << 1, 1 << 1); ++ ++ /* Return ICMP error with a part of the original IP packet included. */ ++ struct ofpbuf ofpacts; ++ ofpbuf_init(&ofpacts, 0); ++ size_t oc_offset = encode_start_controller_op( ++ ACTION_OPCODE_ICMP, true, NX_CTLR_NO_METER, &ofpacts); ++ ++ struct ofpbuf inner_ofpacts; ++ ofpbuf_init(&inner_ofpacts, 0); ++ ++ /* The error packet is no longer too large, set REGBIT_PKT_LARGER = 0 */ ++ /* reg9[1] is REGBIT_PKT_LARGER as defined by northd */ ++ ovs_be32 value = htonl(0); ++ ovs_be32 mask = htonl(1 << 1); ++ ofpact_put_set_field( ++ &inner_ofpacts, mf_from_id(MFF_REG9), &value, &mask); ++ ++ /* The new error packet is delivered locally */ ++ /* REGBIT_EGRESS_LOOPBACK = 1 */ ++ value = htonl(1 << MLF_ALLOW_LOOPBACK_BIT); ++ mask = htonl(1 << MLF_ALLOW_LOOPBACK_BIT); ++ ofpact_put_set_field( ++ &inner_ofpacts, mf_from_id(MFF_LOG_FLAGS), &value, &mask); ++ ++ /* eth.src <-> eth.dst */ ++ put_stack(MFF_ETH_DST, ofpact_put_STACK_PUSH(&inner_ofpacts)); ++ put_stack(MFF_ETH_SRC, ofpact_put_STACK_PUSH(&inner_ofpacts)); ++ put_stack(MFF_ETH_DST, ofpact_put_STACK_POP(&inner_ofpacts)); ++ put_stack(MFF_ETH_SRC, ofpact_put_STACK_POP(&inner_ofpacts)); ++ ++ /* ip.src <-> ip.dst */ ++ put_stack(is_ipv6 ? MFF_IPV6_DST : MFF_IPV4_DST, ++ ofpact_put_STACK_PUSH(&inner_ofpacts)); ++ put_stack(is_ipv6 ? MFF_IPV6_SRC : MFF_IPV4_SRC, ++ ofpact_put_STACK_PUSH(&inner_ofpacts)); ++ put_stack(is_ipv6 ? MFF_IPV6_DST : MFF_IPV4_DST, ++ ofpact_put_STACK_POP(&inner_ofpacts)); ++ put_stack(is_ipv6 ? MFF_IPV6_SRC : MFF_IPV4_SRC, ++ ofpact_put_STACK_POP(&inner_ofpacts)); ++ ++ /* ip.ttl = 255 */ ++ struct ofpact_ip_ttl *ip_ttl = ofpact_put_SET_IP_TTL(&inner_ofpacts); ++ ip_ttl->ttl = 255; ++ ++ uint16_t frag_mtu = mtu - ETHERNET_OVERHEAD; ++ size_t frag_mtu_oc_offset; ++ if (is_ipv6) { ++ /* icmp6.type = 2 (Packet Too Big) */ ++ /* icmp6.code = 0 */ ++ uint8_t icmp_type = 2; ++ uint8_t icmp_code = 0; ++ ofpact_put_set_field( ++ &inner_ofpacts, mf_from_id(MFF_ICMPV6_TYPE), &icmp_type, NULL); ++ ofpact_put_set_field( ++ &inner_ofpacts, mf_from_id(MFF_ICMPV6_CODE), &icmp_code, NULL); ++ ++ /* icmp6.frag_mtu */ ++ frag_mtu_oc_offset = encode_start_controller_op( ++ ACTION_OPCODE_PUT_ICMP6_FRAG_MTU, true, NX_CTLR_NO_METER, ++ &inner_ofpacts); ++ ovs_be32 frag_mtu_ovs = htonl(frag_mtu); ++ ofpbuf_put(&inner_ofpacts, &frag_mtu_ovs, sizeof(frag_mtu_ovs)); ++ } else { ++ /* icmp4.type = 3 (Destination Unreachable) */ ++ /* icmp4.code = 4 (Fragmentation Needed) */ ++ uint8_t icmp_type = 3; ++ uint8_t icmp_code = 4; ++ ofpact_put_set_field( ++ &inner_ofpacts, mf_from_id(MFF_ICMPV4_TYPE), &icmp_type, NULL); ++ ofpact_put_set_field( ++ &inner_ofpacts, mf_from_id(MFF_ICMPV4_CODE), &icmp_code, NULL); ++ ++ /* icmp4.frag_mtu = */ ++ frag_mtu_oc_offset = encode_start_controller_op( ++ ACTION_OPCODE_PUT_ICMP4_FRAG_MTU, true, NX_CTLR_NO_METER, ++ &inner_ofpacts); ++ ovs_be16 frag_mtu_ovs = htons(frag_mtu); ++ ofpbuf_put(&inner_ofpacts, &frag_mtu_ovs, sizeof(frag_mtu_ovs)); ++ } ++ encode_finish_controller_op(frag_mtu_oc_offset, &inner_ofpacts); ++ ++ /* Finally, submit the ICMP error back to the ingress pipeline */ ++ put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, &inner_ofpacts); ++ ++ /* Attach nested actions to ICMP error controller handler */ ++ ofpacts_put_openflow_actions(inner_ofpacts.data, inner_ofpacts.size, ++ &ofpacts, OFP15_VERSION); ++ ++ /* Finalize the ICMP error controller handler */ ++ encode_finish_controller_op(oc_offset, &ofpacts); ++ ++ ofctrl_add_flow(flow_table, OFTABLE_OUTPUT_LARGE_PKT_PROCESS, 100, ++ binding->header_.uuid.parts[0], &match, &ofpacts, ++ &binding->header_.uuid); ++ ++ ofpbuf_uninit(&inner_ofpacts); ++ ofpbuf_uninit(&ofpacts); ++} ++ ++static uint16_t ++get_tunnel_overhead(struct chassis_tunnel const *tun) ++{ ++ uint16_t overhead = 0; ++ enum chassis_tunnel_type type = tun->type; ++ if (type == GENEVE) { ++ overhead += GENEVE_TUNNEL_OVERHEAD; ++ } else if (type == STT) { ++ overhead += STT_TUNNEL_OVERHEAD; ++ } else if (type == VXLAN) { ++ overhead += VXLAN_TUNNEL_OVERHEAD; ++ } else { ++ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); ++ VLOG_WARN_RL(&rl, "Unknown tunnel type %d, can't determine overhead " ++ "size for Path MTU Discovery", type); ++ return 0; ++ } ++ overhead += tun->is_ipv6? IPV6_HEADER_LEN : IP_HEADER_LEN; ++ return overhead; ++} ++ ++static uint16_t ++get_effective_mtu(const struct sbrec_port_binding *mcp, ++ struct ovs_list *remote_tunnels, ++ const struct if_status_mgr *if_mgr) ++{ ++ /* Use interface MTU as a base for calculation */ ++ uint16_t iface_mtu = if_status_mgr_iface_get_mtu(if_mgr, ++ mcp->logical_port); ++ if (!iface_mtu) { ++ return 0; ++ } ++ ++ /* Iterate over all peer tunnels and find the biggest tunnel overhead */ ++ uint16_t overhead = 0; ++ struct tunnel *tun; ++ LIST_FOR_EACH (tun, list_node, remote_tunnels) { ++ overhead = MAX(overhead, get_tunnel_overhead(tun->tun)); ++ } ++ if (!overhead) { ++ return 0; ++ } ++ ++ return iface_mtu - overhead; ++} ++ ++static void ++handle_pkt_too_big_for_ip_version(struct ovn_desired_flow_table *flow_table, ++ const struct sbrec_port_binding *binding, ++ const struct sbrec_port_binding *mcp, ++ uint16_t mtu, bool is_ipv6) ++{ ++ /* ingress */ ++ determine_if_pkt_too_big(flow_table, binding, mcp, mtu, is_ipv6, ++ MFF_LOG_INPORT); ++ reply_imcp_error_if_pkt_too_big(flow_table, binding, mcp, mtu, is_ipv6, ++ MFF_LOG_INPORT); ++ ++ /* egress */ ++ determine_if_pkt_too_big(flow_table, binding, mcp, mtu, is_ipv6, ++ MFF_LOG_OUTPORT); ++ reply_imcp_error_if_pkt_too_big(flow_table, binding, mcp, mtu, is_ipv6, ++ MFF_LOG_OUTPORT); ++} ++ ++static void ++handle_pkt_too_big(struct ovn_desired_flow_table *flow_table, ++ struct ovs_list *remote_tunnels, ++ const struct sbrec_port_binding *binding, ++ const struct sbrec_port_binding *mcp, ++ const struct if_status_mgr *if_mgr) ++{ ++ uint16_t mtu = get_effective_mtu(mcp, remote_tunnels, if_mgr); ++ if (!mtu) { ++ return; ++ } ++ handle_pkt_too_big_for_ip_version(flow_table, binding, mcp, mtu, false); ++ handle_pkt_too_big_for_ip_version(flow_table, binding, mcp, mtu, true); ++} ++ + static void + enforce_tunneling_for_multichassis_ports( + struct local_datapath *ld, +@@ -1111,7 +1347,8 @@ enforce_tunneling_for_multichassis_ports( + const struct sbrec_chassis *chassis, + const struct hmap *chassis_tunnels, + enum mf_field_id mff_ovn_geneve, +- struct ovn_desired_flow_table *flow_table) ++ struct ovn_desired_flow_table *flow_table, ++ const struct if_status_mgr *if_mgr) + { + if (shash_is_empty(&ld->multichassis_ports)) { + return; +@@ -1156,6 +1393,8 @@ enforce_tunneling_for_multichassis_ports( + binding->header_.uuid.parts[0], &match, &ofpacts, + &binding->header_.uuid); + ofpbuf_uninit(&ofpacts); ++ ++ handle_pkt_too_big(flow_table, tuns, binding, mcp, if_mgr); + } + + struct tunnel *tun_elem; +@@ -1177,6 +1416,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, + const struct sbrec_port_binding *binding, + const struct sbrec_chassis *chassis, + const struct physical_debug *debug, ++ const struct if_status_mgr *if_mgr, + struct ovn_desired_flow_table *flow_table, + struct ofpbuf *ofpacts_p) + { +@@ -1233,12 +1473,12 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, + || ha_chassis_group_is_active(binding->ha_chassis_group, + active_tunnels, chassis))) { + +- /* Table 38, priority 100. ++ /* Table 40, priority 100. + * ======================= + * + * Implements output to local hypervisor. Each flow matches a + * logical output port on the local hypervisor, and resubmits to +- * table 39. For ports of type "chassisredirect", the logical ++ * table 41. For ports of type "chassisredirect", the logical + * output port is changed from the "chassisredirect" port to the + * underlying distributed port. */ + +@@ -1275,7 +1515,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, + ct_zones); + put_zones_ofpacts(&zone_ids, ofpacts_p); + +- /* Resubmit to table 39. */ ++ /* Resubmit to table 41. */ + put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p); + } + +@@ -1491,7 +1731,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, + ofport, flow_table); + } + +- /* Table 39, priority 160. ++ /* Table 41, priority 160. + * ======================= + * + * Do not forward local traffic from a localport to a localnet port. +@@ -1561,13 +1801,13 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, + } + } + +- /* Table 37, priority 150. ++ /* Table 39, priority 150. + * ======================= + * + * Handles packets received from ports of type "localport". These + * ports are present on every hypervisor. Traffic that originates at + * one should never go over a tunnel to a remote hypervisor, +- * so resubmit them to table 38 for local delivery. */ ++ * so resubmit them to table 40 for local delivery. */ + if (!strcmp(binding->type, "localport")) { + ofpbuf_clear(ofpacts_p); + put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts_p); +@@ -1581,7 +1821,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, + } + } else if (access_type == PORT_LOCALNET) { + /* Remote port connected by localnet port */ +- /* Table 38, priority 100. ++ /* Table 40, priority 100. + * ======================= + * + * Implements switching to localnet port. Each flow matches a +@@ -1596,14 +1836,16 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, + + put_load(localnet_port->tunnel_key, MFF_LOG_OUTPORT, 0, 32, ofpacts_p); + +- /* Resubmit to table 38. */ ++ /* Resubmit to table 40. */ + put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts_p); + ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, + binding->header_.uuid.parts[0], + &match, ofpacts_p, &binding->header_.uuid); + +- enforce_tunneling_for_multichassis_ports( +- ld, binding, chassis, chassis_tunnels, mff_ovn_geneve, flow_table); ++ enforce_tunneling_for_multichassis_ports(ld, binding, chassis, ++ chassis_tunnels, ++ mff_ovn_geneve, flow_table, ++ if_mgr); + + /* No more tunneling to set up. */ + goto out; +@@ -1613,7 +1855,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, + const char *redirect_type = smap_get(&binding->options, + "redirect-type"); + +- /* Table 38, priority 100. ++ /* Table 40, priority 100. + * ======================= + * + * Handles traffic that needs to be sent to a remote hypervisor. Each +@@ -1841,7 +2083,7 @@ consider_mc_group(struct ovsdb_idl_index *sbrec_port_binding_by_name, + } + } + +- /* Table 38, priority 100. ++ /* Table 40, priority 100. + * ======================= + * + * Handle output to the local logical ports in the multicast group, if +@@ -1857,7 +2099,7 @@ consider_mc_group(struct ovsdb_idl_index *sbrec_port_binding_by_name, + &match, &ofpacts, &mc->header_.uuid); + } + +- /* Table 37, priority 100. ++ /* Table 39, priority 100. + * ======================= + * + * Handle output to the remote chassis in the multicast group, if +@@ -1908,7 +2150,7 @@ physical_eval_port_binding(struct physical_ctx *p_ctx, + p_ctx->patch_ofports, + p_ctx->chassis_tunnels, + pb, p_ctx->chassis, &p_ctx->debug, +- flow_table, &ofpacts); ++ p_ctx->if_mgr, flow_table, &ofpacts); + ofpbuf_uninit(&ofpacts); + } + +@@ -2032,10 +2274,10 @@ physical_run(struct physical_ctx *p_ctx, + p_ctx->patch_ofports, + p_ctx->chassis_tunnels, binding, + p_ctx->chassis, &p_ctx->debug, +- flow_table, &ofpacts); ++ p_ctx->if_mgr, flow_table, &ofpacts); + } + +- /* Handle output to multicast groups, in tables 37 and 38. */ ++ /* Handle output to multicast groups, in tables 40 and 41. */ + const struct sbrec_multicast_group *mc; + SBREC_MULTICAST_GROUP_TABLE_FOR_EACH (mc, p_ctx->mc_group_table) { + consider_mc_group(p_ctx->sbrec_port_binding_by_name, +@@ -2056,7 +2298,7 @@ physical_run(struct physical_ctx *p_ctx, + * encapsulations have metadata about the ingress and egress logical ports. + * VXLAN encapsulations have metadata about the egress logical port only. + * We set MFF_LOG_DATAPATH, MFF_LOG_INPORT, and MFF_LOG_OUTPORT from the +- * tunnel key data where possible, then resubmit to table 38 to handle ++ * tunnel key data where possible, then resubmit to table 40 to handle + * packets to the local hypervisor. */ + struct chassis_tunnel *tun; + HMAP_FOR_EACH (tun, hmap_node, p_ctx->chassis_tunnels) { +@@ -2158,27 +2400,52 @@ physical_run(struct physical_ctx *p_ctx, + */ + add_default_drop_flow(p_ctx, OFTABLE_PHY_TO_LOG, flow_table); + +- /* Table 37, priority 150. ++ /* Table 37-38, priority 0. ++ * ======================== ++ * ++ * Default resubmit actions for OFTABLE_OUTPUT_LARGE_PKT_* tables. ++ */ ++ struct match match; ++ match_init_catchall(&match); ++ ofpbuf_clear(&ofpacts); ++ put_resubmit(OFTABLE_REMOTE_OUTPUT, &ofpacts); ++ ofctrl_add_flow(flow_table, OFTABLE_OUTPUT_LARGE_PKT_DETECT, 0, 0, &match, ++ &ofpacts, hc_uuid); ++ ++ match_init_catchall(&match); ++ match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0, ++ MLF_ALLOW_LOOPBACK, MLF_ALLOW_LOOPBACK); ++ ofpbuf_clear(&ofpacts); ++ put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); ++ ofctrl_add_flow(flow_table, OFTABLE_OUTPUT_LARGE_PKT_PROCESS, 10, 0, ++ &match, &ofpacts, hc_uuid); ++ ++ match_init_catchall(&match); ++ ofpbuf_clear(&ofpacts); ++ put_resubmit(OFTABLE_REMOTE_OUTPUT, &ofpacts); ++ ofctrl_add_flow(flow_table, OFTABLE_OUTPUT_LARGE_PKT_PROCESS, 0, 0, &match, ++ &ofpacts, hc_uuid); ++ ++ /* Table 39, priority 150. + * ======================= + * + * Handles packets received from a VXLAN tunnel which get resubmitted to + * OFTABLE_LOG_INGRESS_PIPELINE due to lack of needed metadata in VXLAN, +- * explicitly skip sending back out any tunnels and resubmit to table 38 ++ * explicitly skip sending back out any tunnels and resubmit to table 40 + * for local delivery, except packets which have MLF_ALLOW_LOOPBACK bit + * set. + */ +- struct match match; + match_init_catchall(&match); + match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0, MLF_RCV_FROM_RAMP, + MLF_RCV_FROM_RAMP | MLF_ALLOW_LOOPBACK); + +- /* Resubmit to table 38. */ ++ /* Resubmit to table 40. */ + ofpbuf_clear(&ofpacts); + put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); + ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 150, 0, + &match, &ofpacts, hc_uuid); + +- /* Table 37, priority 150. ++ /* Table 39, priority 150. + * ======================= + * + * Packets that should not be sent to other hypervisors. +@@ -2186,13 +2453,13 @@ physical_run(struct physical_ctx *p_ctx, + match_init_catchall(&match); + match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0, + MLF_LOCAL_ONLY, MLF_LOCAL_ONLY); +- /* Resubmit to table 38. */ ++ /* Resubmit to table 40. */ + ofpbuf_clear(&ofpacts); + put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); + ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 150, 0, + &match, &ofpacts, hc_uuid); + +- /* Table 37, Priority 0. ++ /* Table 39, Priority 0. + * ======================= + * + * Resubmit packets that are not directed at tunnels or part of a +@@ -2203,18 +2470,18 @@ physical_run(struct physical_ctx *p_ctx, + ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 0, 0, &match, + &ofpacts, hc_uuid); + +- /* Table 38, priority 0. ++ /* Table 40, priority 0. + * ====================== + * + * Drop packets that do not match previous flows. + */ + add_default_drop_flow(p_ctx, OFTABLE_LOCAL_OUTPUT, flow_table); + +- /* Table 39, Priority 0. ++ /* Table 41, Priority 0. + * ======================= + * + * Resubmit packets that don't output to the ingress port (already checked +- * in table 38) to the logical egress pipeline, clearing the logical ++ * in table 40) to the logical egress pipeline, clearing the logical + * registers (for consistent behavior with packets that get tunneled). */ + match_init_catchall(&match); + ofpbuf_clear(&ofpacts); +diff --git a/controller/physical.h b/controller/physical.h +index f450dca94..1f1ed55ef 100644 +--- a/controller/physical.h ++++ b/controller/physical.h +@@ -52,11 +52,13 @@ struct physical_ctx { + struct ovsdb_idl_index *sbrec_port_binding_by_name; + struct ovsdb_idl_index *sbrec_port_binding_by_datapath; + const struct sbrec_port_binding_table *port_binding_table; ++ const struct ovsrec_interface_table *ovs_interface_table; + const struct sbrec_multicast_group_table *mc_group_table; + const struct ovsrec_bridge *br_int; + const struct sbrec_chassis_table *chassis_table; + const struct sbrec_chassis *chassis; + const struct sset *active_tunnels; ++ const struct if_status_mgr *if_mgr; + struct hmap *local_datapaths; + struct sset *local_lports; + const struct simap *ct_zones; diff --git a/controller/pinctrl.c b/controller/pinctrl.c -index 795847729..761783562 100644 +index 795847729..cd9760f07 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c +@@ -627,7 +627,7 @@ set_actions_and_enqueue_msg(struct rconn *swconn, + } + + /* Forwards a packet to 'out_port_key' even if that's on a remote +- * hypervisor, i.e., the packet is re-injected in table OFTABLE_REMOTE_OUTPUT. ++ * hypervisor, i.e., the packet is re-injected in table OFTABLE_OUTPUT_INIT. + */ + static void + pinctrl_forward_pkt(struct rconn *swconn, int64_t dp_key, +@@ -644,7 +644,7 @@ pinctrl_forward_pkt(struct rconn *swconn, int64_t dp_key, + + struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts); + resubmit->in_port = OFPP_CONTROLLER; +- resubmit->table_id = OFTABLE_REMOTE_OUTPUT; ++ resubmit->table_id = OFTABLE_OUTPUT_INIT; + + struct ofputil_packet_out po = { + .packet = dp_packet_data(pkt), +@@ -870,7 +870,7 @@ pinctrl_parse_dhcpv6_advt(struct rconn *swconn, const struct flow *ip_flow, + 0, 32, &ofpacts); + struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts); + resubmit->in_port = OFPP_CONTROLLER; +- resubmit->table_id = OFTABLE_REMOTE_OUTPUT; ++ resubmit->table_id = OFTABLE_OUTPUT_INIT; + + struct ofputil_packet_out po = { + .packet = dp_packet_data(&packet), +@@ -1499,7 +1499,7 @@ buffered_push_packet(struct buffered_packets *bp, + + struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&bi->ofpacts); + resubmit->in_port = OFPP_CONTROLLER; +- resubmit->table_id = OFTABLE_REMOTE_OUTPUT; ++ resubmit->table_id = OFTABLE_OUTPUT_INIT; + + bi->p = packet; + @@ -2444,19 +2444,19 @@ compose_out_dhcpv6_opts(struct ofpbuf *userdata, struct ofpbuf *out_dhcpv6_opts, ovs_be32 iaid) { @@ -1263,7 +2512,21 @@ index 795847729..761783562 100644 case DHCPV6_OPT_SERVER_ID_CODE: { /* The Server Identifier option carries a DUID -@@ -7190,7 +7190,9 @@ bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time) +@@ -2988,6 +2988,13 @@ pinctrl_handle_dns_lookup( + goto exit; + } + ++ /* Check if there is an additional record present, which is unsupported */ ++ if (in_dns_header->arcount) { ++ VLOG_DBG_RL(&rl, "Received DNS query with additional records, which" ++ " is unsupported"); ++ goto exit; ++ } ++ + struct udp_header *in_udp = dp_packet_l4(pkt_in); + size_t udp_len = ntohs(in_udp->udp_len); + size_t l4_len = dp_packet_l4_size(pkt_in); +@@ -7190,7 +7197,9 @@ bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time) pinctrl_send_bfd_tx_msg(swconn, entry, false); tx_timeout = MAX(entry->local_min_tx, entry->remote_min_rx); @@ -1288,10 +2551,42 @@ index 11a07dd38..02a9953ba 100644 ovn (23.03.0-1) unstable; urgency=low * New upstream version +diff --git a/include/ovn/actions.h b/include/ovn/actions.h +index 28479ede1..c973fce9c 100644 +--- a/include/ovn/actions.h ++++ b/include/ovn/actions.h +@@ -895,6 +895,9 @@ void ovnacts_free(struct ovnact[], size_t ovnacts_len); + char *ovnact_op_to_string(uint32_t); + int encode_ra_dnssl_opt(char *data, char *buf, int buf_len); + ++size_t encode_start_controller_op(enum action_opcode opcode, bool pause, ++ uint32_t meter_id, struct ofpbuf *ofpacts); ++void encode_finish_controller_op(size_t ofs, struct ofpbuf *ofpacts); + void encode_controller_op(enum action_opcode opcode, uint32_t meter_id, + struct ofpbuf *ofpacts); + diff --git a/lib/actions.c b/lib/actions.c -index 781549d75..2b566c85e 100644 +index 781549d75..ec27223f9 100644 --- a/lib/actions.c +++ b/lib/actions.c +@@ -79,7 +79,7 @@ ovnact_init(struct ovnact *ovnact, enum ovnact_type type, size_t len) + ovnact->len = len; + } + +-static size_t ++size_t + encode_start_controller_op(enum action_opcode opcode, bool pause, + uint32_t meter_id, struct ofpbuf *ofpacts) + { +@@ -100,7 +100,7 @@ encode_start_controller_op(enum action_opcode opcode, bool pause, + return ofs; + } + +-static void ++void + encode_finish_controller_op(size_t ofs, struct ofpbuf *ofpacts) + { + struct ofpact_controller *oc = ofpbuf_at_assert(ofpacts, ofs, sizeof *oc); @@ -2882,26 +2882,26 @@ static void encode_put_dhcpv6_option(const struct ovnact_gen_option *o, struct ofpbuf *ofpacts) @@ -1479,6 +2774,324 @@ index 2b20bc380..d718ed39a 100644 /* These are not defined in ovs/lib/dhcp.h, hence defining here. */ #define OVN_DHCP_MSG_DECLINE 4 #define OVN_DHCP_MSG_RELEASE 7 +diff --git a/lib/ovn-util.h b/lib/ovn-util.h +index a1a418a24..7510fda4b 100644 +--- a/lib/ovn-util.h ++++ b/lib/ovn-util.h +@@ -28,6 +28,13 @@ + #define ROUTE_ORIGIN_CONNECTED "connected" + #define ROUTE_ORIGIN_STATIC "static" + ++#define ETH_CRC_LENGTH 4 ++#define ETHERNET_OVERHEAD (ETH_HEADER_LEN + ETH_CRC_LENGTH) ++ ++#define GENEVE_TUNNEL_OVERHEAD 38 ++#define STT_TUNNEL_OVERHEAD 18 ++#define VXLAN_TUNNEL_OVERHEAD 30 ++ + struct eth_addr; + struct nbrec_logical_router_port; + struct ovsrec_flow_sample_collector_set_table; +diff --git a/northd/en-sync-sb.c b/northd/en-sync-sb.c +index 6e33901a8..20f0d8a82 100644 +--- a/northd/en-sync-sb.c ++++ b/northd/en-sync-sb.c +@@ -22,7 +22,6 @@ + #include "openvswitch/util.h" + + #include "en-sync-sb.h" +-#include "include/ovn/expr.h" + #include "lib/inc-proc-eng.h" + #include "lib/lb.h" + #include "lib/ovn-nb-idl.h" +@@ -34,8 +33,15 @@ + + VLOG_DEFINE_THIS_MODULE(en_sync_to_sb); + ++/* This is just a type wrapper to enforce that it has to be sorted. */ ++struct sorted_addresses { ++ const char **arr; ++ size_t n; ++}; ++ ++ + static void sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, +- const char **addrs, size_t n_addrs, ++ struct sorted_addresses *addresses, + struct shash *sb_address_sets); + static void sync_addr_sets(const struct nbrec_address_set_table *, + const struct nbrec_port_group_table *, +@@ -44,11 +50,17 @@ static void sync_addr_sets(const struct nbrec_address_set_table *, + struct hmap *datapaths); + static const struct sbrec_address_set *sb_address_set_lookup_by_name( + struct ovsdb_idl_index *, const char *name); +-static void update_sb_addr_set(const char **nb_addresses, size_t n_addresses, ++static void update_sb_addr_set(struct sorted_addresses *, + const struct sbrec_address_set *); + static void build_port_group_address_set(const struct nbrec_port_group *, + struct svec *ipv4_addrs, + struct svec *ipv6_addrs); ++static struct sorted_addresses ++sorted_addresses_from_nbrec(const struct nbrec_address_set *nb_as); ++static struct sorted_addresses ++sorted_addresses_from_svec(struct svec *addresses); ++static struct sorted_addresses ++sorted_addresses_from_sset(struct sset *addresses); + + void * + en_sync_to_sb_init(struct engine_node *node OVS_UNUSED, +@@ -133,8 +145,9 @@ sync_to_sb_addr_set_nb_address_set_handler(struct engine_node *node, + if (!sb_addr_set) { + return false; + } +- update_sb_addr_set((const char **) nb_addr_set->addresses, +- nb_addr_set->n_addresses, sb_addr_set); ++ struct sorted_addresses addrs = ++ sorted_addresses_from_nbrec(nb_addr_set); ++ update_sb_addr_set(&addrs, sb_addr_set); + } + + return true; +@@ -180,10 +193,14 @@ sync_to_sb_addr_set_nb_port_group_handler(struct engine_node *node, + struct svec ipv4_addrs = SVEC_EMPTY_INITIALIZER; + struct svec ipv6_addrs = SVEC_EMPTY_INITIALIZER; + build_port_group_address_set(nb_pg, &ipv4_addrs, &ipv6_addrs); +- update_sb_addr_set((const char **) ipv4_addrs.names, ipv4_addrs.n, +- sb_addr_set_v4); +- update_sb_addr_set((const char **) ipv6_addrs.names, ipv6_addrs.n, +- sb_addr_set_v6); ++ ++ struct sorted_addresses ipv4_addrs_sorted = ++ sorted_addresses_from_svec(&ipv4_addrs); ++ struct sorted_addresses ipv6_addrs_sorted = ++ sorted_addresses_from_svec(&ipv6_addrs); ++ ++ update_sb_addr_set(&ipv4_addrs_sorted, sb_addr_set_v4); ++ update_sb_addr_set(&ipv6_addrs_sorted, sb_addr_set_v6); + + free(ipv4_addrs_name); + free(ipv6_addrs_name); +@@ -197,7 +214,7 @@ sync_to_sb_addr_set_nb_port_group_handler(struct engine_node *node, + /* static functions. */ + static void + sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, +- const char **addrs, size_t n_addrs, ++ struct sorted_addresses *addresses, + struct shash *sb_address_sets) + { + const struct sbrec_address_set *sb_address_set; +@@ -206,10 +223,10 @@ sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, + if (!sb_address_set) { + sb_address_set = sbrec_address_set_insert(ovnsb_txn); + sbrec_address_set_set_name(sb_address_set, name); +- sbrec_address_set_set_addresses(sb_address_set, +- addrs, n_addrs); ++ sbrec_address_set_set_addresses(sb_address_set, addresses->arr, ++ addresses->n); + } else { +- update_sb_addr_set(addrs, n_addrs, sb_address_set); ++ update_sb_addr_set(addresses, sb_address_set); + } + } + +@@ -243,8 +260,11 @@ sync_addr_sets(const struct nbrec_address_set_table *nb_address_set_table, + + /* Service monitor MAC. */ + const char *svc_monitor_macp = northd_get_svc_monitor_mac(); +- sync_addr_set(ovnsb_txn, "svc_monitor_mac", &svc_monitor_macp, 1, +- &sb_address_sets); ++ struct sorted_addresses svc = { ++ .arr = &svc_monitor_macp, ++ .n = 1, ++ }; ++ sync_addr_set(ovnsb_txn, "svc_monitor_mac", &svc, &sb_address_sets); + + /* sync port group generated address sets first */ + const struct nbrec_port_group *nb_port_group; +@@ -255,14 +275,16 @@ sync_addr_sets(const struct nbrec_address_set_table *nb_address_set_table, + build_port_group_address_set(nb_port_group, &ipv4_addrs, &ipv6_addrs); + char *ipv4_addrs_name = xasprintf("%s_ip4", nb_port_group->name); + char *ipv6_addrs_name = xasprintf("%s_ip6", nb_port_group->name); ++ ++ struct sorted_addresses ipv4_addrs_sorted = ++ sorted_addresses_from_svec(&ipv4_addrs); ++ struct sorted_addresses ipv6_addrs_sorted = ++ sorted_addresses_from_svec(&ipv6_addrs); ++ + sync_addr_set(ovnsb_txn, ipv4_addrs_name, +- /* "char **" is not compatible with "const char **" */ +- (const char **) ipv4_addrs.names, +- ipv4_addrs.n, &sb_address_sets); ++ &ipv4_addrs_sorted, &sb_address_sets); + sync_addr_set(ovnsb_txn, ipv6_addrs_name, +- /* "char **" is not compatible with "const char **" */ +- (const char **) ipv6_addrs.names, +- ipv6_addrs.n, &sb_address_sets); ++ &ipv6_addrs_sorted, &sb_address_sets); + free(ipv4_addrs_name); + free(ipv6_addrs_name); + svec_destroy(&ipv4_addrs); +@@ -279,27 +301,26 @@ sync_addr_sets(const struct nbrec_address_set_table *nb_address_set_table, + if (sset_count(&od->lb_ips->ips_v4_reachable)) { + char *ipv4_addrs_name = lr_lb_address_set_name(od->tunnel_key, + AF_INET); +- const char **ipv4_addrs = +- sset_array(&od->lb_ips->ips_v4_reachable); + +- sync_addr_set(ovnsb_txn, ipv4_addrs_name, ipv4_addrs, +- sset_count(&od->lb_ips->ips_v4_reachable), +- &sb_address_sets); ++ struct sorted_addresses ipv4_addrs_sorted = ++ sorted_addresses_from_sset(&od->lb_ips->ips_v4_reachable); ++ ++ sync_addr_set(ovnsb_txn, ipv4_addrs_name, ++ &ipv4_addrs_sorted, &sb_address_sets); ++ free(ipv4_addrs_sorted.arr); + free(ipv4_addrs_name); +- free(ipv4_addrs); + } + + if (sset_count(&od->lb_ips->ips_v6_reachable)) { + char *ipv6_addrs_name = lr_lb_address_set_name(od->tunnel_key, + AF_INET6); +- const char **ipv6_addrs = +- sset_array(&od->lb_ips->ips_v6_reachable); ++ struct sorted_addresses ipv6_addrs_sorted = ++ sorted_addresses_from_sset(&od->lb_ips->ips_v6_reachable); + +- sync_addr_set(ovnsb_txn, ipv6_addrs_name, ipv6_addrs, +- sset_count(&od->lb_ips->ips_v6_reachable), +- &sb_address_sets); ++ sync_addr_set(ovnsb_txn, ipv6_addrs_name, ++ &ipv6_addrs_sorted, &sb_address_sets); ++ free(ipv6_addrs_sorted.arr); + free(ipv6_addrs_name); +- free(ipv6_addrs); + } + } + +@@ -308,10 +329,10 @@ sync_addr_sets(const struct nbrec_address_set_table *nb_address_set_table, + const struct nbrec_address_set *nb_address_set; + NBREC_ADDRESS_SET_TABLE_FOR_EACH (nb_address_set, + nb_address_set_table) { ++ struct sorted_addresses addrs = ++ sorted_addresses_from_nbrec(nb_address_set); + sync_addr_set(ovnsb_txn, nb_address_set->name, +- /* "char **" is not compatible with "const char **" */ +- (const char **) nb_address_set->addresses, +- nb_address_set->n_addresses, &sb_address_sets); ++ &addrs, &sb_address_sets); + } + + struct shash_node *node; +@@ -323,48 +344,39 @@ sync_addr_sets(const struct nbrec_address_set_table *nb_address_set_table, + } + + static void +-update_sb_addr_set(const char **nb_addresses, size_t n_addresses, ++update_sb_addr_set(struct sorted_addresses *nb_addresses, + const struct sbrec_address_set *sb_as) + { +- struct expr_constant_set *cs_nb_as = +- expr_constant_set_create_integers( +- (const char *const *) nb_addresses, n_addresses); +- struct expr_constant_set *cs_sb_as = +- expr_constant_set_create_integers( +- (const char *const *) sb_as->addresses, sb_as->n_addresses); +- +- struct expr_constant_set *addr_added = NULL; +- struct expr_constant_set *addr_deleted = NULL; +- expr_constant_set_integers_diff(cs_sb_as, cs_nb_as, &addr_added, +- &addr_deleted); +- +- struct ds ds = DS_EMPTY_INITIALIZER; +- if (addr_added && addr_added->n_values) { +- for (size_t i = 0; i < addr_added->n_values; i++) { +- ds_clear(&ds); +- expr_constant_format(&addr_added->values[i], EXPR_C_INTEGER, &ds); +- sbrec_address_set_update_addresses_addvalue(sb_as, ds_cstr(&ds)); ++ size_t nb_index, sb_index; ++ ++ const char **nb_arr = nb_addresses->arr; ++ char **sb_arr = sb_as->addresses; ++ size_t nb_n = nb_addresses->n; ++ size_t sb_n = sb_as->n_addresses; ++ ++ for (nb_index = sb_index = 0; nb_index < nb_n && sb_index < sb_n;) { ++ int cmp = strcmp(nb_arr[nb_index], sb_arr[sb_index]); ++ if (cmp < 0) { ++ sbrec_address_set_update_addresses_addvalue(sb_as, ++ nb_arr[nb_index]); ++ nb_index++; ++ } else if (cmp > 0) { ++ sbrec_address_set_update_addresses_delvalue(sb_as, ++ sb_arr[sb_index]); ++ sb_index++; ++ } else { ++ nb_index++; ++ sb_index++; + } + } + +- if (addr_deleted && addr_deleted->n_values) { +- for (size_t i = 0; i < addr_deleted->n_values; i++) { +- ds_clear(&ds); +- expr_constant_format(&addr_deleted->values[i], +- EXPR_C_INTEGER, &ds); +- sbrec_address_set_update_addresses_delvalue(sb_as, ds_cstr(&ds)); +- } ++ for (; nb_index < nb_n; nb_index++) { ++ sbrec_address_set_update_addresses_addvalue(sb_as, nb_arr[nb_index]); + } + +- ds_destroy(&ds); +- expr_constant_set_destroy(cs_nb_as); +- free(cs_nb_as); +- expr_constant_set_destroy(cs_sb_as); +- free(cs_sb_as); +- expr_constant_set_destroy(addr_added); +- free(addr_added); +- expr_constant_set_destroy(addr_deleted); +- free(addr_deleted); ++ for (; sb_index < sb_n; sb_index++) { ++ sbrec_address_set_update_addresses_delvalue(sb_as, sb_arr[sb_index]); ++ } + } + + static void +@@ -403,3 +415,32 @@ sb_address_set_lookup_by_name(struct ovsdb_idl_index *sbrec_addr_set_by_name, + + return retval; + } ++ ++static struct sorted_addresses ++sorted_addresses_from_nbrec(const struct nbrec_address_set *nb_as) ++{ ++ /* The DB is already sorted. */ ++ return (struct sorted_addresses) { ++ .arr = (const char **) nb_as->addresses, ++ .n = nb_as->n_addresses, ++ }; ++} ++ ++static struct sorted_addresses ++sorted_addresses_from_svec(struct svec *addresses) ++{ ++ svec_sort(addresses); ++ return (struct sorted_addresses) { ++ .arr = (const char **) addresses->names, ++ .n = addresses->n, ++ }; ++} ++ ++static struct sorted_addresses ++sorted_addresses_from_sset(struct sset *addresses) ++{ ++ return (struct sorted_addresses) { ++ .arr = sset_sort(addresses), ++ .n = sset_count(addresses), ++ }; ++} diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c index d23993a55..fd025c92b 100644 --- a/northd/inc-proc-northd.c @@ -1532,10 +3145,19 @@ index d23993a55..fd025c92b 100644 + ds_destroy(&ds); +} diff --git a/northd/northd.c b/northd/northd.c -index 7ad4cdfad..045282fac 100644 +index 7ad4cdfad..66f14e9dd 100644 --- a/northd/northd.c +++ b/northd/northd.c -@@ -432,6 +432,13 @@ build_chassis_features(const struct northd_input *input_data, +@@ -239,6 +239,8 @@ enum ovn_stage { + * one of the logical router's own IP addresses. */ + #define REGBIT_EGRESS_LOOPBACK "reg9[0]" + /* Register to store the result of check_pkt_larger action. */ ++/* This register is also used by ovn-controller in ++ * OFTABLE_OUTPUT_LARGE_PKT_DETECT table, for a similar goal. */ + #define REGBIT_PKT_LARGER "reg9[1]" + #define REGBIT_LOOKUP_NEIGHBOR_RESULT "reg9[2]" + #define REGBIT_LOOKUP_NEIGHBOR_IP_RESULT "reg9[3]" +@@ -432,6 +434,13 @@ build_chassis_features(const struct northd_input *input_data, const struct sbrec_chassis *chassis; SBREC_CHASSIS_TABLE_FOR_EACH (chassis, input_data->sbrec_chassis) { @@ -1549,7 +3171,7 @@ index 7ad4cdfad..045282fac 100644 bool ct_no_masked_label = smap_get_bool(&chassis->other_config, OVN_FEATURE_CT_NO_MASKED_LABEL, -@@ -552,7 +559,7 @@ free_chassis_queueid(struct hmap *set, const struct uuid *uuid, +@@ -552,7 +561,7 @@ free_chassis_queueid(struct hmap *set, const struct uuid *uuid, static inline bool port_has_qos_params(const struct smap *opts) { @@ -1558,7 +3180,7 @@ index 7ad4cdfad..045282fac 100644 smap_get(opts, "qos_burst")); } -@@ -1641,6 +1648,10 @@ ovn_port_destroy(struct hmap *ports, struct ovn_port *port) +@@ -1641,6 +1650,10 @@ ovn_port_destroy(struct hmap *ports, struct ovn_port *port) * use it. */ hmap_remove(ports, &port->key_node); @@ -1569,7 +3191,7 @@ index 7ad4cdfad..045282fac 100644 for (int i = 0; i < port->n_lsp_addrs; i++) { destroy_lport_addresses(&port->lsp_addrs[i]); } -@@ -3881,7 +3892,7 @@ build_lb_vip_actions(struct ovn_lb_vip *lb_vip, +@@ -3881,7 +3894,7 @@ build_lb_vip_actions(struct ovn_lb_vip *lb_vip, const char *ct_lb_action = features->ct_no_masked_label ? "ct_lb_mark" : "ct_lb"; bool reject = !lb_vip->n_backends && lb_vip->empty_backend_rej; @@ -1578,7 +3200,7 @@ index 7ad4cdfad..045282fac 100644 if (lb_vip_nb->lb_health_check) { ds_put_format(action, "%s(backends=", ct_lb_action); -@@ -5779,20 +5790,24 @@ skip_port_from_conntrack(struct ovn_datapath *od, struct ovn_port *op, +@@ -5779,20 +5792,24 @@ skip_port_from_conntrack(struct ovn_datapath *od, struct ovn_port *op, * know about the connection, as the icmp request went through the logical * router on hostA, not hostB. This would only work with distributed * conntrack state across all chassis. */ @@ -1613,7 +3235,7 @@ index 7ad4cdfad..045282fac 100644 } static void -@@ -5867,7 +5882,8 @@ build_pre_acls(struct ovn_datapath *od, const struct hmap *port_groups, +@@ -5867,7 +5884,8 @@ build_pre_acls(struct ovn_datapath *od, const struct hmap *port_groups, } for (size_t i = 0; i < od->n_localnet_ports; i++) { skip_port_from_conntrack(od, od->localnet_ports[i], @@ -1623,7 +3245,7 @@ index 7ad4cdfad..045282fac 100644 110, lflows); } -@@ -6036,10 +6052,17 @@ build_pre_lb(struct ovn_datapath *od, const struct shash *meter_groups, +@@ -6036,10 +6054,17 @@ build_pre_lb(struct ovn_datapath *od, const struct shash *meter_groups, S_SWITCH_IN_PRE_LB, S_SWITCH_OUT_PRE_LB, 110, lflows); } @@ -1645,7 +3267,7 @@ index 7ad4cdfad..045282fac 100644 } /* Do not sent statless flows via conntrack */ -@@ -6700,6 +6723,8 @@ build_port_group_lswitches(struct northd_input *input_data, +@@ -6700,6 +6725,8 @@ build_port_group_lswitches(struct northd_input *input_data, } } @@ -1654,7 +3276,7 @@ index 7ad4cdfad..045282fac 100644 static void build_acls(struct ovn_datapath *od, const struct chassis_features *features, struct hmap *lflows, const struct hmap *port_groups, -@@ -6847,20 +6872,26 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features, +@@ -6847,20 +6874,26 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features, ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX - 3, ds_cstr(&match), ct_out_acl_action); @@ -1689,7 +3311,7 @@ index 7ad4cdfad..045282fac 100644 /* Ingress or Egress ACL Table (Various priorities). */ for (size_t i = 0; i < od->nbs->n_acls; i++) { struct nbrec_acl *acl = od->nbs->acls[i]; -@@ -7089,7 +7120,9 @@ build_lb_rules_pre_stateful(struct hmap *lflows, struct ovn_northd_lb *lb, +@@ -7089,7 +7122,9 @@ build_lb_rules_pre_stateful(struct hmap *lflows, struct ovn_northd_lb *lb, * - load balancing affinity check: * table=lr_in_lb_aff_check, priority=100 * match=(new_lb_match) @@ -1700,7 +3322,7 @@ index 7ad4cdfad..045282fac 100644 * * - load balancing: * table=lr_in_dnat, priority=150 -@@ -7130,16 +7163,11 @@ build_lb_affinity_lr_flows(struct hmap *lflows, struct ovn_northd_lb *lb, +@@ -7130,16 +7165,11 @@ build_lb_affinity_lr_flows(struct hmap *lflows, struct ovn_northd_lb *lb, return; } @@ -1718,7 +3340,7 @@ index 7ad4cdfad..045282fac 100644 bool ipv6 = !IN6_IS_ADDR_V4MAPPED(&lb_vip->vip); const char *ip_match = ipv6 ? "ip6" : "ip4"; -@@ -7155,6 +7183,20 @@ build_lb_affinity_lr_flows(struct hmap *lflows, struct ovn_northd_lb *lb, +@@ -7155,6 +7185,20 @@ build_lb_affinity_lr_flows(struct hmap *lflows, struct ovn_northd_lb *lb, ct_flag = "; force_snat"; } @@ -1739,7 +3361,7 @@ index 7ad4cdfad..045282fac 100644 /* Prepare common part of affinity LB and affinity learn action. */ ds_put_format(&aff_action, "%s = %s; ", reg_vip, lb_vip->vip_str); ds_put_cstr(&aff_action_learn, "commit_lb_aff(vip = \""); -@@ -7252,6 +7294,7 @@ build_lb_affinity_lr_flows(struct hmap *lflows, struct ovn_northd_lb *lb, +@@ -7252,6 +7296,7 @@ build_lb_affinity_lr_flows(struct hmap *lflows, struct ovn_northd_lb *lb, ds_destroy(&aff_action_learn); ds_destroy(&aff_match); ds_destroy(&aff_match_learn); @@ -1747,6 +3369,73 @@ index 7ad4cdfad..045282fac 100644 } /* Builds the logical switch flows related to load balancer affinity. +@@ -7628,38 +7673,36 @@ build_lb_hairpin(struct ovn_datapath *od, struct hmap *lflows) + static void + build_vtep_hairpin(struct ovn_datapath *od, struct hmap *lflows) + { +- /* Ingress Pre-ARP flows for VTEP hairpining traffic. Priority 1000: +- * Packets that received from non-VTEP ports should continue processing. */ ++ if (!od->has_vtep_lports) { ++ /* There is no need in these flows if datapath has no vtep lports. */ ++ return; ++ } + ++ /* Ingress Pre-ARP flows for VTEP hairpining traffic. Priority 1000: ++ * Packets received from VTEP ports must go directly to L2LKP table. ++ */ + char *action = xasprintf("next(pipeline=ingress, table=%d);", + ovn_stage_get_table(S_SWITCH_IN_L2_LKUP)); +- /* send all traffic from VTEP directly to L2LKP table. */ + ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 1000, + REGBIT_FROM_RAMP" == 1", action); + free(action); + +- struct ds match = DS_EMPTY_INITIALIZER; +- size_t n_ports = od->n_router_ports; +- bool dp_has_l3dgw_ports = false; +- for (int i = 0; i < n_ports; i++) { +- if (is_l3dgw_port(od->router_ports[i]->peer)) { +- ds_put_format(&match, "%sis_chassis_resident(%s)%s", +- i == 0 ? REGBIT_FROM_RAMP" == 1 && (" : "", +- od->router_ports[i]->peer->cr_port->json_key, +- i < n_ports - 1 ? " || " : ")"); +- dp_has_l3dgw_ports = true; +- } +- } +- + /* Ingress pre-arp flow for traffic from VTEP (ramp) switch. + * Priority 2000: Packets, that were received from VTEP (ramp) switch and + * router ports of current datapath are l3dgw ports and they reside on + * current chassis, should be passed to next table for ARP/ND hairpin +- * processing. +- */ +- if (dp_has_l3dgw_ports) { +- ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 2000, ds_cstr(&match), +- "next;"); ++ * processing. */ ++ struct ds match = DS_EMPTY_INITIALIZER; ++ for (int i = 0; i < od->n_router_ports; i++) { ++ struct ovn_port *op = od->router_ports[i]->peer; ++ if (is_l3dgw_port(op)) { ++ ds_clear(&match); ++ ds_put_format(&match, ++ REGBIT_FROM_RAMP" == 1 && is_chassis_resident(%s)", ++ op->cr_port->json_key); ++ ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 2000, ++ ds_cstr(&match), "next;"); ++ } + } + ds_destroy(&match); + } +@@ -8877,7 +8920,7 @@ build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od, + if (od->nbs) { + + ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 110, +- "eth.dst == $svc_monitor_mac", ++ "eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)", + "handle_svc_check(inport);"); + + struct mcast_switch_info *mcast_sw_info = &od->mcast_info.sw; @@ -10450,10 +10493,8 @@ enum lrouter_nat_lb_flow_type { struct lrouter_nat_lb_flows_ctx { @@ -1966,7 +3655,33 @@ index 7ad4cdfad..045282fac 100644 } /* Handles the match criteria and actions in logical flow -@@ -12814,8 +12808,7 @@ build_gateway_redirect_flows_for_lrouter( +@@ -11698,6 +11692,25 @@ build_neigh_learning_flows_for_lrouter( + ovn_lflow_add(lflows, od, S_ROUTER_IN_LOOKUP_NEIGHBOR, 100, "nd_na", + ds_cstr(actions)); + ++ if (!learn_from_arp_request) { ++ /* Add flow to skip GARP LLA if we don't know it already. ++ * From RFC 2461, section 4.4, Neighbor Advertisement Message ++ * Format, the Destination Address should be: ++ * For solicited advertisements, the Source Address of ++ * an invoking Neighbor Solicitation or, if the ++ * solicitation's Source Address is the unspecified ++ * address, the all-nodes multicast address. */ ++ ds_clear(actions); ++ ds_put_format(actions, REGBIT_LOOKUP_NEIGHBOR_RESULT ++ " = lookup_nd(inport, ip6.src, nd.tll); " ++ REGBIT_LOOKUP_NEIGHBOR_IP_RESULT ++ " = lookup_nd_ip(inport, ip6.src); next;"); ++ ovn_lflow_add(lflows, od, S_ROUTER_IN_LOOKUP_NEIGHBOR, 110, ++ "nd_na && ip6.src == fe80::/10 " ++ "&& ip6.dst == ff00::/8", ++ ds_cstr(actions)); ++ } ++ + ds_clear(actions); + ds_put_format(actions, REGBIT_LOOKUP_NEIGHBOR_RESULT + " = lookup_nd(inport, ip6.src, nd.sll); %snext;", +@@ -12814,8 +12827,7 @@ build_gateway_redirect_flows_for_lrouter( for (int j = 0; j < od->n_nat_entries; j++) { const struct ovn_nat *nat = &od->nat_entries[j]; @@ -1976,7 +3691,7 @@ index 7ad4cdfad..045282fac 100644 (!nat->nb->allowed_ext_ips && !nat->nb->exempted_ext_ips)) { continue; } -@@ -13038,9 +13031,27 @@ build_misc_local_traffic_drop_flows_for_lrouter( +@@ -13038,9 +13050,27 @@ build_misc_local_traffic_drop_flows_for_lrouter( ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 50, "eth.bcast", debug_drop_action()); @@ -2005,7 +3720,7 @@ index 7ad4cdfad..045282fac 100644 /* Pass other traffic not already handled to the next table for * routing. */ -@@ -13224,7 +13235,7 @@ build_ipv6_input_flows_for_lrouter_port( +@@ -13224,7 +13254,7 @@ build_ipv6_input_flows_for_lrouter_port( "outport = %s; flags.loopback = 1; output; };", ds_cstr(&ip_ds), op->json_key); ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT, @@ -2014,7 +3729,7 @@ index 7ad4cdfad..045282fac 100644 copp_meter_get(COPP_ICMP6_ERR, op->od->nbr->copp, meter_groups), &op->nbrp->header_); -@@ -13352,7 +13363,7 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op, +@@ -13352,7 +13382,7 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op, "outport = %s; flags.loopback = 1; output; };", ds_cstr(&ip_ds), op->json_key); ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT, @@ -2023,7 +3738,7 @@ index 7ad4cdfad..045282fac 100644 copp_meter_get(COPP_ICMP4_ERR, op->od->nbr->copp, meter_groups), &op->nbrp->header_); -@@ -13597,13 +13608,13 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, +@@ -13597,13 +13627,13 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, return; } @@ -2039,7 +3754,7 @@ index 7ad4cdfad..045282fac 100644 ds_put_format(actions, "next;"); } else { ds_put_cstr(actions, "ct_snat;"); -@@ -13628,7 +13639,7 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, +@@ -13628,7 +13658,7 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, l3dgw_port->cr_port->json_key); } @@ -2048,7 +3763,7 @@ index 7ad4cdfad..045282fac 100644 ds_put_format(actions, "next;"); } else { ds_put_cstr(actions, "ct_snat_in_czone;"); -@@ -13670,7 +13681,7 @@ build_lrouter_in_dnat_flow(struct hmap *lflows, struct ovn_datapath *od, +@@ -13670,7 +13700,7 @@ build_lrouter_in_dnat_flow(struct hmap *lflows, struct ovn_datapath *od, * IP address that needs to be DNATted from a external IP address * to a logical IP address. */ if (!strcmp(nat->type, "dnat") || !strcmp(nat->type, "dnat_and_snat")) { @@ -2057,7 +3772,7 @@ index 7ad4cdfad..045282fac 100644 if (od->is_gw_router) { /* Packet when it goes from the initiator to destination. -@@ -13692,7 +13703,7 @@ build_lrouter_in_dnat_flow(struct hmap *lflows, struct ovn_datapath *od, +@@ -13692,7 +13722,7 @@ build_lrouter_in_dnat_flow(struct hmap *lflows, struct ovn_datapath *od, ds_put_format(actions, "flags.force_snat_for_dnat = 1; "); } @@ -2066,7 +3781,7 @@ index 7ad4cdfad..045282fac 100644 ds_put_format(actions, "flags.loopback = 1; " "ip%s.dst=%s; next;", is_v6 ? "6" : "4", nat->logical_ip); -@@ -13782,8 +13793,7 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od, +@@ -13782,8 +13812,7 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od, ETH_ADDR_ARGS(mac)); } @@ -2076,7 +3791,7 @@ index 7ad4cdfad..045282fac 100644 ds_put_format(actions, "next;"); } else { ds_put_format(actions, -@@ -13839,7 +13849,7 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, +@@ -13839,7 +13868,7 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, return; } @@ -2085,7 +3800,7 @@ index 7ad4cdfad..045282fac 100644 if (od->is_gw_router) { ds_clear(match); ds_put_format(match, "ip && ip%s.src == %s", -@@ -13905,7 +13915,7 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, +@@ -13905,7 +13934,7 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, ETH_ADDR_ARGS(mac)); } @@ -2094,7 +3809,7 @@ index 7ad4cdfad..045282fac 100644 ds_put_format(actions, "ip%s.src=%s; next;", is_v6 ? "6" : "4", nat->external_ip); } else { -@@ -14217,10 +14227,10 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, +@@ -14217,10 +14246,10 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, ovn_lflow_add(lflows, od, S_ROUTER_OUT_EGR_LOOP, 0, "1", "next;"); ovn_lflow_add(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 0, "1", "next;"); @@ -2109,7 +3824,7 @@ index 7ad4cdfad..045282fac 100644 * * Allow traffic that is related to an existing conntrack entry. * At the same time apply NAT for this traffic. -@@ -14231,16 +14241,10 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, +@@ -14231,16 +14260,10 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, * that's generated from a non-listening UDP port. */ if (od->has_lb_vip && features->ct_lb_related) { ds_clear(match); @@ -2126,7 +3841,7 @@ index 7ad4cdfad..045282fac 100644 ds_put_format(match, " && %s.skip_snat == 1", ct_flag_reg); ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 70, ds_cstr(match), "flags.skip_snat_for_lb = 1; ct_commit_nat;"); -@@ -14251,10 +14255,34 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, +@@ -14251,10 +14274,34 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, "flags.force_snat_for_lb = 1; ct_commit_nat;"); ds_truncate(match, match_len); @@ -2163,7 +3878,7 @@ index 7ad4cdfad..045282fac 100644 } /* If the router has load balancer or DNAT rules, re-circulate every packet -@@ -14267,6 +14295,9 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, +@@ -14267,6 +14314,9 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, * flag set. Some NICs are unable to offload these flows. */ if (od->is_gw_router && (od->nbr->n_nat || od->has_lb_vip)) { @@ -2174,7 +3889,7 @@ index 7ad4cdfad..045282fac 100644 "ip", "flags.loopback = 1; ct_dnat;"); ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 50, diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml -index 2eab2c4ae..e16d7d080 100644 +index 2eab2c4ae..5b3559d45 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -748,6 +748,12 @@ @@ -2203,7 +3918,46 @@ index 2eab2c4ae..e16d7d080 100644

-@@ -2056,6 +2056,16 @@ output; +@@ -1090,24 +1090,28 @@ +

-@@ -4721,6 +4683,11 @@ nd_ns { +@@ -4721,6 +4687,11 @@ nd_ns {

Egress Table 1: UNDNAT on Gateway Routers

    @@ -2467,7 +4221,7 @@ index 2eab2c4ae..e16d7d080 100644
  • For all IP packets, a priority-50 flow with an action flags.loopback = 1; ct_dnat;. -@@ -4998,7 +4965,19 @@ nd_ns { +@@ -4998,7 +4969,19 @@ nd_ns {
@@ -2488,7 +4242,7 @@ index 2eab2c4ae..e16d7d080 100644

For distributed logical routers where one of the logical router -@@ -5070,7 +5049,7 @@ clone { +@@ -5070,7 +5053,7 @@ clone { @@ -2497,10 +4251,42 @@ index 2eab2c4ae..e16d7d080 100644

Packets that reach this table are ready for delivery. It contains: +diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c +index 5f895b053..7d24648ff 100644 +--- a/northd/ovn-northd.c ++++ b/northd/ovn-northd.c +@@ -33,6 +33,7 @@ + #include "lib/ovn-l7.h" + #include "lib/ovn-nb-idl.h" + #include "lib/ovn-sb-idl.h" ++#include "lib/ovs-rcu.h" + #include "openvswitch/poll-loop.h" + #include "simap.h" + #include "stopwatch.h" +@@ -1048,6 +1049,8 @@ main(int argc, char *argv[]) + ovsdb_idl_loop_destroy(&ovnnb_idl_loop); + ovsdb_idl_loop_destroy(&ovnsb_idl_loop); + service_stop(); ++ run_update_worker_pool(0); ++ ovsrcu_exit(); + + exit(res); + } diff --git a/ovn-architecture.7.xml b/ovn-architecture.7.xml -index cb1064f71..86c6258e0 100644 +index cb1064f71..a2a87ec28 100644 --- a/ovn-architecture.7.xml +++ b/ovn-architecture.7.xml +@@ -1233,8 +1233,8 @@ + output port field, and since they do not carry a logical output port + field in the tunnel key, when a packet is received from ramp switch + VXLAN tunnel by an OVN hypervisor, the packet is resubmitted to table 8 +- to determine the output port(s); when the packet reaches table 37, +- these packets are resubmitted to table 38 for local delivery by ++ to determine the output port(s); when the packet reaches table 39, ++ these packets are resubmitted to table 40 for local delivery by + checking a MLF_RCV_FROM_RAMP flag, which is set when the packet + arrives from a ramp tunnel. +

@@ -1318,7 +1318,7 @@ output port is known. These pieces of information are obtained from the tunnel encapsulation metadata (see Tunnel @@ -2510,6 +4296,210 @@ index cb1064f71..86c6258e0 100644

+@@ -1439,38 +1439,42 @@ + +
  • +

    +- OpenFlow tables 37 through 39 implement the output action +- in the logical ingress pipeline. Specifically, table 37 handles +- packets to remote hypervisors, table 38 handles packets to the local +- hypervisor, and table 39 checks whether packets whose logical ingress +- and egress port are the same should be discarded. ++ OpenFlow tables 37 through 41 implement the output action ++ in the logical ingress pipeline. Specifically, table 37 serves as an ++ entry point to egress pipeline. Table 37 detects IP packets that are ++ too big for a corresponding interface. Table 38 produces ICMPv4 ++ Fragmentation Needed (or ICMPv6 Too Big) errors and deliver them back ++ to the offending port. table 39 handles packets to remote hypervisors, ++ table 40 handles packets to the local hypervisor, and table 41 checks ++ whether packets whose logical ingress and egress port are the same ++ should be discarded. +

    + +

    + Logical patch ports are a special case. Logical patch ports do not + have a physical location and effectively reside on every hypervisor. +- Thus, flow table 38, for output to ports on the local hypervisor, ++ Thus, flow table 40, for output to ports on the local hypervisor, + naturally implements output to unicast logical patch ports too. + However, applying the same logic to a logical patch port that is part + of a logical multicast group yields packet duplication, because each + hypervisor that contains a logical port in the multicast group will + also output the packet to the logical patch port. Thus, multicast +- groups implement output to logical patch ports in table 37. ++ groups implement output to logical patch ports in table 39. +

    + +

    +- Each flow in table 37 matches on a logical output port for unicast or ++ Each flow in table 39 matches on a logical output port for unicast or + multicast logical ports that include a logical port on a remote + hypervisor. Each flow's actions implement sending a packet to the port + it matches. For unicast logical output ports on remote hypervisors, + the actions set the tunnel key to the correct value, then send the + packet on the tunnel port to the correct hypervisor. (When the remote + hypervisor receives the packet, table 0 there will recognize it as a +- tunneled packet and pass it along to table 38.) For multicast logical ++ tunneled packet and pass it along to table 40.) For multicast logical + output ports, the actions send one copy of the packet to each remote + hypervisor, in the same way as for unicast destinations. If a + multicast group includes a logical port or ports on the local +- hypervisor, then its actions also resubmit to table 38. Table 37 also ++ hypervisor, then its actions also resubmit to table 40. Table 39 also + includes: +

    + +@@ -1478,7 +1482,7 @@ +
  • + A higher-priority rule to match packets received from ramp switch + tunnels, based on flag MLF_RCV_FROM_RAMP, and resubmit these packets +- to table 38 for local delivery. Packets received from ramp switch ++ to table 40 for local delivery. Packets received from ramp switch + tunnels reach here because of a lack of logical output port field in + the tunnel key and thus these packets needed to be submitted to table + 8 to determine the output port. +@@ -1486,7 +1490,7 @@ +
  • + A higher-priority rule to match packets received from ports of type + localport, based on the logical input port, and resubmit +- these packets to table 38 for local delivery. Ports of type ++ these packets to table 40 for local delivery. Ports of type + localport exist on every hypervisor and by definition + their traffic should never go out through a tunnel. +
  • +@@ -1501,41 +1505,41 @@ + packets, the packets only need to be delivered to local ports. + +
  • +- A fallback flow that resubmits to table 38 if there is no other ++ A fallback flow that resubmits to table 40 if there is no other + match. +
  • + + +

    +- Flows in table 38 resemble those in table 37 but for logical ports that ++ Flows in table 40 resemble those in table 39 but for logical ports that + reside locally rather than remotely. For unicast logical output ports +- on the local hypervisor, the actions just resubmit to table 39. For ++ on the local hypervisor, the actions just resubmit to table 41. For + multicast output ports that include one or more logical ports on the + local hypervisor, for each such logical port P, the actions + change the logical output port to P, then resubmit to table +- 39. ++ 41. +

    + +

    + A special case is that when a localnet port exists on the datapath, + remote port is connected by switching to the localnet port. In this +- case, instead of adding a flow in table 37 to reach the remote port, a +- flow is added in table 38 to switch the logical outport to the localnet +- port, and resubmit to table 38 as if it were unicasted to a logical ++ case, instead of adding a flow in table 39 to reach the remote port, a ++ flow is added in table 40 to switch the logical outport to the localnet ++ port, and resubmit to table 40 as if it were unicasted to a logical + port on the local hypervisor. +

    + +

    +- Table 39 matches and drops packets for which the logical input and ++ Table 41 matches and drops packets for which the logical input and + output ports are the same and the MLF_ALLOW_LOOPBACK flag is not + set. It also drops MLF_LOCAL_ONLY packets directed to a localnet port. +- It resubmits other packets to table 40. ++ It resubmits other packets to table 42. +

    + + +
  • +

    +- OpenFlow tables 40 through 63 execute the logical egress pipeline from ++ OpenFlow tables 42 through 62 execute the logical egress pipeline from + the Logical_Flow table in the OVN Southbound database. + The egress pipeline can perform a final stage of validation before + packet delivery. Eventually, it may execute an output +@@ -1554,7 +1558,7 @@ +

  • +

    + Table 64 bypasses OpenFlow loopback when MLF_ALLOW_LOOPBACK is set. +- Logical loopback was handled in table 39, but OpenFlow by default also ++ Logical loopback was handled in table 41, but OpenFlow by default also + prevents loopback to the OpenFlow ingress port. Thus, when + MLF_ALLOW_LOOPBACK is set, OpenFlow table 64 saves the OpenFlow ingress + port, sets it to zero, resubmits to table 65 for logical-to-physical +@@ -1592,8 +1596,8 @@ + traverse tables 0 to 65 as described in the previous section + Architectural Physical Life Cycle of a Packet, using the + logical datapath representing the logical switch that the sender is +- attached to. At table 37, the packet will use the fallback flow that +- resubmits locally to table 38 on the same hypervisor. In this case, ++ attached to. At table 39, the packet will use the fallback flow that ++ resubmits locally to table 40 on the same hypervisor. In this case, + all of the processing from table 0 to table 65 occurs on the hypervisor + where the sender resides. +

    +@@ -1624,7 +1628,7 @@ +

    + The packet traverses tables 8 to 65 a third and final time. If the + destination VM or container resides on a remote hypervisor, then table +- 37 will send the packet on a tunnel port from the sender's hypervisor ++ 39 will send the packet on a tunnel port from the sender's hypervisor + to the remote hypervisor. Finally table 65 will output the packet + directly to the destination VM or container. +

    +@@ -1651,9 +1655,9 @@ + When a hypervisor processes a packet on a logical datapath + representing a logical switch, and the logical egress port is a + l3gateway port representing connectivity to a gateway +- router, the packet will match a flow in table 37 that sends the ++ router, the packet will match a flow in table 39 that sends the + packet on a tunnel port to the chassis where the gateway router +- resides. This processing in table 37 is done in the same manner as ++ resides. This processing in table 39 is done in the same manner as + for VIFs. +

    + +@@ -1746,21 +1750,21 @@ + chassis, one additional mechanism is required. When a packet + leaves the ingress pipeline and the logical egress port is the + distributed gateway port, one of two different sets of actions is +- required at table 37: ++ required at table 39: +

    + +
      +
    • + If the packet can be handled locally on the sender's hypervisor + (e.g. one-to-one NAT traffic), then the packet should just be +- resubmitted locally to table 38, in the normal manner for ++ resubmitted locally to table 40, in the normal manner for + distributed logical patch ports. +
    • + +
    • + However, if the packet needs to be handled on the chassis + associated with the distributed gateway port (e.g. one-to-many +- SNAT traffic or non-NAT traffic), then table 37 must send the ++ SNAT traffic or non-NAT traffic), then table 39 must send the + packet on a tunnel port to that chassis. +
    • +
    +@@ -1772,11 +1776,11 @@ + egress port to the type chassisredirect logical port is + simply a way to indicate that although the packet is destined for + the distributed gateway port, it needs to be redirected to a +- different chassis. At table 37, packets with this logical egress +- port are sent to a specific chassis, in the same way that table 37 ++ different chassis. At table 39, packets with this logical egress ++ port are sent to a specific chassis, in the same way that table 39 + directs packets whose logical egress port is a VIF or a type + l3gateway port to different chassis. Once the packet +- arrives at that chassis, table 38 resets the logical egress port to ++ arrives at that chassis, table 40 resets the logical egress port to + the value representing the distributed gateway port. For each + distributed gateway port, there is one type + chassisredirect port, in addition to the distributed diff --git a/ovn-nb.xml b/ovn-nb.xml index 8d56d0c6e..35acda107 100644 --- a/ovn-nb.xml @@ -2572,7 +4562,7 @@ index d281f861c..6c4c6621c 100644 [Install] WantedBy=multi-user.target diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at -index bbe142ae3..27fc44232 100644 +index bbe142ae3..dd7eda516 100644 --- a/tests/ovn-controller.at +++ b/tests/ovn-controller.at @@ -493,7 +493,8 @@ check ovn-nbctl --wait=hv sync @@ -2616,6 +4606,579 @@ index bbe142ae3..27fc44232 100644 cat hv1/ovn-controller.log +@@ -868,7 +873,7 @@ meta=$(ovn-sbctl get datapath ls1 tunnel_key) + port=$(ovn-sbctl get port_binding ls1-rp tunnel_key) + check ovn-nbctl lrp-add lr0 rp-ls1 00:00:01:01:02:03 192.168.1.254/24 + +-OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int | grep table=38 | grep -q "reg15=0x${port},metadata=0x${meta}"]) ++OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int | grep table=40 | grep -q "reg15=0x${port},metadata=0x${meta}"]) + + OVN_CLEANUP([hv1]) + AT_CLEANUP +@@ -912,14 +917,14 @@ for i in $(seq 10); do + check ovn-nbctl add address_set as1 addresses 10.0.0.$i + check ovn-nbctl --wait=hv sync + if test "$i" = 3; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1 actions=drop + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.2 actions=drop + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.3 actions=drop + ]) + fi +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$i ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$i + ]) + done + +@@ -934,15 +939,15 @@ for i in $(seq 10); do + check ovn-nbctl remove address_set as1 addresses 10.0.0.$i + check ovn-nbctl --wait=hv sync + if test "$i" = 9; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}'], [0], [dnl + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10 actions=drop + ]) + fi + if test "$i" = 10; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) + else +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((10 - $i)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((10 - $i)) + ]) + fi + done +@@ -960,7 +965,7 @@ for i in $(seq 10); do + check ovn-nbctl add address_set as1 addresses 10.0.0.$i,10.0.1.$i + check ovn-nbctl --wait=hv sync + if test "$i" = 3; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1 actions=drop + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.2 actions=drop +@@ -970,7 +975,7 @@ priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.1.2 actions=dr + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.1.3 actions=drop + ]) + fi +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i * 2)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i * 2)) + ]) + done + +@@ -987,11 +992,11 @@ reprocess_count_old=$(read_counter consider_logical_flow) + check ovn-nbctl add address_set as1 addresses 10.0.0.21,10.0.0.22 -- \ + remove address_set as1 addresses 10.0.0.10 + check ovn-nbctl --wait=hv sync +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.21], [0], [1 ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.21], [0], [1 + ]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.22], [0], [1 ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.22], [0], [1 + ]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.10], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.10], [1], [ignore]) + + reprocess_count_new=$(read_counter consider_logical_flow) + AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [0 +@@ -1003,9 +1008,9 @@ reprocess_count_old=$(read_counter consider_logical_flow) + check ovn-nbctl remove address_set as1 addresses 10.0.0.21,10.0.0.22 -- \ + add address_set as1 addresses 10.0.0.10 + check ovn-nbctl --wait=hv sync +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.21], [1], [ignore]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.22], [1], [ignore]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.10], [0], [1 ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.21], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.22], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.10], [0], [1 + ]) + + reprocess_count_new=$(read_counter consider_logical_flow) +@@ -1018,9 +1023,9 @@ reprocess_count_old=$(read_counter consider_logical_flow) + check ovn-nbctl add address_set as1 addresses 10.0.0.21 -- \ + remove address_set as1 addresses 10.0.0.10 + check ovn-nbctl --wait=hv sync +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.21], [0], [1 ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.21], [0], [1 + ]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.10], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.10], [1], [ignore]) + + reprocess_count_new=$(read_counter consider_logical_flow) + AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [0 +@@ -1032,12 +1037,12 @@ reprocess_count_old=$(read_counter consider_logical_flow) + check ovn-nbctl add address_set as1 addresses 10.0.0.22,10.0.0.23 -- \ + remove address_set as1 addresses 10.0.0.9,10.0.0.8 + check ovn-nbctl --wait=hv sync +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.22], [0], [1 ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.22], [0], [1 + ]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.23], [0], [1 ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.23], [0], [1 + ]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.8], [1], [ignore]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.9], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.8], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.9], [1], [ignore]) + + reprocess_count_new=$(read_counter consider_logical_flow) + AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [0 +@@ -1085,7 +1090,7 @@ for i in $(seq 10); do + check ovn-nbctl add address_set as1 addresses 10.0.0.$i + check ovn-nbctl --wait=hv sync + if test "$i" = 1; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl + priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1,tp_dst=111 actions=drop + priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1,tp_dst=222 actions=drop +@@ -1093,12 +1098,12 @@ priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1,tp_dst=33 + ]) + else + # (1 conj_id flow + 3 tp_dst flows) = 4 extra flows +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i + 4)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i + 4)) + ]) + fi + + if test "$i" = 3; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | \ + sed -r 's/conjunction.*,/conjunction,/' | \ + sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl +@@ -1124,17 +1129,17 @@ for i in $(seq 10); do + check ovn-nbctl remove address_set as1 addresses 10.0.0.$i + check ovn-nbctl --wait=hv sync + if test "$i" = 10; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) + elif test "$i" = 9; then + # no conjunction left +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl + priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,tp_dst=111 actions=drop + priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,tp_dst=222 actions=drop + priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,tp_dst=333 actions=drop + ]) + else +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((14 - $i)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((14 - $i)) + ]) + fi + done +@@ -1150,7 +1155,7 @@ for i in $(seq 10); do + check ovn-nbctl add address_set as1 addresses 10.0.0.$i,10.0.1.$i + check ovn-nbctl --wait=hv sync + if test "$i" = 3; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | \ + sed -r 's/conjunction.*,/conjunction,/' | \ + sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl +@@ -1166,7 +1171,7 @@ priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,tp_dst=222 actions=conjun + priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,tp_dst=333 actions=conjunction,2/2) + ]) + fi +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i * 2 + 4)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i * 2 + 4)) + ]) + done + +@@ -1182,11 +1187,11 @@ reprocess_count_old=$(read_counter consider_logical_flow) + check ovn-nbctl add address_set as1 addresses 10.0.0.21,10.0.0.22 -- \ + remove address_set as1 addresses 10.0.0.10 + check ovn-nbctl --wait=hv sync +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.21], [0], [1 ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.21], [0], [1 + ]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.22], [0], [1 ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.22], [0], [1 + ]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.10], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.10], [1], [ignore]) + + reprocess_count_new=$(read_counter consider_logical_flow) + AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [0 +@@ -1198,9 +1203,9 @@ reprocess_count_old=$(read_counter consider_logical_flow) + check ovn-nbctl remove address_set as1 addresses 10.0.0.21,10.0.0.22 -- \ + add address_set as1 addresses 10.0.0.10 + check ovn-nbctl --wait=hv sync +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.21], [1], [ignore]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.22], [1], [ignore]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.10], [0], [1 ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.21], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.22], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.10], [0], [1 + ]) + + reprocess_count_new=$(read_counter consider_logical_flow) +@@ -1213,9 +1218,9 @@ reprocess_count_old=$(read_counter consider_logical_flow) + check ovn-nbctl add address_set as1 addresses 10.0.0.21 -- \ + remove address_set as1 addresses 10.0.0.10 + check ovn-nbctl --wait=hv sync +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.21], [0], [1 ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.21], [0], [1 + ]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.10], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.10], [1], [ignore]) + + reprocess_count_new=$(read_counter consider_logical_flow) + AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [0 +@@ -1227,12 +1232,12 @@ reprocess_count_old=$(read_counter consider_logical_flow) + check ovn-nbctl add address_set as1 addresses 10.0.0.22,10.0.0.23 -- \ + remove address_set as1 addresses 10.0.0.9,10.0.0.8 + check ovn-nbctl --wait=hv sync +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.22], [0], [1 ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.22], [0], [1 + ]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.23], [0], [1 ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.23], [0], [1 + ]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.8], [1], [ignore]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.9], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.8], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.9], [1], [ignore]) + + reprocess_count_new=$(read_counter consider_logical_flow) + AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [0 +@@ -1282,18 +1287,18 @@ for i in $(seq 10); do + add address_set as2 addresses 10.0.0.$j + check ovn-nbctl --wait=hv sync + if test "$i" = 1; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1,nw_dst=10.0.0.6 actions=drop + ]) + else + # (1 conj_id + nw_src * i + nw_dst * i) = 1 + i*2 flows +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i*2 + 1)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i*2 + 1)) + ]) + fi + + if test "$i" = 3; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | \ + sed -r 's/conjunction.*,/conjunction,/' | \ + sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl +@@ -1321,15 +1326,15 @@ for i in $(seq 10); do + remove address_set as2 addresses 10.0.0.$j + check ovn-nbctl --wait=hv sync + if test "$i" = 10; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) + elif test "$i" = 9; then + # no conjunction left +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,nw_dst=10.0.0.15 actions=drop + ]) + else +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((21 - $i*2)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((21 - $i*2)) + ]) + fi + done +@@ -1350,14 +1355,14 @@ for i in $(seq 2 10); do + check ovn-nbctl add address_set as1 addresses 10.0.0.$i + check ovn-nbctl --wait=hv sync + if test "$i" = 3; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1,nw_dst=10.0.0.6 actions=drop + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.2,nw_dst=10.0.0.6 actions=drop + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.3,nw_dst=10.0.0.6 actions=drop + ]) + fi +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$i ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$i + ]) + done + +@@ -1376,16 +1381,16 @@ for i in $(seq 10); do + check ovn-nbctl remove address_set as1 addresses 10.0.0.$i + check ovn-nbctl --wait=hv sync + if test "$i" = 9; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}'], [0], [dnl + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,nw_dst=10.0.0.6 actions=drop + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,nw_dst=10.0.0.7 actions=drop + ]) + elif test "$i" = 10; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) + else + # 2 dst + (10 - i) src + 1 conj_id +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((10 - $i + 3)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((10 - $i + 3)) + ]) + fi + done +@@ -1439,18 +1444,18 @@ for i in $(seq 10); do + add address_set as2 addresses 10.0.0.$j + check ovn-nbctl --wait=hv sync + if test "$i" = 1; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_dst=10.0.0.6 actions=drop + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1 actions=drop + ]) + else +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i*2)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i*2)) + ]) + fi + + if test "$i" = 3; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | \ + sed -r 's/conjunction.*,/conjunction,/' | \ + sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl +@@ -1477,9 +1482,9 @@ for i in $(seq 10); do + remove address_set as2 addresses 10.0.0.$j + check ovn-nbctl --wait=hv sync + if test "$i" = 10; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) + else +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((20 - $i*2)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((20 - $i*2)) + ]) + fi + done +@@ -1535,21 +1540,21 @@ for i in $(seq 10); do + add address_set as2 addresses 10.0.0.$j + check ovn-nbctl --wait=hv sync + if test "$i" = 1; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1 actions=drop + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.6 actions=drop + ]) + elif test "$i" -lt 6; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i*2)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i*2)) + ]) + else +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((5 + $i)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((5 + $i)) + ]) + fi + + if test "$i" = 3; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | \ + sed -r 's/conjunction.*,/conjunction,/' | \ + sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl +@@ -1576,12 +1581,12 @@ for i in $(seq 10); do + remove address_set as2 addresses 10.0.0.$j + check ovn-nbctl --wait=hv sync + if test "$i" = 10; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) + elif test "$i" -lt 6; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((15 - $i)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((15 - $i)) + ]) + else +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((10 - ($i - 5)*2)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((10 - ($i - 5)*2)) + ]) + fi + done +@@ -1633,18 +1638,18 @@ for i in $(seq 10); do + check ovn-nbctl add address_set as1 addresses 10.0.0.$i + check ovn-nbctl --wait=hv sync + if test "$i" = 1; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1,nw_dst=10.0.0.1 actions=drop + ]) + else + # (1 conj_id + nw_src * i + nw_dst * i) = 1 + i*2 flows +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i*2 + 1)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i*2 + 1)) + ]) + fi + + if test "$i" = 3; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | \ + sed -r 's/conjunction.*,/conjunction,/' | \ + sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl +@@ -1670,15 +1675,15 @@ for i in $(seq 10); do + check ovn-nbctl remove address_set as1 addresses 10.0.0.$i + check ovn-nbctl --wait=hv sync + if test "$i" = 10; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) + elif test "$i" = 9; then + # no conjunction left +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,nw_dst=10.0.0.10 actions=drop + ]) + else +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((21 - $i*2)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((21 - $i*2)) + ]) + fi + done +@@ -1694,7 +1699,7 @@ for i in $(seq 10); do + check ovn-nbctl add address_set as1 addresses 10.0.0.$i,10.0.1.$i + check ovn-nbctl --wait=hv sync + if test "$i" = 3; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | \ + sed -r 's/conjunction.*,/conjunction,/' | \ + sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl +@@ -1713,7 +1718,7 @@ priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.1.2 actions=co + priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.1.3 actions=conjunction,2/2) + ]) + fi +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i * 4 + 1)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i * 4 + 1)) + ]) + done + +@@ -1734,7 +1739,7 @@ check ovn-nbctl --wait=hv sync + reprocess_count_old=$(read_counter consider_logical_flow) + check ovn-nbctl add address_set as1 addresses 10.0.0.4,10.0.0.5 + check ovn-nbctl --wait=hv sync +-AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | \ + sed -r 's/conjunction.*,/conjunction,/' | \ + sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl +@@ -1758,7 +1763,7 @@ AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [1 + # Delete 2 IPs + reprocess_count_old=$(read_counter consider_logical_flow) + check ovn-nbctl --wait=hv remove address_set as1 addresses 10.0.0.4,10.0.0.5 +-AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | \ + sed -r 's/conjunction.*,/conjunction,/' | \ + sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl +@@ -1816,7 +1821,7 @@ check ovn-nbctl acl-add ls1 to-lport 100 'outport == "ls1-lp1" && ip4.src == $as + check ovn-nbctl acl-add ls1 to-lport 100 'outport == "ls1-lp1" && ip4.src == $as2 && tcp && tcp.dst == {201, 202}' drop + + check ovn-nbctl --wait=hv sync +-AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | \ + sed -r 's/conjunction.[[0-9]]*,/conjunction,/g' | \ + sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl +@@ -1841,7 +1846,7 @@ reprocess_count_old=$(read_counter consider_logical_flow) + check ovn-nbctl add address_set as1 addresses 10.0.0.14,10.0.0.33 -- \ + add address_set as2 addresses 10.0.0.24,10.0.0.33 + check ovn-nbctl --wait=hv sync +-AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | \ + sed -r 's/conjunction.[[0-9]]*,/conjunction,/g' | \ + sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl +@@ -1872,7 +1877,7 @@ reprocess_count_old=$(read_counter consider_logical_flow) + check ovn-nbctl remove address_set as1 addresses 10.0.0.14,10.0.0.33 -- \ + remove address_set as2 addresses 10.0.0.24,10.0.0.33 + check ovn-nbctl --wait=hv sync +-AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | \ + sed -r 's/conjunction.[[0-9]]*,/conjunction,/g' | \ + sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl +@@ -1937,14 +1942,14 @@ for i in $(seq 5); do + check ovn-nbctl add address_set as1 addresses "aa\:aa\:aa\:aa\:aa\:0$i" + check ovn-nbctl --wait=hv sync + if test "$i" = 3; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl + priority=1100,reg15=0x$port_key,metadata=0x$dp_key,dl_src=aa:aa:aa:aa:aa:01 actions=drop + priority=1100,reg15=0x$port_key,metadata=0x$dp_key,dl_src=aa:aa:aa:aa:aa:02 actions=drop + priority=1100,reg15=0x$port_key,metadata=0x$dp_key,dl_src=aa:aa:aa:aa:aa:03 actions=drop + ]) + fi +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$i ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$i + ]) + done + +@@ -1958,17 +1963,17 @@ reprocess_count_old=$(read_counter consider_logical_flow) + for i in $(seq 5); do + check ovn-nbctl remove address_set as1 addresses "aa\:aa\:aa\:aa\:aa\:0$i" + check ovn-nbctl --wait=hv sync +- ovs-ofctl dump-flows br-int table=44 | grep "priority=1100" ++ ovs-ofctl dump-flows br-int table=46 | grep "priority=1100" + if test "$i" = 4; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}'], [0], [dnl + priority=1100,reg15=0x$port_key,metadata=0x$dp_key,dl_src=aa:aa:aa:aa:aa:05 actions=drop + ]) + fi + if test "$i" = 5; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) + else +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((5 - $i)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((5 - $i)) + ]) + fi + done +@@ -2018,14 +2023,14 @@ for i in $(seq 5); do + check ovn-nbctl add address_set as1 addresses "ff\:\:0$i" + check ovn-nbctl --wait=hv sync + if test "$i" = 3; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl + priority=1100,ipv6,reg15=0x$port_key,metadata=0x$dp_key,ipv6_src=ff::1 actions=drop + priority=1100,ipv6,reg15=0x$port_key,metadata=0x$dp_key,ipv6_src=ff::2 actions=drop + priority=1100,ipv6,reg15=0x$port_key,metadata=0x$dp_key,ipv6_src=ff::3 actions=drop + ]) + fi +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$i ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$i + ]) + done + +@@ -2040,15 +2045,15 @@ for i in $(seq 5); do + check ovn-nbctl remove address_set as1 addresses "ff\:\:0$i" + check ovn-nbctl --wait=hv sync + if test "$i" = 4; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ + grep -v reply | awk '{print $7, $8}'], [0], [dnl + priority=1100,ipv6,reg15=0x$port_key,metadata=0x$dp_key,ipv6_src=ff::5 actions=drop + ]) + fi + if test "$i" = 5; then +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) + else +- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((5 - $i)) ++ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((5 - $i)) + ]) + fi + done @@ -2060,6 +2065,57 @@ AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [2 OVN_CLEANUP([hv1]) AT_CLEANUP @@ -2643,7 +5206,7 @@ index bbe142ae3..27fc44232 100644 +ovn-nbctl create address_set name=as1 addresses=8.8.8.8 +check ovn-nbctl acl-add ls1 to-lport 100 'outport == "ls1-lp1" && ip4.src == $as1' drop +check ovn-nbctl --wait=hv sync -+AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [1 ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [1 +]) + +# pause ovn-northd @@ -2659,13 +5222,13 @@ index bbe142ae3..27fc44232 100644 +# undefined. This test runs the scenario ten times to make sure different +# orders are covered and handled properly. + -+flow_count=$(ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100") ++flow_count=$(ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100") +for i in $(seq 10); do + # Delete and recreate the SB address set with same name and an extra IP. + addrs_=$(fetch_column address_set addresses name=as1) + addrs=${addrs_// /,} + AT_CHECK([ovn-sbctl destroy address_set as1 -- create address_set name=as1 addresses=$addrs,1.1.1.$i], [0], [ignore]) -+ OVS_WAIT_UNTIL([test $(as hv1 ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100") = "$(($i + 1))"]) ++ OVS_WAIT_UNTIL([test $(as hv1 ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100") = "$(($i + 1))"]) +done + +OVN_CLEANUP([hv1]) @@ -2772,7 +5335,7 @@ index 2fffe1850..478a32f5a 100644 AT_CHECK([ovsdb-tool create ovn-nb.db $abs_top_srcdir/ovn-nb.ovsschema]) diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at -index 3fa02d2b3..846f10e88 100644 +index 3fa02d2b3..93854dfdc 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -2486,6 +2486,7 @@ check ovn-nbctl --wait=sb \ @@ -2796,7 +5359,31 @@ index 3fa02d2b3..846f10e88 100644 table=8 (ls_in_acl ), priority=65535, match=(1), action=(next;) ]) -@@ -3757,18 +3761,18 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl +@@ -2871,7 +2875,6 @@ AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort | sed 's/tabl + AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/g'], [0], [dnl + table=??(ls_in_hairpin ), priority=0 , match=(1), action=(next;) + table=??(ls_in_hairpin ), priority=1 , match=((reg0[[6]] == 1 || reg0[[12]] == 1)), action=(eth.dst <-> eth.src; outport = inport; flags.loopback = 1; output;) +- table=??(ls_in_hairpin ), priority=1000 , match=(reg0[[14]] == 1), action=(next(pipeline=ingress, table=??);) + ]) + + check ovn-nbctl -- ls-lb-del sw0 lb0 +@@ -2887,7 +2890,6 @@ AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort | sed 's/tabl + + AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/g'], [0], [dnl + table=??(ls_in_hairpin ), priority=0 , match=(1), action=(next;) +- table=??(ls_in_hairpin ), priority=1000 , match=(reg0[[14]] == 1), action=(next(pipeline=ingress, table=??);) + ]) + + check ovn-nbctl -- add load_balancer_group $lbg load_balancer $lb0 +@@ -2908,7 +2910,6 @@ AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort | sed 's/tabl + AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/g'], [0], [dnl + table=??(ls_in_hairpin ), priority=0 , match=(1), action=(next;) + table=??(ls_in_hairpin ), priority=1 , match=((reg0[[6]] == 1 || reg0[[12]] == 1)), action=(eth.dst <-> eth.src; outport = inport; flags.loopback = 1; output;) +- table=??(ls_in_hairpin ), priority=1000 , match=(reg0[[14]] == 1), action=(next(pipeline=ingress, table=??);) + ]) + + AT_CLEANUP +@@ -3757,18 +3758,18 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -2822,7 +5409,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -3788,18 +3792,18 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl +@@ -3788,18 +3789,18 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -2848,7 +5435,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -3813,6 +3817,7 @@ AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [ +@@ -3813,6 +3814,7 @@ AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [ AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) @@ -2856,7 +5443,7 @@ index 3fa02d2b3..846f10e88 100644 table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -@@ -3838,18 +3843,18 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl +@@ -3838,18 +3840,18 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -2882,7 +5469,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -3864,6 +3869,7 @@ AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [ +@@ -3864,6 +3866,7 @@ AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [ AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) @@ -2890,7 +5477,7 @@ index 3fa02d2b3..846f10e88 100644 table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -@@ -3902,18 +3908,18 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl +@@ -3902,18 +3905,18 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -2916,7 +5503,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -3929,6 +3935,7 @@ AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [ +@@ -3929,6 +3932,7 @@ AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [ AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) @@ -2924,7 +5511,7 @@ index 3fa02d2b3..846f10e88 100644 table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -@@ -3953,14 +3960,13 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl +@@ -3953,14 +3957,13 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -2943,7 +5530,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -3970,6 +3976,7 @@ AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sed 's/table=./t +@@ -3970,6 +3973,7 @@ AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sed 's/table=./t AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) @@ -2951,7 +5538,7 @@ index 3fa02d2b3..846f10e88 100644 table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -@@ -4111,6 +4118,7 @@ check ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0 +@@ -4111,6 +4115,7 @@ check ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0 check ovn-nbctl --wait=sb sync check_stateful_flows() { @@ -2959,7 +5546,7 @@ index 3fa02d2b3..846f10e88 100644 ovn-sbctl dump-flows sw0 > sw0flows AT_CAPTURE_FILE([sw0flows]) -@@ -4144,12 +4152,12 @@ check_stateful_flows() { +@@ -4144,12 +4149,12 @@ check_stateful_flows() { table=??(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_mark.blocked = 0; ct_label.label = reg3; }; next;) ]) @@ -2975,7 +5562,7 @@ index 3fa02d2b3..846f10e88 100644 table=1 (ls_out_pre_lb ), priority=110 , match=(nd || nd_rs || nd_ra || mldv1 || mldv2), action=(next;) table=1 (ls_out_pre_lb ), priority=110 , match=(reg0[[16]] == 1), action=(next;) ]) -@@ -4169,13 +4177,13 @@ check_stateful_flows() { +@@ -4169,13 +4174,13 @@ check_stateful_flows() { ]) } @@ -2991,7 +5578,7 @@ index 3fa02d2b3..846f10e88 100644 # Remove load balancers from sw0 check ovn-nbctl ls-lb-del sw0 lb0 -@@ -4231,6 +4239,15 @@ AT_CHECK([grep "ls_out_stateful" sw0flows | sort], [0], [dnl +@@ -4231,6 +4236,15 @@ AT_CHECK([grep "ls_out_stateful" sw0flows | sort], [0], [dnl table=7 (ls_out_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_mark.blocked = 0; ct_label.label = reg3; }; next;) ]) @@ -3007,7 +5594,88 @@ index 3fa02d2b3..846f10e88 100644 AT_CLEANUP ]) -@@ -5211,25 +5228,23 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl +@@ -4871,7 +4885,7 @@ check ovn-nbctl lsp-set-options ls2-ro2 router-port=ro2-ls2 + ovn-sbctl lflow-list ls1 > ls1_lflows + AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), action=(handle_svc_check(inport);) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:02), action=(outport = "vm1"; output;) + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) +@@ -4883,7 +4897,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], + ovn-sbctl lflow-list ls2 > ls2_lflows + AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | sed 's/table=../table=??/' | sort], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), action=(handle_svc_check(inport);) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:02:02), action=(outport = "vm2"; output;) + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) +@@ -4903,7 +4917,7 @@ check ovn-nbctl --wait=sb lr-nat-add ro2 snat 20.0.0.200 192.168.2.200/30 + ovn-sbctl lflow-list ls1 > ls1_lflows + AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), action=(handle_svc_check(inport);) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:02), action=(outport = "vm1"; output;) + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) +@@ -4916,7 +4930,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], + ovn-sbctl lflow-list ls2 > ls2_lflows + AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | sed 's/table=../table=??/' | sort], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), action=(handle_svc_check(inport);) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:02:02), action=(outport = "vm2"; output;) + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) +@@ -4937,7 +4951,7 @@ check ovn-nbctl --wait=sb lr-nat-add ro2 snat 40.0.0.200 192.168.2.148/30 + ovn-sbctl lflow-list ls1 > ls1_lflows + AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), action=(handle_svc_check(inport);) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:02), action=(outport = "vm1"; output;) + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) +@@ -4951,7 +4965,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], + ovn-sbctl lflow-list ls2 > ls2_lflows + AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | sed 's/table=../table=??/' | sort], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), action=(handle_svc_check(inport);) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:02:02), action=(outport = "vm2"; output;) + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) +@@ -4970,7 +4984,7 @@ ovn-nbctl --wait=sb lr-lb-add ro1 lb1 + ovn-sbctl lflow-list ls1 > ls1_lflows + AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), action=(handle_svc_check(inport);) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:02), action=(outport = "vm1"; output;) + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) +@@ -4988,7 +5002,7 @@ ovn-nbctl --wait=sb lb-add lb1 192.168.4.100:80 10.0.0.10:80 + ovn-sbctl lflow-list ls1 > ls1_lflows + AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), action=(handle_svc_check(inport);) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:02), action=(outport = "vm1"; output;) + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) +@@ -5012,7 +5026,7 @@ ovn-nbctl --wait=sb lrp-set-gateway-chassis ro1-ls1 chassis-1 30 + ovn-sbctl lflow-list ls1 > ls1_lflows + AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), action=(handle_svc_check(inport);) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;) + table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:02), action=(outport = "vm1"; output;) + table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) +@@ -5211,25 +5225,23 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -3044,7 +5712,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -5284,25 +5299,23 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl +@@ -5284,25 +5296,23 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -3081,7 +5749,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -5314,6 +5327,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor +@@ -5314,6 +5324,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) @@ -3089,7 +5757,7 @@ index 3fa02d2b3..846f10e88 100644 table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -@@ -5349,25 +5363,23 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl +@@ -5349,25 +5360,23 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -3126,7 +5794,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -5379,6 +5391,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor +@@ -5379,6 +5388,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) @@ -3134,7 +5802,7 @@ index 3fa02d2b3..846f10e88 100644 table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -@@ -5416,28 +5429,25 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl +@@ -5416,28 +5426,25 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -3176,7 +5844,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -5449,6 +5459,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor +@@ -5449,6 +5456,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) @@ -3184,7 +5852,7 @@ index 3fa02d2b3..846f10e88 100644 table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -@@ -5496,31 +5507,27 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl +@@ -5496,31 +5504,27 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -3231,7 +5899,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -5532,6 +5539,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor +@@ -5532,6 +5536,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) @@ -3239,7 +5907,7 @@ index 3fa02d2b3..846f10e88 100644 table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -@@ -5572,18 +5580,17 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl +@@ -5572,18 +5577,17 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -3264,7 +5932,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -5594,6 +5601,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor +@@ -5594,6 +5598,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) @@ -3272,7 +5940,7 @@ index 3fa02d2b3..846f10e88 100644 table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -@@ -5634,9 +5642,11 @@ ovn-sbctl set service_monitor $sm_vip2 status=offline +@@ -5634,9 +5639,11 @@ ovn-sbctl set service_monitor $sm_vip2 status=offline AT_CHECK([ovn-sbctl dump-flows lr0 | grep "lr_in_dnat" | sort], [0], [dnl table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) @@ -3286,7 +5954,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -5646,9 +5656,11 @@ check ovn-nbctl --wait=sb set load_balancer lb5 options:skip_snat=true +@@ -5646,9 +5653,11 @@ check ovn-nbctl --wait=sb set load_balancer lb5 options:skip_snat=true AT_CHECK([ovn-sbctl dump-flows lr0 | grep "lr_in_dnat" | sort], [0], [dnl table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) @@ -3300,7 +5968,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -5660,9 +5672,58 @@ check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="route +@@ -5660,9 +5669,58 @@ check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="route AT_CHECK([ovn-sbctl dump-flows lr0 | grep "lr_in_dnat" | sort], [0], [dnl table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) @@ -3361,7 +6029,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -6692,11 +6753,12 @@ dnl Flows to skip TTL == {0, 1} check for IGMP and MLD packets. +@@ -6692,11 +6750,12 @@ dnl Flows to skip TTL == {0, 1} check for IGMP and MLD packets. AT_CHECK([grep -e 'lr_in_ip_input ' lrflows | grep -e 'igmp' -e 'mld' -e 'ip.ttl == {0, 1}' | sed 's/table=../table=??/'], [0], [dnl table=??(lr_in_ip_input ), priority=120 , match=((mldv1 || mldv2) && ip.ttl == 1), action=(next;) table=??(lr_in_ip_input ), priority=120 , match=(igmp && ip.ttl == 1), action=(next;) @@ -3379,7 +6047,7 @@ index 3fa02d2b3..846f10e88 100644 ]) dnl Flows to "route" (statically forward) without decrementing TTL for -@@ -6755,6 +6817,7 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], +@@ -6755,6 +6814,7 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) @@ -3387,7 +6055,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) -@@ -6809,6 +6872,7 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], +@@ -6809,6 +6869,7 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], table=??(ls_in_acl_after_lb ), priority=2003 , match=(reg0[[8]] == 1 && (ip4 && icmp)), action=(next;) table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[10]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(ct_commit { ct_mark.blocked = 1; }; /* drop */) table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[9]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(/* drop */) @@ -3395,7 +6063,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) -@@ -6863,6 +6927,7 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], +@@ -6863,6 +6924,7 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], table=??(ls_in_acl_after_lb ), priority=2001 , match=(reg0[[9]] == 1 && (ip4)), action=(/* drop */) table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[10]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(ct_commit { ct_mark.blocked = 1; }; /* drop */) table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[9]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(/* drop */) @@ -3403,7 +6071,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) -@@ -7154,11 +7219,14 @@ flow="inport == \"lsp1\" && eth.src == 00:00:00:00:00:01 && eth.dst == 00:00:00: +@@ -7154,11 +7216,14 @@ flow="inport == \"lsp1\" && eth.src == 00:00:00:00:00:01 && eth.dst == 00:00:00: AS_BOX([No ACL, default_acl_drop not set]) check ovn-nbctl --wait=sb sync AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl @@ -3418,7 +6086,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_out_acl ), priority=65535, match=(1), action=(next;) table=??(ls_out_acl_hint ), priority=65535, match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) -@@ -7173,11 +7241,14 @@ output("lsp2"); +@@ -7173,11 +7238,14 @@ output("lsp2"); AS_BOX([No ACL, default_acl_drop false]) check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=false AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl @@ -3433,7 +6101,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_out_acl ), priority=65535, match=(1), action=(next;) table=??(ls_out_acl_hint ), priority=65535, match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) -@@ -7192,11 +7263,14 @@ output("lsp2"); +@@ -7192,11 +7260,14 @@ output("lsp2"); AS_BOX([No ACL, default_acl_drop true]) check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=true AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl @@ -3448,7 +6116,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_out_acl ), priority=65535, match=(1), action=(next;) table=??(ls_out_acl_hint ), priority=65535, match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) -@@ -7218,12 +7292,15 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ +@@ -7218,12 +7289,15 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl ), priority=1001 , match=(ip4 && tcp), action=(next;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) @@ -3464,7 +6132,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7240,12 +7317,15 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ +@@ -7240,12 +7314,15 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl ), priority=1001 , match=(ip4 && tcp), action=(next;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) @@ -3480,7 +6148,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7262,12 +7342,15 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ +@@ -7262,12 +7339,15 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ table=??(ls_in_acl ), priority=0 , match=(1), action=(drop;) table=??(ls_in_acl ), priority=1001 , match=(ip4 && tcp), action=(next;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) @@ -3496,7 +6164,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7292,6 +7375,7 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ +@@ -7292,6 +7372,7 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(drop;) @@ -3504,7 +6172,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) -@@ -7343,13 +7427,16 @@ check ovn-nbctl --wait=sb remove NB_Global . options default_acl_drop +@@ -7343,13 +7424,16 @@ check ovn-nbctl --wait=sb remove NB_Global . options default_acl_drop AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) @@ -3521,7 +6189,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7365,13 +7452,16 @@ check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=false +@@ -7365,13 +7449,16 @@ check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=false AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) @@ -3538,7 +6206,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7387,13 +7477,16 @@ check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=true +@@ -7387,13 +7474,16 @@ check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=true AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl table=??(ls_in_acl ), priority=0 , match=(1), action=(drop;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) @@ -3555,7 +6223,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7418,6 +7511,7 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ +@@ -7418,6 +7508,7 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(drop;) table=??(ls_in_acl_after_lb ), priority=1001 , match=(reg0[[7]] == 1 && (ip4 && tcp)), action=(reg0[[1]] = 1; next;) table=??(ls_in_acl_after_lb ), priority=1001 , match=(reg0[[8]] == 1 && (ip4 && tcp)), action=(next;) @@ -3563,7 +6231,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) -@@ -7469,13 +7563,16 @@ check ovn-nbctl --wait=sb remove NB_Global . options default_acl_drop +@@ -7469,13 +7560,16 @@ check ovn-nbctl --wait=sb remove NB_Global . options default_acl_drop AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) @@ -3580,7 +6248,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7491,13 +7588,16 @@ check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=false +@@ -7491,13 +7585,16 @@ check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=false AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) @@ -3597,7 +6265,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7513,13 +7613,16 @@ check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=true +@@ -7513,13 +7610,16 @@ check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=true AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl table=??(ls_in_acl ), priority=0 , match=(1), action=(drop;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) @@ -3614,7 +6282,7 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7542,6 +7645,7 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ +@@ -7542,6 +7642,7 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(drop;) @@ -3622,7 +6290,61 @@ index 3fa02d2b3..846f10e88 100644 table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) -@@ -7886,8 +7990,10 @@ check ovn-nbctl \ +@@ -7719,7 +7820,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), 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;) +@@ -7744,7 +7845,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), 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;) +@@ -7770,7 +7871,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), 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;) +@@ -7797,7 +7898,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), 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;) +@@ -7824,7 +7925,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), 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;) +@@ -7854,7 +7955,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl + 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=110 , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), 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;) +@@ -7886,8 +7987,10 @@ check ovn-nbctl \ AS_BOX([No chassis registered - use ct_lb_mark and ct_mark.natted]) check ovn-nbctl --wait=sb sync AT_CHECK([ovn-sbctl lflow-list | grep -e natted -e ct_lb], [0], [dnl @@ -3635,7 +6357,7 @@ index 3fa02d2b3..846f10e88 100644 table=6 (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip4.dst == 66.66.66.66), action=(reg1 = 66.66.66.66; ct_lb_mark;) table=6 (ls_in_pre_stateful ), priority=110 , match=(reg0[[2]] == 1), action=(ct_lb_mark;) table=12(ls_in_lb ), priority=110 , match=(ct.new && ip4.dst == 66.66.66.66), action=(reg0[[1]] = 0; ct_lb_mark(backends=42.42.42.2);) -@@ -7898,8 +8004,10 @@ AS_BOX([Chassis registered that doesn't support ct_lb_mark - use ct_lb and ct_la +@@ -7898,8 +8001,10 @@ AS_BOX([Chassis registered that doesn't support ct_lb_mark - use ct_lb and ct_la check ovn-sbctl chassis-add hv geneve 127.0.0.1 check ovn-nbctl --wait=sb sync AT_CHECK([ovn-sbctl lflow-list | grep -e natted -e ct_lb], [0], [dnl @@ -3648,7 +6370,7 @@ index 3fa02d2b3..846f10e88 100644 table=6 (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip4.dst == 66.66.66.66), action=(reg1 = 66.66.66.66; ct_lb;) table=6 (ls_in_pre_stateful ), priority=110 , match=(reg0[[2]] == 1), action=(ct_lb;) table=12(ls_in_lb ), priority=110 , match=(ct.new && ip4.dst == 66.66.66.66), action=(reg0[[1]] = 0; ct_lb(backends=42.42.42.2);) -@@ -7910,8 +8018,10 @@ AS_BOX([Chassis upgrades and supports ct_lb_mark - use ct_lb_mark and ct_mark.na +@@ -7910,8 +8015,10 @@ AS_BOX([Chassis upgrades and supports ct_lb_mark - use ct_lb_mark and ct_mark.na check ovn-sbctl set chassis hv other_config:ct-no-masked-label=true check ovn-nbctl --wait=sb sync AT_CHECK([ovn-sbctl lflow-list | grep -e natted -e ct_lb], [0], [dnl @@ -3661,7 +6383,7 @@ index 3fa02d2b3..846f10e88 100644 table=6 (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip4.dst == 66.66.66.66), action=(reg1 = 66.66.66.66; ct_lb_mark;) table=6 (ls_in_pre_stateful ), priority=110 , match=(reg0[[2]] == 1), action=(ct_lb_mark;) table=12(ls_in_lb ), priority=110 , match=(ct.new && ip4.dst == 66.66.66.66), action=(reg0[[1]] = 0; ct_lb_mark(backends=42.42.42.2);) -@@ -8244,15 +8354,17 @@ AT_CAPTURE_FILE([R1flows]) +@@ -8244,15 +8351,17 @@ AT_CAPTURE_FILE([R1flows]) AT_CHECK([grep "lr_in_lb_aff_check" R1flows | sort], [0], [dnl table=6 (lr_in_lb_aff_check ), priority=0 , match=(1), action=(next;) @@ -3682,7 +6404,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -8270,11 +8382,13 @@ AT_CAPTURE_FILE([R1flows_skip_snat]) +@@ -8270,11 +8379,13 @@ AT_CAPTURE_FILE([R1flows_skip_snat]) AT_CHECK([grep "lr_in_dnat " R1flows_skip_snat | sort], [0], [dnl table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) @@ -3698,7 +6420,7 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -8289,11 +8403,13 @@ AT_CAPTURE_FILE([R1flows_force_snat]) +@@ -8289,11 +8400,13 @@ AT_CAPTURE_FILE([R1flows_force_snat]) AT_CHECK([grep "lr_in_dnat " R1flows_force_snat | sort], [0], [dnl table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) @@ -3714,7 +6436,31 @@ index 3fa02d2b3..846f10e88 100644 table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -8569,12 +8685,13 @@ ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows0 +@@ -8330,8 +8443,9 @@ rm -f northd/ovn-northd.log + check as northd ovn-appctl -t NORTHD_TYPE vlog/reopen + check as northd ovn-appctl -t NORTHD_TYPE vlog/set jsonrpc:dbg + check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats +-check ovn-nbctl add address_set $foo_as_uuid addresses 1.1.1.3 +-wait_column '1.1.1.1 1.1.1.2 1.1.1.3' Address_Set addresses name=foo ++check ovn-nbctl add address_set $foo_as_uuid addresses 1.1.1.3 -- \ ++ add address_set $foo_as_uuid addresses 1.1.2.1/4 ++wait_column '1.1.1.1 1.1.1.2 1.1.1.3 1.1.2.1/4' Address_Set addresses name=foo + + # There should be no recompute of the sync_to_sb_addr_set engine node . + AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats sync_to_sb_addr_set recompute], [0], [0 +@@ -8341,8 +8455,9 @@ AT_CHECK([grep transact northd/ovn-northd.log | grep Address_Set | \ + grep -c mutate], [0], [1 + ]) + +-check ovn-nbctl add address_set $foo_as_uuid addresses \ +-1.1.1.4 -- remove address_set $foo_as_uuid addresses 1.1.1.1 ++check ovn-nbctl add address_set $foo_as_uuid addresses 1.1.1.4 -- \ ++ remove address_set $foo_as_uuid addresses 1.1.1.1 -- \ ++ remove address_set $foo_as_uuid addresses 1.1.2.1/4 + wait_column '1.1.1.2 1.1.1.3 1.1.1.4' Address_Set addresses name=foo + + # There should be no recompute of the sync_to_sb_addr_set engine node . +@@ -8569,12 +8684,13 @@ ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows0 AT_CHECK([grep -e "lr_in_defrag" -e "lr_in_dnat" lflows0], [0], [dnl table=? (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -3732,7 +6478,7 @@ index 3fa02d2b3..846f10e88 100644 table=? (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=? (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -8588,6 +8705,7 @@ AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows0 | grep "priority=65532"], +@@ -8588,6 +8704,7 @@ AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows0 | grep "priority=65532"], table=? (ls_out_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;) table=? (ls_out_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=? (ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) @@ -3740,7 +6486,7 @@ index 3fa02d2b3..846f10e88 100644 table=?(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) ]) -@@ -8599,10 +8717,12 @@ ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows1 +@@ -8599,10 +8716,12 @@ ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows1 AT_CHECK([grep -e "lr_in_defrag" -e "lr_in_dnat" lflows1], [0], [dnl table=? (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -3756,7 +6502,7 @@ index 3fa02d2b3..846f10e88 100644 ]) AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows1 | grep "priority=65532"], [0], [dnl -@@ -8614,6 +8734,7 @@ AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows1 | grep "priority=65532"], +@@ -8614,6 +8733,7 @@ AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows1 | grep "priority=65532"], table=? (ls_out_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;) table=? (ls_out_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) table=? (ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) @@ -3764,7 +6510,7 @@ index 3fa02d2b3..846f10e88 100644 table=?(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) ]) -@@ -8625,12 +8746,13 @@ ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows2 +@@ -8625,12 +8745,13 @@ ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows2 AT_CHECK([grep -e "lr_in_defrag" -e "lr_in_dnat" lflows2], [0], [dnl table=? (lr_in_defrag ), priority=0 , match=(1), action=(next;) @@ -3782,7 +6528,7 @@ index 3fa02d2b3..846f10e88 100644 table=? (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) table=? (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) -@@ -8644,8 +8766,104 @@ AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows2 | grep "priority=65532"], +@@ -8644,8 +8765,104 @@ AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows2 | grep "priority=65532"], table=? (ls_out_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;) table=? (ls_out_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=? (ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) @@ -3888,10 +6634,189 @@ index 3fa02d2b3..846f10e88 100644 +AT_CLEANUP +]) diff --git a/tests/ovn.at b/tests/ovn.at -index 55de7c85b..3515a1e3c 100644 +index 55de7c85b..ed91d32d0 100644 --- a/tests/ovn.at +++ b/tests/ovn.at -@@ -5753,7 +5753,7 @@ check ovn-nbctl --wait=hv sync +@@ -992,10 +992,10 @@ next(pipeline=ingress, table=11); + + next(pipeline=egress); + formats as next(pipeline=egress, table=11); +- encodes as resubmit(,51) ++ encodes as resubmit(,53) + + next(pipeline=egress, table=5); +- encodes as resubmit(,45) ++ encodes as resubmit(,47) + + next(table=10); + formats as next(10); +@@ -4414,24 +4414,13 @@ response=${sha}${lrpmac}08060001080006040002${lrpmac}${tpa}${sha}${spa} + echo $response >> 3.expected + + # First ensure basic flow contents are as we expect. +-AT_CHECK([ovn-sbctl lflow-list lsw0 | grep 'reg0[\[14\]]' | sort | sed 's/table=../table=??/g' | sed 's/is_chassis_resident([[^)]]*)/is_chassis_resident("??")/g'], [0], [dnl ++AT_CHECK([ovn-sbctl lflow-list lsw0 | grep 'reg0[\[14\]]' | sort | sed 's/table=../table=??/g'], [0], [dnl + table=??(ls_in_check_port_sec), priority=70 , match=(inport == "lp-vtep"), action=(reg0[[14]] = 1; next(pipeline=ingress, table=??);) + table=??(ls_in_hairpin ), priority=1000 , match=(reg0[[14]] == 1), action=(next(pipeline=ingress, table=??);) +- table=??(ls_in_hairpin ), priority=2000 , match=(reg0[[14]] == 1 && (is_chassis_resident("??") || is_chassis_resident("??"))), action=(next;) ++ table=??(ls_in_hairpin ), priority=2000 , match=(reg0[[14]] == 1 && is_chassis_resident("cr-lrp1")), action=(next;) ++ table=??(ls_in_hairpin ), priority=2000 , match=(reg0[[14]] == 1 && is_chassis_resident("cr-lrp2")), action=(next;) + ]) + +-# We've ensured that the expected hairpin flows are present +-# and that the expected number of "is_chassis_resident" fields are in +-# the flow. Now we need to ensure the contents are correct. +-# Unfortunately, the order of the "is_chassis_resident" fields is +-# unpredictable. Therefore we sort them so the order is predictable. +-actual_chassis=$(ovn-sbctl lflow-list lsw0 | grep 'ls_in_hairpin' | grep 'priority=2000' | grep -o 'is_chassis_resident([[^)]]*)' | sort) +- +-expected_chassis='is_chassis_resident("cr-lrp1") +-is_chassis_resident("cr-lrp2")' +- +-check test "$expected_chassis" = "$actual_chassis" +- + # dump information with counters + echo "------ OVN dump ------" + ovn-nbctl show +@@ -5055,6 +5044,7 @@ AT_CLEANUP + + OVN_FOR_EACH_NORTHD([ + AT_SETUP([IP relocation using GARP request]) ++AT_SKIP_IF([test $HAVE_SCAPY = no]) + ovn_start + + # Logical network: +@@ -5154,7 +5144,9 @@ done + test_ip() { + # This packet has bad checksums but logical L3 routing doesn't check. + local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 +- local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 ++ local packet=$(fmt_pkt "Ether(dst='${dst_mac}', src='${src_mac}')/ \ ++ IP(dst='${dst_ip}', src='${src_ip}')/ \ ++ UDP(sport=53, dport=4369)") + shift; shift; shift; shift; shift + hv=hv`vif_to_hv $inport` + as $hv ovs-appctl netdev-dummy/receive vif$inport $packet +@@ -5169,7 +5161,9 @@ test_ip() { + # Routing decrements TTL and updates source and dest MAC + # (and checksum). + out_lrp=`vif_to_lrp $outport` +- echo f000000000${outport}00000000ff0${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 ++ echo $(fmt_pkt "Ether(dst='f0:00:00:00:00:${outport}', src='00:00:00:00:ff:${out_lrp}')/ \ ++ IP(src='${src_ip}', dst='${dst_ip}', ttl=63)/ \ ++ UDP(sport=53, dport=4369)") + fi >> $outport.expected + done + } +@@ -5185,8 +5179,10 @@ test_ip() { + # SHA and REPLY_HA are each 12 hex digits. + # SPA and TPA are each 8 hex digits. + test_arp() { +- local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5 +- local request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} ++ local inport=$1 sha=$2 spa=$3 tpa=$3 ++ local request=$(fmt_pkt "Ether(dst='ff:ff:ff:ff:ff:ff', src='${sha}')/ \ ++ ARP(hwsrc='${sha}', hwdst='ff:ff:ff:ff:ff:ff', psrc='${spa}', pdst='${tpa}')") ++ + hv=hv`vif_to_hv $inport` + as $hv ovs-appctl netdev-dummy/receive vif$inport $request + +@@ -5199,53 +5195,72 @@ test_arp() { + echo $request >> $i$j$k.expected + fi + done ++} + +- # Expect to receive the reply, if any. +- if test X$reply_ha != X; then +- lrp=`vif_to_lrp $inport` +- local reply=${sha}00000000ff0${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa} +- echo $reply >> $inport.expected +- fi ++test_na() { ++ local inport=$1 sha=$2 spa=$3 ++ local request=$(fmt_pkt "Ether(dst='ff:ff:ff:ff:ff:ff', src='${sha}')/ \ ++ IPv6(dst='ff01::1', src='${spa}')/ \ ++ ICMPv6ND_NA(tgt='${spa}')") ++ ++ hv=hv`vif_to_hv $inport` ++ as $hv ovs-appctl netdev-dummy/receive vif$inport $request ++ ++ # Expect to receive the broadcast ARP on the other logical switch ports if ++ # IP address is not configured to the switch patch port. ++ local i=`vif_to_ls $inport` ++ local j ++ for j in 1 2; do ++ if test $i$j != $inport; then ++ echo $request >> $i$j$k.expected ++ fi ++ done + } + +-# lp11 send GARP request to announce ownership of 192.168.1.100. ++# lp11 send GARP request to announce ownership of 192.168.1.100 and fe80::abcd:1. + +-sha=f00000000011 +-spa=`ip_to_hex 192 168 1 100` +-tpa=$spa ++sha="f0:00:00:00:00:11" ++spa="192.168.1.100" ++spa6="fe80::abcd:1" + + # When always_learn_from_arp_request=false, the new mac-binding will not be learned + # through GARP request. + ovn-nbctl --wait=hv set logical_router lr0 options:always_learn_from_arp_request=false + +-test_arp 11 $sha $spa $tpa ++test_arp 11 $sha $spa ++test_na 11 $sha $spa6 + sleep 1 +-check_row_count MAC_Binding 0 ip="192.168.1.100" ++check_row_count MAC_Binding 0 ip="$spa" ++check_row_count MAC_Binding 0 ip=\"$spa6\" + + # When always_learn_from_arp_request=true, the new mac-binding will be learned. + ovn-nbctl --wait=hv set logical_router lr0 options:always_learn_from_arp_request=true + +-test_arp 11 $sha $spa $tpa +-OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding ip="192.168.1.100" | wc -l` -gt 0]) ++test_arp 11 $sha $spa ++test_na 11 $sha $spa6 ++wait_row_count MAC_Binding 1 ip="$spa" mac=\"$sha\" ++wait_row_count MAC_Binding 1 ip=\"$spa6\" mac=\"$sha\" + ovn-nbctl --wait=hv sync + + # Send an IP packet from lp21 to 192.168.1.100, which should go to lp11. + +-smac=f00000000021 +-dmac=00000000ff02 +-sip=`ip_to_hex 192 168 2 11` +-dip=`ip_to_hex 192 168 1 100` ++smac="f0:00:00:00:00:21" ++dmac="00:00:00:00:ff:02" ++sip="192.168.2.11" ++dip="192.168.1.100" + test_ip 21 $smac $dmac $sip $dip 11 + +-# lp12 send GARP request to announce ownership of 192.168.1.100. ++# lp12 send GARP request to announce ownership of 192.168.1.100 and fe80::abcd:1. + + # Even when always_learn_from_arp_request=false, the existing mac-binding should be + # updated through GARP request. + ovn-nbctl --wait=hv set logical_router lr0 options:always_learn_from_arp_request=false + +-sha=f00000000012 +-test_arp 12 $sha $spa $tpa +-wait_row_count MAC_Binding 1 ip="192.168.1.100" mac='"f0:00:00:00:00:12"' ++sha="f0:00:00:00:00:12" ++test_arp 12 $sha $spa ++test_na 11 $sha $spa6 ++wait_row_count MAC_Binding 1 ip="$spa" mac=\"$sha\" ++wait_row_count MAC_Binding 1 ip=\"$spa6\" mac=\"$sha\" + ovn-nbctl --wait=hv sync + # give to the hv the time to send queued ip packets + sleep 1 +@@ -5753,7 +5768,7 @@ check ovn-nbctl --wait=hv sync packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac && eth.dst==$rp_ls1_mac && ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip && ip4.dst==$ls2_lp1_ip && udp && udp.src==53 && udp.dst==4369" @@ -3900,7 +6825,7 @@ index 55de7c85b..3515a1e3c 100644 echo "---------NB dump-----" -@@ -5803,7 +5803,7 @@ packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac && eth.dst==$rp_ls1_mac && +@@ -5803,7 +5818,7 @@ packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac && eth.dst==$rp_ls1_mac && ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip && ip4.dst==$ls2_lp1_ip && udp && udp.src==53 && udp.dst==4369" @@ -3909,7 +6834,7 @@ index 55de7c85b..3515a1e3c 100644 # The 2nd packet sent shound not be received. OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) -@@ -7741,7 +7741,6 @@ ls3_p1_mac=00:00:00:01:02:05 +@@ -7741,7 +7756,6 @@ ls3_p1_mac=00:00:00:01:02:05 check ovn-nbctl --wait=hv lr-policy-add R1 10 "ip4.src==192.168.1.0/24 && ip4.dst==172.16.1.0/24" drop # Check logical flow @@ -3917,7 +6842,7 @@ index 55de7c85b..3515a1e3c 100644 AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "192.168.1.0" | wc -l], [0], [dnl 1 ]) -@@ -7751,15 +7750,12 @@ packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && +@@ -7751,15 +7765,12 @@ packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip && udp && udp.src==53 && udp.dst==4369" @@ -3936,7 +6861,7 @@ index 55de7c85b..3515a1e3c 100644 # Expected to drop the packet. $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" pbr-hv/vif2-tx.pcap > vif2.packets -@@ -7770,7 +7766,7 @@ AT_FAIL_IF([test "$rcvd_packet" != ""]) +@@ -7770,7 +7781,7 @@ AT_FAIL_IF([test "$rcvd_packet" != ""]) check ovn-nbctl --wait=hv lr-policy-add R1 20 "ip4.src==192.168.1.0/24 && ip4.dst==172.16.1.0/24" allow # Check logical flow @@ -3945,7 +6870,7 @@ index 55de7c85b..3515a1e3c 100644 2 ]) -@@ -7778,15 +7774,12 @@ AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "192.168.1.0" | wc -l] +@@ -7778,15 +7789,12 @@ AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "192.168.1.0" | wc -l] packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip && udp && udp.src==53 && udp.dst==4369" @@ -3965,7 +6890,7 @@ index 55de7c85b..3515a1e3c 100644 # Expected packet has TTL decreased by 1 expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac && -@@ -7802,7 +7795,7 @@ check ovn-nbctl --wait=hv lr-policy-add R1 30 "ip4.src==192.168.1.0/24 && ip4.ds +@@ -7802,7 +7810,7 @@ check ovn-nbctl --wait=hv lr-policy-add R1 30 "ip4.src==192.168.1.0/24 && ip4.ds # Check logical flow AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \ grep "192.168.1.0" | \ @@ -3974,7 +6899,7 @@ index 55de7c85b..3515a1e3c 100644 1 ]) -@@ -7810,21 +7803,12 @@ AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \ +@@ -7810,21 +7818,12 @@ AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \ packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip && udp && udp.src==53 && udp.dst==4369" @@ -4000,7 +6925,7 @@ index 55de7c85b..3515a1e3c 100644 echo "packet hit reroute policy" # Expected packet has TTL decreased by 1 -@@ -7927,9 +7911,7 @@ ls3_p1_mac=00:00:00:01:02:05 +@@ -7927,9 +7926,7 @@ ls3_p1_mac=00:00:00:01:02:05 check ovn-nbctl --wait=sb lr-policy-add R1 10 "ip6.src==2001::/64 && ip6.dst==2002::/64" drop # Check logical flow @@ -4011,7 +6936,7 @@ index 55de7c85b..3515a1e3c 100644 1 ]) -@@ -7938,15 +7920,12 @@ packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && +@@ -7938,15 +7935,12 @@ packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip && udp && udp.src==53 && udp.dst==4369" @@ -4030,7 +6955,7 @@ index 55de7c85b..3515a1e3c 100644 # Expected to drop the packet. $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" pbr-hv/vif2-tx.pcap > vif2.packets -@@ -7956,9 +7935,7 @@ AT_FAIL_IF([test -s vif2.packets]) +@@ -7956,9 +7950,7 @@ AT_FAIL_IF([test -s vif2.packets]) check ovn-nbctl --wait=sb lr-policy-add R1 20 "ip6.src==2001::/64 && ip6.dst==2002::/64" allow # Check logical flow @@ -4041,7 +6966,7 @@ index 55de7c85b..3515a1e3c 100644 2 ]) -@@ -7966,16 +7943,12 @@ AT_CHECK([grep lr_in_policy sbflows2 | grep "2001" | wc -l], [0], [dnl +@@ -7966,16 +7958,12 @@ AT_CHECK([grep lr_in_policy sbflows2 | grep "2001" | wc -l], [0], [dnl packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip && udp && udp.src==53 && udp.dst==4369" @@ -4062,7 +6987,7 @@ index 55de7c85b..3515a1e3c 100644 # Expected packet has TTL decreased by 1 expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac && -@@ -7989,11 +7962,9 @@ OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected]) +@@ -7989,11 +7977,9 @@ OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected]) check ovn-nbctl --wait=sb lr-policy-add R1 30 "ip6.src==2001::/64 && ip6.dst==2002::/64" reroute 2003::2 # Check logical flow @@ -4076,7 +7001,7 @@ index 55de7c85b..3515a1e3c 100644 1 ]) -@@ -8001,19 +7972,12 @@ AT_CHECK([grep lr_in_policy sbflows4 | \ +@@ -8001,19 +7987,12 @@ AT_CHECK([grep lr_in_policy sbflows4 | \ packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip && udp && udp.src==53 && udp.dst==4369" @@ -4100,7 +7025,7 @@ index 55de7c85b..3515a1e3c 100644 # Expected packet has TTL decreased by 1 expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac && -@@ -9531,73 +9495,73 @@ AT_CAPTURE_FILE([sbflows]) +@@ -9531,73 +9510,73 @@ AT_CAPTURE_FILE([sbflows]) packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac && ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip && tcp && tcp.flags==2 && tcp.src==4360 && tcp.dst==80" @@ -4184,9 +7109,86 @@ index 55de7c85b..3515a1e3c 100644 -as hv ovs-appctl -t ovn-controller inject-pkt "$packet" +OVS_WAIT_UNTIL([as hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - OVS_WAIT_UNTIL([ test 8 = $(grep -c 'acl_log' hv/ovn-controller.log) ]) + OVS_WAIT_UNTIL([ test 8 = $(grep -c 'acl_log' hv/ovn-controller.log) ]) + +@@ -10206,14 +10185,21 @@ AT_CHECK([test ! -z $foo2_zoneid]) + bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2) + AT_CHECK([test ! -z $bar2_zoneid]) + +-ovn-nbctl lsp-del bar2 ++# When a port is removed from a logical switch, the ct-zone is flushed, then ++# the ct-zone-id is removed from external_ids. This is done in two steps( ++# ct-zone-id is removed when the transaction flushing the ct_zone is complete). ++# ovn-nbctl --wait=hv sync does not take this into account, and hence we need ++# two "wait=hv" before we are sure that the ct-zone-id is removed from ++# external_ids. ++ovn-nbctl --wait=hv lsp-del bar2 + ovn-nbctl --wait=hv sync + + bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2) + AT_CHECK([test -z $bar2_zoneid]) + + # Add back bar2 +-ovn-nbctl lsp-add bar bar2 vm2 1 \ ++# Same comment as above: two "wait=hv" are needed. ++ovn-nbctl --wait=hv lsp-add bar bar2 vm2 1 \ + -- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3" + wait_for_ports_up + ovn-nbctl --wait=hv sync +@@ -11214,7 +11200,7 @@ hv1_gw1_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=ov + hv1_gw2_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=ovn-gw2-0) + + OVS_WAIT_UNTIL([ +- test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=37 | grep -c "active_backup,ofport,members:$hv1_gw1_ofport,$hv1_gw2_ofport") ++ test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=39 | grep -c "active_backup,ofport,members:$hv1_gw1_ofport,$hv1_gw2_ofport") + ]) + + test_ip_packet() +@@ -11324,7 +11310,7 @@ AT_CHECK( + ]) + + OVS_WAIT_UNTIL([ +- test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=37 | grep -c "active_backup,ofport,members:$hv1_gw2_ofport,$hv1_gw1_ofport") ++ test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=39 | grep -c "active_backup,ofport,members:$hv1_gw2_ofport,$hv1_gw1_ofport") + ]) + + test_ip_packet gw2 gw1 0 +@@ -11502,7 +11488,7 @@ hv1_gw1_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=ov + hv1_gw2_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=ovn-gw2-0) + + OVS_WAIT_UNTIL([ +- test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=37 | grep -c "active_backup,ofport,members:$hv1_gw1_ofport,$hv1_gw2_ofport") ++ test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=39 | grep -c "active_backup,ofport,members:$hv1_gw1_ofport,$hv1_gw2_ofport") + ]) + + test_ip_packet() +@@ -11582,7 +11568,7 @@ AT_CHECK([ovn-nbctl --wait=hv \ + ]) + + OVS_WAIT_UNTIL([ +- test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=37 | grep -c "active_backup,ofport,members:$hv1_gw2_ofport,$hv1_gw1_ofport") ++ test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=39 | grep -c "active_backup,ofport,members:$hv1_gw2_ofport,$hv1_gw1_ofport") + ]) -@@ -12254,7 +12218,7 @@ nexthop_mac="f00000010204" + test_ip_packet gw2 gw1 +@@ -11748,12 +11734,12 @@ AT_CAPTURE_FILE([hv2flows]) + + AT_CHECK( + [# Check that redirect mapping is programmed only on hv2 +- grep table=38 hv1flows | grep =0x3,metadata=0x1 | wc -l +- grep table=38 hv2flows | grep =0x3,metadata=0x1 | grep load:0x2- | wc -l ++ grep table=40 hv1flows | grep =0x3,metadata=0x1 | wc -l ++ grep table=40 hv2flows | grep =0x3,metadata=0x1 | grep load:0x2- | wc -l + + # Check that hv1 sends chassisredirect port traffic to hv2 +- grep table=37 hv1flows | grep =0x3,metadata=0x1 | grep output | wc -l +- grep table=37 hv2flows | grep =0x3,metadata=0x1 | wc -l ++ grep table=39 hv1flows | grep =0x3,metadata=0x1 | grep output | wc -l ++ grep table=39 hv2flows | grep =0x3,metadata=0x1 | wc -l + + # Check that arp reply on distributed gateway port is only programmed on hv2 + grep arp hv1flows | grep load:0x2- | grep =0x2,metadata=0x1 | wc -l +@@ -12254,7 +12240,7 @@ nexthop_mac="f00000010204" AS_BOX([Send ip packet from foo1 to 8.8.8.8]) src_mac="f00000010203" dst_mac="000001010203" @@ -4195,7 +7197,7 @@ index 55de7c85b..3515a1e3c 100644 AS_BOX([Wait for GARPs announcing gw IP to arrive]) OVS_WAIT_UNTIL([ -@@ -12265,15 +12229,12 @@ grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1 +@@ -12265,15 +12251,12 @@ grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1 AS_BOX([Verify VLAN tagged packet on bridge connecting hv1 and hv2]) # VLAN tagged packet with router port(192.168.1.1) MAC as destination MAC # is expected on bridge connecting hv1 and hv2 @@ -4213,7 +7215,18 @@ index 55de7c85b..3515a1e3c 100644 echo $expected > hv3-vif1.expected check as hv1 ovs-appctl dpctl/del-flows -@@ -12304,7 +12265,7 @@ cat hv1-br-ex_n2.expected > expout +@@ -12284,8 +12267,8 @@ as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet + as hv1 ovs-appctl ofproto/trace br-int in_port=hv1-vif1 $packet + sleep 2 + +-AS_BOX([On hv1, table 37 check that no packet goes via the tunnel port]) +-OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=37 \ ++AS_BOX([On hv1, table 40 check that no packet goes via the tunnel port]) ++OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=39 \ + | grep "NXM_NX_TUN_ID" | grep -v n_packets=0 | wc -l], [0], [[0 + ]]) + +@@ -12304,7 +12287,7 @@ cat hv1-br-ex_n2.expected > expout AT_CHECK([sort hv1-br-ex_n2], [0], [expout]) AS_BOX([Check expected packet on nexthop interface]) @@ -4222,20 +7235,30 @@ index 55de7c85b..3515a1e3c 100644 cat hv3-vif1.expected > expout AT_CHECK([sort hv3-vif1], [0], [expout]) -@@ -13268,30 +13229,27 @@ as hv2 ovs-ofctl dump-flows br-int table=37 +@@ -13260,38 +13243,35 @@ echo $hv2_gw1_ofport + echo $hv2_gw2_ofport + + echo "--- hv1 ---" +-as hv1 ovs-ofctl dump-flows br-int table=37 ++as hv1 ovs-ofctl dump-flows br-int table=39 + + echo "--- hv2 ---" +-as hv2 ovs-ofctl dump-flows br-int table=37 ++as hv2 ovs-ofctl dump-flows br-int table=39 + gw1_chassis=$(fetch_column Chassis _uuid name=gw1) gw2_chassis=$(fetch_column Chassis _uuid name=gw2) -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=37 | \ -grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \ -+OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=37 | \ ++OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=39 | \ +grep active_backup | grep members:$hv1_gw1_ofport,$hv1_gw2_ofport \ | wc -l], [0], [1 ]) -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=37 | \ -grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \ -+OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=37 | \ ++OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=39 | \ +grep active_backup | grep members:$hv2_gw1_ofport,$hv2_gw2_ofport \ | wc -l], [0], [1 ]) @@ -4265,25 +7288,25 @@ index 55de7c85b..3515a1e3c 100644 # check that the chassis redirect port has been claimed by the gw1 chassis wait_row_count Port_Binding 1 logical_port=cr-outside chassis=$gw1_chassis -@@ -13314,13 +13272,13 @@ wait_for_ports_up +@@ -13314,13 +13294,13 @@ wait_for_ports_up check ovn-nbctl --wait=hv sync # we make sure that the hypervisors noticed, and inverted the slave ports -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=37 | \ -grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \ -+OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=37 | \ ++OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=39 | \ +grep active_backup | grep members:$hv1_gw2_ofport,$hv1_gw1_ofport \ | wc -l], [0], [1 ]) -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=37 | \ -grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \ -+OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=37 | \ ++OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=39 | \ +grep active_backup | grep members:$hv2_gw2_ofport,$hv2_gw1_ofport \ | wc -l], [0], [1 ]) -@@ -13372,11 +13330,11 @@ AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv1-0],[0], +@@ -13372,11 +13352,11 @@ AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv1-0],[0], ]]) # make sure that flows for handling the outside router port reside on gw2 now @@ -4299,7 +7322,7 @@ index 55de7c85b..3515a1e3c 100644 ]]) # disconnect GW2 from the network, GW1 should take over -@@ -13386,12 +13344,12 @@ as main ovs-vsctl del-port n1 $port +@@ -13386,12 +13366,12 @@ as main ovs-vsctl del-port n1 $port bfd_dump @@ -4317,14 +7340,14 @@ index 55de7c85b..3515a1e3c 100644 ]]) # check that the chassis redirect port has been reclaimed by the gw1 chassis -@@ -13470,45 +13428,16 @@ ovn-nbctl set Logical_Router_Port outside ha_chassis_group=$hagrp1_uuid +@@ -13470,45 +13450,16 @@ ovn-nbctl set Logical_Router_Port outside ha_chassis_group=$hagrp1_uuid wait_row_count HA_Chassis_Group 1 wait_row_count HA_Chassis 2 -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=37 | \ -grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \ -| wc -l], [0], [1 -+OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=37 | \ ++OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=39 | \ +grep active_backup | grep members:$hv1_gw1_ofport,$hv1_gw2_ofport \ +| wc -l], [0], [0 ]) @@ -4332,7 +7355,7 @@ index 55de7c85b..3515a1e3c 100644 -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=37 | \ -grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \ -| wc -l], [0], [1 -+OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=37 | \ ++OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=39 | \ +grep active_backup | grep members:$hv2_gw1_ofport,$hv2_gw2_ofport \ +| wc -l], [0], [0 ]) @@ -4369,19 +7392,19 @@ index 55de7c85b..3515a1e3c 100644 # Re add the ovs ports. for i in 1 2; do as hv$i -@@ -13519,6 +13448,34 @@ for i in 1 2; do +@@ -13519,6 +13470,34 @@ for i in 1 2; do ofport-request=1 done +# Re-add gw2 +as gw2 ovn_attach n1 br-phys 192.168.0.1 + -+OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=37 | \ ++OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=39 | \ +grep active_backup | grep members:$hv1_gw1_ofport,$hv1_gw2_ofport \ +| wc -l], [0], [1 +]) + -+OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=37 | \ ++OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=39 | \ +grep active_backup | grep members:$hv2_gw1_ofport,$hv2_gw2_ofport \ +| wc -l], [0], [1 +]) @@ -4404,20 +7427,20 @@ index 55de7c85b..3515a1e3c 100644 hv1_ch_uuid=$(fetch_column Chassis _uuid name=hv1) hv2_ch_uuid=$(fetch_column Chassis _uuid name=hv2) exp_ref_ch_list="$hv1_ch_uuid $hv2_ch_uuid" -@@ -13527,29 +13484,18 @@ wait_column "$exp_ref_ch_list" HA_Chassis_Group ref_chassis +@@ -13527,29 +13506,18 @@ wait_column "$exp_ref_ch_list" HA_Chassis_Group ref_chassis # Increase the priority of gw2 ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 40 -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=37 | \ -grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \ -+OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=37 | \ ++OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=39 | \ +grep active_backup | grep members:$hv1_gw2_ofport,$hv1_gw1_ofport \ | wc -l], [0], [1 ]) -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=37 | \ -grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \ -+OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=37 | \ ++OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=39 | \ +grep active_backup | grep members:$hv2_gw2_ofport,$hv2_gw1_ofport \ | wc -l], [0], [1 ]) @@ -4439,7 +7462,7 @@ index 55de7c85b..3515a1e3c 100644 # check BFD enablement on tunnel ports from gw1 ######### as gw1 -@@ -13588,11 +13534,11 @@ AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv1-0],[0], +@@ -13588,11 +13556,11 @@ AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv1-0],[0], ]]) # make sure that flows for handling the outside router port reside on gw2 now @@ -4455,7 +7478,7 @@ index 55de7c85b..3515a1e3c 100644 ]]) # disconnect GW2 from the network, GW1 should take over -@@ -13603,11 +13549,11 @@ as main ovs-vsctl del-port n1 $port +@@ -13603,11 +13571,11 @@ as main ovs-vsctl del-port n1 $port bfd_dump # make sure that flows for handling the outside router port reside on gw2 now @@ -4471,7 +7494,7 @@ index 55de7c85b..3515a1e3c 100644 ]]) # check that the chassis redirect port has been reclaimed by the gw1 chassis -@@ -13889,6 +13835,133 @@ OVN_CLEANUP([gw1],[gw2],[hv1]) +@@ -13889,6 +13857,133 @@ OVN_CLEANUP([gw1],[gw2],[hv1]) AT_CLEANUP ]) @@ -4605,7 +7628,390 @@ index 55de7c85b..3515a1e3c 100644 OVN_FOR_EACH_NORTHD([ AT_SETUP([IPv6 Neighbor Solicitation for unknown MAC]) AT_KEYWORDS([ovn-nd_ns for unknown mac]) -@@ -17210,7 +17283,7 @@ test_icmp() { +@@ -14162,10 +14257,12 @@ wait_column "$hv1_uuid" Port_Binding requested_chassis logical_port=lsp0 + wait_column "$hv2_uuid" Port_Binding additional_chassis logical_port=lsp0 + wait_column "$hv2_uuid" Port_Binding requested_additional_chassis logical_port=lsp0 + +-# Check ovn-installed updated for main chassis ++# Check ovn-installed updated for both chassis + wait_for_ports_up +-OVS_WAIT_UNTIL([test `as hv1 ovs-vsctl get Interface lsp0 external_ids:ovn-installed` = '"true"']) +-OVS_WAIT_UNTIL([test x`as hv2 ovs-vsctl get Interface lsp0 external_ids:ovn-installed` = x]) ++ ++for hv in hv1 hv2; do ++ OVS_WAIT_UNTIL([test `as $hv ovs-vsctl get Interface lsp0 external_ids:ovn-installed` = '"true"']) ++done + + # Check that setting iface:encap-ip populates Port_Binding:additional_encap + wait_row_count Encap 2 chassis_name=hv1 +@@ -14192,7 +14289,7 @@ wait_column "$hv2_uuid" Port_Binding requested_chassis logical_port=lsp0 + wait_column "" Port_Binding additional_chassis logical_port=lsp0 + wait_column "" Port_Binding requested_additional_chassis logical_port=lsp0 + +-# Check ovn-installed updated for main chassis and not for other chassis ++# Check ovn-installed updated for main chassis and removed from additional chassis + wait_for_ports_up + OVS_WAIT_UNTIL([test `as hv2 ovs-vsctl get Interface lsp0 external_ids:ovn-installed` = '"true"']) + OVS_WAIT_UNTIL([test x`as hv1 ovs-vsctl get Interface lsp0 external_ids:ovn-installed` = x]) +@@ -15071,6 +15168,327 @@ OVN_CLEANUP([hv1],[hv2],[hv3]) + AT_CLEANUP + ]) + ++m4_define([MULTICHASSIS_PATH_MTU_DISCOVERY_TEST], ++ [OVN_FOR_EACH_NORTHD([ ++ AT_SETUP([localnet connectivity with multiple requested-chassis, path mtu discovery (ip=$1, tunnel=$2, mtu=$3)]) ++ AT_KEYWORDS([multi-chassis]) ++ AT_SKIP_IF([test $HAVE_SCAPY = no]) ++ ++ ovn_start ++ ++ net_add n1 ++ for i in 1 2; do ++ sim_add hv$i ++ as hv$i ++ check ovs-vsctl add-br br-phys ++ if test "x$1" = "xipv6"; then ++ ovn_attach n1 br-phys fd00::$i 64 $2 ++ else ++ ovn_attach n1 br-phys 192.168.0.$i 24 $2 ++ fi ++ check ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys ++ done ++ ++ first_mac=00:00:00:00:00:01 ++ second_mac=00:00:00:00:00:02 ++ multi1_mac=00:00:00:00:00:f0 ++ multi2_mac=00:00:00:00:00:f1 ++ first_ip=10.0.0.1 ++ second_ip=10.0.0.2 ++ multi1_ip=10.0.0.10 ++ multi2_ip=10.0.0.20 ++ first_ip6=abcd::1 ++ second_ip6=abcd::2 ++ multi1_ip6=abcd::f0 ++ multi2_ip6=abcd::f1 ++ ++ check ovn-nbctl ls-add ls0 ++ check ovn-nbctl lsp-add ls0 first ++ check ovn-nbctl lsp-add ls0 second ++ check ovn-nbctl lsp-add ls0 multi1 ++ check ovn-nbctl lsp-add ls0 multi2 ++ check ovn-nbctl lsp-set-addresses first "${first_mac} ${first_ip} ${first_ip6}" ++ check ovn-nbctl lsp-set-addresses second "${second_mac} ${second_ip} ${second_ip6}" ++ check ovn-nbctl lsp-set-addresses multi1 "${multi1_mac} ${multi1_ip} ${multi1_ip6}" ++ check ovn-nbctl lsp-set-addresses multi2 "${multi2_mac} ${multi2_ip} ${multi2_ip6}" ++ ++ check ovn-nbctl lsp-add ls0 public ++ check ovn-nbctl lsp-set-type public localnet ++ check ovn-nbctl lsp-set-addresses public unknown ++ check ovn-nbctl lsp-set-options public network_name=phys ++ ++ check ovn-nbctl lsp-set-options first requested-chassis=hv1 ++ check ovn-nbctl lsp-set-options second requested-chassis=hv2 ++ check ovn-nbctl lsp-set-options multi1 requested-chassis=hv1,hv2 ++ check ovn-nbctl lsp-set-options multi2 requested-chassis=hv1,hv2 ++ ++ as hv1 check ovs-vsctl -- add-port br-int first -- \ ++ set Interface first external-ids:iface-id=first \ ++ options:tx_pcap=hv1/first-tx.pcap \ ++ options:rxq_pcap=hv1/first-rx.pcap \ ++ ofport-request=1 ++ as hv2 check ovs-vsctl -- add-port br-int second -- \ ++ set Interface second external-ids:iface-id=second \ ++ options:tx_pcap=hv2/second-tx.pcap \ ++ options:rxq_pcap=hv2/second-rx.pcap \ ++ ofport-request=2 ++ ++ # Create interfaces for multichassis ports on both hv1 and hv2 ++ for hv in hv1 hv2; do ++ for i in 1 2; do ++ as $hv check ovs-vsctl -- add-port br-int multi${i} -- \ ++ set Interface multi${i} external-ids:iface-id=multi${i} \ ++ options:tx_pcap=$hv/multi${i}-tx.pcap \ ++ options:rxq_pcap=$hv/multi${i}-rx.pcap \ ++ ofport-request=${i}00 ++ done ++ done ++ ++ send_ip_packet() { ++ local inport=${1} hv=${2} eth_src=${3} eth_dst=${4} ipv4_src=${5} ipv4_dst=${6} data=${7} fail=${8} mtu=${9:-$3} ++ packet=$(fmt_pkt " ++ Ether(dst='${eth_dst}', src='${eth_src}') / ++ IP(src='${ipv4_src}', dst='${ipv4_dst}') / ++ ICMP(type=8) / bytes.fromhex('${data}') ++ ") ++ as hv${hv} ovs-appctl netdev-dummy/receive ${inport} ${packet} ++ if [[ x"${fail}" != x0 ]]; then ++ original_ip_frame=$(fmt_pkt " ++ IP(src='${ipv4_src}', dst='${ipv4_dst}') / ++ ICMP(type=8) / bytes.fromhex('${data}') ++ ") ++ # IP(flags=2) means DF (Don't Fragment) = 1 ++ # ICMP(type=3, code=4) means Destination Unreachable, Fragmentation Needed ++ packet=$(fmt_pkt " ++ Ether(dst='${eth_src}', src='${eth_dst}') / ++ IP(src='${ipv4_dst}', dst='${ipv4_src}', ttl=255, flags=2, id=0) / ++ ICMP(type=3, code=4, nexthopmtu=${mtu}) / ++ bytes.fromhex('${original_ip_frame:0:$((534 * 2))}') ++ ") ++ fi ++ echo ${packet} ++ } ++ ++ send_ip6_packet() { ++ local inport=${1} hv=${2} eth_src=${3} eth_dst=${4} ipv6_src=${5} ipv6_dst=${6} data=${7} fail=${8} mtu=${9:-$3} ++ packet=$(fmt_pkt " ++ Ether(dst='${eth_dst}', src='${eth_src}') / ++ IPv6(src='${ipv6_src}', dst='${ipv6_dst}') / ++ ICMPv6EchoRequest() / bytes.fromhex('${data}') ++ ") ++ as hv${hv} ovs-appctl netdev-dummy/receive ${inport} ${packet} ++ if [[ x"${fail}" != x0 ]]; then ++ original_ip_frame=$(fmt_pkt " ++ IPv6(src='${ipv6_src}', dst='${ipv6_dst}') / ++ ICMPv6EchoRequest() / bytes.fromhex('${data}') ++ ") ++ packet=$(fmt_pkt " ++ Ether(dst='${eth_src}', src='${eth_dst}') / ++ IPv6(src='${ipv6_dst}', dst='${ipv6_src}', hlim=255) / ++ ICMPv6PacketTooBig(mtu=${mtu}) / ++ bytes.fromhex('${original_ip_frame:0:$((1218 * 2))}') ++ ") ++ fi ++ echo ${packet} ++ } ++ ++ reset_env() { ++ for port in first multi1 multi2; do ++ as hv1 reset_pcap_file $port hv1/$port ++ done ++ for port in second multi1 multi2; do ++ as hv2 reset_pcap_file $port hv2/$port ++ done ++ for port in hv1/multi1 hv2/multi1 hv1/multi2 hv2/multi2 hv1/first hv2/second; do ++ : > $port.expected ++ done ++ } ++ ++ check_pkts() { ++ for port in hv1/multi1 hv2/multi1 hv1/multi2 hv2/multi2 hv1/first hv2/second; do ++ OVN_CHECK_PACKETS_REMOVE_BROADCAST([${port}-tx.pcap], [${port}.expected]) ++ done ++ } ++ ++ payload() { ++ echo $(cat /dev/urandom | tr -cd 'a-f0-9' | head -c ${1}) ++ } ++ ++ wait_for_ports_up ++ OVN_POPULATE_ARP ++ ++ reset_env ++ ++ AS_BOX([Packets of proper size are delivered from multichassis to regular ports]) ++ ++ len=1000 ++ packet=$(send_ip_packet multi1 1 $multi1_mac $first_mac $multi1_ip $first_ip $(payload $len) 0) ++ echo $packet >> hv1/first.expected ++ ++ packet=$(send_ip_packet multi1 1 $multi1_mac $second_mac $multi1_ip $second_ip $(payload $len) 0) ++ echo $packet >> hv2/second.expected ++ ++ packet=$(send_ip6_packet multi1 1 $multi1_mac $first_mac $multi1_ip6 $first_ip6 $(payload $len) 0) ++ echo $packet >> hv1/first.expected ++ ++ packet=$(send_ip6_packet multi1 1 $multi1_mac $second_mac $multi1_ip6 $second_ip6 $(payload $len) 0) ++ echo $packet >> hv2/second.expected ++ ++ check_pkts ++ reset_env ++ ++ AS_BOX([Oversized packets are not delivered from multichassis to regular ports]) ++ ++ len=3000 ++ packet=$(send_ip_packet multi1 1 $multi1_mac $first_mac $multi1_ip $first_ip $(payload $len) 1) ++ echo $packet >> hv1/multi1.expected ++ ++ packet=$(send_ip_packet multi1 1 $multi1_mac $second_mac $multi1_ip $second_ip $(payload $len) 1) ++ echo $packet >> hv1/multi1.expected ++ ++ packet=$(send_ip6_packet multi1 1 $multi1_mac $first_mac $multi1_ip6 $first_ip6 $(payload $len) 1) ++ echo $packet >> hv1/multi1.expected ++ ++ packet=$(send_ip6_packet multi1 1 $multi1_mac $second_mac $multi1_ip6 $second_ip6 $(payload $len) 1) ++ echo $packet >> hv1/multi1.expected ++ ++ check_pkts ++ reset_env ++ ++ AS_BOX([Packets of proper size are delivered from regular to multichassis ports]) ++ ++ len=1000 ++ packet=$(send_ip_packet first 1 $first_mac $multi1_mac $first_ip $multi1_ip $(payload $len) 0) ++ echo $packet >> hv1/multi1.expected ++ echo $packet >> hv2/multi1.expected ++ ++ packet=$(send_ip_packet second 2 $second_mac $multi1_mac $second_ip $multi1_ip $(payload $len) 0) ++ echo $packet >> hv1/multi1.expected ++ echo $packet >> hv2/multi1.expected ++ ++ packet=$(send_ip6_packet first 1 $first_mac $multi1_mac $first_ip6 $multi1_ip6 $(payload $len) 0) ++ echo $packet >> hv1/multi1.expected ++ echo $packet >> hv2/multi1.expected ++ ++ packet=$(send_ip6_packet second 2 $second_mac $multi1_mac $second_ip6 $multi1_ip6 $(payload $len) 0) ++ echo $packet >> hv1/multi1.expected ++ echo $packet >> hv2/multi1.expected ++ ++ check_pkts ++ reset_env ++ ++ AS_BOX([Oversized packets are not delivered from regular to multichassis ports]) ++ ++ len=3000 ++ packet=$(send_ip_packet first 1 $first_mac $multi1_mac $first_ip $multi1_ip $(payload $len) 1) ++ echo $packet >> hv1/first.expected ++ ++ packet=$(send_ip_packet second 2 $second_mac $multi1_mac $second_ip $multi1_ip $(payload $len) 1) ++ echo $packet >> hv2/second.expected ++ ++ packet=$(send_ip6_packet first 1 $first_mac $multi1_mac $first_ip6 $multi1_ip6 $(payload $len) 1) ++ echo $packet >> hv1/first.expected ++ ++ packet=$(send_ip6_packet second 2 $second_mac $multi1_mac $second_ip6 $multi1_ip6 $(payload $len) 1) ++ echo $packet >> hv2/second.expected ++ ++ check_pkts ++ reset_env ++ ++ AS_BOX([Packets of proper size are delivered from multichassis to multichassis ports]) ++ ++ len=1000 ++ packet=$(send_ip_packet multi1 1 $multi1_mac $multi2_mac $multi1_ip $multi2_ip $(payload $len) 0) ++ echo $packet >> hv1/multi2.expected ++ echo $packet >> hv2/multi2.expected ++ ++ packet=$(send_ip6_packet multi1 1 $multi1_mac $multi2_mac $multi1_ip6 $multi2_ip6 $(payload $len) 0) ++ echo $packet >> hv1/multi2.expected ++ echo $packet >> hv2/multi2.expected ++ ++ check_pkts ++ reset_env ++ ++ AS_BOX([Oversized packets are not delivered from multichassis to multichassis ports]) ++ ++ len=3000 ++ packet=$(send_ip_packet multi1 1 $multi1_mac $multi2_mac $multi1_ip $multi2_ip $(payload $len) 1) ++ echo $packet >> hv1/multi1.expected ++ ++ packet=$(send_ip6_packet multi1 1 $multi1_mac $multi2_mac $multi1_ip6 $multi2_ip6 $(payload $len) 1) ++ echo $packet >> hv1/multi1.expected ++ ++ check_pkts ++ reset_env ++ ++ AS_BOX([MTU updates are honored in ICMP Path MTU calculation]) ++ ++ set_mtu() { ++ local hv=${1} iface=${2} new_mtu=${3} ++ ++ iface_uuid=$(as ${hv} ovs-vsctl --bare --columns _uuid find Interface name=${iface}) ++ check as ${hv} ovs-vsctl set interface ${iface_uuid} mtu_request=${new_mtu} ++ } ++ ++ set_mtu_for_all_ports() { ++ for port in multi1 multi2 first; do ++ set_mtu hv1 ${port} ${1} ++ done ++ for port in multi1 multi2 second; do ++ set_mtu hv2 ${port} ${1} ++ done ++ } ++ ++ initial_mtu=1500 # all interfaces are 1500 by default ++ new_mtu=1400 ++ set_mtu_for_all_ports ${new_mtu} ++ mtu_diff=$((${initial_mtu} - ${new_mtu})) ++ ++ len=3000 ++ expected_ip_mtu=$(($3 - ${mtu_diff})) ++ packet=$(send_ip_packet first 1 $first_mac $multi1_mac $first_ip $multi1_ip $(payload $len) 1 ${expected_ip_mtu}) ++ echo $packet >> hv1/first.expected ++ ++ packet=$(send_ip_packet second 2 $second_mac $multi1_mac $second_ip $multi1_ip $(payload $len) 1 ${expected_ip_mtu}) ++ echo $packet >> hv2/second.expected ++ ++ packet=$(send_ip6_packet first 1 $first_mac $multi1_mac $first_ip6 $multi1_ip6 $(payload $len) 1 ${expected_ip_mtu}) ++ echo $packet >> hv1/first.expected ++ ++ packet=$(send_ip6_packet second 2 $second_mac $multi1_mac $second_ip6 $multi1_ip6 $(payload $len) 1 ${expected_ip_mtu}) ++ echo $packet >> hv2/second.expected ++ ++ packet=$(send_ip_packet multi1 1 $multi1_mac $first_mac $multi1_ip $first_ip $(payload $len) 1 ${expected_ip_mtu}) ++ echo $packet >> hv1/multi1.expected ++ ++ packet=$(send_ip_packet multi1 1 $multi1_mac $second_mac $multi1_ip $second_ip $(payload $len) 1 ${expected_ip_mtu}) ++ echo $packet >> hv1/multi1.expected ++ ++ packet=$(send_ip6_packet multi1 1 $multi1_mac $first_mac $multi1_ip6 $first_ip6 $(payload $len) 1 ${expected_ip_mtu}) ++ echo $packet >> hv1/multi1.expected ++ ++ packet=$(send_ip6_packet multi1 1 $multi1_mac $second_mac $multi1_ip6 $second_ip6 $(payload $len) 1 ${expected_ip_mtu}) ++ echo $packet >> hv1/multi1.expected ++ ++ packet=$(send_ip_packet multi1 1 $multi1_mac $multi2_mac $multi1_ip $multi2_ip $(payload $len) 1 ${expected_ip_mtu}) ++ echo $packet >> hv1/multi1.expected ++ ++ packet=$(send_ip6_packet multi1 1 $multi1_mac $multi2_mac $multi1_ip6 $multi2_ip6 $(payload $len) 1 ${expected_ip_mtu}) ++ echo $packet >> hv1/multi1.expected ++ ++ check_pkts ++ ++ OVN_CLEANUP([hv1],[hv2]) ++ ++ AT_CLEANUP ++ ])]) ++ ++# NOTE(ihar) no STT variants because it's not supported by upstream kernels ++MULTICHASSIS_PATH_MTU_DISCOVERY_TEST([ipv4], [geneve], [1424]) ++MULTICHASSIS_PATH_MTU_DISCOVERY_TEST([ipv6], [geneve], [1404]) ++MULTICHASSIS_PATH_MTU_DISCOVERY_TEST([ipv4], [vxlan], [1432]) ++MULTICHASSIS_PATH_MTU_DISCOVERY_TEST([ipv6], [vxlan], [1412]) ++ + OVN_FOR_EACH_NORTHD([ + AT_SETUP([options:activation-strategy for logical port]) + AT_KEYWORDS([multi-chassis]) +@@ -16278,25 +16696,25 @@ sleep 2 + # Get total number of ipv4 packets that received on ovs + + # sender side +-flow=$(as hv1 ovs-ofctl dump-flows br-int table=44 | grep priority=2002|grep ip,metadata=0x1) ++flow=$(as hv1 ovs-ofctl dump-flows br-int table=46 | grep priority=2002|grep ip,metadata=0x1) + n_pkts="$(echo $flow|awk -F',' '{ print $4 }'|awk -F'=' '{ print $2 }')" + check test $n_pkts -eq 1 + + # receiver side +-flow=$(as hv2 ovs-ofctl dump-flows br-int table=44 | grep priority=2002|grep ip,metadata=0x1) ++flow=$(as hv2 ovs-ofctl dump-flows br-int table=46 | grep priority=2002|grep ip,metadata=0x1) + n_pkts="$(echo $flow|awk -F',' '{ print $4 }'|awk -F'=' '{ print $2 }')" + check test $n_pkts -eq 1 + + # Get total number of ipv6 packets that received on ovs + + # sender side +-flow=$(as hv1 ovs-ofctl dump-flows br-int table=44 | grep priority=2002|grep ipv6,metadata=0x1) ++flow=$(as hv1 ovs-ofctl dump-flows br-int table=46 | grep priority=2002|grep ipv6,metadata=0x1) + n_pkts="$(echo $flow|awk -F',' '{ print $4 }'|awk -F'=' '{ print $2 }')" + check test $n_pkts -eq 1 + + + # receiver side +-flow=$(as hv2 ovs-ofctl dump-flows br-int table=44 | grep priority=2002|grep ipv6,metadata=0x1) ++flow=$(as hv2 ovs-ofctl dump-flows br-int table=46 | grep priority=2002|grep ipv6,metadata=0x1) + n_pkts="$(echo $flow|awk -F',' '{ print $4 }'|awk -F'=' '{ print $2 }')" + check test $n_pkts -eq 1 + +@@ -17210,7 +17628,7 @@ test_icmp() { icmp4.code==0" shift; shift; shift; shift; shift; shift hv=hv`vif_to_hv $inport` @@ -4614,7 +8020,165 @@ index 55de7c85b..3515a1e3c 100644 in_ls=`vif_to_ls $inport` in_lrp=`vif_to_lrp $inport` for outport; do -@@ -18276,7 +18349,7 @@ AT_SETUP([TTL exceeded]) +@@ -17856,17 +18274,17 @@ check ovn-nbctl acl-add ls1 to-lport 3 'ip4.src==10.0.0.1' allow + check ovn-nbctl --wait=hv sync + + # Check OVS flows, the less restrictive flows should have been installed. +-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ ++AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | \ + grep "priority=1003" | \ + sed 's/conjunction([[^)]]*)/conjunction()/g' | \ + sed 's/conj_id=[[0-9]]*,/conj_id=xxx,/g' | sort], [0], [dnl +- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) +- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) +- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45) +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ++ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) ++ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) ++ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,47) ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() + ]) + + # Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed. +@@ -17901,17 +18319,17 @@ check ovn-nbctl acl-del ls1 to-lport 3 'ip4.src==10.0.0.1 || ip4.src==10.0.0.1' + check ovn-nbctl --wait=hv sync + + # Check OVS flows, the second less restrictive allow ACL should have been installed. +-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ ++AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | \ + grep "priority=1003" | \ + sed 's/conjunction([[^)]]*)/conjunction()/g' | \ + sed 's/conj_id=[[0-9]]*,/conj_id=xxx,/g' | sort], [0], [dnl +- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) +- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) +- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45) +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ++ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) ++ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) ++ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,47) ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() + ]) + + # Remove the less restrictive allow ACL. +@@ -17919,17 +18337,17 @@ check ovn-nbctl acl-del ls1 to-lport 3 'ip4.src==10.0.0.1' + check ovn-nbctl --wait=hv sync + + # Check OVS flows, the 10.0.0.1 conjunction should have been reinstalled. +-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ ++AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | \ + grep "priority=1003" | \ + sed 's/conjunction([[^)]]*)/conjunction()/g' | \ + sed 's/conj_id=[[0-9]]*,/conj_id=xxx,/g' | sort], [0], [dnl +- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) +- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) +- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(),conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ++ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) ++ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) ++ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(),conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() + ]) + + # Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed. +@@ -17959,17 +18377,17 @@ check ovn-nbctl acl-add ls1 to-lport 3 'ip4.src==10.0.0.1' allow + check ovn-nbctl --wait=hv sync + + # Check OVS flows, the less restrictive flows should have been installed. +-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ ++AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | \ + grep "priority=1003" | \ + sed 's/conjunction([[^)]]*)/conjunction()/g' | \ + sed 's/conj_id=[[0-9]]*,/conj_id=xxx,/g' | sort], [0], [dnl +- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) +- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) +- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45) +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ++ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) ++ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) ++ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,47) ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() + ]) + + # Add another ACL that overlaps with the existing less restrictive ones. +@@ -17980,20 +18398,20 @@ check ovn-nbctl --wait=hv sync + # with an additional conjunction action. + # + # New non-conjunctive flows should be added to match on 'udp'. +-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ ++AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | \ + grep "priority=1003" | \ + sed 's/conjunction([[^)]]*)/conjunction()/g' | \ + sed 's/conj_id=[[0-9]]*,/conj_id=xxx,/g' | sort], [0], [dnl +- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) +- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) +- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) +- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction(),conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction(),conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45) +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction(),conjunction() +- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() +- table=44, priority=1003,udp,metadata=0x1 actions=resubmit(,45) +- table=44, priority=1003,udp6,metadata=0x1 actions=resubmit(,45) ++ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) ++ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) ++ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) ++ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction(),conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction(),conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,47) ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction(),conjunction() ++ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ++ table=46, priority=1003,udp,metadata=0x1 actions=resubmit(,47) ++ table=46, priority=1003,udp6,metadata=0x1 actions=resubmit(,47) + ]) + + OVN_CLEANUP([hv1]) +@@ -18048,17 +18466,17 @@ check ovn-nbctl acl-add pg1 to-lport 100 'outport == @pg1 && ip4.src == $as2' al + + wait_for_ports_up + check ovn-nbctl --wait=hv sync +-ovs-ofctl dump-flows br-int table=44 +-AT_CHECK([test `ovs-ofctl dump-flows br-int table=44 | grep -c conj_id` = 2]) ++ovs-ofctl dump-flows br-int table=46 ++AT_CHECK([test `ovs-ofctl dump-flows br-int table=46 | grep -c conj_id` = 2]) + + echo ------- + # Add another address in as1, so that the 1st ACL will now generate 2 conjunctions. + ovn-nbctl set address_set as1 addresses="10.0.0.1,10.0.0.2" + check ovn-nbctl --wait=hv sync + +-ovs-ofctl dump-flows br-int table=44 ++ovs-ofctl dump-flows br-int table=46 + # There should be 3 conjunctions in total (2 from 1st ACL + 1 from 2nd ACL) +-AT_CHECK([test `ovs-ofctl dump-flows br-int table=44 | grep -c conj_id` = 3]) ++AT_CHECK([test `ovs-ofctl dump-flows br-int table=46 | grep -c conj_id` = 3]) + + OVN_CLEANUP([hv1]) + AT_CLEANUP +@@ -18276,7 +18694,7 @@ AT_SETUP([TTL exceeded]) AT_KEYWORDS([ttl-exceeded]) ovn_start @@ -4623,7 +8187,7 @@ index 55de7c85b..3515a1e3c 100644 # # Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv4 packet with # ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified and TTL set to 1. -@@ -18292,6 +18365,7 @@ test_ip_packet() { +@@ -18292,6 +18710,7 @@ test_ip_packet() { local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6 ip_router=$7 ip_chksum=$8 local exp_ip_chksum=$9 exp_icmp_chksum=${10} shift 10 @@ -4631,7 +8195,7 @@ index 55de7c85b..3515a1e3c 100644 local ip_ttl=01 local packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst} -@@ -18300,27 +18374,31 @@ test_ip_packet() { +@@ -18300,27 +18719,31 @@ test_ip_packet() { local icmp_type_code_response=0b00 local icmp_data=00000000 local reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data} @@ -4669,7 +8233,7 @@ index 55de7c85b..3515a1e3c 100644 as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet } -@@ -18343,6 +18421,8 @@ for i in 1 2; do +@@ -18343,6 +18766,8 @@ for i in 1 2; do options:tx_pcap=hv$i/vif$i-tx.pcap \ options:rxq_pcap=hv$i/vif$i-rx.pcap \ ofport-request=$i @@ -4678,7 +8242,7 @@ index 55de7c85b..3515a1e3c 100644 done ovn-nbctl lr-add lr0 -@@ -18358,10 +18438,22 @@ OVN_POPULATE_ARP +@@ -18358,10 +18783,22 @@ OVN_POPULATE_ARP wait_for_ports_up ovn-nbctl --wait=hv sync @@ -4703,7 +8267,7 @@ index 55de7c85b..3515a1e3c 100644 OVN_CLEANUP([hv1], [hv2]) AT_CLEANUP ]) -@@ -18656,7 +18748,7 @@ packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac && eth.dst==$sw1_ro_mac && +@@ -18656,7 +19093,7 @@ packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac && eth.dst==$sw1_ro_mac && udp && udp.src==53 && udp.dst==4369" # Start by Sending the packet and make sure it makes it there as expected @@ -4712,7 +8276,7 @@ index 55de7c85b..3515a1e3c 100644 # Expected packet has TTL decreased by 1 expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac && -@@ -18670,7 +18762,7 @@ OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) +@@ -18670,7 +19107,7 @@ OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) as hv2 ovs-appctl -t ovn-controller exit # Now send the packet again. This time, it should not arrive. @@ -4721,7 +8285,7 @@ index 55de7c85b..3515a1e3c 100644 OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) -@@ -19552,7 +19644,7 @@ packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac && eth.dst==$sw1_ro_mac && +@@ -19552,7 +19989,7 @@ packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac && eth.dst==$sw1_ro_mac && udp && udp.src==53 && udp.dst==4369" # Start by Sending the packet and make sure it makes it there as expected @@ -4730,7 +8294,7 @@ index 55de7c85b..3515a1e3c 100644 # Expected packet has TTL decreased by 1 expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac && -@@ -19566,7 +19658,7 @@ OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) +@@ -19566,7 +20003,7 @@ OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) as hv2 ovs-appctl -t ovn-controller exit --restart # Now send the packet again. This time, it should still arrive @@ -4739,7 +8303,7 @@ index 55de7c85b..3515a1e3c 100644 cat expected expected > expected2 -@@ -19705,7 +19797,7 @@ test_ip_packet_larger() { +@@ -19705,7 +20142,7 @@ test_ip_packet_larger() { # Set the packet length to 114. pkt_len=0072 packet=${dst_mac}${src_mac}08004500${pkt_len}000000004001c3dd @@ -4748,7 +8312,7 @@ index 55de7c85b..3515a1e3c 100644 orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 -@@ -19729,10 +19821,10 @@ test_ip_packet_larger() { +@@ -19729,10 +20166,10 @@ test_ip_packet_larger() { # Packet to expect at br-phys. src_mac="000020201213" dst_mac="00000012af11" @@ -4762,7 +8326,7 @@ index 55de7c85b..3515a1e3c 100644 expected=${expected}000000000000000000000000000000000000 expected=${expected}000000000000000000000000000000000000 expected=${expected}000000000000000000000000000000000000 -@@ -19793,7 +19885,7 @@ test_ip_packet_larger_ext() { +@@ -19793,7 +20230,7 @@ test_ip_packet_larger_ext() { # Set the packet length to 114. pkt_len=0072 packet=${dst_mac}${src_mac}08004500${pkt_len}000000004001${checksum} @@ -4771,7 +8335,7 @@ index 55de7c85b..3515a1e3c 100644 orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 -@@ -19810,7 +19902,7 @@ test_ip_packet_larger_ext() { +@@ -19810,7 +20247,7 @@ test_ip_packet_larger_ext() { dst_ip=`ip_to_hex 172 168 0 4` # pkt len should be 146 (28 (icmp packet) + 118 (orig ip + payload)) reply_pkt_len=008e @@ -4780,7 +8344,7 @@ index 55de7c85b..3515a1e3c 100644 icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe01${reply_checksum} icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000$(printf "%04x" $mtu) icmp_reply=${icmp_reply}4500${pkt_len}000000004001${checksum} -@@ -19985,10 +20077,10 @@ OVS_WAIT_FOR_OUTPUT([ +@@ -19985,10 +20422,10 @@ OVS_WAIT_FOR_OUTPUT([ ]) AS_BOX([testing ingress traffic mtu 100 - IPv4]) @@ -4793,7 +8357,7 @@ index 55de7c85b..3515a1e3c 100644 AS_BOX([testing ingress traffic mtu 100 - IPv6]) test_ip6_packet_larger_ext 1 000020201213 20000000000000000000000000000001 100 cc7a -@@ -20055,10 +20147,10 @@ OVS_WAIT_FOR_OUTPUT([ +@@ -20055,10 +20492,10 @@ OVS_WAIT_FOR_OUTPUT([ ]) AS_BOX([testing ingress traffic mtu 100 for gw router - IPv4]) @@ -4806,7 +8370,29 @@ index 55de7c85b..3515a1e3c 100644 OVN_CLEANUP([hv1]) AT_CLEANUP -@@ -21116,7 +21208,7 @@ check_virtual_offlows_not_present hv2 +@@ -21012,9 +21449,9 @@ check_virtual_offlows_present() { + lr0_dp_key=$(printf "%x" $(fetch_column Datapath_Binding tunnel_key external_ids:name=lr0)) + lr0_public_dp_key=$(printf "%x" $(fetch_column Port_Binding tunnel_key logical_port=lr0-public)) + +- AT_CHECK_UNQUOTED([as $hv ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | grep "priority=2000"], [0], [dnl +- table=44, priority=2000,ip,metadata=0x$sw0_dp_key actions=resubmit(,45) +- table=44, priority=2000,ipv6,metadata=0x$sw0_dp_key actions=resubmit(,45) ++ AT_CHECK_UNQUOTED([as $hv ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | grep "priority=2000"], [0], [dnl ++ table=46, priority=2000,ip,metadata=0x$sw0_dp_key actions=resubmit(,47) ++ table=46, priority=2000,ipv6,metadata=0x$sw0_dp_key actions=resubmit(,47) + ]) + + AT_CHECK_UNQUOTED([as $hv ovs-ofctl dump-flows br-int table=11 | ofctl_strip_all | \ +@@ -21025,7 +21462,7 @@ check_virtual_offlows_present() { + + check_virtual_offlows_not_present() { + hv=$1 +- AT_CHECK([as $hv ovs-ofctl dump-flows br-int table=45 | ofctl_strip_all | grep "priority=2000"], [1], [dnl ++ AT_CHECK([as $hv ovs-ofctl dump-flows br-int table=47 | ofctl_strip_all | grep "priority=2000"], [1], [dnl + ]) + + AT_CHECK([as $hv ovs-ofctl dump-flows br-int table=11 | ofctl_strip_all | \ +@@ -21116,7 +21553,7 @@ check_virtual_offlows_not_present hv2 send_garp 1 1 $eth_src $eth_dst $spa $tpa OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ @@ -4815,7 +8401,7 @@ index 55de7c85b..3515a1e3c 100644 AT_CHECK([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ logical_port=sw0-vir) = xsw0-p1]) -@@ -21184,7 +21276,7 @@ tpa=$(ip_to_hex 10 0 0 10) +@@ -21184,7 +21621,7 @@ tpa=$(ip_to_hex 10 0 0 10) send_garp 1 2 $eth_src $eth_dst $spa $tpa OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ @@ -4824,7 +8410,7 @@ index 55de7c85b..3515a1e3c 100644 OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ logical_port=sw0-vir) = xsw0-p3]) -@@ -21217,7 +21309,7 @@ tpa=$(ip_to_hex 10 0 0 10) +@@ -21217,7 +21654,7 @@ tpa=$(ip_to_hex 10 0 0 10) send_garp 2 1 $eth_src $eth_dst $spa $tpa OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ @@ -4833,7 +8419,7 @@ index 55de7c85b..3515a1e3c 100644 AT_CHECK([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ logical_port=sw0-vir) = xsw0-p2]) -@@ -21249,7 +21341,7 @@ tpa=$(ip_to_hex 10 0 0 4) +@@ -21249,7 +21686,7 @@ tpa=$(ip_to_hex 10 0 0 4) send_arp_reply 1 1 $eth_src $eth_dst $spa $tpa OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ @@ -4842,7 +8428,7 @@ index 55de7c85b..3515a1e3c 100644 sleep 1 AT_CHECK([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ -@@ -21275,7 +21367,7 @@ check_virtual_offlows_not_present hv2 +@@ -21275,7 +21712,7 @@ check_virtual_offlows_not_present hv2 as hv1 ovs-vsctl del-port hv1-vif1 OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ @@ -4851,7 +8437,7 @@ index 55de7c85b..3515a1e3c 100644 sleep 1 AT_CHECK([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ -@@ -21310,7 +21402,7 @@ send_arp_reply 2 1 $eth_src $eth_dst $spa $tpa +@@ -21310,7 +21747,7 @@ send_arp_reply 2 1 $eth_src $eth_dst $spa $tpa sleep 1 OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ @@ -4860,7 +8446,7 @@ index 55de7c85b..3515a1e3c 100644 sleep 1 AT_CHECK([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ logical_port=sw0-vir) = xsw0-p2]) -@@ -21335,7 +21427,7 @@ check_virtual_offlows_not_present hv1 +@@ -21335,7 +21772,7 @@ check_virtual_offlows_not_present hv1 ovn-nbctl lsp-del sw0-p2 OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ @@ -4869,7 +8455,7 @@ index 55de7c85b..3515a1e3c 100644 AT_CHECK([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ logical_port=sw0-vir) = x]) -@@ -21516,7 +21608,7 @@ AT_CAPTURE_FILE([offlows]) +@@ -21516,7 +21953,7 @@ AT_CAPTURE_FILE([offlows]) packet0="inport==\"sw0-p11\" && eth.src==00:00:00:00:00:11 && eth.dst==00:00:00:00:00:21 && ip4 && ip.ttl==64 && ip4.src==192.168.1.11 && ip4.dst==192.168.1.100 && tcp && tcp.src==10000 && tcp.dst==80" @@ -4878,7 +8464,7 @@ index 55de7c85b..3515a1e3c 100644 ovn-nbctl --wait=hv ovn-sbctl list controller_event > events -@@ -21545,7 +21637,7 @@ packet1="inport==\"sw1-p0\" && eth.src==00:00:00:00:00:33 && eth.dst==00:00:00:0 +@@ -21545,7 +21982,7 @@ packet1="inport==\"sw1-p0\" && eth.src==00:00:00:00:00:33 && eth.dst==00:00:00:0 ip4 && ip.ttl==64 && ip4.src==192.168.2.11 && ip4.dst==192.168.2.100 && tcp && tcp.src==10000 && tcp.dst==80" @@ -4887,7 +8473,7 @@ index 55de7c85b..3515a1e3c 100644 ovn-nbctl --wait=hv ovn-sbctl list controller_event uuid=$(ovn-sbctl list controller_event | awk '/_uuid/{print $3}') -@@ -21561,7 +21653,7 @@ packet2="inport==\"sw0-p11\" && eth.src==00:00:00:00:00:11 && eth.dst==00:00:00: +@@ -21561,7 +21998,7 @@ packet2="inport==\"sw0-p11\" && eth.src==00:00:00:00:00:11 && eth.dst==00:00:00: ip6 && ip.ttl==64 && ip6.src==2001::11 && ip6.dst==2001::10 && tcp && tcp.src==10000 && tcp.dst==50051" @@ -4896,7 +8482,16 @@ index 55de7c85b..3515a1e3c 100644 ovn-nbctl --wait=hv ovn-sbctl list controller_event uuid=$(ovn-sbctl list controller_event | awk '/_uuid/{print $3}') -@@ -23744,7 +23836,7 @@ send_garp 1 1 $eth_src $eth_dst $spa $tpa +@@ -23619,7 +24056,7 @@ m4_define([DVR_N_S_PING], + OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv4/vif-north-tx.pcap], [vif-north.expected]) + + # Confirm that packets did not go out via tunnel port. +- AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=38 | grep NXM_NX_TUN_METADATA0 | grep n_packets=0 | wc -l], [0], [[0 ++ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=39 | grep NXM_NX_TUN_METADATA0 | grep n_packets=0 | wc -l], [0], [[0 + ]]) + + # Confirm that packet went out via localnet port +@@ -23744,7 +24181,7 @@ send_garp 1 1 $eth_src $eth_dst $spa $tpa wait_row_count MAC_Binding 1 @@ -4905,7 +8500,7 @@ index 55de7c85b..3515a1e3c 100644 list mac_binding], [0], [lr0-sw0 10.0.0.30 50:54:00:00:00:03 -@@ -23791,7 +23883,7 @@ grep table_id=10 | wc -l`]) +@@ -23791,7 +24228,7 @@ grep table_id=10 | wc -l`]) check_row_count MAC_Binding 1 @@ -4914,7 +8509,7 @@ index 55de7c85b..3515a1e3c 100644 list mac_binding], [0], [lr0-sw0 10.0.0.30 50:54:00:00:00:13 -@@ -23820,7 +23912,7 @@ OVS_WAIT_UNTIL( +@@ -23820,7 +24257,7 @@ OVS_WAIT_UNTIL( | wc -l`] ) @@ -4923,7 +8518,7 @@ index 55de7c85b..3515a1e3c 100644 find mac_binding ip=10.0.0.50], [0], [lr0-sw0 10.0.0.50 50:54:00:00:00:33 -@@ -24377,7 +24469,7 @@ AT_CAPTURE_FILE([sbflows2]) +@@ -24377,7 +24814,7 @@ AT_CAPTURE_FILE([sbflows2]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows > sbflows2 ovn-sbctl dump-flows lr0 | grep ct_lb_mark | grep priority=120 | sed 's/table=..//'], 0, @@ -4932,7 +8527,7 @@ index 55de7c85b..3515a1e3c 100644 ]) # get the svc monitor mac. -@@ -24419,8 +24511,7 @@ AT_CHECK( +@@ -24419,8 +24856,7 @@ AT_CHECK( AT_CAPTURE_FILE([sbflows4]) ovn-sbctl dump-flows lr0 > sbflows4 AT_CHECK([grep lr_in_dnat sbflows4 | grep priority=120 | sed 's/table=..//' | sort], [0], [dnl @@ -4942,7 +8537,7 @@ index 55de7c85b..3515a1e3c 100644 ]) # Delete sw0-p1 -@@ -24576,7 +24667,7 @@ AT_CAPTURE_FILE([sbflows2]) +@@ -24576,7 +25012,7 @@ AT_CAPTURE_FILE([sbflows2]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows > sbflows2 ovn-sbctl dump-flows lr0 | grep ct_lb_mark | grep priority=120 | sed 's/table=..//'], 0, @@ -4951,7 +8546,7 @@ index 55de7c85b..3515a1e3c 100644 ]) # get the svc monitor mac. -@@ -24618,8 +24709,7 @@ AT_CHECK( +@@ -24618,8 +25054,7 @@ AT_CHECK( AT_CAPTURE_FILE([sbflows4]) ovn-sbctl dump-flows lr0 > sbflows4 AT_CHECK([grep lr_in_dnat sbflows4 | grep priority=120 | sed 's/table=..//' | sort], [0], [dnl @@ -4961,7 +8556,7 @@ index 55de7c85b..3515a1e3c 100644 ]) # Delete sw0-p1 -@@ -25447,7 +25537,7 @@ for s_az in $(seq 1 $n_az); do +@@ -25447,7 +25882,7 @@ for s_az in $(seq 1 $n_az); do udp && udp.src==53 && udp.dst==4369" echo "sending: $packet" AT_CHECK([ovn_trace --ovs "$packet" > ${s_az}-${d_az}-$i.ovn-trace]) @@ -4970,7 +8565,7 @@ index 55de7c85b..3515a1e3c 100644 ovs_inport=$(ovs-vsctl --bare --columns=ofport find Interface external-ids:iface-id="$ovn_inport") ovs_packet=$(echo $packet | ovstest test-ovn expr-to-packets) -@@ -26002,7 +26092,7 @@ for i in $(seq 5001 5010); do +@@ -26002,7 +26437,7 @@ for i in $(seq 5001 5010); do packet="inport==\"lsp11\" && eth.src==f0:00:00:00:01:11 && eth.dst==00:00:00:01:01:01 && ip4 && ip.ttl==64 && ip4.src==192.168.1.11 && ip4.dst==10.0.0.123 && tcp && tcp.src==$i && tcp.dst==80" @@ -4979,7 +8574,7 @@ index 55de7c85b..3515a1e3c 100644 for j in 1 2; do # Assume all packets go to lsp2${j}. -@@ -26121,7 +26211,7 @@ wait_for_ports_up +@@ -26121,7 +26556,7 @@ wait_for_ports_up # Test 1 packet="inport==\"lsp11\" && eth.src==f0:00:00:00:01:11 && eth.dst==00:00:00:01:01:01 && ip4 && ip.ttl==64 && ip4.src==192.168.1.11 && ip4.dst==2.2.2.2 && icmp" @@ -4988,7 +8583,7 @@ index 55de7c85b..3515a1e3c 100644 # Assume no packets go neither to lsp21 nor to lsp22. > expected_lsp21 -@@ -26151,7 +26241,7 @@ done +@@ -26151,7 +26586,7 @@ done # Test 2 packet="inport==\"lsp11\" && eth.src==f0:00:00:00:01:11 && eth.dst==00:00:00:01:01:01 && ip4 && ip.ttl==64 && ip4.src==192.168.1.11 && ip4.dst==1.1.1.1 && icmp" @@ -4997,7 +8592,7 @@ index 55de7c85b..3515a1e3c 100644 # Assume all packets go to lsp22. exp_packet="eth.src==00:00:00:01:02:01 && eth.dst==f0:00:00:00:02:22 && -@@ -26181,7 +26271,7 @@ done +@@ -26181,7 +26616,7 @@ done # Test 3 packet="inport==\"lsp21\" && eth.src==f0:00:00:00:02:21 && eth.dst==00:00:00:01:02:01 && ip4 && ip.ttl==64 && ip4.src==192.168.2.21 && ip4.dst==2.2.2.2 && icmp" @@ -5006,7 +8601,7 @@ index 55de7c85b..3515a1e3c 100644 # Assume all packets go to lsp21. exp_packet="eth.src==00:00:00:01:02:01 && eth.dst==f0:00:00:00:02:21 && -@@ -26278,7 +26368,7 @@ wait_for_ports_up +@@ -26278,7 +26713,7 @@ wait_for_ports_up # test 1 packet="inport==\"lsp11\" && eth.src==f0:00:00:00:01:11 && eth.dst==00:00:00:01:01:01 && ip4 && ip.ttl==64 && ip4.src==192.168.1.11 && ip4.dst==192.168.2.21 && icmp" @@ -5015,7 +8610,7 @@ index 55de7c85b..3515a1e3c 100644 # Assume all packets go to lsp21. exp_packet="eth.src==00:00:00:01:02:01 && eth.dst==f0:00:00:00:02:21 && ip4 && -@@ -26312,7 +26402,7 @@ ovs-vsctl set interface hv1-vif2 options:tx_pcap=hv1/vif2-tx.pcap +@@ -26312,7 +26747,7 @@ ovs-vsctl set interface hv1-vif2 options:tx_pcap=hv1/vif2-tx.pcap # test 2 packet="inport==\"lsp11\" && eth.src==f0:00:00:00:01:11 && eth.dst==00:00:00:01:01:01 && ip4 && ip.ttl==64 && ip4.src==192.168.1.11 && ip4.dst==192.168.2.200 && icmp" @@ -5024,7 +8619,7 @@ index 55de7c85b..3515a1e3c 100644 # Assume all packets go to lsp11. exp_packet="eth.src==00:00:00:01:01:01 && eth.dst==f0:00:00:00:01:11 && ip4 && -@@ -26417,7 +26507,7 @@ for i in $(seq 1 2); do +@@ -26417,7 +26852,7 @@ for i in $(seq 1 2); do packet="inport==\"lsp${i}1\" && eth.src==f0:00:00:00:0${i}:1${i} && eth.dst==00:00:00:01:0${i}:01 && ip4 && ip.ttl==64 && ip4.src==192.168.${i}.${i}1 && ip4.dst==10.0.0.1 && icmp" @@ -5033,7 +8628,7 @@ index 55de7c85b..3515a1e3c 100644 # Assume all packets go to lsp${di}1. exp_packet="eth.src==00:00:00:01:0${di}:01 && eth.dst==f0:00:00:00:0${di}:1${di} && -@@ -26530,7 +26620,7 @@ for i in $(seq 1 2); do +@@ -26530,7 +26965,7 @@ for i in $(seq 1 2); do packet="inport==\"lsp${i}1\" && eth.src==f0:00:00:00:0${i}:1${i} && eth.dst==00:00:00:01:0${i}:01 && ip6 && ip.ttl==64 && ip6.src==2001:db8:${i}::${i}1 && ip6.dst==2001:db8:2000::1 && icmp6" @@ -5042,7 +8637,7 @@ index 55de7c85b..3515a1e3c 100644 # Assume all packets go to lsp${di}1. exp_packet="eth.src==00:00:00:01:0${di}:01 && eth.dst==f0:00:00:00:0${di}:1${di} && ip6 && -@@ -26650,7 +26740,7 @@ dst_ip=172.16.1.11 +@@ -26650,7 +27085,7 @@ dst_ip=172.16.1.11 packet="inport==\"lsp11\" && eth.src==$src_mac && eth.dst==$dst_mac && ip4 && ip.ttl==64 && ip4.src==$src_ip && ip4.dst==$dst_ip && udp && udp.src==53 && udp.dst==4369" @@ -5051,7 +8646,7 @@ index 55de7c85b..3515a1e3c 100644 # Check if the packet hit the forwarding group policy AT_CAPTURE_FILE([offlows2]) -@@ -27173,7 +27263,7 @@ ovn_attach n1 br-phys 192.168.0.1 +@@ -27173,7 +27608,7 @@ ovn_attach n1 br-phys 192.168.0.1 # Chassis hv1 should add flows for the ls1 datapath in table 8 (ls_in_port_sec_l2). dp_key=$(ovn-sbctl --bare --columns tunnel_key list Datapath_Binding ls1) @@ -5060,7 +8655,7 @@ index 55de7c85b..3515a1e3c 100644 OVN_CLEANUP([hv1]) AT_CLEANUP -@@ -27199,7 +27289,7 @@ ovs-vsctl add-br br-phys +@@ -27199,7 +27634,7 @@ ovs-vsctl add-br br-phys ovn_attach n1 br-phys 192.168.0.1 # Port_Binding should be released. @@ -5069,7 +8664,7 @@ index 55de7c85b..3515a1e3c 100644 OVN_CLEANUP([hv1]) AT_CLEANUP -@@ -27332,22 +27422,24 @@ sleep 5 +@@ -27332,22 +27767,24 @@ sleep 5 send_ipv4_pkt() { local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 local ip_src=$5 ip_dst=$6 @@ -5099,7 +8694,7 @@ index 55de7c85b..3515a1e3c 100644 AT_CAPTURE_FILE([offlows2]) OVS_WAIT_UNTIL([ -@@ -27364,7 +27456,8 @@ AT_CHECK([ +@@ -27364,7 +27801,8 @@ AT_CHECK([ # Send the pkt from sw0-port2. Packet should not be marked. send_ipv4_pkt hv1 hv1-vif2 505400000004 00000000ff01 \ @@ -5109,7 +8704,7 @@ index 55de7c85b..3515a1e3c 100644 AT_CHECK([ test 1 -eq $(as hv1 ovs-ofctl dump-flows br-phys table=0 | \ -@@ -27398,7 +27491,8 @@ AT_CHECK([ +@@ -27398,7 +27836,8 @@ AT_CHECK([ ovn-nbctl set logical_router_policy $pol1 options:pkt_mark=2 send_ipv4_pkt hv1 hv1-vif1 505400000003 00000000ff01 \ @@ -5119,7 +8714,7 @@ index 55de7c85b..3515a1e3c 100644 OVS_WAIT_UNTIL([ test 1 -eq $(as hv1 ovs-ofctl dump-flows br-int table=23 | \ -@@ -27431,7 +27525,8 @@ AT_CHECK([ +@@ -27431,7 +27870,8 @@ AT_CHECK([ # Send with src ip 10.0.0.5. The reroute policy should be hit # and the packet should be marked with 5. send_ipv4_pkt hv1 hv1-vif1 505400000003 00000000ff01 \ @@ -5129,7 +8724,7 @@ index 55de7c85b..3515a1e3c 100644 OVS_WAIT_UNTIL([ test 1 -eq $(as hv1 ovs-ofctl dump-flows br-phys table=0 | \ -@@ -27443,7 +27538,7 @@ OVS_WAIT_UNTIL([ +@@ -27443,7 +27883,7 @@ OVS_WAIT_UNTIL([ src_ip6=aef00000000000000000000000000004 dst_ip6=bef00000000000000000000000000004 @@ -5138,7 +8733,7 @@ index 55de7c85b..3515a1e3c 100644 OVS_WAIT_UNTIL([ test 1 -eq $(as hv1 ovs-ofctl dump-flows br-phys table=0 | \ -@@ -27463,7 +27558,7 @@ AT_CHECK([ +@@ -27463,7 +27903,7 @@ AT_CHECK([ src_ip6=aef00000000000000000000000000004 dst_ip6=bef00000000000000000000000000005 @@ -5147,7 +8742,64 @@ index 55de7c85b..3515a1e3c 100644 OVS_WAIT_UNTIL([ test 1 -eq $(as hv1 ovs-ofctl dump-flows br-phys table=0 | \ -@@ -28737,7 +28832,7 @@ src_mac="f00000000102" +@@ -27970,22 +28410,22 @@ AT_CHECK([test ! -z $p1_zoneid]) + p2_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-sw0-p2 | sed 's/"//g') + AT_CHECK([test ! -z $p2_zoneid]) + +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ + reg15=0x${p1_dpkey} | grep REG13 | wc -l) -eq 1]) + +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ + reg15=0x${p1_dpkey} | grep "load:0x${p1_zoneid}->NXM_NX_REG13" | wc -l) -eq 1]) + +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw1_dpkey},\ ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw1_dpkey},\ + reg15=0x${p2_dpkey} | grep REG13 | wc -l) -eq 1]) + +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw1_dpkey},\ ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw1_dpkey},\ + reg15=0x${p2_dpkey} | grep "load:0x${p2_zoneid}->NXM_NX_REG13" | wc -l) -eq 1]) + + ovs-vsctl set interface hv1-vif1 external_ids:iface-id=foo + OVS_WAIT_UNTIL([test x$(ovn-nbctl lsp-get-up sw0-p1) = xdown]) + +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ + reg15=0x${p1_dpkey} | grep REG13 | wc -l) -eq 0]) + + p1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-sw0-p1 | sed 's/"//g') +@@ -27997,16 +28437,16 @@ OVS_WAIT_UNTIL([test x$(ovn-nbctl lsp-get-up sw0-p1) = xup]) + p1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-sw0-p1 | sed 's/"//g') + AT_CHECK([test ! -z $p1_zoneid]) + +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ + reg15=0x${p1_dpkey} | grep REG13 | wc -l) -eq 1]) + +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ + reg15=0x${p1_dpkey} | grep "load:0x${p1_zoneid}->NXM_NX_REG13" | wc -l) -eq 1]) + + ovs-vsctl del-port hv1-vif2 + OVS_WAIT_UNTIL([test x$(ovn-nbctl lsp-get-up sw0-p2) = xdown]) + +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ + reg15=0x${p2_dpkey} | grep REG13 | wc -l) -eq 0]) + + p2_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-sw0-p2 | sed 's/"//g') +@@ -28014,7 +28454,7 @@ AT_CHECK([test -z $p2_zoneid]) + + ovn-nbctl lsp-del sw0-p1 + +-OVS_WAIT_UNTIL([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ ++OVS_WAIT_UNTIL([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ + reg15=0x${p1_dpkey} | grep REG13 | wc -l) -eq 0]) + + p1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-sw0-p1 | sed 's/"//g') +@@ -28737,7 +29177,7 @@ src_mac="f00000000102" dst_mac="000000000101" src_ip=`ip_to_hex 10 0 1 2` dst_ip=`ip_to_hex 10 0 1 1` @@ -5156,7 +8808,7 @@ index 55de7c85b..3515a1e3c 100644 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet # Even after configuring a router owned IP for SNAT, no packet-ins should -@@ -28763,7 +28858,7 @@ src_mac="f00000000202" +@@ -28763,7 +29203,7 @@ src_mac="f00000000202" dst_mac="000000000201" src_ip=`ip_to_hex 10 0 2 2` dst_ip=`ip_to_hex 10 0 1 1` @@ -5165,7 +8817,7 @@ index 55de7c85b..3515a1e3c 100644 as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet # Still no packet-ins should reach ovn-controller. -@@ -29548,7 +29643,9 @@ OVS_WAIT_UNTIL([test x$(ovn-nbctl lsp-get-up sw1-p1) = xup]) +@@ -29548,7 +29988,9 @@ OVS_WAIT_UNTIL([test x$(ovn-nbctl lsp-get-up sw1-p1) = xup]) check ovn-nbctl lb-add lb-ipv4-tcp 88.88.88.88:8080 42.42.42.1:4041 tcp check ovn-nbctl lb-add lb-ipv4-udp 88.88.88.88:4040 42.42.42.1:2021 udp @@ -5175,7 +8827,7 @@ index 55de7c85b..3515a1e3c 100644 check ovn-nbctl --wait=hv lb-add lb-ipv6-udp [[8800::0088]]:4040 [[4200::1]]:2021 udp AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | grep -v NXST], [1], [dnl -@@ -29839,6 +29936,119 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep - +@@ -29839,6 +30281,119 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep - table=70, priority=100,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) ]) @@ -5295,7 +8947,149 @@ index 55de7c85b..3515a1e3c 100644 # Check backwards compatibility with ovn-northd versions that don't store the # original destination tuple. # -@@ -31743,7 +31953,7 @@ packet="inport==\"sw1-lp1\" && eth.src==00:00:04:01:02:03 && +@@ -30354,46 +30909,46 @@ AT_CHECK([kill -0 $(cat hv1/ovn-controller.pid)]) + check ovn-nbctl --wait=hv sync + + # Check OVS flows are installed properly. +-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ ++AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | \ + grep "priority=2002" | grep conjunction | \ + sed 's/conjunction([[^)]]*)/conjunction()/g' | \ + sed 's/reg15=0x[[1-9]]/reg15=0xN/g' | sort], [0], [dnl +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x10/0xfff0 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x100/0xff00 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x1000/0xf000 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2/0xfffe actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x20/0xffe0 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x200/0xfe00 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2000/0xe000 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4/0xfffc actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x40/0xffc0 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x400/0xfc00 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4000/0xc000 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8/0xfff8 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x80/0xff80 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x800/0xf800 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8000/0x8000 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=1 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x100/0x100,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x10/0xfff0 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x100/0xff00 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x1000/0xf000 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2/0xfffe actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x20/0xffe0 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x200/0xfe00 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2000/0xe000 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4/0xfffc actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x40/0xffc0 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x400/0xfc00 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4000/0xc000 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8/0xfff8 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x80/0xff80 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x800/0xf800 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8000/0x8000 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=1 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() +- table=44, priority=2002,udp,reg0=0x80/0x80,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x10/0xfff0 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x100/0xff00 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x1000/0xf000 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2/0xfffe actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x20/0xffe0 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x200/0xfe00 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2000/0xe000 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4/0xfffc actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x40/0xffc0 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x400/0xfc00 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4000/0xc000 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8/0xfff8 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x80/0xff80 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x800/0xf800 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8000/0x8000 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=1 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x100/0x100,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x10/0xfff0 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x100/0xff00 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x1000/0xf000 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2/0xfffe actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x20/0xffe0 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x200/0xfe00 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2000/0xe000 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4/0xfffc actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x40/0xffc0 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x400/0xfc00 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4000/0xc000 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8/0xfff8 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x80/0xff80 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x800/0xf800 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8000/0x8000 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=1 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() ++ table=46, priority=2002,udp,reg0=0x80/0x80,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() + ]) + + OVN_CLEANUP([hv1]) +@@ -31568,7 +32123,7 @@ ovs-vsctl add-port br-int lsp0-0 -- set interface lsp0-0 external_ids:iface-id=l + ovs-vsctl add-port br-int lsp0-1 -- set interface lsp0-1 external_ids:iface-id=lsp0-1 + + check ovn-nbctl --wait=hv sync +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 22]) ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 22]) + + # Save the current lflow_run counter + lflow_run=$(ovn-appctl -t ovn-controller coverage/read-counter lflow_run) +@@ -31578,7 +32133,7 @@ lflow_run=$(ovn-appctl -t ovn-controller coverage/read-counter lflow_run) + # 1. Remove half of the ports from pg1. The excepted conjunction flows should be: + # 2 + 10 = 12 + check ovn-nbctl --wait=hv pg-set-ports pg1 $(for i in 0 1 2 3 4; do for j in 0 1; do echo lsp${i}-${j}; done; done) +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 12]) ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 12]) + + # 2. Unbind lsp0-0. The there shouldn't be any conjunction flows because the + # port group const set should have only one member (lsp0-1). And the total +@@ -31586,25 +32141,25 @@ AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l + # 10. + ovs-vsctl del-port br-int lsp0-0 + check ovn-nbctl --wait=hv sync +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 0]) +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep 192.168 | wc -l) == 10]) ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 0]) ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep 192.168 | wc -l) == 10]) + + # 3. Rebind lsp0-0. The expected conjunction flows are back to 12. + ovs-vsctl add-port br-int lsp0-0 -- set interface lsp0-0 external_ids:iface-id=lsp0-0 + check ovn-nbctl --wait=hv sync +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 12]) ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 12]) + + # 4. Bind a lsp (lsp9-0) that doesn't belong to pg1, should not see any change. + ovs-vsctl add-port br-int lsp9-0 -- set interface lsp9-0 external_ids:iface-id=lsp9-0 + check ovn-nbctl --wait=hv sync +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 12]) ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 12]) + + # 5. Bind another 2 lsps (lsp1-0 lsp1-1) that belong to pg1 and on a different + # LS (ls1), should see conjunction flows doubled (12 x 2 = 24) + ovs-vsctl add-port br-int lsp1-0 -- set interface lsp1-0 external_ids:iface-id=lsp1-0 + ovs-vsctl add-port br-int lsp1-1 -- set interface lsp1-1 external_ids:iface-id=lsp1-1 + check ovn-nbctl --wait=hv sync +-AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 24]) ++AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 24]) + + # 6. Simulate a SB port-group "del and add" notification to ovn-controller in the + # same IDL iteration. ovn-controller should still program the same flows. In +@@ -31629,7 +32184,7 @@ for i in $(seq 1 10); do + check ovn-nbctl --wait=hv sync + + # Finally check flow count is the same as before. +- AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 24]) ++ AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 24]) + done + + # Make sure all the above was performed with I-P (no recompute) +@@ -31743,7 +32298,7 @@ packet="inport==\"sw1-lp1\" && eth.src==00:00:04:01:02:03 && ip4.src==10.0.0.100 && ip4.dst==20.0.0.200 && udp && udp.src==53 && udp.dst==4369" @@ -5304,7 +9098,7 @@ index 55de7c85b..3515a1e3c 100644 # Check if packet hit the drop rule AT_CHECK([ovs-ofctl dump-flows br-int | grep "nw_dst=20.0.0.0/24" | \ -@@ -31770,7 +31980,7 @@ packet="inport==\"sw1-lp1\" && eth.src==00:00:04:01:02:03 && +@@ -31770,7 +32325,7 @@ packet="inport==\"sw1-lp1\" && eth.src==00:00:04:01:02:03 && ip4.src==10.0.0.100 && ip4.dst==20.0.0.200 && udp && udp.src==53 && udp.dst==4369" @@ -5313,7 +9107,7 @@ index 55de7c85b..3515a1e3c 100644 # Check if packet hit the drop rule AT_CHECK([ovs-ofctl dump-flows br-int "nw_src=10.0.0.0/24" | \ -@@ -31857,7 +32067,7 @@ packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$bcast_mac && +@@ -31857,7 +32412,7 @@ packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$bcast_mac && arp.op==1 && arp.sha==$ls1_p1_mac && arp.spa==$ls1_p1_ip && arp.tha==$bcast_mac && arp.tpa==$proxy_ip1" @@ -5322,7 +9116,53 @@ index 55de7c85b..3515a1e3c 100644 as hv1 ovs-ofctl dump-flows br-int| grep 169.254.239.254 | grep priority=50 > debug1 AT_CAPTURE_FILE([debug1]) -@@ -32108,7 +32318,6 @@ ovn-nbctl lrp-set-gateway-chassis DR-S3 hv4 +@@ -31916,8 +32471,8 @@ check ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip4.src == 10.0. + + # The first ACL should be programmed, but the second one shouldn't. + check ovn-nbctl --wait=hv sync +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.111], [0], [ignore]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.122], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.111], [0], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.122], [1], [ignore]) + + # Now create the lport lp2. + check ovn-nbctl lsp-add lsw0 lp2 \ +@@ -31925,12 +32480,12 @@ check ovn-nbctl lsp-add lsw0 lp2 \ + + check ovn-nbctl --wait=hv sync + # Now the second ACL should be programmed. +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.122], [0], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.122], [0], [ignore]) + + # Remove the lport lp2 again, the OVS flow for the second ACL should be + # removed. + check ovn-nbctl --wait=hv lsp-del lp2 +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.122], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.122], [1], [ignore]) + + # Test similar scenario but when the referenced lport is not bound locally. + +@@ -31944,8 +32499,8 @@ check ovn-nbctl acl-add lsw0 to-lport 1002 'inport == "lp4" && ip4.dst == 10.0.0 + + # The ACL for lp3 should be programmed, but the one for lp4 shouldn't. + check ovn-nbctl --wait=hv sync +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.133], [0], [ignore]) +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.144], [1], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.133], [0], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.144], [1], [ignore]) + + # Now create the lport lp4. + check ovn-nbctl lsp-add lsw0 lp4 \ +@@ -31953,7 +32508,7 @@ check ovn-nbctl lsp-add lsw0 lp4 \ + + # Now the ACL for lp4 should be programmed. + check ovn-nbctl --wait=hv sync +-AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.144], [0], [ignore]) ++AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.144], [0], [ignore]) + + OVN_CLEANUP([hv1]) + AT_CLEANUP +@@ -32108,7 +32663,6 @@ ovn-nbctl lrp-set-gateway-chassis DR-S3 hv4 ovn-nbctl --wait=sb sync OVN_POPULATE_ARP @@ -5330,7 +9170,7 @@ index 55de7c85b..3515a1e3c 100644 vif_to_ls () { case ${1} in dnl ( vif?[[11]]) echo ls ;; dnl ( -@@ -32222,6 +32431,9 @@ echo "Send Dummy ARP" +@@ -32222,6 +32776,9 @@ echo "Send Dummy ARP" sip=`ip_to_hex 172 16 1 10` tip=`ip_to_hex 172 16 1 50` test_arp vif-north1 f0f000000011 $sip $tip @@ -5340,7 +9180,7 @@ index 55de7c85b..3515a1e3c 100644 echo "Send traffic North to South" sip=`ip_to_hex 172 16 1 10` -@@ -32242,6 +32454,9 @@ echo "Send Dummy ARP" +@@ -32242,6 +32799,9 @@ echo "Send Dummy ARP" sip=`ip_to_hex 10 0 0 10` tip=`ip_to_hex 10 0 0 50` test_arp vif-north2 f0f000000022 $sip $tip @@ -5350,7 +9190,7 @@ index 55de7c85b..3515a1e3c 100644 echo "Send traffic South to North2" sip=`ip_to_hex 20 0 0 10` -@@ -32255,6 +32470,9 @@ echo "Send Dummy ARP" +@@ -32255,6 +32815,9 @@ echo "Send Dummy ARP" sip=`ip_to_hex 192 168 0 10` tip=`ip_to_hex 192 168 0 50` test_arp vif-north3 f0f000000033 $sip $tip @@ -5360,7 +9200,24 @@ index 55de7c85b..3515a1e3c 100644 echo "Send traffic South to North3" sip=`ip_to_hex 20 0 0 10` -@@ -34926,7 +35144,8 @@ check ovs-vsctl add-port br-int p1 -- set interface p1 external_ids:iface-id=lsp +@@ -33384,7 +33947,7 @@ check ovn-nbctl --wait=hv sync + # Use constants so that if tables or registers change, this test can + # be updated easily. + DNAT_TABLE=15 +-SNAT_TABLE=43 ++SNAT_TABLE=45 + DNAT_ZONE_REG="NXM_NX_REG11[[0..15]]" + SNAT_ZONE_REG="NXM_NX_REG12[[0..15]]" + +@@ -33929,6 +34492,7 @@ m4_define([MULTIPLE_OVS_INT], + ovs-ofctl dump-flows br-int | grep $cookie | + sed -e 's/duration=[[0-9.]]*s, //g' | + sed -e 's/idle_age=[[0-9]]*, //g' | ++ sed -e 's/hard_age=[[0-9]]*, //g' | + sed -e 's/n_packets=[[0-9]]*, //g' | + sed -e 's/n_bytes=[[0-9]]*, //g' + } +@@ -34926,7 +35490,8 @@ check ovs-vsctl add-port br-int p1 -- set interface p1 external_ids:iface-id=lsp wait_for_ports_up ovn-nbctl --wait=hv sync @@ -5370,7 +9227,7 @@ index 55de7c85b..3515a1e3c 100644 check ovn-nbctl ls-lb-add sw lb1 # Remove a single backend -@@ -34949,7 +35168,8 @@ AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.0.10:0, backend=192.168. +@@ -34949,7 +35514,8 @@ AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.0.10:0, backend=192.168. AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.0.10:0, backend=192.168.10.30:0, protocol=0" hv1/ovn-controller.log], [0]) # Check flush for LB with port and protocol @@ -5380,7 +9237,7 @@ index 55de7c85b..3515a1e3c 100644 check ovn-nbctl ls-lb-add sw lb1 check ovn-nbctl lb-del lb1 check ovn-nbctl --wait=hv sync -@@ -34958,7 +35178,8 @@ AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.30.10:80, backend=192.16 +@@ -34958,7 +35524,8 @@ AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.30.10:80, backend=192.16 AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.30.10:80, backend=192.168.40.20:8090, protocol=17" hv1/ovn-controller.log], [0]) # Check recompute when LB is no longer local @@ -5390,7 +9247,7 @@ index 55de7c85b..3515a1e3c 100644 check ovn-nbctl ls-lb-add sw lb1 check ovs-vsctl remove interface p1 external_ids iface-id check ovn-appctl inc-engine/recompute -@@ -34968,6 +35189,193 @@ AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.50.10:80, backend=192.16 +@@ -34968,6 +35535,193 @@ AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.50.10:80, backend=192.16 AT_CHECK([test "$(grep -c "Flushing CT for 5-tuple" hv1/ovn-controller.log)" = "6"], [0]) @@ -5684,9 +9541,18 @@ index d65f359a6..b8c5ae9ad 100644 # NETNS_DAEMONIZE([namespace], [command], [pidfile]) # diff --git a/tests/system-ovn-kmod.at b/tests/system-ovn-kmod.at -index dd4996041..3c3e5bc61 100644 +index dd4996041..a1aee3313 100644 --- a/tests/system-ovn-kmod.at +++ b/tests/system-ovn-kmod.at +@@ -172,7 +172,7 @@ ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"192.168.1.2:12345,192 + + ovn-nbctl list load_balancer + ovn-sbctl dump-flows R2 +-OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=41 | \ ++OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=43 | \ + grep 'nat(src=20.0.0.2)']) + + dnl Test load-balancing that includes L4 ports in NAT. @@ -215,3 +215,139 @@ as OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d /connection dropped.*/d"]) @@ -5828,7 +9694,7 @@ index dd4996041..3c3e5bc61 100644 +AT_CLEANUP +]) diff --git a/tests/system-ovn.at b/tests/system-ovn.at -index 84a459d6a..40f808515 100644 +index 84a459d6a..0b6e9f602 100644 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -1569,7 +1569,6 @@ bar3_ct=$(ovs-appctl dpctl/dump-conntrack | grep 30.0.0.2 | grep 172.16.1.4 -c) @@ -5859,6 +9725,24 @@ index 84a459d6a..40f808515 100644 else AT_CHECK([test $bar3_ct -eq 0]) fi +@@ -2246,7 +2243,7 @@ ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"192.168.1.2:80,192.16 + + ovn-nbctl list load_balancer + ovn-sbctl dump-flows R2 +-OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=43 | \ ++OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=45 | \ + grep 'nat(src=20.0.0.2)']) + + check ovs-appctl dpctl/flush-conntrack +@@ -2285,7 +2282,7 @@ ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"192.168.1.2:80,192.16 + + ovn-nbctl list load_balancer + ovn-sbctl dump-flows R2 +-OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=43 | \ ++OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=45 | \ + grep 'nat(src=20.0.0.2)']) + + rm -f wget*.log @@ -4850,9 +4847,9 @@ NS_CHECK_EXEC([lsp], [tcpdump -l -nn -c 3 -i lsp ${filter} > lsp.pcap 2>tcpdump_ OVS_WAIT_UNTIL([grep "listening" tcpdump_err]) @@ -5885,6 +9769,24 @@ index 84a459d6a..40f808515 100644 # Check hairpin traffic. OVS_WAIT_UNTIL([ +@@ -5084,7 +5081,7 @@ OVS_WAIT_UNTIL([ + ]) + + OVS_WAIT_UNTIL([ +- n_pkt=$(ovs-ofctl dump-flows br-int table=44 | grep -v n_packets=0 | \ ++ n_pkt=$(ovs-ofctl dump-flows br-int table=46 | grep -v n_packets=0 | \ + grep controller | grep tp_dst=84 -c) + test $n_pkt -eq 1 + ]) +@@ -5334,7 +5331,7 @@ OVS_WAIT_UNTIL([ + ]) + + OVS_WAIT_UNTIL([ +- n_pkt=$(ovs-ofctl dump-flows br-int table=44 | grep -v n_packets=0 | \ ++ n_pkt=$(ovs-ofctl dump-flows br-int table=46 | grep -v n_packets=0 | \ + grep controller | grep tp_dst=84 -c) + test $n_pkt -eq 1 + ]) @@ -7190,7 +7187,7 @@ NS_EXEC([sw01], [tcpdump -l -n -i sw01 icmp -Q in > reject.pcap &]) check ovn-nbctl --may-exist meter-add acl-meter drop 10 pktps 0 ip netns exec sw01 scapy -H <<-EOF @@ -6146,7 +10048,7 @@ index 84a459d6a..40f808515 100644 OVS_WAIT_FOR_OUTPUT([ for i in `seq 1 20`; do ip netns exec foo1 wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log; -@@ -10690,6 +10734,191 @@ check ovn-nbctl lb-del lb2 +@@ -10690,6 +10734,535 @@ check ovn-nbctl lb-del lb2 OVS_WAIT_UNTIL([test "$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.3) | wc -l)" = "0"]) @@ -6335,13 +10237,22 @@ index 84a459d6a..40f808515 100644 + test "${total_icmp1_pkts}" -gt "${total_icmp_pkts}" +]) + - OVS_APP_EXIT_AND_WAIT([ovn-controller]) - - as ovn-sb -@@ -10706,3 +10935,605 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d - /connection dropped.*/d"]) - AT_CLEANUP - ]) ++OVS_APP_EXIT_AND_WAIT([ovn-controller]) ++ ++as ovn-sb ++OVS_APP_EXIT_AND_WAIT([ovsdb-server]) ++ ++as ovn-nb ++OVS_APP_EXIT_AND_WAIT([ovsdb-server]) ++ ++as northd ++OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) ++ ++as ++OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d ++/connection dropped.*/d"]) ++AT_CLEANUP ++]) + +# This tests port->up/down and ovn-installed after adding and removing Ports and Interfaces. +# 3 Conditions x 3 tests: @@ -6670,22 +10581,13 @@ index 84a459d6a..40f808515 100644 +check_ports_up +check_ports_bound + -+OVS_APP_EXIT_AND_WAIT([ovn-controller]) -+ -+as ovn-sb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as ovn-nb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as northd -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) -+ -+as -+OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -+/connection dropped.*/d"]) -+AT_CLEANUP -+]) + OVS_APP_EXIT_AND_WAIT([ovn-controller]) + + as ovn-sb +@@ -10706,3 +11279,338 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d + /connection dropped.*/d"]) + AT_CLEANUP + ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn mirroring]) @@ -6744,6 +10646,9 @@ index 84a459d6a..40f808515 100644 +ovn-nbctl mirror-add mirror0 gre 1 to-lport 172.16.0.100 +ovn-nbctl lsp-attach-mirror bar1 mirror0 + ++OVN_POPULATE_ARP ++check ovn-nbctl --wait=hv sync ++ +ADD_NAMESPACES(mirror) +ADD_VETH(mirror, mirror, br-mirror, "2003::b/64", "f0:00:00:01:07:06", \ + "2003::1", "nodad", "172.16.0.100/24", "172.16.0.1") @@ -6767,7 +10672,8 @@ index 84a459d6a..40f808515 100644 + +ovn-nbctl mirror-del mirror0 +ovn-nbctl mirror-add mirror1 gre 2 to-lport 2003::b -+ovn-nbctl lsp-attach-mirror bar1 mirror1 ++ ++ovn-nbctl --wait=hv lsp-attach-mirror bar1 mirror1 + +NS_CHECK_EXEC([mirror], [tcpdump -l -c 3 -neei mirror proto GRE > gre_mirror6.pcap 2>gre_mirror6_error &]) +OVS_WAIT_UNTIL([grep "listening" gre_mirror6_error]) @@ -6786,7 +10692,7 @@ index 84a459d6a..40f808515 100644 + +ovn-nbctl mirror-del mirror1 +ovn-nbctl mirror-add mirror2 erspan 3 to-lport 172.16.0.100 -+ovn-nbctl lsp-attach-mirror bar1 mirror2 ++ovn-nbctl --wait=hv lsp-attach-mirror bar1 mirror2 + +NS_CHECK_EXEC([mirror], [tcpdump -l -c 3 -neei mirror ip[[22:2]]=0x88be > erspan_mirror4.pcap 2>erspan_mirror4_error &]) +OVS_WAIT_UNTIL([grep "listening" erspan_mirror4_error]) @@ -6804,7 +10710,7 @@ index 84a459d6a..40f808515 100644 + +ovn-nbctl mirror-del mirror2 +ovn-nbctl mirror-add mirror3 erspan 4 to-lport 2003::b -+ovn-nbctl lsp-attach-mirror bar1 mirror3 ++ovn-nbctl --wait=hv lsp-attach-mirror bar1 mirror3 + +NS_CHECK_EXEC([mirror], [tcpdump -l -c 3 -neei mirror ip6[[42:2]]=0x88be > erspan_mirror6.pcap 2>erspan_mirror6_error &]) +OVS_WAIT_UNTIL([grep "listening" erspan_mirror6_error]) @@ -6821,7 +10727,7 @@ index 84a459d6a..40f808515 100644 +killall tcpdump + +uuid=$(fetch_column nb:mirror _uuid name="mirror3") -+ovn-nbctl set mirror $uuid type=gre ++ovn-nbctl --wait=hv set mirror $uuid type=gre + +NS_CHECK_EXEC([mirror], [tcpdump -c 3 -l -neei mirror proto GRE > gre_mirror6.pcap 2>gre_mirror6_error &]) +OVS_WAIT_UNTIL([grep "listening" gre_mirror6_error]) @@ -6944,6 +10850,79 @@ index 84a459d6a..40f808515 100644 + +AT_CLEANUP +]) ++ ++OVN_FOR_EACH_NORTHD([ ++AT_SETUP([Traffic to router port via LLA]) ++ovn_start ++OVS_TRAFFIC_VSWITCHD_START() ++ADD_BR([br-int]) ++ADD_BR([br-phys], [set Bridge br-phys fail-mode=standalone]) ++ ++# Set external-ids in br-int needed for ovn-controller ++ovs-vsctl \ ++ -- set Open_vSwitch . external-ids:system-id=hv1 \ ++ -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ ++ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ ++ -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ ++ -- set bridge br-int fail-mode=secure other-config:disable-in-band=true ++ ++start_daemon ovn-controller ++ ++check ovn-nbctl lr-add lr0 ++check ovn-nbctl lrp-add lr0 lr0-ls0 00:00:00:00:00:01 fd00::1/64 ++ ++check ovn-nbctl ls-add ls0 ++check ovn-nbctl lsp-add ls0 vif0 \ ++ -- lsp-set-addresses vif0 "00:00:00:00:00:02 fd00::2" ++check ovn-nbctl lsp-add ls0 ls0-lr0 \ ++ -- lsp-set-type ls0-lr0 router \ ++ -- lsp-set-addresses ls0-lr0 router \ ++ -- lsp-set-options ls0-lr0 router-port=lr0-ls0 ++ ++ADD_NAMESPACES(vif0) ++ADD_VETH(vif0, vif0, br-int, "fd00::2/64", "00:00:00:00:00:02", "fd00::1") ++OVS_WAIT_UNTIL([test "$(ip netns exec vif0 ip a | grep fe80:: | grep tentative)" = ""]) ++ ++check ovn-nbctl set logical_router lr0 options:always_learn_from_arp_request=false ++ ++OVN_POPULATE_ARP ++wait_for_ports_up ++check ovn-nbctl --wait=sb sync ++ ++NS_CHECK_EXEC([vif0], [ping -q -c 3 -i 0.3 -w 2 fe80::200:ff:fe00:1 | FORMAT_PING], \ ++[0], [dnl ++3 packets transmitted, 3 received, 0% packet loss, time 0ms ++]) ++ ++check_row_count mac_binding 1 mac=\"00:00:00:00:00:02\" ++ovn-sbctl --all destroy mac_binding ++ ++ovn-nbctl --wait=hv set logical_router lr0 options:always_learn_from_arp_request=true ++ ++NS_CHECK_EXEC([vif0], [ping -q -c 3 -i 0.3 -w 2 fe80::200:ff:fe00:1 | FORMAT_PING], \ ++[0], [dnl ++3 packets transmitted, 3 received, 0% packet loss, time 0ms ++]) ++ ++check_row_count mac_binding 1 mac=\"00:00:00:00:00:02\" ++ ++OVS_APP_EXIT_AND_WAIT([ovn-controller]) ++ ++as ovn-sb ++OVS_APP_EXIT_AND_WAIT([ovsdb-server]) ++ ++as ovn-nb ++OVS_APP_EXIT_AND_WAIT([ovsdb-server]) ++ ++as northd ++OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) ++ ++as ++OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d ++/connection dropped.*/d"]) ++ ++AT_CLEANUP ++]) diff --git a/utilities/containers/py-requirements.txt b/utilities/containers/py-requirements.txt index d7bd21e0d..0d90765c9 100644 --- a/utilities/containers/py-requirements.txt diff --git a/SPECS/ovn23.03.spec b/SPECS/ovn23.03.spec index e3ac702..de8ca26 100644 --- a/SPECS/ovn23.03.spec +++ b/SPECS/ovn23.03.spec @@ -51,7 +51,7 @@ Summary: Open Virtual Network support Group: System Environment/Daemons URL: http://www.ovn.org/ Version: 23.03.0 -Release: 50%{?commit0:.%{date}git%{shortcommit0}}%{?dist} +Release: 69%{?commit0:.%{date}git%{shortcommit0}}%{?dist} Provides: openvswitch%{pkgver}-ovn-common = %{?epoch:%{epoch}:}%{version}-%{release} Obsoletes: openvswitch%{pkgver}-ovn-common < 2.11.0-1 @@ -524,6 +524,82 @@ fi %{_unitdir}/ovn-controller-vtep.service %changelog +* Fri Jun 09 2023 Igor Zhukov - 23.03.0-69 +- call ovsrcu_exit() before exit in ovn-northd and ovn-controller to make valgrind happy +[Upstream: a3aba935cda359db5d9c99e8ea9ba688e4f888bc] + +* Thu Jun 08 2023 Dumitru Ceara - 23.03.0-68 +- controller: Turn OFTABLE_OUTPUT_INIT into an alias. +[Upstream: 8c274866a29534c6ecb80f0242798edbb078bfda] + +* Thu Jun 08 2023 Ihar Hrachyshka - 23.03.0-67 +- Implement MTU Path Discovery for multichassis ports +[Upstream: 44e07200a8f04b70bbcba20d2b5346aa840b4f40] + +* Thu Jun 08 2023 Ihar Hrachyshka - 23.03.0-66 +- Add new egress tables to accommodate for too-big packets handling +[Upstream: 44d6692e28478e4e971de09045f42cc5c3000540] + +* Thu Jun 08 2023 Ihar Hrachyshka - 23.03.0-65 +- if-status: track interfaces for additional chassis +[Upstream: 57f15c6d78b4fbcd9ead81328e06a714b75942f0] + +* Thu Jun 08 2023 Ihar Hrachyshka - 23.03.0-64 +- Track interface MTU in if-status-mgr +[Upstream: e6f097fe148deb3f60c2e2fc57e80f91986f248e] + +* Thu Jun 08 2023 Ihar Hrachyshka - 23.03.0-63 +- Track ip version of tunnel in chassis_tunnel struct +[Upstream: c8fccfa720b7d8e176be05bfd37fd6e74764ee3d] + +* Thu Jun 08 2023 Ales Musil - 23.03.0-62 +- northd: Add logical flow to skip GARP with LLA (#2211240) +[Upstream: dc0b0b55d93cb2516f1759b65f198485597d4575] + +* Thu Jun 08 2023 Vladislav Odintsov - 23.03.0-61 +- northd: match only on supported protocols to handle_svc_check (#1913162) +[Upstream: 822861db016d9360d6a88a486d5db8d5936e66fa] + +* Thu Jun 08 2023 Xavier Simonart - 23.03.0-60 +- tests: Fixed "nested containers" test +[Upstream: f914cf2cab4b4a872d246961c6521cd8a48f2bd3] + +* Thu Jun 08 2023 Xavier Simonart - 23.03.0-59 +- tests: fix flaky Multiple OVS interfaces bound to same logical ports +[Upstream: 8f29930c22687c3247a784e1e2fe4a6dc0fdd86c] + +* Thu Jun 08 2023 Ales Musil - 23.03.0-58 +- system-tests: Prevent flakiness in ovn mirroring +[Upstream: 352041d0fa66772d86980f46c63e023c40286723] + +* Thu Jun 08 2023 Ales Musil - 23.03.0-57 +- northd: Fix address set incremental processing (#2196885) +[Upstream: e8baef1c0fc671fe4e2d3af63de979e22a0c899d] + +* Tue May 30 2023 Brian Haley - 23.03.0-56 +- controller: Ignore DNS queries with RRs +[Upstream: 529ea698f5d1d2b7083210318cfc0a64b701ca62] + +* Tue May 30 2023 Ales Musil - 23.03.0-55 +- ci: ovn-kubernetes: Align the timeouts with u/s ovnk +[Upstream: ecc0a06af3bb47fe49ee897896af35a0efe33486] + +* Tue May 30 2023 Dumitru Ceara - 23.03.0-54 +- controller: Handle OpenFlow errors. (#2134880) +[Upstream: 158463b94f5b6c37a37d9755ba9d5ef7473d35d3] + +* Tue May 30 2023 Vladislav Odintsov - 23.03.0-53 +- controller: fix typo in comments +[Upstream: f24e9bf7b4b5822e0d37a4382fe49607c132a3ee] + +* Tue May 30 2023 Vladislav Odintsov - 23.03.0-52 +- northd: build vtep hairpin lflows only for lswitches with vtep lports +[Upstream: 222f74acea04c9ae46bb3767ff256f8249ee7ab8] + +* Tue May 30 2023 Vladislav Odintsov - 23.03.0-51 +- northd: fix ls_in_hairpin l3dgw flow generation +[Upstream: e4f8547be8774c085ef212fbed3e5e76e77d661c] + * Fri May 26 2023 Han Zhou - 23.03.0-50 - ovn-controller.c: Fix assertion failure during address set update. [Upstream: 777786f38a61041898891ccbb3f139b0552e5794]