Message ID | 20211118181331.93028-1-numans@ovn.org |
---|---|
State | Changes Requested |
Headers | show |
Series | [ovs-dev,v2,1/2] actions: Add new actions - ct_dnat_in_czone and ct_snat_in_czone. | expand |
Context | Check | Description |
---|---|---|
ovsrobot/apply-robot | success | apply and check: success |
ovsrobot/github-robot-_Build_and_Test | success | github build: passed |
ovsrobot/github-robot-_ovn-kubernetes | fail | github build: failed |
Hi Numan, I had one question in the code and then one small finding in the documentation. See below: On 11/18/21 13:13, numans@ovn.org wrote: > From: Numan Siddique <numans@ovn.org> > > Make of use of these new actions for the distributed routers > for NAT. These new actions ensure that both sNAT and dNAT > happens in the same zone. This approach solves a couple of > problems: > > - The datapath flows generated for external traffic which requires > dNAT (N -> S) or sNAT (S -> N) are completely HWOL'able. > > - Since there is only one zone, it would avoid multiple recirculations > (improving the performance). > > If the packet needs to be both sNATted and dNATted (for hairpin traffic > with source and destination on the same chassis), then sNAT is done > in a separate zone. To detect this scenario, this patch adds a few > extra logical flows. For each dnat_and_snat entry prior to this patch > ovn-northd was generating 9 logical flows and with this patch it now > generates 12 logical flows. > > Similar approach can be taken for gateway routers. > > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1984953 > Signed-off-by: Numan Siddique <numans@ovn.org> > --- > > v1 -> v2 > ------ > * Rebased and resolved conflicts. > > include/ovn/logical-fields.h | 1 + > lib/logical-fields.c | 4 + > northd/northd.c | 147 +++++++-- > northd/ovn-northd.8.xml | 201 +++++++++--- > tests/ovn-northd.at | 575 +++++++++++++++++++---------------- > tests/ovn.at | 2 +- > tests/system-ovn.at | 64 ++-- > 7 files changed, 607 insertions(+), 387 deletions(-) > > diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h > index c9675f81c..2118f7933 100644 > --- a/include/ovn/logical-fields.h > +++ b/include/ovn/logical-fields.h > @@ -70,6 +70,7 @@ enum mff_log_flags_bits { > MLF_LOOKUP_FDB_BIT = 8, > MLF_SKIP_SNAT_FOR_LB_BIT = 9, > MLF_LOCALPORT_BIT = 10, > + MLF_USE_SNAT_ZONE = 11, > }; > > /* MFF_LOG_FLAGS_REG flag assignments */ > diff --git a/lib/logical-fields.c b/lib/logical-fields.c > index 7b3d431e0..352a48c89 100644 > --- a/lib/logical-fields.c > +++ b/lib/logical-fields.c > @@ -125,6 +125,10 @@ ovn_init_symtab(struct shash *symtab) > MLF_SKIP_SNAT_FOR_LB_BIT); > expr_symtab_add_subfield(symtab, "flags.skip_snat_for_lb", NULL, > flags_str); > + snprintf(flags_str, sizeof flags_str, "flags[%d]", > + MLF_USE_SNAT_ZONE); > + expr_symtab_add_subfield(symtab, "flags.use_snat_zone", NULL, > + flags_str); > > /* Connection tracking state. */ > expr_symtab_add_field_scoped(symtab, "ct_mark", MFF_CT_MARK, NULL, false, > diff --git a/northd/northd.c b/northd/northd.c > index 0ff61deec..e4d051a94 100644 > --- a/northd/northd.c > +++ b/northd/northd.c > @@ -159,11 +159,14 @@ enum ovn_stage { > PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 18, "lr_in_arp_request") \ > \ > /* Logical router egress stages. */ \ > - PIPELINE_STAGE(ROUTER, OUT, UNDNAT, 0, "lr_out_undnat") \ > - PIPELINE_STAGE(ROUTER, OUT, POST_UNDNAT, 1, "lr_out_post_undnat") \ > - PIPELINE_STAGE(ROUTER, OUT, SNAT, 2, "lr_out_snat") \ > - PIPELINE_STAGE(ROUTER, OUT, EGR_LOOP, 3, "lr_out_egr_loop") \ > - PIPELINE_STAGE(ROUTER, OUT, DELIVERY, 4, "lr_out_delivery") > + PIPELINE_STAGE(ROUTER, OUT, CHECK_DNAT_LOCAL, 0, \ > + "lr_out_chk_dnat_local") \ > + PIPELINE_STAGE(ROUTER, OUT, UNDNAT, 1, "lr_out_undnat") \ > + PIPELINE_STAGE(ROUTER, OUT, POST_UNDNAT, 2, "lr_out_post_undnat") \ > + PIPELINE_STAGE(ROUTER, OUT, SNAT, 3, "lr_out_snat") \ > + PIPELINE_STAGE(ROUTER, OUT, POST_SNAT, 4, "lr_out_post_snat") \ > + PIPELINE_STAGE(ROUTER, OUT, EGR_LOOP, 5, "lr_out_egr_loop") \ > + PIPELINE_STAGE(ROUTER, OUT, DELIVERY, 6, "lr_out_delivery") > > #define PIPELINE_STAGE(DP_TYPE, PIPELINE, STAGE, TABLE, NAME) \ > S_##DP_TYPE##_##PIPELINE##_##STAGE \ > @@ -210,6 +213,7 @@ enum ovn_stage { > #define REGBIT_PKT_LARGER "reg9[1]" > #define REGBIT_LOOKUP_NEIGHBOR_RESULT "reg9[2]" > #define REGBIT_LOOKUP_NEIGHBOR_IP_RESULT "reg9[3]" > +#define REGBIT_DST_NAT_IP_LOCAL "reg9[4]" > > /* Register to store the eth address associated to a router port for packets > * received in S_ROUTER_IN_ADMISSION. > @@ -9568,9 +9572,10 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, > undnat_match_p, est_actions, > &lb->nlb->header_); > } else { > - ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 120, > - undnat_match_p, "ct_dnat;", > - &lb->nlb->header_); > + ovn_lflow_add_with_hint( > + lflows, od, S_ROUTER_OUT_UNDNAT, 120, undnat_match_p, > + od->is_gw_router ? "ct_dnat;" : "ct_dnat_in_czone;", > + &lb->nlb->header_); > } > free(undnat_match_p); > next: > @@ -9865,7 +9870,7 @@ lrouter_nat_add_ext_ip_match(struct ovn_datapath *od, > uint16_t priority; > > /* Priority of logical flows corresponding to exempted_ext_ips is > - * +1 of the corresponding regulr NAT rule. > + * +2 of the corresponding regular NAT rule. > * For example, if we have following NAT rule and we associate > * exempted external ips to it: > * "ovn-nbctl lr-nat-add router dnat_and_snat 10.15.24.139 50.0.0.11" > @@ -9873,17 +9878,17 @@ lrouter_nat_add_ext_ip_match(struct ovn_datapath *od, > * And now we associate exempted external ip address set to it. > * Now corresponding to above rule we will have following logical > * flows: > - * lr_out_snat...priority=162, match=(..ip4.dst == $exempt_range), > + * lr_out_snat...priority=163, match=(..ip4.dst == $exempt_range), > * action=(next;) > * lr_out_snat...priority=161, match=(..), action=(ct_snat(....);) > * > */ > if (is_src) { > /* S_ROUTER_IN_DNAT uses priority 100 */ > - priority = 100 + 1; > + priority = 100 + 2; > } else { > /* S_ROUTER_OUT_SNAT uses priority (mask + 1 + 128 + 1) */ > - priority = count_1bits(ntohl(mask)) + 2; > + priority = count_1bits(ntohl(mask)) + 3; I'm having trouble following why these priorities were raised. I looked at the changes to ovn-northd.8.xml to see if they were mentioned, but I couldn't find anything there that referenced the change. What am I missing here? :) > > if (!od->is_gw_router) { > priority += 128; > @@ -12268,9 +12273,9 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, > /* Traffic received on l3dgw_port is subject to NAT. */ > ds_clear(match); > ds_clear(actions); > - ds_put_format(match, "ip && ip%s.dst == %s && inport == %s", > - is_v6 ? "6" : "4", nat->external_ip, > - od->l3dgw_ports[0]->json_key); > + ds_put_format(match, "ip && ip%s.dst == %s && inport == %s && " > + "flags.loopback == 0", is_v6 ? "6" : "4", > + nat->external_ip, od->l3dgw_ports[0]->json_key); > if (!distributed && od->n_l3dgw_ports) { > /* Flows for NAT rules that are centralized are only > * programmed on the gateway chassis. */ > @@ -12282,12 +12287,31 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, > ds_put_format(actions, "ip%s.dst=%s; next;", > is_v6 ? "6" : "4", nat->logical_ip); > } else { > - ds_put_cstr(actions, "ct_snat;"); > + ds_put_cstr(actions, "ct_snat_in_czone;"); > } > > ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT, > 100, ds_cstr(match), ds_cstr(actions), > &nat->header_); > + > + if (!stateless) { > + ds_clear(match); > + ds_clear(actions); > + ds_put_format(match, "ip && ip%s.dst == %s && inport == %s && " > + "flags.loopback == 1 && flags.use_snat_zone == 1", > + is_v6 ? "6" : "4", nat->external_ip, > + od->l3dgw_ports[0]->json_key); > + if (!distributed && od->n_l3dgw_ports) { > + /* Flows for NAT rules that are centralized are only > + * programmed on the gateway chassis. */ > + ds_put_format(match, " && is_chassis_resident(%s)", > + od->l3dgw_ports[0]->cr_port->json_key); > + } > + ds_put_cstr(actions, "ct_snat;"); > + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT, > + 100, ds_cstr(match), ds_cstr(actions), > + &nat->header_); > + } > } > } > > @@ -12364,7 +12388,7 @@ build_lrouter_in_dnat_flow(struct hmap *lflows, struct ovn_datapath *od, > ds_put_format(actions, "ip%s.dst=%s; next;", > is_v6 ? "6" : "4", nat->logical_ip); > } else { > - ds_put_format(actions, "ct_dnat(%s", nat->logical_ip); > + ds_put_format(actions, "ct_dnat_in_czone(%s", nat->logical_ip); > if (nat->external_port_range[0]) { > ds_put_format(actions, ",%s", nat->external_port_range); > } > @@ -12417,7 +12441,8 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od, > ds_put_format(actions, "ip%s.src=%s; next;", > is_v6 ? "6" : "4", nat->external_ip); > } else { > - ds_put_format(actions, "ct_dnat;"); > + ds_put_format(actions, > + od->is_gw_router ? "ct_dnat;" : "ct_dnat_in_czone;"); > } > > ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 100, > @@ -12425,6 +12450,36 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od, > &nat->header_); > } > > +static void > +build_lrouter_out_is_dnat_local(struct hmap *lflows, struct ovn_datapath *od, > + const struct nbrec_nat *nat, struct ds *match, > + struct ds *actions, bool distributed, > + bool is_v6) > +{ > + /* Note that this only applies for NAT on a distributed router. > + */ > + if (!od->n_l3dgw_ports) { > + return; > + } > + > + ds_clear(match); > + ds_put_format(match, "ip && ip%s.dst == %s && ", > + is_v6 ? "6" : "4", nat->external_ip); > + if (distributed) { > + ds_put_format(match, "is_chassis_resident(\"%s\")", nat->logical_port); > + } else { > + ds_put_format(match, "is_chassis_resident(%s)", > + od->l3dgw_ports[0]->cr_port->json_key); > + } > + > + ds_clear(actions); > + ds_put_cstr(actions, REGBIT_DST_NAT_IP_LOCAL" = 1; next;"); > + > + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_CHECK_DNAT_LOCAL, > + 50, ds_cstr(match), ds_cstr(actions), > + &nat->header_); > +} > + > static void > build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, > const struct nbrec_nat *nat, struct ds *match, > @@ -12478,16 +12533,19 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, > ds_put_format(match, "ip && ip%s.src == %s && outport == %s", > is_v6 ? "6" : "4", nat->logical_ip, > od->l3dgw_ports[0]->json_key); > - if (!distributed && od->n_l3dgw_ports) { > - /* Flows for NAT rules that are centralized are only > - * programmed on the gateway chassis. */ > - priority += 128; > - ds_put_format(match, " && is_chassis_resident(%s)", > - od->l3dgw_ports[0]->cr_port->json_key); > - } else if (distributed) { > - priority += 128; > - ds_put_format(match, " && is_chassis_resident(\"%s\")", > - nat->logical_port); > + if (od->n_l3dgw_ports) { > + if (distributed) { > + ovs_assert(nat->logical_port); > + priority += 128; > + ds_put_format(match, " && is_chassis_resident(\"%s\")", > + nat->logical_port); > + } else { > + /* Flows for NAT rules that are centralized are only > + * programmed on the gateway chassis. */ > + priority += 128; > + ds_put_format(match, " && is_chassis_resident(%s)", > + od->l3dgw_ports[0]->cr_port->json_key); > + } > } > ds_clear(actions); > > @@ -12505,7 +12563,7 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, > ds_put_format(actions, "ip%s.src=%s; next;", > is_v6 ? "6" : "4", nat->external_ip); > } else { > - ds_put_format(actions, "ct_snat(%s", > + ds_put_format(actions, "ct_snat_in_czone(%s", > nat->external_ip); > if (nat->external_port_range[0]) { > ds_put_format(actions, ",%s", nat->external_port_range); > @@ -12519,6 +12577,24 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, > ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT, > priority, ds_cstr(match), > ds_cstr(actions), &nat->header_); > + > + if (!stateless) { > + ds_put_cstr(match, " && "REGBIT_DST_NAT_IP_LOCAL" == 1"); > + ds_clear(actions); > + if (distributed) { > + ds_put_format(actions, "eth.src = "ETH_ADDR_FMT"; ", > + ETH_ADDR_ARGS(mac)); > + } > + ds_put_format(actions, REGBIT_DST_NAT_IP_LOCAL" = 0; ct_snat(%s", > + nat->external_ip); > + if (nat->external_port_range[0]) { > + ds_put_format(actions, ",%s", nat->external_port_range); > + } > + ds_put_format(actions, ");"); > + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT, > + priority + 1, ds_cstr(match), > + ds_cstr(actions), &nat->header_); > + } > } > } > > @@ -12749,10 +12825,13 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, > /* Packets are allowed by default. */ > ovn_lflow_add(lflows, od, S_ROUTER_IN_DEFRAG, 0, "1", "next;"); > ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, 0, "1", "next;"); > + ovn_lflow_add(lflows, od, S_ROUTER_OUT_CHECK_DNAT_LOCAL, 0, "1", > + REGBIT_DST_NAT_IP_LOCAL" = 0; next;"); > ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, 0, "1", "next;"); > ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 0, "1", "next;"); > ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 0, "1", "next;"); > ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 0, "1", "next;"); > + ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_SNAT, 0, "1", "next;"); > 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;"); > > @@ -12765,8 +12844,7 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, > * not committed, it would produce ongoing datapath flows with the ct.new > * flag set. Some NICs are unable to offload these flows. > */ > - if ((od->is_gw_router || od->n_l3dgw_ports) && > - (od->nbr->n_nat || od->has_lb_vip)) { > + if (od->is_gw_router && (od->nbr->n_nat || od->has_lb_vip)) { > ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 50, > "ip", "flags.loopback = 1; ct_dnat;"); > ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 50, > @@ -12839,6 +12917,10 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, > } > } > > + /* S_ROUTER_OUT_DNAT_LOCAL */ > + build_lrouter_out_is_dnat_local(lflows, od, nat, match, actions, > + distributed, is_v6); > + > /* S_ROUTER_OUT_UNDNAT */ > build_lrouter_out_undnat_flow(lflows, od, nat, match, actions, distributed, > mac, is_v6); > @@ -12912,7 +12994,8 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, > "clone { ct_clear; " > "inport = outport; outport = \"\"; " > "eth.dst <-> eth.src; " > - "flags = 0; flags.loopback = 1; "); > + "flags = 0; flags.loopback = 1; " > + "flags.use_snat_zone = "REGBIT_DST_NAT_IP_LOCAL"; "); > for (int j = 0; j < MFF_N_LOG_REGS; j++) { > ds_put_format(actions, "reg%d = 0; ", j); > } > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > index 21d83718c..fc9d51ea7 100644 > --- a/northd/ovn-northd.8.xml > +++ b/northd/ovn-northd.8.xml > @@ -2879,23 +2879,65 @@ icmp6 { > <p> > For each configuration in the OVN Northbound database, that asks > to change the source IP address of a packet from <var>A</var> to > - <var>B</var>, a priority-100 flow matches <code>ip && > - ip4.dst == <var>B</var> && inport == <var>GW</var></code> or > - <code>ip && > - ip6.dst == <var>B</var> && inport == <var>GW</var></code> > - where <var>GW</var> is the logical router gateway port, with an > - action <code>ct_snat;</code>. If the NAT rule is of type > - dnat_and_snat and has <code>stateless=true</code> in the > - options, then the action would be <code>ip4/6.dst= > - (<var>B</var>)</code>. > + <var>B</var>, two priority-100 flows are added. > </p> > > <p> > If the NAT rule cannot be handled in a distributed manner, then > - the priority-100 flow above is only programmed on the > + the below priority-100 flows are only programmed on the > gateway chassis. > </p> > > + <ul> > + <li> > + <p> > + The first flow matches <code>ip && > + ip4.dst == <var>B</var> && inport == <var>GW</var> > + && flags.loopback == 0</code> or > + <code>ip && > + ip6.dst == <var>B</var> && inport == <var>GW</var> > + && flags.loopback == 0</code> > + where <var>GW</var> is the logical router gateway port, with an > + action <code>ct_snat_in_czone;</code> to unSNAT in the common > + zone. If the NAT rule is of type dnat_and_snat and has > + <code>stateless=true</code> in the options, then the action > + would be <code>ip4/6.dst=(<var>B</var>)</code>. > + </p> > + > + <p> > + If the NAT entry is of type <code>snat</code>, then there is an > + additional match <code>is_chassis_resident(<var>cr-GW</var>) > + </code> where <var>cr-GW</var> is the chassis resident port of > + <var>GW</var>. > + </p> > + </li> > + > + <li> > + <p> > + The second flow matches <code>ip && > + ip4.dst == <var>B</var> && inport == <var>GW</var> > + && flags.loopback == 1 && > + flags.use_snat_zone == 1</code> or > + <code>ip && > + ip6.dst == <var>B</var> && inport == <var>GW</var> > + && flags.loopback == 0 && > + flags.use_snat_zone == 1</code> > + where <var>GW</var> is the logical router gateway port, with an > + action <code>ct_snat;</code> to unSNAT in the snat zone. If the > + NAT rule is of type dnat_and_snat and has > + <code>stateless=true</code> in the options, then the action > + would be <code>ip4/6.dst=(<var>B</var>)</code>. > + </p> > + > + <p> > + If the NAT entry is of type <code>snat</code>, then there is an > + additional match <code>is_chassis_resident(<var>cr-GW</var>) > + </code> where <var>cr-GW</var> is the chassis resident port of > + <var>GW</var>. > + </p> > + </li> > + </ul> > + > <p> > A priority-0 logical flow with match <code>1</code> has actions > <code>next;</code>. > @@ -4031,7 +4073,43 @@ nd_ns { > </li> > </ul> > > - <h3>Egress Table 0: UNDNAT</h3> > + <h3>Egress Table 0: Check DNAT local </h3> > + > + <p> > + This table checks if the packet needs to be DNATed in the router ingress > + table <code>lr_out_dnat</code> after it is SNATed and looped back s/lr_out_dnat/lr_in_dnat/ > + to the ingress pipeline. This check is done only for routers configured > + with distributed gateway ports and NAT entries. This check is done > + so that SNAT and DNAT is done in different zones instead of a common > + zone. > + </p> > + > + <ul> > + <li> > + <p> > + For each NAT rule in the OVN Northbound database on a > + distributed router, a priority-50 logical flow with match > + <code>ip4.dst == <var>E</var> && > + is_chassis_resident(<var>P</var>)</code>, where <var>E</var> is the > + external IP address specified in the NAT rule, <var>GW</var> > + is the logical router distributed gateway port. For dnat_and_snat > + NAT rule, <var>P</var> is the logical port specified in the NAT rule. > + If <ref column="logical_port" > + table="NAT" db="OVN_Northbound"/> column of > + <ref table="NAT" db="OVN_Northbound"/> table is NOT set, then > + <var>P</var> is the <code>chassisredirect port</code> of > + <var>GW</var> with the actions: > + <code>REGBIT_DST_NAT_IP_LOCAL = 1; next; </code> > + </p> > + </li> > + > + <li> > + A priority-0 logical flow with match <code>1</code> has actions > + <code>REGBIT_DST_NAT_IP_LOCAL = 0; next;</code>. > + </li> > + </ul> > + > + <h3>Egress Table 1: UNDNAT</h3> > > <p> > This is for already established connections' reverse traffic. > @@ -4040,6 +4118,23 @@ nd_ns { > is unDNATed here. > </p> > > + <ul> > + <li> > + A priority-0 logical flow with match <code>1</code> has actions > + <code>next;</code>. > + </li> > + </ul> > + > + <h3>Egress Table 1: UNDNAT on Gateway Routers</h3> > + > + <ul> > + <li> > + For all IP packets, a priority-50 flow with an action > + <code>flags.loopback = 1; ct_dnat;</code>. > + </li> > + </ul> > + > + <h3>Egress Table 1: UNDNAT on Distributed Routers</h3> > <ul> > <li> > <p> > @@ -4050,9 +4145,9 @@ nd_ns { > gateway chassis that matches > <code>ip && ip4.src == <var>B</var> && > outport == <var>GW</var></code>, where <var>GW</var> is the logical > - router gateway port with an action <code>ct_dnat;</code>. If the > - backend IPv4 address <var>B</var> is also configured with L4 port > - <var>PORT</var> of protocol <var>P</var>, then the > + router gateway port with an action <code>ct_dnat_in_czone;</code>. > + If the backend IPv4 address <var>B</var> is also configured with > + L4 port <var>PORT</var> of protocol <var>P</var>, then the > match also includes <code>P.src</code> == <var>PORT</var>. These > flows are not added for load balancers with IPv6 <var>VIPs</var>. > </p> > @@ -4072,7 +4167,7 @@ nd_ns { > matches <code>ip && ip4.src == <var>B</var> > && outport == <var>GW</var></code>, where <var>GW</var> > is the logical router gateway port, with an action > - <code>ct_dnat;</code>. If the NAT rule is of type > + <code>ct_dnat_in_czone;</code>. If the NAT rule is of type > dnat_and_snat and has <code>stateless=true</code> in the > options, then the action would be <code>ip4/6.src= > (<var>B</var>)</code>. > @@ -4081,7 +4176,7 @@ nd_ns { > <p> > If the NAT rule cannot be handled in a distributed manner, then > the priority-100 flow above is only programmed on the > - gateway chassis. > + gateway chassis with the action <code>ct_dnat_in_czone</code>. > </p> > > <p> > @@ -4094,26 +4189,17 @@ nd_ns { > </p> > </li> > > - <li> > - For all IP packets, a priority-50 flow with an action > - <code>flags.loopback = 1; ct_dnat;</code>. > - </li> > - > - <li> > - A priority-0 logical flow with match <code>1</code> has actions > - <code>next;</code>. > - </li> > </ul> > > - <h3>Egress Table 1: Post UNDNAT</h3> > + <h3>Egress Table 2: Post UNDNAT</h3> > > <p> > <ul> > <li> > A priority-50 logical flow is added that commits any untracked flows > - from the previous table <code>lr_out_undnat</code>. This flow > - matches on <code>ct.new && ip</code> with action > - <code>ct_commit { } ; next; </code>. > + from the previous table <code>lr_out_undnat</code> for Gateway > + routers. This flow matches on <code>ct.new && ip</code> > + with action <code>ct_commit { } ; next; </code>. > </li> > > <li> > @@ -4124,7 +4210,7 @@ nd_ns { > </ul> > </p> > > - <h3>Egress Table 2: SNAT</h3> > + <h3>Egress Table 3: SNAT</h3> > > <p> > Packets that are configured to be SNATed get their source IP address > @@ -4140,7 +4226,7 @@ nd_ns { > </li> > </ul> > > - <p>Egress Table 2: SNAT on Gateway Routers</p> > + <p>Egress Table 3: SNAT on Gateway Routers</p> > > <ul> > <li> > @@ -4239,7 +4325,7 @@ nd_ns { > </li> > </ul> > > - <p>Egress Table 2: SNAT on Distributed Routers</p> > + <p>Egress Table 3: SNAT on Distributed Routers</p> > > <ul> > <li> > @@ -4247,28 +4333,46 @@ nd_ns { > For each configuration in the OVN Northbound database, that asks > to change the source IP address of a packet from an IP address of > <var>A</var> or to change the source IP address of a packet that > - belongs to network <var>A</var> to <var>B</var>, a flow matches > - <code>ip && ip4.src == <var>A</var> && > - outport == <var>GW</var></code>, where <var>GW</var> is the > - logical router gateway port, with an action > - <code>ct_snat(<var>B</var>);</code>. The priority of the flow > - is calculated based on the mask of <var>A</var>, with matches > - having larger masks getting higher priorities. If the NAT rule > - is of type dnat_and_snat and has <code>stateless=true</code> > - in the options, then the action would be <code>ip4/6.src= > - (<var>B</var>)</code>. > + belongs to network <var>A</var> to <var>B</var>, two flows are > + added. The priority of these flows are calculated based on the > + mask of <var>A</var>, with matches having larger masks getting > + higher priorities. > </p> > > <p> > If the NAT rule cannot be handled in a distributed manner, then > - the flow above is only programmed on the > - gateway chassis increasing flow priority by 128 in > - order to be run first > + the below flows are only programmed on the gateway chassis increasing > + flow priority by 128 in order to be run first. > </p> > > + <ul> > + <li> > + The first flow is added with the match > + <code>ip && ip4.src == <var>A</var> && > + outport == <var>GW</var></code>, where <var>GW</var> is the > + logical router gateway port, with an action > + <code>ct_snat_in_czone(<var>B</var>);</code> to SNATed in the > + common zone. If the NAT rule is of type dnat_and_snat and has > + <code>stateless=true</code> in the options, then the action > + would be <code>ip4/6.src=(<var>B</var>)</code>. > + </li> > + > + <li> > + The second flow is added with the match > + <code>ip && ip4.src == <var>A</var> && > + outport == <var>GW</var> && > + REGBIT_DST_NAT_IP_LOCAL == 0</code>, where <var>GW</var> is the > + logical router gateway port, with an action > + <code>ct_snat(<var>B</var>);</code> to SNAT in the snat zone. > + If the NAT rule is of type dnat_and_snat and has > + <code>stateless=true</code> in the options, then the action would > + be <code>ip4/6.src=(<var>B</var>)</code>. > + </li> > + </ul> > + > <p> > If the NAT rule can be handled in a distributed manner, then > - there is an additional action > + there is an additional action (for both the flows) > <code>eth.src = <var>EA</var>;</code>, where <var>EA</var> > is the ethernet address associated with the IP address > <var>A</var> in the NAT rule. This allows upstream MAC > @@ -4299,7 +4403,7 @@ nd_ns { > </li> > </ul> > > - <h3>Egress Table 3: Egress Loopback</h3> > + <h3>Egress Table 4: Egress Loopback</h3> > > <p> > For distributed logical routers where one of the logical router > @@ -4344,6 +4448,7 @@ clone { > outport = ""; > flags = 0; > flags.loopback = 1; > + flags.use_snat_zone = REGBIT_DST_NAT_IP_LOCAL; > reg0 = 0; > reg1 = 0; > ... > @@ -4368,7 +4473,7 @@ clone { > </li> > </ul> > > - <h3>Egress Table 4: Delivery</h3> > + <h3>Egress Table 5: Delivery</h3> > > <p> > Packets that reach this table are ready for delivery. It contains: > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > index 85b47a18f..70ec5e2e3 100644 > --- a/tests/ovn-northd.at > +++ b/tests/ovn-northd.at > @@ -877,25 +877,25 @@ check_flow_match_sets() { > echo > echo "IPv4: stateful" > ovn-nbctl --wait=sb lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 > -check_flow_match_sets 2 2 3 0 0 0 0 > +check_flow_match_sets 3 4 2 0 0 0 0 > ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 > > echo > echo "IPv4: stateless" > ovn-nbctl --wait=sb --stateless lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 > -check_flow_match_sets 2 0 1 2 2 0 0 > +check_flow_match_sets 2 0 0 2 2 0 0 > ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 > > echo > echo "IPv6: stateful" > ovn-nbctl --wait=sb lr-nat-add R1 dnat_and_snat fd01::1 fd11::2 > -check_flow_match_sets 2 2 3 0 0 0 0 > +check_flow_match_sets 3 4 2 0 0 0 0 > ovn-nbctl lr-nat-del R1 dnat_and_snat fd01::1 > > echo > echo "IPv6: stateless" > ovn-nbctl --wait=sb --stateless lr-nat-add R1 dnat_and_snat fd01::1 fd11::2 > -check_flow_match_sets 2 0 1 0 0 2 2 > +check_flow_match_sets 2 0 0 0 0 2 2 > > AT_CLEANUP > ]) > @@ -924,9 +924,9 @@ echo "CR-LRP UUID is: " $uuid > ovn-nbctl --portrange lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 1-3000 > > AT_CAPTURE_FILE([sbflows]) > -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows && test 2 = `grep -c lr_in_unsnat sbflows`]) > +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows && test 3 = `grep -c lr_in_unsnat sbflows`]) > AT_CHECK([grep -c 'ct_snat.*3000' sbflows && grep -c 'ct_dnat.*3000' sbflows], > - [0], [1 > + [0], [2 > 1 > ]) > > @@ -934,9 +934,9 @@ ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 > ovn-nbctl --wait=sb --portrange lr-nat-add R1 snat 172.16.1.1 50.0.0.11 1-3000 > > AT_CAPTURE_FILE([sbflows2]) > -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows2 && test 2 = `grep -c lr_in_unsnat sbflows`]) > +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows2 && test 3 = `grep -c lr_in_unsnat sbflows`]) > AT_CHECK([grep -c 'ct_snat.*3000' sbflows2 && grep -c 'ct_dnat.*3000' sbflows2], > - [1], [1 > + [1], [2 > 0 > ]) > > @@ -944,7 +944,7 @@ ovn-nbctl lr-nat-del R1 snat 172.16.1.1 > ovn-nbctl --wait=sb --portrange --stateless lr-nat-add R1 dnat_and_snat 172.16.1.2 50.0.0.12 1-3000 > > AT_CAPTURE_FILE([sbflows3]) > -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows3 && test 3 = `grep -c lr_in_unsnat sbflows3`]) > +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows3 && test 4 = `grep -c lr_in_unsnat sbflows3`]) > AT_CHECK([grep 'ct_[s]dnat.*172\.16\.1\.2.*3000' sbflows3], [1]) > > ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 > @@ -1008,17 +1008,20 @@ AT_CAPTURE_FILE([drflows]) > ovn-sbctl dump-flows CR > crflows > AT_CAPTURE_FILE([crflows]) > > -AT_CHECK([ > - grep -c lr_out_snat drflows > - grep -c lr_out_snat crflows > - grep lr_out_snat drflows | grep "ip4.src == 50.0.0.11" | grep -c "ip4.dst == $allowed_range" > - grep lr_out_snat crflows | grep "ip4.src == 50.0.0.11" | grep -c "ip4.dst == $allowed_range"], [0], [dnl > -3 > -3 > -1 > -1 > +AT_CHECK([grep -e "lr_out_snat" drflows | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ct_snat_in_czone(172.16.1.1);) > + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.1);) > +]) > + > +AT_CHECK([grep -e "lr_out_snat" crflows | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ct_snat(172.16.1.1);) > ]) > > + > # SNAT with DISALLOWED_IPs > check ovn-nbctl lr-nat-del DR snat 50.0.0.11 > check ovn-nbctl lr-nat-del CR snat 50.0.0.11 > @@ -1036,19 +1039,19 @@ AT_CAPTURE_FILE([drflows2]) > ovn-sbctl dump-flows CR > crflows2 > AT_CAPTURE_FILE([crflows2]) > > -AT_CHECK([ > - grep -c lr_out_snat drflows2 > - grep -c lr_out_snat crflows2 > - grep lr_out_snat drflows2 | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep -c "priority=162" > - grep lr_out_snat drflows2 | grep "ip4.src == 50.0.0.11" | grep -c "priority=161" > - grep lr_out_snat crflows2 | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep -c "priority=34" > - grep lr_out_snat crflows2 | grep "ip4.src == 50.0.0.11" | grep -c "priority=33"], [0], [dnl > -4 > -4 > -1 > -1 > -1 > -1 > +AT_CHECK([grep -e "lr_out_snat" drflows2 | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ct_snat_in_czone(172.16.1.1);) > + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.1);) > + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) > +]) > + > +AT_CHECK([grep -e "lr_out_snat" crflows2 | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ct_snat(172.16.1.1);) > + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) > ]) > > # Stateful FIP with ALLOWED_IPs > @@ -1059,25 +1062,24 @@ check ovn-nbctl lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11 > check ovn-nbctl lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 > > check ovn-nbctl lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 allowed_range > -check ovn-nbctl lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range > +check ovn-nbctl --wait=sb lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range > > -ovn-nbctl show DR > -ovn-sbctl dump-flows DR > -ovn-nbctl show CR > -ovn-sbctl dump-flows CR > - > -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ > -wc -l`]) > -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ > -wc -l`]) > +ovn-sbctl dump-flows DR > drflows3 > +AT_CAPTURE_FILE([drflows2]) > +ovn-sbctl dump-flows CR > crflows3 > +AT_CAPTURE_FILE([crflows2]) > > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 > +AT_CHECK([grep -e "lr_out_snat" drflows3 | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ct_snat_in_czone(172.16.1.2);) > + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.2);) > ]) > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 > -]) > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 > -]) > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 > + > +AT_CHECK([grep -e "lr_out_snat" crflows3 | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ct_snat(172.16.1.2);) > ]) > > # Stateful FIP with DISALLOWED_IPs > @@ -1088,26 +1090,26 @@ ovn-nbctl lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11 > ovn-nbctl lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 > > ovn-nbctl --is-exempted lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 disallowed_range > -ovn-nbctl --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range > +check ovn-nbctl --wait=sb --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range > > -ovn-nbctl show DR > -ovn-sbctl dump-flows DR > -ovn-nbctl show CR > -ovn-sbctl dump-flows CR > - > -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ > -wc -l`]) > -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ > -wc -l`]) > +ovn-sbctl dump-flows DR > drflows4 > +AT_CAPTURE_FILE([drflows2]) > +ovn-sbctl dump-flows CR > crflows4 > +AT_CAPTURE_FILE([crflows2]) > > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=162" | wc -l], [0], [1 > -]) > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 > +AT_CHECK([grep -e "lr_out_snat" drflows4 | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ct_snat_in_czone(172.16.1.2);) > + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.2);) > + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) > ]) > > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=34" | wc -l], [0], [1 > -]) > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 > +AT_CHECK([grep -e "lr_out_snat" crflows4 | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ct_snat(172.16.1.2);) > + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) > ]) > > # Stateless FIP with DISALLOWED_IPs > @@ -1120,24 +1122,21 @@ ovn-nbctl --stateless lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 > ovn-nbctl lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 allowed_range > ovn-nbctl lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range > > -ovn-nbctl show DR > -ovn-sbctl dump-flows DR > - > -ovn-nbctl show CR > -ovn-sbctl dump-flows CR > - > -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ > -wc -l`]) > -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ > -wc -l`]) > +ovn-sbctl dump-flows DR > drflows5 > +AT_CAPTURE_FILE([drflows2]) > +ovn-sbctl dump-flows CR > crflows5 > +AT_CAPTURE_FILE([crflows2]) > > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 > +AT_CHECK([grep -e "lr_out_snat" drflows5 | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ip4.src=172.16.1.2; next;) > ]) > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 > -]) > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 > -]) > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 > + > +AT_CHECK([grep -e "lr_out_snat" crflows5 | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ip4.src=172.16.1.2; next;) > ]) > > # Stateful FIP with DISALLOWED_IPs > @@ -1150,23 +1149,25 @@ ovn-nbctl --stateless lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 > ovn-nbctl --is-exempted lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 disallowed_range > ovn-nbctl --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range > > -ovn-nbctl show DR > -ovn-sbctl dump-flows DR > -ovn-nbctl show CR > -ovn-sbctl dump-flows CR > +ovn-nbctl --wait=sb sync > > -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ > -wc -l`]) > -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ > -wc -l`]) > +ovn-sbctl dump-flows DR > drflows6 > +AT_CAPTURE_FILE([drflows2]) > +ovn-sbctl dump-flows CR > crflows6 > +AT_CAPTURE_FILE([crflows2]) > > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=162" | wc -l], [0], [1 > -]) > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 > +AT_CHECK([grep -e "lr_out_snat" drflows6 | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ip4.src=172.16.1.2; next;) > + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) > ]) > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=34" | wc -l], [0], [1 > -]) > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 > + > +AT_CHECK([grep -e "lr_out_snat" crflows6 | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ip4.src=172.16.1.2; next;) > + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) > ]) > > AT_CLEANUP > @@ -3475,14 +3476,14 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(ct_lb(backends=10.0.0.40:8080);) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > ]) > > check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="20.0.0.4 aef0::4" > @@ -3511,21 +3512,21 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > - table=2 (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip4), action=(ct_snat(20.0.0.4);) > - table=2 (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip6), action=(ct_snat(aef0::4);) > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip4), action=(ct_snat(20.0.0.4);) > + table=? (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip6), action=(ct_snat(aef0::4);) > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > ]) > > check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="router_ip" > @@ -3557,22 +3558,22 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > ]) > > check ovn-nbctl --wait=sb remove logical_router lr0 options chassis > @@ -3584,9 +3585,9 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl > table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > ]) > > check ovn-nbctl set logical_router lr0 options:chassis=ch1 > @@ -3617,23 +3618,23 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw1"), action=(ct_snat(bef0::1);) > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw1"), action=(ct_snat(bef0::1);) > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > ]) > > check ovn-nbctl --wait=sb lb-add lb2 10.0.0.20:80 10.0.0.40:8080 > @@ -3661,18 +3662,18 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.20 && tcp && reg9[[16..31]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=120 , match=(flags.skip_snat_for_lb == 1 && ip), action=(next;) > +AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=120 , match=(flags.skip_snat_for_lb == 1 && ip), action=(next;) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > ]) > > AT_CLEANUP > @@ -4176,6 +4177,8 @@ check ovn-nbctl lsp-set-options lrp1-attachment router-port=lrp1 > check ovn-nbctl lr-nat-add lr0 dnat 42.42.42.42 192.168.0.2 > check ovn-nbctl --wait=sb sync > > +ovn-trace --minimal 'inport == "sw1-port1" && eth.src == 50:54:00:00:00:03 && eth.dst == 00:00:00:00:ff:02 && ip4.dst == 42.42.42.42 && ip4.src == 11.0.0.2 && ip.ttl == 64' > + > AT_CHECK([ovn-trace --minimal 'inport == "sw1-port1" && eth.src == 50:54:00:00:00:03 && eth.dst == 00:00:00:00:ff:02 && ip4.dst == 42.42.42.42 && ip4.src == 11.0.0.2 && ip.ttl == 64' | grep "output(\"sw0-port1\")"], [0], [ignore]) > > dnl If we remove the DNAT entry we will be unable to trace to the DNAT address > @@ -4761,17 +4764,17 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > ]) > > # Create few dnat_and_snat entries > @@ -4797,17 +4800,21 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > +]) > + > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > ]) > > ovn-sbctl chassis-add gw1 geneve 127.0.0.1 > @@ -4828,9 +4835,12 @@ AT_CAPTURE_FILE([lr0flows]) > > AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl > table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) > - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > ]) > > AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl > @@ -4839,26 +4849,34 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl > > AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) > - table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);) > + table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone(10.0.0.3);) > +]) > + > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.10 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.20 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.30 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > - table=0 (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > - table=2 (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.10);) > - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.30);) > - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.20);) > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=? (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.10);) > + table=? (lr_out_snat ), priority=154 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.10);) > + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.30);) > + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.20);) > + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.30);) > + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.20);) > ]) > > # Associate load balancer to lr0 > @@ -4879,9 +4897,12 @@ AT_CAPTURE_FILE([lr0flows]) > > AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl > table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) > - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > ]) > > AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl > @@ -4894,7 +4915,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl > > AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) > - table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);) > + table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone(10.0.0.3);) > table=6 (lr_in_dnat ), priority=110 , match=(ct.est && ip4 && reg0 == 172.168.0.200 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) > table=6 (lr_in_dnat ), priority=110 , match=(ct.new && ip4 && reg0 == 172.168.0.200 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.80,10.0.0.81);) > table=6 (lr_in_dnat ), priority=120 , match=(ct.est && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) > @@ -4905,27 +4926,35 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > - table=0 (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.4 && tcp.src == 8080)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && tcp.src == 82) || (ip4.src == 10.0.0.60 && tcp.src == 82)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && udp.src == 6062) || (ip4.src == 10.0.0.60 && udp.src == 6062)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.80) || (ip4.src == 10.0.0.81)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.10 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.20 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.30 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > +]) > + > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.4 && tcp.src == 8080)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && tcp.src == 82) || (ip4.src == 10.0.0.60 && tcp.src == 82)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && udp.src == 6062) || (ip4.src == 10.0.0.60 && udp.src == 6062)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.80) || (ip4.src == 10.0.0.81)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > - table=2 (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.10);) > - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.30);) > - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.20);) > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=? (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.10);) > + table=? (lr_out_snat ), priority=154 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.10);) > + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.30);) > + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.20);) > + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.30);) > + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.20);) > ]) > > # Make the logical router as Gateway router > @@ -4965,22 +4994,26 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +]) > + > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > ]) > > # Set lb force snat logical router. > @@ -5020,24 +5053,28 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > +]) > + > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > ]) > > # Add a LB VIP same as router ip. > @@ -5081,24 +5118,28 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +]) > + > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > ]) > > # Add IPv6 router port and LB. > @@ -5155,26 +5196,30 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip6 && xxreg0 == def0::2 && tcp && reg9[[16..31]] == 8000), action=(flags.force_snat_for_lb = 1; ct_lb(backends=[[aef0::2]]:80,[[aef0::3]]:80);) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > +]) > + > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-public"), action=(ct_snat(def0::10);) > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw0"), action=(ct_snat(aef0::1);) > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-public"), action=(ct_snat(def0::10);) > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw0"), action=(ct_snat(aef0::1);) > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > ]) > > check ovn-nbctl lrp-del lr0-sw0 > @@ -5209,19 +5254,23 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > ]) > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > +]) > + > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > ]) > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > ]) > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > ]) > > AT_CLEANUP > diff --git a/tests/ovn.at b/tests/ovn.at > index 0d606b42f..ae5744407 100644 > --- a/tests/ovn.at > +++ b/tests/ovn.at > @@ -21604,7 +21604,7 @@ AT_CAPTURE_FILE([sbflows]) > AT_CHECK([for regex in ct_snat ct_dnat ip4.dst= ip4.src=; do > grep -c "$regex" sbflows; > done], [0], [0 > -1 > +0 > 2 > 2 > ]) > diff --git a/tests/system-ovn.at b/tests/system-ovn.at > index c9f5771c9..7f6cb32dc 100644 > --- a/tests/system-ovn.at > +++ b/tests/system-ovn.at > @@ -2224,7 +2224,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=42 | \ > +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. > @@ -2262,7 +2262,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=42 | \ > +OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=43 | \ > grep 'nat(src=20.0.0.2)']) > > rm -f wget*.log > @@ -3711,17 +3711,24 @@ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > icmpv6,orig=(src=fd20::2,dst=fd20::3,id=<cleared>,type=128,code=0),reply=(src=fd11::2,dst=fd20::2,id=<cleared>,type=129,code=0),zone=<cleared> > ]) > > +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > + > # South-North SNAT: 'foo2' pings 'alice1'. But 'alice1' receives traffic > -# from 172.16.1.4 > +# from fd20::4 > NS_CHECK_EXEC([foo2], [ping6 -q -c 3 -i 0.3 -w 2 fd20::2 | FORMAT_PING], \ > [0], [dnl > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > ]) > > -# We verify that SNAT indeed happened via 'dump-conntrack' command. > +ovs-appctl dpctl/dump-conntrack | grep icmpv6 > AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd11::3) | \ > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > -icmpv6,orig=(src=fd11::3,dst=fd20::2,id=<cleared>,type=128,code=0),reply=(src=fd20::2,dst=fd11::3,id=<cleared>,type=129,code=0),zone=<cleared> > +]) > + > +# We verify that SNAT indeed happened via 'dump-conntrack' command. > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::4) | \ > +sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > +icmpv6,orig=(src=fd11::3,dst=fd20::2,id=<cleared>,type=128,code=0),reply=(src=fd20::2,dst=fd20::4,id=<cleared>,type=129,code=0),zone=<cleared> > ]) > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > @@ -3861,11 +3868,9 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \ > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > ]) > > -# We verify that the connection is tracked but not NATted. This is due to the > -# unDNAT table in the egress router pipeline > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ > +# We verify that the connection is not tracked. > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > -icmp,orig=(src=192.168.1.2,dst=192.168.2.2,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> > ]) > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > @@ -3875,11 +3880,9 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \ > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > ]) > > -# We verify that the connection is tracked but not NATted. This is due to the > -# unDNAT table in the egress router pipeline > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ > +# We verify that the connection is not tracked. > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > -icmp,orig=(src=192.168.1.3,dst=192.168.2.2,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=192.168.1.3,id=<cleared>,type=0,code=0),zone=<cleared> > ]) > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > @@ -3889,14 +3892,13 @@ NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.3 | FORMAT_PING], \ > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > ]) > > -# We verify that the connection is tracked but not NATted. This is due to the > -# unDNAT table in the egress router pipeline > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ > +# We verify that the connection is not tracked. > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > -icmp,orig=(src=192.168.2.2,dst=192.168.1.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.3,dst=192.168.2.2,id=<cleared>,type=0,code=0),zone=<cleared> > ]) > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > + > # East-West NAT: 'foo1' pings 'bar1' using 172.16.1.4. > NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ > [0], [dnl > @@ -3905,11 +3907,10 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ > > # Check conntrack entries. First SNAT of 'foo1' address happens. > # Then DNAT of 'bar1' address happens (listed first below). > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) | \ > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(172.16.1.4) | \ > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > icmp,orig=(src=172.16.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared> > icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared> > -icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> > ]) > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > @@ -3922,7 +3923,7 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ > > # Check conntrack entries. First SNAT of 'foo2' address happens. > # Then DNAT of 'bar1' address happens (listed first below). > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \ > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(172.16.1.1) | \ > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> > icmp,orig=(src=192.168.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> > @@ -4055,13 +4056,6 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > ]) > > -# We verify that the connection is tracked but not NATted. This is due to the > -# unDNAT table in the egress router pipeline > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ > -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > -icmpv6,orig=(src=fd11::2,dst=fd12::2,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd11::2,id=<cleared>,type=129,code=0),zone=<cleared> > -]) > - > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > # East-West No NAT: 'foo2' pings 'bar1' using fd12::2. > NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ > @@ -4069,13 +4063,6 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > ]) > > -# We verify that the connection is tracked but not NATted. This is due to the > -# unDNAT table in the egress router pipeline > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ > -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > -icmpv6,orig=(src=fd11::3,dst=fd12::2,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd11::3,id=<cleared>,type=129,code=0),zone=<cleared> > -]) > - > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > # East-West No NAT: 'bar1' pings 'foo2' using fd11::3. > NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 fd11::3 | FORMAT_PING], \ > @@ -4083,13 +4070,6 @@ NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 fd11::3 | FORMAT_PING], \ > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > ]) > > -# We verify that the connection is tracked but not NATted. This is due to the > -# unDNAT table in the egress router pipeline > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ > -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > -icmpv6,orig=(src=fd12::2,dst=fd11::3,id=<cleared>,type=128,code=0),reply=(src=fd11::3,dst=fd12::2,id=<cleared>,type=129,code=0),zone=<cleared> > -]) > - > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > # East-West NAT: 'foo1' pings 'bar1' using fd20::4. > NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd20::4 | FORMAT_PING], \ > @@ -4101,7 +4081,6 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd20::4 | FORMAT_PING], \ > # Then DNAT of 'bar1' address happens (listed first below). > AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::4) | \ > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > -icmpv6,orig=(src=fd11::2,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd20::4,dst=fd11::2,id=<cleared>,type=129,code=0),zone=<cleared> > icmpv6,orig=(src=fd11::2,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd20::4,dst=fd20::3,id=<cleared>,type=129,code=0),zone=<cleared> > icmpv6,orig=(src=fd20::3,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd20::3,id=<cleared>,type=129,code=0),zone=<cleared> > ]) > @@ -6037,7 +6016,6 @@ NS_CHECK_EXEC([sw01-x], [ping -q -c 3 -i 0.3 -w 2 172.16.1.100 | FORMAT_PING], \ > AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.100) | \ > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > icmp,orig=(src=192.168.1.2,dst=172.16.1.100,id=<cleared>,type=8,code=0),reply=(src=172.16.1.100,dst=172.16.1.20,id=<cleared>,type=0,code=0),zone=<cleared> > -icmp,orig=(src=192.168.1.2,dst=172.16.1.100,id=<cleared>,type=8,code=0),reply=(src=172.16.1.100,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> > ]) > > OVS_APP_EXIT_AND_WAIT([ovn-controller]) >
On Thu, Nov 18, 2021 at 4:49 PM Mark Michelson <mmichels@redhat.com> wrote: > > Hi Numan, > > I had one question in the code and then one small finding in the > documentation. See below: > > On 11/18/21 13:13, numans@ovn.org wrote: > > From: Numan Siddique <numans@ovn.org> > > > > Make of use of these new actions for the distributed routers > > for NAT. These new actions ensure that both sNAT and dNAT > > happens in the same zone. This approach solves a couple of > > problems: > > > > - The datapath flows generated for external traffic which requires > > dNAT (N -> S) or sNAT (S -> N) are completely HWOL'able. > > > > - Since there is only one zone, it would avoid multiple recirculations > > (improving the performance). > > > > If the packet needs to be both sNATted and dNATted (for hairpin traffic > > with source and destination on the same chassis), then sNAT is done > > in a separate zone. To detect this scenario, this patch adds a few > > extra logical flows. For each dnat_and_snat entry prior to this patch > > ovn-northd was generating 9 logical flows and with this patch it now > > generates 12 logical flows. > > > > Similar approach can be taken for gateway routers. > > > > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1984953 > > Signed-off-by: Numan Siddique <numans@ovn.org> > > --- > > > > v1 -> v2 > > ------ > > * Rebased and resolved conflicts. > > > > include/ovn/logical-fields.h | 1 + > > lib/logical-fields.c | 4 + > > northd/northd.c | 147 +++++++-- > > northd/ovn-northd.8.xml | 201 +++++++++--- > > tests/ovn-northd.at | 575 +++++++++++++++++++---------------- > > tests/ovn.at | 2 +- > > tests/system-ovn.at | 64 ++-- > > 7 files changed, 607 insertions(+), 387 deletions(-) > > > > diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h > > index c9675f81c..2118f7933 100644 > > --- a/include/ovn/logical-fields.h > > +++ b/include/ovn/logical-fields.h > > @@ -70,6 +70,7 @@ enum mff_log_flags_bits { > > MLF_LOOKUP_FDB_BIT = 8, > > MLF_SKIP_SNAT_FOR_LB_BIT = 9, > > MLF_LOCALPORT_BIT = 10, > > + MLF_USE_SNAT_ZONE = 11, > > }; > > > > /* MFF_LOG_FLAGS_REG flag assignments */ > > diff --git a/lib/logical-fields.c b/lib/logical-fields.c > > index 7b3d431e0..352a48c89 100644 > > --- a/lib/logical-fields.c > > +++ b/lib/logical-fields.c > > @@ -125,6 +125,10 @@ ovn_init_symtab(struct shash *symtab) > > MLF_SKIP_SNAT_FOR_LB_BIT); > > expr_symtab_add_subfield(symtab, "flags.skip_snat_for_lb", NULL, > > flags_str); > > + snprintf(flags_str, sizeof flags_str, "flags[%d]", > > + MLF_USE_SNAT_ZONE); > > + expr_symtab_add_subfield(symtab, "flags.use_snat_zone", NULL, > > + flags_str); > > > > /* Connection tracking state. */ > > expr_symtab_add_field_scoped(symtab, "ct_mark", MFF_CT_MARK, NULL, false, > > diff --git a/northd/northd.c b/northd/northd.c > > index 0ff61deec..e4d051a94 100644 > > --- a/northd/northd.c > > +++ b/northd/northd.c > > @@ -159,11 +159,14 @@ enum ovn_stage { > > PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 18, "lr_in_arp_request") \ > > \ > > /* Logical router egress stages. */ \ > > - PIPELINE_STAGE(ROUTER, OUT, UNDNAT, 0, "lr_out_undnat") \ > > - PIPELINE_STAGE(ROUTER, OUT, POST_UNDNAT, 1, "lr_out_post_undnat") \ > > - PIPELINE_STAGE(ROUTER, OUT, SNAT, 2, "lr_out_snat") \ > > - PIPELINE_STAGE(ROUTER, OUT, EGR_LOOP, 3, "lr_out_egr_loop") \ > > - PIPELINE_STAGE(ROUTER, OUT, DELIVERY, 4, "lr_out_delivery") > > + PIPELINE_STAGE(ROUTER, OUT, CHECK_DNAT_LOCAL, 0, \ > > + "lr_out_chk_dnat_local") \ > > + PIPELINE_STAGE(ROUTER, OUT, UNDNAT, 1, "lr_out_undnat") \ > > + PIPELINE_STAGE(ROUTER, OUT, POST_UNDNAT, 2, "lr_out_post_undnat") \ > > + PIPELINE_STAGE(ROUTER, OUT, SNAT, 3, "lr_out_snat") \ > > + PIPELINE_STAGE(ROUTER, OUT, POST_SNAT, 4, "lr_out_post_snat") \ > > + PIPELINE_STAGE(ROUTER, OUT, EGR_LOOP, 5, "lr_out_egr_loop") \ > > + PIPELINE_STAGE(ROUTER, OUT, DELIVERY, 6, "lr_out_delivery") > > > > #define PIPELINE_STAGE(DP_TYPE, PIPELINE, STAGE, TABLE, NAME) \ > > S_##DP_TYPE##_##PIPELINE##_##STAGE \ > > @@ -210,6 +213,7 @@ enum ovn_stage { > > #define REGBIT_PKT_LARGER "reg9[1]" > > #define REGBIT_LOOKUP_NEIGHBOR_RESULT "reg9[2]" > > #define REGBIT_LOOKUP_NEIGHBOR_IP_RESULT "reg9[3]" > > +#define REGBIT_DST_NAT_IP_LOCAL "reg9[4]" > > > > /* Register to store the eth address associated to a router port for packets > > * received in S_ROUTER_IN_ADMISSION. > > @@ -9568,9 +9572,10 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, > > undnat_match_p, est_actions, > > &lb->nlb->header_); > > } else { > > - ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 120, > > - undnat_match_p, "ct_dnat;", > > - &lb->nlb->header_); > > + ovn_lflow_add_with_hint( > > + lflows, od, S_ROUTER_OUT_UNDNAT, 120, undnat_match_p, > > + od->is_gw_router ? "ct_dnat;" : "ct_dnat_in_czone;", > > + &lb->nlb->header_); > > } > > free(undnat_match_p); > > next: > > @@ -9865,7 +9870,7 @@ lrouter_nat_add_ext_ip_match(struct ovn_datapath *od, > > uint16_t priority; > > > > /* Priority of logical flows corresponding to exempted_ext_ips is > > - * +1 of the corresponding regulr NAT rule. > > + * +2 of the corresponding regular NAT rule. > > * For example, if we have following NAT rule and we associate > > * exempted external ips to it: > > * "ovn-nbctl lr-nat-add router dnat_and_snat 10.15.24.139 50.0.0.11" > > @@ -9873,17 +9878,17 @@ lrouter_nat_add_ext_ip_match(struct ovn_datapath *od, > > * And now we associate exempted external ip address set to it. > > * Now corresponding to above rule we will have following logical > > * flows: > > - * lr_out_snat...priority=162, match=(..ip4.dst == $exempt_range), > > + * lr_out_snat...priority=163, match=(..ip4.dst == $exempt_range), > > * action=(next;) > > * lr_out_snat...priority=161, match=(..), action=(ct_snat(....);) > > * > > */ > > if (is_src) { > > /* S_ROUTER_IN_DNAT uses priority 100 */ > > - priority = 100 + 1; > > + priority = 100 + 2; > > } else { > > /* S_ROUTER_OUT_SNAT uses priority (mask + 1 + 128 + 1) */ > > - priority = count_1bits(ntohl(mask)) + 2; > > + priority = count_1bits(ntohl(mask)) + 3; > > I'm having trouble following why these priorities were raised. I looked > at the changes to ovn-northd.8.xml to see if they were mentioned, but I > couldn't find anything there that referenced the change. What am I > missing here? :) Hi Mark, Thanks for the review. Let me try to explain with an example. Suppose a logical router - LR has below dnat_and_snat entry ovn-nbctl lr-nat-add LR dnat_and_snat 172.16.1.2 50.0.0.11 And It also has the below configured ovn-nbctl create Address_Set name=disallowed_range addresses=\"2.2.2.2\" ovn-nbctl --is-exempted lr-nat-update-ext-ip LR dnat_and_snat 172.16.1.2 disallowed_range Before this patch, below logical flows were programmed in LR_OUT_SNAT stage table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "LR-S1" && is_chassis_resident("cr-DR-S1")), action=(ct_snat_in_czone(172.16.1.1);) table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "LR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) The priority-162 flow basically skips the SNAT if the destination ip belongs to the address set 'disallowed_range' Now this patch changes the priority-162 to 163 flow and adds another flow with the priority - 162. table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ct_snat_in_czone(172.16.1.1);) table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && reg9[4] == 1), action=(reg9[4] = 0; ct_snat(172.16.1.1);) table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) If you notice, the priority-162 flow is almost the same as the prio-161 flow with the extra match - reg9[4] == 1. I'll update the documentation accordingly. This patch could also do something like below table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && reg9[4] == 0), action=(ct_snat_in_czone(172.16.1.1);) table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && reg9[4] == 1), action=(reg9[4] = 0; ct_snat(172.16.1.1);) table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) Let me know which one you'd prefer ? I guess both would work. Thanks Numan > > > > > if (!od->is_gw_router) { > > priority += 128; > > @@ -12268,9 +12273,9 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, > > /* Traffic received on l3dgw_port is subject to NAT. */ > > ds_clear(match); > > ds_clear(actions); > > - ds_put_format(match, "ip && ip%s.dst == %s && inport == %s", > > - is_v6 ? "6" : "4", nat->external_ip, > > - od->l3dgw_ports[0]->json_key); > > + ds_put_format(match, "ip && ip%s.dst == %s && inport == %s && " > > + "flags.loopback == 0", is_v6 ? "6" : "4", > > + nat->external_ip, od->l3dgw_ports[0]->json_key); > > if (!distributed && od->n_l3dgw_ports) { > > /* Flows for NAT rules that are centralized are only > > * programmed on the gateway chassis. */ > > @@ -12282,12 +12287,31 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, > > ds_put_format(actions, "ip%s.dst=%s; next;", > > is_v6 ? "6" : "4", nat->logical_ip); > > } else { > > - ds_put_cstr(actions, "ct_snat;"); > > + ds_put_cstr(actions, "ct_snat_in_czone;"); > > } > > > > ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT, > > 100, ds_cstr(match), ds_cstr(actions), > > &nat->header_); > > + > > + if (!stateless) { > > + ds_clear(match); > > + ds_clear(actions); > > + ds_put_format(match, "ip && ip%s.dst == %s && inport == %s && " > > + "flags.loopback == 1 && flags.use_snat_zone == 1", > > + is_v6 ? "6" : "4", nat->external_ip, > > + od->l3dgw_ports[0]->json_key); > > + if (!distributed && od->n_l3dgw_ports) { > > + /* Flows for NAT rules that are centralized are only > > + * programmed on the gateway chassis. */ > > + ds_put_format(match, " && is_chassis_resident(%s)", > > + od->l3dgw_ports[0]->cr_port->json_key); > > + } > > + ds_put_cstr(actions, "ct_snat;"); > > + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT, > > + 100, ds_cstr(match), ds_cstr(actions), > > + &nat->header_); > > + } > > } > > } > > > > @@ -12364,7 +12388,7 @@ build_lrouter_in_dnat_flow(struct hmap *lflows, struct ovn_datapath *od, > > ds_put_format(actions, "ip%s.dst=%s; next;", > > is_v6 ? "6" : "4", nat->logical_ip); > > } else { > > - ds_put_format(actions, "ct_dnat(%s", nat->logical_ip); > > + ds_put_format(actions, "ct_dnat_in_czone(%s", nat->logical_ip); > > if (nat->external_port_range[0]) { > > ds_put_format(actions, ",%s", nat->external_port_range); > > } > > @@ -12417,7 +12441,8 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od, > > ds_put_format(actions, "ip%s.src=%s; next;", > > is_v6 ? "6" : "4", nat->external_ip); > > } else { > > - ds_put_format(actions, "ct_dnat;"); > > + ds_put_format(actions, > > + od->is_gw_router ? "ct_dnat;" : "ct_dnat_in_czone;"); > > } > > > > ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 100, > > @@ -12425,6 +12450,36 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od, > > &nat->header_); > > } > > > > +static void > > +build_lrouter_out_is_dnat_local(struct hmap *lflows, struct ovn_datapath *od, > > + const struct nbrec_nat *nat, struct ds *match, > > + struct ds *actions, bool distributed, > > + bool is_v6) > > +{ > > + /* Note that this only applies for NAT on a distributed router. > > + */ > > + if (!od->n_l3dgw_ports) { > > + return; > > + } > > + > > + ds_clear(match); > > + ds_put_format(match, "ip && ip%s.dst == %s && ", > > + is_v6 ? "6" : "4", nat->external_ip); > > + if (distributed) { > > + ds_put_format(match, "is_chassis_resident(\"%s\")", nat->logical_port); > > + } else { > > + ds_put_format(match, "is_chassis_resident(%s)", > > + od->l3dgw_ports[0]->cr_port->json_key); > > + } > > + > > + ds_clear(actions); > > + ds_put_cstr(actions, REGBIT_DST_NAT_IP_LOCAL" = 1; next;"); > > + > > + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_CHECK_DNAT_LOCAL, > > + 50, ds_cstr(match), ds_cstr(actions), > > + &nat->header_); > > +} > > + > > static void > > build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, > > const struct nbrec_nat *nat, struct ds *match, > > @@ -12478,16 +12533,19 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, > > ds_put_format(match, "ip && ip%s.src == %s && outport == %s", > > is_v6 ? "6" : "4", nat->logical_ip, > > od->l3dgw_ports[0]->json_key); > > - if (!distributed && od->n_l3dgw_ports) { > > - /* Flows for NAT rules that are centralized are only > > - * programmed on the gateway chassis. */ > > - priority += 128; > > - ds_put_format(match, " && is_chassis_resident(%s)", > > - od->l3dgw_ports[0]->cr_port->json_key); > > - } else if (distributed) { > > - priority += 128; > > - ds_put_format(match, " && is_chassis_resident(\"%s\")", > > - nat->logical_port); > > + if (od->n_l3dgw_ports) { > > + if (distributed) { > > + ovs_assert(nat->logical_port); > > + priority += 128; > > + ds_put_format(match, " && is_chassis_resident(\"%s\")", > > + nat->logical_port); > > + } else { > > + /* Flows for NAT rules that are centralized are only > > + * programmed on the gateway chassis. */ > > + priority += 128; > > + ds_put_format(match, " && is_chassis_resident(%s)", > > + od->l3dgw_ports[0]->cr_port->json_key); > > + } > > } > > ds_clear(actions); > > > > @@ -12505,7 +12563,7 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, > > ds_put_format(actions, "ip%s.src=%s; next;", > > is_v6 ? "6" : "4", nat->external_ip); > > } else { > > - ds_put_format(actions, "ct_snat(%s", > > + ds_put_format(actions, "ct_snat_in_czone(%s", > > nat->external_ip); > > if (nat->external_port_range[0]) { > > ds_put_format(actions, ",%s", nat->external_port_range); > > @@ -12519,6 +12577,24 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, > > ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT, > > priority, ds_cstr(match), > > ds_cstr(actions), &nat->header_); > > + > > + if (!stateless) { > > + ds_put_cstr(match, " && "REGBIT_DST_NAT_IP_LOCAL" == 1"); > > + ds_clear(actions); > > + if (distributed) { > > + ds_put_format(actions, "eth.src = "ETH_ADDR_FMT"; ", > > + ETH_ADDR_ARGS(mac)); > > + } > > + ds_put_format(actions, REGBIT_DST_NAT_IP_LOCAL" = 0; ct_snat(%s", > > + nat->external_ip); > > + if (nat->external_port_range[0]) { > > + ds_put_format(actions, ",%s", nat->external_port_range); > > + } > > + ds_put_format(actions, ");"); > > + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT, > > + priority + 1, ds_cstr(match), > > + ds_cstr(actions), &nat->header_); > > + } > > } > > } > > > > @@ -12749,10 +12825,13 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, > > /* Packets are allowed by default. */ > > ovn_lflow_add(lflows, od, S_ROUTER_IN_DEFRAG, 0, "1", "next;"); > > ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, 0, "1", "next;"); > > + ovn_lflow_add(lflows, od, S_ROUTER_OUT_CHECK_DNAT_LOCAL, 0, "1", > > + REGBIT_DST_NAT_IP_LOCAL" = 0; next;"); > > ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, 0, "1", "next;"); > > ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 0, "1", "next;"); > > ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 0, "1", "next;"); > > ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 0, "1", "next;"); > > + ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_SNAT, 0, "1", "next;"); > > 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;"); > > > > @@ -12765,8 +12844,7 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, > > * not committed, it would produce ongoing datapath flows with the ct.new > > * flag set. Some NICs are unable to offload these flows. > > */ > > - if ((od->is_gw_router || od->n_l3dgw_ports) && > > - (od->nbr->n_nat || od->has_lb_vip)) { > > + if (od->is_gw_router && (od->nbr->n_nat || od->has_lb_vip)) { > > ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 50, > > "ip", "flags.loopback = 1; ct_dnat;"); > > ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 50, > > @@ -12839,6 +12917,10 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, > > } > > } > > > > + /* S_ROUTER_OUT_DNAT_LOCAL */ > > + build_lrouter_out_is_dnat_local(lflows, od, nat, match, actions, > > + distributed, is_v6); > > + > > /* S_ROUTER_OUT_UNDNAT */ > > build_lrouter_out_undnat_flow(lflows, od, nat, match, actions, distributed, > > mac, is_v6); > > @@ -12912,7 +12994,8 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, > > "clone { ct_clear; " > > "inport = outport; outport = \"\"; " > > "eth.dst <-> eth.src; " > > - "flags = 0; flags.loopback = 1; "); > > + "flags = 0; flags.loopback = 1; " > > + "flags.use_snat_zone = "REGBIT_DST_NAT_IP_LOCAL"; "); > > for (int j = 0; j < MFF_N_LOG_REGS; j++) { > > ds_put_format(actions, "reg%d = 0; ", j); > > } > > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > > index 21d83718c..fc9d51ea7 100644 > > --- a/northd/ovn-northd.8.xml > > +++ b/northd/ovn-northd.8.xml > > @@ -2879,23 +2879,65 @@ icmp6 { > > <p> > > For each configuration in the OVN Northbound database, that asks > > to change the source IP address of a packet from <var>A</var> to > > - <var>B</var>, a priority-100 flow matches <code>ip && > > - ip4.dst == <var>B</var> && inport == <var>GW</var></code> or > > - <code>ip && > > - ip6.dst == <var>B</var> && inport == <var>GW</var></code> > > - where <var>GW</var> is the logical router gateway port, with an > > - action <code>ct_snat;</code>. If the NAT rule is of type > > - dnat_and_snat and has <code>stateless=true</code> in the > > - options, then the action would be <code>ip4/6.dst= > > - (<var>B</var>)</code>. > > + <var>B</var>, two priority-100 flows are added. > > </p> > > > > <p> > > If the NAT rule cannot be handled in a distributed manner, then > > - the priority-100 flow above is only programmed on the > > + the below priority-100 flows are only programmed on the > > gateway chassis. > > </p> > > > > + <ul> > > + <li> > > + <p> > > + The first flow matches <code>ip && > > + ip4.dst == <var>B</var> && inport == <var>GW</var> > > + && flags.loopback == 0</code> or > > + <code>ip && > > + ip6.dst == <var>B</var> && inport == <var>GW</var> > > + && flags.loopback == 0</code> > > + where <var>GW</var> is the logical router gateway port, with an > > + action <code>ct_snat_in_czone;</code> to unSNAT in the common > > + zone. If the NAT rule is of type dnat_and_snat and has > > + <code>stateless=true</code> in the options, then the action > > + would be <code>ip4/6.dst=(<var>B</var>)</code>. > > + </p> > > + > > + <p> > > + If the NAT entry is of type <code>snat</code>, then there is an > > + additional match <code>is_chassis_resident(<var>cr-GW</var>) > > + </code> where <var>cr-GW</var> is the chassis resident port of > > + <var>GW</var>. > > + </p> > > + </li> > > + > > + <li> > > + <p> > > + The second flow matches <code>ip && > > + ip4.dst == <var>B</var> && inport == <var>GW</var> > > + && flags.loopback == 1 && > > + flags.use_snat_zone == 1</code> or > > + <code>ip && > > + ip6.dst == <var>B</var> && inport == <var>GW</var> > > + && flags.loopback == 0 && > > + flags.use_snat_zone == 1</code> > > + where <var>GW</var> is the logical router gateway port, with an > > + action <code>ct_snat;</code> to unSNAT in the snat zone. If the > > + NAT rule is of type dnat_and_snat and has > > + <code>stateless=true</code> in the options, then the action > > + would be <code>ip4/6.dst=(<var>B</var>)</code>. > > + </p> > > + > > + <p> > > + If the NAT entry is of type <code>snat</code>, then there is an > > + additional match <code>is_chassis_resident(<var>cr-GW</var>) > > + </code> where <var>cr-GW</var> is the chassis resident port of > > + <var>GW</var>. > > + </p> > > + </li> > > + </ul> > > + > > <p> > > A priority-0 logical flow with match <code>1</code> has actions > > <code>next;</code>. > > @@ -4031,7 +4073,43 @@ nd_ns { > > </li> > > </ul> > > > > - <h3>Egress Table 0: UNDNAT</h3> > > + <h3>Egress Table 0: Check DNAT local </h3> > > + > > + <p> > > + This table checks if the packet needs to be DNATed in the router ingress > > + table <code>lr_out_dnat</code> after it is SNATed and looped back > > s/lr_out_dnat/lr_in_dnat/ > > > + to the ingress pipeline. This check is done only for routers configured > > + with distributed gateway ports and NAT entries. This check is done > > + so that SNAT and DNAT is done in different zones instead of a common > > + zone. > > + </p> > > + > > + <ul> > > + <li> > > + <p> > > + For each NAT rule in the OVN Northbound database on a > > + distributed router, a priority-50 logical flow with match > > + <code>ip4.dst == <var>E</var> && > > + is_chassis_resident(<var>P</var>)</code>, where <var>E</var> is the > > + external IP address specified in the NAT rule, <var>GW</var> > > + is the logical router distributed gateway port. For dnat_and_snat > > + NAT rule, <var>P</var> is the logical port specified in the NAT rule. > > + If <ref column="logical_port" > > + table="NAT" db="OVN_Northbound"/> column of > > + <ref table="NAT" db="OVN_Northbound"/> table is NOT set, then > > + <var>P</var> is the <code>chassisredirect port</code> of > > + <var>GW</var> with the actions: > > + <code>REGBIT_DST_NAT_IP_LOCAL = 1; next; </code> > > + </p> > > + </li> > > + > > + <li> > > + A priority-0 logical flow with match <code>1</code> has actions > > + <code>REGBIT_DST_NAT_IP_LOCAL = 0; next;</code>. > > + </li> > > + </ul> > > + > > + <h3>Egress Table 1: UNDNAT</h3> > > > > <p> > > This is for already established connections' reverse traffic. > > @@ -4040,6 +4118,23 @@ nd_ns { > > is unDNATed here. > > </p> > > > > + <ul> > > + <li> > > + A priority-0 logical flow with match <code>1</code> has actions > > + <code>next;</code>. > > + </li> > > + </ul> > > + > > + <h3>Egress Table 1: UNDNAT on Gateway Routers</h3> > > + > > + <ul> > > + <li> > > + For all IP packets, a priority-50 flow with an action > > + <code>flags.loopback = 1; ct_dnat;</code>. > > + </li> > > + </ul> > > + > > + <h3>Egress Table 1: UNDNAT on Distributed Routers</h3> > > <ul> > > <li> > > <p> > > @@ -4050,9 +4145,9 @@ nd_ns { > > gateway chassis that matches > > <code>ip && ip4.src == <var>B</var> && > > outport == <var>GW</var></code>, where <var>GW</var> is the logical > > - router gateway port with an action <code>ct_dnat;</code>. If the > > - backend IPv4 address <var>B</var> is also configured with L4 port > > - <var>PORT</var> of protocol <var>P</var>, then the > > + router gateway port with an action <code>ct_dnat_in_czone;</code>. > > + If the backend IPv4 address <var>B</var> is also configured with > > + L4 port <var>PORT</var> of protocol <var>P</var>, then the > > match also includes <code>P.src</code> == <var>PORT</var>. These > > flows are not added for load balancers with IPv6 <var>VIPs</var>. > > </p> > > @@ -4072,7 +4167,7 @@ nd_ns { > > matches <code>ip && ip4.src == <var>B</var> > > && outport == <var>GW</var></code>, where <var>GW</var> > > is the logical router gateway port, with an action > > - <code>ct_dnat;</code>. If the NAT rule is of type > > + <code>ct_dnat_in_czone;</code>. If the NAT rule is of type > > dnat_and_snat and has <code>stateless=true</code> in the > > options, then the action would be <code>ip4/6.src= > > (<var>B</var>)</code>. > > @@ -4081,7 +4176,7 @@ nd_ns { > > <p> > > If the NAT rule cannot be handled in a distributed manner, then > > the priority-100 flow above is only programmed on the > > - gateway chassis. > > + gateway chassis with the action <code>ct_dnat_in_czone</code>. > > </p> > > > > <p> > > @@ -4094,26 +4189,17 @@ nd_ns { > > </p> > > </li> > > > > - <li> > > - For all IP packets, a priority-50 flow with an action > > - <code>flags.loopback = 1; ct_dnat;</code>. > > - </li> > > - > > - <li> > > - A priority-0 logical flow with match <code>1</code> has actions > > - <code>next;</code>. > > - </li> > > </ul> > > > > - <h3>Egress Table 1: Post UNDNAT</h3> > > + <h3>Egress Table 2: Post UNDNAT</h3> > > > > <p> > > <ul> > > <li> > > A priority-50 logical flow is added that commits any untracked flows > > - from the previous table <code>lr_out_undnat</code>. This flow > > - matches on <code>ct.new && ip</code> with action > > - <code>ct_commit { } ; next; </code>. > > + from the previous table <code>lr_out_undnat</code> for Gateway > > + routers. This flow matches on <code>ct.new && ip</code> > > + with action <code>ct_commit { } ; next; </code>. > > </li> > > > > <li> > > @@ -4124,7 +4210,7 @@ nd_ns { > > </ul> > > </p> > > > > - <h3>Egress Table 2: SNAT</h3> > > + <h3>Egress Table 3: SNAT</h3> > > > > <p> > > Packets that are configured to be SNATed get their source IP address > > @@ -4140,7 +4226,7 @@ nd_ns { > > </li> > > </ul> > > > > - <p>Egress Table 2: SNAT on Gateway Routers</p> > > + <p>Egress Table 3: SNAT on Gateway Routers</p> > > > > <ul> > > <li> > > @@ -4239,7 +4325,7 @@ nd_ns { > > </li> > > </ul> > > > > - <p>Egress Table 2: SNAT on Distributed Routers</p> > > + <p>Egress Table 3: SNAT on Distributed Routers</p> > > > > <ul> > > <li> > > @@ -4247,28 +4333,46 @@ nd_ns { > > For each configuration in the OVN Northbound database, that asks > > to change the source IP address of a packet from an IP address of > > <var>A</var> or to change the source IP address of a packet that > > - belongs to network <var>A</var> to <var>B</var>, a flow matches > > - <code>ip && ip4.src == <var>A</var> && > > - outport == <var>GW</var></code>, where <var>GW</var> is the > > - logical router gateway port, with an action > > - <code>ct_snat(<var>B</var>);</code>. The priority of the flow > > - is calculated based on the mask of <var>A</var>, with matches > > - having larger masks getting higher priorities. If the NAT rule > > - is of type dnat_and_snat and has <code>stateless=true</code> > > - in the options, then the action would be <code>ip4/6.src= > > - (<var>B</var>)</code>. > > + belongs to network <var>A</var> to <var>B</var>, two flows are > > + added. The priority of these flows are calculated based on the > > + mask of <var>A</var>, with matches having larger masks getting > > + higher priorities. > > </p> > > > > <p> > > If the NAT rule cannot be handled in a distributed manner, then > > - the flow above is only programmed on the > > - gateway chassis increasing flow priority by 128 in > > - order to be run first > > + the below flows are only programmed on the gateway chassis increasing > > + flow priority by 128 in order to be run first. > > </p> > > > > + <ul> > > + <li> > > + The first flow is added with the match > > + <code>ip && ip4.src == <var>A</var> && > > + outport == <var>GW</var></code>, where <var>GW</var> is the > > + logical router gateway port, with an action > > + <code>ct_snat_in_czone(<var>B</var>);</code> to SNATed in the > > + common zone. If the NAT rule is of type dnat_and_snat and has > > + <code>stateless=true</code> in the options, then the action > > + would be <code>ip4/6.src=(<var>B</var>)</code>. > > + </li> > > + > > + <li> > > + The second flow is added with the match > > + <code>ip && ip4.src == <var>A</var> && > > + outport == <var>GW</var> && > > + REGBIT_DST_NAT_IP_LOCAL == 0</code>, where <var>GW</var> is the > > + logical router gateway port, with an action > > + <code>ct_snat(<var>B</var>);</code> to SNAT in the snat zone. > > + If the NAT rule is of type dnat_and_snat and has > > + <code>stateless=true</code> in the options, then the action would > > + be <code>ip4/6.src=(<var>B</var>)</code>. > > + </li> > > + </ul> > > + > > <p> > > If the NAT rule can be handled in a distributed manner, then > > - there is an additional action > > + there is an additional action (for both the flows) > > <code>eth.src = <var>EA</var>;</code>, where <var>EA</var> > > is the ethernet address associated with the IP address > > <var>A</var> in the NAT rule. This allows upstream MAC > > @@ -4299,7 +4403,7 @@ nd_ns { > > </li> > > </ul> > > > > - <h3>Egress Table 3: Egress Loopback</h3> > > + <h3>Egress Table 4: Egress Loopback</h3> > > > > <p> > > For distributed logical routers where one of the logical router > > @@ -4344,6 +4448,7 @@ clone { > > outport = ""; > > flags = 0; > > flags.loopback = 1; > > + flags.use_snat_zone = REGBIT_DST_NAT_IP_LOCAL; > > reg0 = 0; > > reg1 = 0; > > ... > > @@ -4368,7 +4473,7 @@ clone { > > </li> > > </ul> > > > > - <h3>Egress Table 4: Delivery</h3> > > + <h3>Egress Table 5: Delivery</h3> > > > > <p> > > Packets that reach this table are ready for delivery. It contains: > > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > > index 85b47a18f..70ec5e2e3 100644 > > --- a/tests/ovn-northd.at > > +++ b/tests/ovn-northd.at > > @@ -877,25 +877,25 @@ check_flow_match_sets() { > > echo > > echo "IPv4: stateful" > > ovn-nbctl --wait=sb lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 > > -check_flow_match_sets 2 2 3 0 0 0 0 > > +check_flow_match_sets 3 4 2 0 0 0 0 > > ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 > > > > echo > > echo "IPv4: stateless" > > ovn-nbctl --wait=sb --stateless lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 > > -check_flow_match_sets 2 0 1 2 2 0 0 > > +check_flow_match_sets 2 0 0 2 2 0 0 > > ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 > > > > echo > > echo "IPv6: stateful" > > ovn-nbctl --wait=sb lr-nat-add R1 dnat_and_snat fd01::1 fd11::2 > > -check_flow_match_sets 2 2 3 0 0 0 0 > > +check_flow_match_sets 3 4 2 0 0 0 0 > > ovn-nbctl lr-nat-del R1 dnat_and_snat fd01::1 > > > > echo > > echo "IPv6: stateless" > > ovn-nbctl --wait=sb --stateless lr-nat-add R1 dnat_and_snat fd01::1 fd11::2 > > -check_flow_match_sets 2 0 1 0 0 2 2 > > +check_flow_match_sets 2 0 0 0 0 2 2 > > > > AT_CLEANUP > > ]) > > @@ -924,9 +924,9 @@ echo "CR-LRP UUID is: " $uuid > > ovn-nbctl --portrange lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 1-3000 > > > > AT_CAPTURE_FILE([sbflows]) > > -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows && test 2 = `grep -c lr_in_unsnat sbflows`]) > > +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows && test 3 = `grep -c lr_in_unsnat sbflows`]) > > AT_CHECK([grep -c 'ct_snat.*3000' sbflows && grep -c 'ct_dnat.*3000' sbflows], > > - [0], [1 > > + [0], [2 > > 1 > > ]) > > > > @@ -934,9 +934,9 @@ ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 > > ovn-nbctl --wait=sb --portrange lr-nat-add R1 snat 172.16.1.1 50.0.0.11 1-3000 > > > > AT_CAPTURE_FILE([sbflows2]) > > -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows2 && test 2 = `grep -c lr_in_unsnat sbflows`]) > > +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows2 && test 3 = `grep -c lr_in_unsnat sbflows`]) > > AT_CHECK([grep -c 'ct_snat.*3000' sbflows2 && grep -c 'ct_dnat.*3000' sbflows2], > > - [1], [1 > > + [1], [2 > > 0 > > ]) > > > > @@ -944,7 +944,7 @@ ovn-nbctl lr-nat-del R1 snat 172.16.1.1 > > ovn-nbctl --wait=sb --portrange --stateless lr-nat-add R1 dnat_and_snat 172.16.1.2 50.0.0.12 1-3000 > > > > AT_CAPTURE_FILE([sbflows3]) > > -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows3 && test 3 = `grep -c lr_in_unsnat sbflows3`]) > > +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows3 && test 4 = `grep -c lr_in_unsnat sbflows3`]) > > AT_CHECK([grep 'ct_[s]dnat.*172\.16\.1\.2.*3000' sbflows3], [1]) > > > > ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 > > @@ -1008,17 +1008,20 @@ AT_CAPTURE_FILE([drflows]) > > ovn-sbctl dump-flows CR > crflows > > AT_CAPTURE_FILE([crflows]) > > > > -AT_CHECK([ > > - grep -c lr_out_snat drflows > > - grep -c lr_out_snat crflows > > - grep lr_out_snat drflows | grep "ip4.src == 50.0.0.11" | grep -c "ip4.dst == $allowed_range" > > - grep lr_out_snat crflows | grep "ip4.src == 50.0.0.11" | grep -c "ip4.dst == $allowed_range"], [0], [dnl > > -3 > > -3 > > -1 > > -1 > > +AT_CHECK([grep -e "lr_out_snat" drflows | sed 's/table=../table=??/' | sort], [0], [dnl > > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ct_snat_in_czone(172.16.1.1);) > > + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.1);) > > +]) > > + > > +AT_CHECK([grep -e "lr_out_snat" crflows | sed 's/table=../table=??/' | sort], [0], [dnl > > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ct_snat(172.16.1.1);) > > ]) > > > > + > > # SNAT with DISALLOWED_IPs > > check ovn-nbctl lr-nat-del DR snat 50.0.0.11 > > check ovn-nbctl lr-nat-del CR snat 50.0.0.11 > > @@ -1036,19 +1039,19 @@ AT_CAPTURE_FILE([drflows2]) > > ovn-sbctl dump-flows CR > crflows2 > > AT_CAPTURE_FILE([crflows2]) > > > > -AT_CHECK([ > > - grep -c lr_out_snat drflows2 > > - grep -c lr_out_snat crflows2 > > - grep lr_out_snat drflows2 | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep -c "priority=162" > > - grep lr_out_snat drflows2 | grep "ip4.src == 50.0.0.11" | grep -c "priority=161" > > - grep lr_out_snat crflows2 | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep -c "priority=34" > > - grep lr_out_snat crflows2 | grep "ip4.src == 50.0.0.11" | grep -c "priority=33"], [0], [dnl > > -4 > > -4 > > -1 > > -1 > > -1 > > -1 > > +AT_CHECK([grep -e "lr_out_snat" drflows2 | sed 's/table=../table=??/' | sort], [0], [dnl > > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ct_snat_in_czone(172.16.1.1);) > > + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.1);) > > + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) > > +]) > > + > > +AT_CHECK([grep -e "lr_out_snat" crflows2 | sed 's/table=../table=??/' | sort], [0], [dnl > > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ct_snat(172.16.1.1);) > > + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) > > ]) > > > > # Stateful FIP with ALLOWED_IPs > > @@ -1059,25 +1062,24 @@ check ovn-nbctl lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11 > > check ovn-nbctl lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 > > > > check ovn-nbctl lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 allowed_range > > -check ovn-nbctl lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range > > +check ovn-nbctl --wait=sb lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range > > > > -ovn-nbctl show DR > > -ovn-sbctl dump-flows DR > > -ovn-nbctl show CR > > -ovn-sbctl dump-flows CR > > - > > -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ > > -wc -l`]) > > -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ > > -wc -l`]) > > +ovn-sbctl dump-flows DR > drflows3 > > +AT_CAPTURE_FILE([drflows2]) > > +ovn-sbctl dump-flows CR > crflows3 > > +AT_CAPTURE_FILE([crflows2]) > > > > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 > > +AT_CHECK([grep -e "lr_out_snat" drflows3 | sed 's/table=../table=??/' | sort], [0], [dnl > > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ct_snat_in_czone(172.16.1.2);) > > + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.2);) > > ]) > > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 > > -]) > > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 > > -]) > > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 > > + > > +AT_CHECK([grep -e "lr_out_snat" crflows3 | sed 's/table=../table=??/' | sort], [0], [dnl > > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ct_snat(172.16.1.2);) > > ]) > > > > # Stateful FIP with DISALLOWED_IPs > > @@ -1088,26 +1090,26 @@ ovn-nbctl lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11 > > ovn-nbctl lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 > > > > ovn-nbctl --is-exempted lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 disallowed_range > > -ovn-nbctl --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range > > +check ovn-nbctl --wait=sb --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range > > > > -ovn-nbctl show DR > > -ovn-sbctl dump-flows DR > > -ovn-nbctl show CR > > -ovn-sbctl dump-flows CR > > - > > -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ > > -wc -l`]) > > -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ > > -wc -l`]) > > +ovn-sbctl dump-flows DR > drflows4 > > +AT_CAPTURE_FILE([drflows2]) > > +ovn-sbctl dump-flows CR > crflows4 > > +AT_CAPTURE_FILE([crflows2]) > > > > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=162" | wc -l], [0], [1 > > -]) > > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 > > +AT_CHECK([grep -e "lr_out_snat" drflows4 | sed 's/table=../table=??/' | sort], [0], [dnl > > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ct_snat_in_czone(172.16.1.2);) > > + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.2);) > > + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) > > ]) > > > > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=34" | wc -l], [0], [1 > > -]) > > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 > > +AT_CHECK([grep -e "lr_out_snat" crflows4 | sed 's/table=../table=??/' | sort], [0], [dnl > > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ct_snat(172.16.1.2);) > > + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) > > ]) > > > > # Stateless FIP with DISALLOWED_IPs > > @@ -1120,24 +1122,21 @@ ovn-nbctl --stateless lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 > > ovn-nbctl lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 allowed_range > > ovn-nbctl lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range > > > > -ovn-nbctl show DR > > -ovn-sbctl dump-flows DR > > - > > -ovn-nbctl show CR > > -ovn-sbctl dump-flows CR > > - > > -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ > > -wc -l`]) > > -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ > > -wc -l`]) > > +ovn-sbctl dump-flows DR > drflows5 > > +AT_CAPTURE_FILE([drflows2]) > > +ovn-sbctl dump-flows CR > crflows5 > > +AT_CAPTURE_FILE([crflows2]) > > > > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 > > +AT_CHECK([grep -e "lr_out_snat" drflows5 | sed 's/table=../table=??/' | sort], [0], [dnl > > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ip4.src=172.16.1.2; next;) > > ]) > > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 > > -]) > > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 > > -]) > > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 > > + > > +AT_CHECK([grep -e "lr_out_snat" crflows5 | sed 's/table=../table=??/' | sort], [0], [dnl > > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ip4.src=172.16.1.2; next;) > > ]) > > > > # Stateful FIP with DISALLOWED_IPs > > @@ -1150,23 +1149,25 @@ ovn-nbctl --stateless lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 > > ovn-nbctl --is-exempted lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 disallowed_range > > ovn-nbctl --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range > > > > -ovn-nbctl show DR > > -ovn-sbctl dump-flows DR > > -ovn-nbctl show CR > > -ovn-sbctl dump-flows CR > > +ovn-nbctl --wait=sb sync > > > > -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ > > -wc -l`]) > > -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ > > -wc -l`]) > > +ovn-sbctl dump-flows DR > drflows6 > > +AT_CAPTURE_FILE([drflows2]) > > +ovn-sbctl dump-flows CR > crflows6 > > +AT_CAPTURE_FILE([crflows2]) > > > > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=162" | wc -l], [0], [1 > > -]) > > -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 > > +AT_CHECK([grep -e "lr_out_snat" drflows6 | sed 's/table=../table=??/' | sort], [0], [dnl > > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ip4.src=172.16.1.2; next;) > > + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) > > ]) > > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=34" | wc -l], [0], [1 > > -]) > > -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 > > + > > +AT_CHECK([grep -e "lr_out_snat" crflows6 | sed 's/table=../table=??/' | sort], [0], [dnl > > + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ip4.src=172.16.1.2; next;) > > + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) > > ]) > > > > AT_CLEANUP > > @@ -3475,14 +3476,14 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(ct_lb(backends=10.0.0.40:8080);) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > ]) > > > > check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="20.0.0.4 aef0::4" > > @@ -3511,21 +3512,21 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > > - table=2 (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip4), action=(ct_snat(20.0.0.4);) > > - table=2 (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip6), action=(ct_snat(aef0::4);) > > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip4), action=(ct_snat(20.0.0.4);) > > + table=? (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip6), action=(ct_snat(aef0::4);) > > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > ]) > > > > check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="router_ip" > > @@ -3557,22 +3558,22 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) > > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) > > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > ]) > > > > check ovn-nbctl --wait=sb remove logical_router lr0 options chassis > > @@ -3584,9 +3585,9 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl > > table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > ]) > > > > check ovn-nbctl set logical_router lr0 options:chassis=ch1 > > @@ -3617,23 +3618,23 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw1"), action=(ct_snat(bef0::1);) > > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw1"), action=(ct_snat(bef0::1);) > > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > ]) > > > > check ovn-nbctl --wait=sb lb-add lb2 10.0.0.20:80 10.0.0.40:8080 > > @@ -3661,18 +3662,18 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.20 && tcp && reg9[[16..31]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=120 , match=(flags.skip_snat_for_lb == 1 && ip), action=(next;) > > +AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=120 , match=(flags.skip_snat_for_lb == 1 && ip), action=(next;) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > ]) > > > > AT_CLEANUP > > @@ -4176,6 +4177,8 @@ check ovn-nbctl lsp-set-options lrp1-attachment router-port=lrp1 > > check ovn-nbctl lr-nat-add lr0 dnat 42.42.42.42 192.168.0.2 > > check ovn-nbctl --wait=sb sync > > > > +ovn-trace --minimal 'inport == "sw1-port1" && eth.src == 50:54:00:00:00:03 && eth.dst == 00:00:00:00:ff:02 && ip4.dst == 42.42.42.42 && ip4.src == 11.0.0.2 && ip.ttl == 64' > > + > > AT_CHECK([ovn-trace --minimal 'inport == "sw1-port1" && eth.src == 50:54:00:00:00:03 && eth.dst == 00:00:00:00:ff:02 && ip4.dst == 42.42.42.42 && ip4.src == 11.0.0.2 && ip.ttl == 64' | grep "output(\"sw0-port1\")"], [0], [ignore]) > > > > dnl If we remove the DNAT entry we will be unable to trace to the DNAT address > > @@ -4761,17 +4764,17 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > ]) > > > > # Create few dnat_and_snat entries > > @@ -4797,17 +4800,21 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > +]) > > + > > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > ]) > > > > ovn-sbctl chassis-add gw1 geneve 127.0.0.1 > > @@ -4828,9 +4835,12 @@ AT_CAPTURE_FILE([lr0flows]) > > > > AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl > > table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) > > - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > > - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > > - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > > ]) > > > > AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl > > @@ -4839,26 +4849,34 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl > > > > AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) > > - table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);) > > + table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone(10.0.0.3);) > > +]) > > + > > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > > + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.10 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > > + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.20 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > > + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.30 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > - table=0 (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > - table=2 (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.10);) > > - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.30);) > > - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.20);) > > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=? (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.10);) > > + table=? (lr_out_snat ), priority=154 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.10);) > > + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.30);) > > + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.20);) > > + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.30);) > > + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.20);) > > ]) > > > > # Associate load balancer to lr0 > > @@ -4879,9 +4897,12 @@ AT_CAPTURE_FILE([lr0flows]) > > > > AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl > > table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) > > - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > > - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > > - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > > + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > > ]) > > > > AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl > > @@ -4894,7 +4915,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl > > > > AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) > > - table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);) > > + table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone(10.0.0.3);) > > table=6 (lr_in_dnat ), priority=110 , match=(ct.est && ip4 && reg0 == 172.168.0.200 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) > > table=6 (lr_in_dnat ), priority=110 , match=(ct.new && ip4 && reg0 == 172.168.0.200 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.80,10.0.0.81);) > > table=6 (lr_in_dnat ), priority=120 , match=(ct.est && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) > > @@ -4905,27 +4926,35 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > - table=0 (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > > - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.4 && tcp.src == 8080)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > > - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && tcp.src == 82) || (ip4.src == 10.0.0.60 && tcp.src == 82)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > > - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && udp.src == 6062) || (ip4.src == 10.0.0.60 && udp.src == 6062)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > > - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.80) || (ip4.src == 10.0.0.81)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > > + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.10 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > > + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.20 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > > + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.30 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > > +]) > > + > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > > + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.4 && tcp.src == 8080)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > > + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && tcp.src == 82) || (ip4.src == 10.0.0.60 && tcp.src == 82)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > > + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && udp.src == 6062) || (ip4.src == 10.0.0.60 && udp.src == 6062)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > > + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.80) || (ip4.src == 10.0.0.81)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > - table=2 (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.10);) > > - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.30);) > > - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.20);) > > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=? (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.10);) > > + table=? (lr_out_snat ), priority=154 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.10);) > > + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.30);) > > + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.20);) > > + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.30);) > > + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.20);) > > ]) > > > > # Make the logical router as Gateway router > > @@ -4965,22 +4994,26 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +]) > > + > > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > > ]) > > > > # Set lb force snat logical router. > > @@ -5020,24 +5053,28 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > > +]) > > + > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > > ]) > > > > # Add a LB VIP same as router ip. > > @@ -5081,24 +5118,28 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +]) > > + > > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > > ]) > > > > # Add IPv6 router port and LB. > > @@ -5155,26 +5196,30 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip6 && xxreg0 == def0::2 && tcp && reg9[[16..31]] == 8000), action=(flags.force_snat_for_lb = 1; ct_lb(backends=[[aef0::2]]:80,[[aef0::3]]:80);) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > > +]) > > + > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-public"), action=(ct_snat(def0::10);) > > - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw0"), action=(ct_snat(aef0::1);) > > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > > - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-public"), action=(ct_snat(def0::10);) > > + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw0"), action=(ct_snat(aef0::1);) > > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > > + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > > ]) > > > > check ovn-nbctl lrp-del lr0-sw0 > > @@ -5209,19 +5254,23 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > > table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > > ]) > > > > -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > > - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > > +]) > > + > > +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > > ]) > > > > -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > > - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > > ]) > > > > -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > > - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > > - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > > + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > > + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > > ]) > > > > AT_CLEANUP > > diff --git a/tests/ovn.at b/tests/ovn.at > > index 0d606b42f..ae5744407 100644 > > --- a/tests/ovn.at > > +++ b/tests/ovn.at > > @@ -21604,7 +21604,7 @@ AT_CAPTURE_FILE([sbflows]) > > AT_CHECK([for regex in ct_snat ct_dnat ip4.dst= ip4.src=; do > > grep -c "$regex" sbflows; > > done], [0], [0 > > -1 > > +0 > > 2 > > 2 > > ]) > > diff --git a/tests/system-ovn.at b/tests/system-ovn.at > > index c9f5771c9..7f6cb32dc 100644 > > --- a/tests/system-ovn.at > > +++ b/tests/system-ovn.at > > @@ -2224,7 +2224,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=42 | \ > > +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. > > @@ -2262,7 +2262,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=42 | \ > > +OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=43 | \ > > grep 'nat(src=20.0.0.2)']) > > > > rm -f wget*.log > > @@ -3711,17 +3711,24 @@ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > icmpv6,orig=(src=fd20::2,dst=fd20::3,id=<cleared>,type=128,code=0),reply=(src=fd11::2,dst=fd20::2,id=<cleared>,type=129,code=0),zone=<cleared> > > ]) > > > > +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > + > > # South-North SNAT: 'foo2' pings 'alice1'. But 'alice1' receives traffic > > -# from 172.16.1.4 > > +# from fd20::4 > > NS_CHECK_EXEC([foo2], [ping6 -q -c 3 -i 0.3 -w 2 fd20::2 | FORMAT_PING], \ > > [0], [dnl > > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > > ]) > > > > -# We verify that SNAT indeed happened via 'dump-conntrack' command. > > +ovs-appctl dpctl/dump-conntrack | grep icmpv6 > > AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd11::3) | \ > > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > -icmpv6,orig=(src=fd11::3,dst=fd20::2,id=<cleared>,type=128,code=0),reply=(src=fd20::2,dst=fd11::3,id=<cleared>,type=129,code=0),zone=<cleared> > > +]) > > + > > +# We verify that SNAT indeed happened via 'dump-conntrack' command. > > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::4) | \ > > +sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > +icmpv6,orig=(src=fd11::3,dst=fd20::2,id=<cleared>,type=128,code=0),reply=(src=fd20::2,dst=fd20::4,id=<cleared>,type=129,code=0),zone=<cleared> > > ]) > > > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > @@ -3861,11 +3868,9 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \ > > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > > ]) > > > > -# We verify that the connection is tracked but not NATted. This is due to the > > -# unDNAT table in the egress router pipeline > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ > > +# We verify that the connection is not tracked. > > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ > > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > -icmp,orig=(src=192.168.1.2,dst=192.168.2.2,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> > > ]) > > > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > @@ -3875,11 +3880,9 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \ > > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > > ]) > > > > -# We verify that the connection is tracked but not NATted. This is due to the > > -# unDNAT table in the egress router pipeline > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ > > +# We verify that the connection is not tracked. > > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ > > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > -icmp,orig=(src=192.168.1.3,dst=192.168.2.2,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=192.168.1.3,id=<cleared>,type=0,code=0),zone=<cleared> > > ]) > > > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > @@ -3889,14 +3892,13 @@ NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.3 | FORMAT_PING], \ > > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > > ]) > > > > -# We verify that the connection is tracked but not NATted. This is due to the > > -# unDNAT table in the egress router pipeline > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ > > +# We verify that the connection is not tracked. > > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ > > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > -icmp,orig=(src=192.168.2.2,dst=192.168.1.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.3,dst=192.168.2.2,id=<cleared>,type=0,code=0),zone=<cleared> > > ]) > > > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > + > > # East-West NAT: 'foo1' pings 'bar1' using 172.16.1.4. > > NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ > > [0], [dnl > > @@ -3905,11 +3907,10 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ > > > > # Check conntrack entries. First SNAT of 'foo1' address happens. > > # Then DNAT of 'bar1' address happens (listed first below). > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) | \ > > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(172.16.1.4) | \ > > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > icmp,orig=(src=172.16.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared> > > icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared> > > -icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> > > ]) > > > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > @@ -3922,7 +3923,7 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ > > > > # Check conntrack entries. First SNAT of 'foo2' address happens. > > # Then DNAT of 'bar1' address happens (listed first below). > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \ > > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(172.16.1.1) | \ > > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> > > icmp,orig=(src=192.168.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> > > @@ -4055,13 +4056,6 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ > > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > > ]) > > > > -# We verify that the connection is tracked but not NATted. This is due to the > > -# unDNAT table in the egress router pipeline > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ > > -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > -icmpv6,orig=(src=fd11::2,dst=fd12::2,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd11::2,id=<cleared>,type=129,code=0),zone=<cleared> > > -]) > > - > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > # East-West No NAT: 'foo2' pings 'bar1' using fd12::2. > > NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ > > @@ -4069,13 +4063,6 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ > > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > > ]) > > > > -# We verify that the connection is tracked but not NATted. This is due to the > > -# unDNAT table in the egress router pipeline > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ > > -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > -icmpv6,orig=(src=fd11::3,dst=fd12::2,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd11::3,id=<cleared>,type=129,code=0),zone=<cleared> > > -]) > > - > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > # East-West No NAT: 'bar1' pings 'foo2' using fd11::3. > > NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 fd11::3 | FORMAT_PING], \ > > @@ -4083,13 +4070,6 @@ NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 fd11::3 | FORMAT_PING], \ > > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > > ]) > > > > -# We verify that the connection is tracked but not NATted. This is due to the > > -# unDNAT table in the egress router pipeline > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ > > -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > -icmpv6,orig=(src=fd12::2,dst=fd11::3,id=<cleared>,type=128,code=0),reply=(src=fd11::3,dst=fd12::2,id=<cleared>,type=129,code=0),zone=<cleared> > > -]) > > - > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > # East-West NAT: 'foo1' pings 'bar1' using fd20::4. > > NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd20::4 | FORMAT_PING], \ > > @@ -4101,7 +4081,6 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd20::4 | FORMAT_PING], \ > > # Then DNAT of 'bar1' address happens (listed first below). > > AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::4) | \ > > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > -icmpv6,orig=(src=fd11::2,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd20::4,dst=fd11::2,id=<cleared>,type=129,code=0),zone=<cleared> > > icmpv6,orig=(src=fd11::2,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd20::4,dst=fd20::3,id=<cleared>,type=129,code=0),zone=<cleared> > > icmpv6,orig=(src=fd20::3,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd20::3,id=<cleared>,type=129,code=0),zone=<cleared> > > ]) > > @@ -6037,7 +6016,6 @@ NS_CHECK_EXEC([sw01-x], [ping -q -c 3 -i 0.3 -w 2 172.16.1.100 | FORMAT_PING], \ > > AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.100) | \ > > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > icmp,orig=(src=192.168.1.2,dst=172.16.1.100,id=<cleared>,type=8,code=0),reply=(src=172.16.1.100,dst=172.16.1.20,id=<cleared>,type=0,code=0),zone=<cleared> > > -icmp,orig=(src=192.168.1.2,dst=172.16.1.100,id=<cleared>,type=8,code=0),reply=(src=172.16.1.100,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> > > ]) > > > > OVS_APP_EXIT_AND_WAIT([ovn-controller]) > > > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev >
On 11/18/21 18:42, Numan Siddique wrote: > On Thu, Nov 18, 2021 at 4:49 PM Mark Michelson <mmichels@redhat.com> wrote: >> >> Hi Numan, >> >> I had one question in the code and then one small finding in the >> documentation. See below: >> >> On 11/18/21 13:13, numans@ovn.org wrote: >>> From: Numan Siddique <numans@ovn.org> >>> >>> Make of use of these new actions for the distributed routers >>> for NAT. These new actions ensure that both sNAT and dNAT >>> happens in the same zone. This approach solves a couple of >>> problems: >>> >>> - The datapath flows generated for external traffic which requires >>> dNAT (N -> S) or sNAT (S -> N) are completely HWOL'able. >>> >>> - Since there is only one zone, it would avoid multiple recirculations >>> (improving the performance). >>> >>> If the packet needs to be both sNATted and dNATted (for hairpin traffic >>> with source and destination on the same chassis), then sNAT is done >>> in a separate zone. To detect this scenario, this patch adds a few >>> extra logical flows. For each dnat_and_snat entry prior to this patch >>> ovn-northd was generating 9 logical flows and with this patch it now >>> generates 12 logical flows. >>> >>> Similar approach can be taken for gateway routers. >>> >>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1984953 >>> Signed-off-by: Numan Siddique <numans@ovn.org> >>> --- >>> >>> v1 -> v2 >>> ------ >>> * Rebased and resolved conflicts. >>> >>> include/ovn/logical-fields.h | 1 + >>> lib/logical-fields.c | 4 + >>> northd/northd.c | 147 +++++++-- >>> northd/ovn-northd.8.xml | 201 +++++++++--- >>> tests/ovn-northd.at | 575 +++++++++++++++++++---------------- >>> tests/ovn.at | 2 +- >>> tests/system-ovn.at | 64 ++-- >>> 7 files changed, 607 insertions(+), 387 deletions(-) >>> >>> diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h >>> index c9675f81c..2118f7933 100644 >>> --- a/include/ovn/logical-fields.h >>> +++ b/include/ovn/logical-fields.h >>> @@ -70,6 +70,7 @@ enum mff_log_flags_bits { >>> MLF_LOOKUP_FDB_BIT = 8, >>> MLF_SKIP_SNAT_FOR_LB_BIT = 9, >>> MLF_LOCALPORT_BIT = 10, >>> + MLF_USE_SNAT_ZONE = 11, >>> }; >>> >>> /* MFF_LOG_FLAGS_REG flag assignments */ >>> diff --git a/lib/logical-fields.c b/lib/logical-fields.c >>> index 7b3d431e0..352a48c89 100644 >>> --- a/lib/logical-fields.c >>> +++ b/lib/logical-fields.c >>> @@ -125,6 +125,10 @@ ovn_init_symtab(struct shash *symtab) >>> MLF_SKIP_SNAT_FOR_LB_BIT); >>> expr_symtab_add_subfield(symtab, "flags.skip_snat_for_lb", NULL, >>> flags_str); >>> + snprintf(flags_str, sizeof flags_str, "flags[%d]", >>> + MLF_USE_SNAT_ZONE); >>> + expr_symtab_add_subfield(symtab, "flags.use_snat_zone", NULL, >>> + flags_str); >>> >>> /* Connection tracking state. */ >>> expr_symtab_add_field_scoped(symtab, "ct_mark", MFF_CT_MARK, NULL, false, >>> diff --git a/northd/northd.c b/northd/northd.c >>> index 0ff61deec..e4d051a94 100644 >>> --- a/northd/northd.c >>> +++ b/northd/northd.c >>> @@ -159,11 +159,14 @@ enum ovn_stage { >>> PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 18, "lr_in_arp_request") \ >>> \ >>> /* Logical router egress stages. */ \ >>> - PIPELINE_STAGE(ROUTER, OUT, UNDNAT, 0, "lr_out_undnat") \ >>> - PIPELINE_STAGE(ROUTER, OUT, POST_UNDNAT, 1, "lr_out_post_undnat") \ >>> - PIPELINE_STAGE(ROUTER, OUT, SNAT, 2, "lr_out_snat") \ >>> - PIPELINE_STAGE(ROUTER, OUT, EGR_LOOP, 3, "lr_out_egr_loop") \ >>> - PIPELINE_STAGE(ROUTER, OUT, DELIVERY, 4, "lr_out_delivery") >>> + PIPELINE_STAGE(ROUTER, OUT, CHECK_DNAT_LOCAL, 0, \ >>> + "lr_out_chk_dnat_local") \ >>> + PIPELINE_STAGE(ROUTER, OUT, UNDNAT, 1, "lr_out_undnat") \ >>> + PIPELINE_STAGE(ROUTER, OUT, POST_UNDNAT, 2, "lr_out_post_undnat") \ >>> + PIPELINE_STAGE(ROUTER, OUT, SNAT, 3, "lr_out_snat") \ >>> + PIPELINE_STAGE(ROUTER, OUT, POST_SNAT, 4, "lr_out_post_snat") \ >>> + PIPELINE_STAGE(ROUTER, OUT, EGR_LOOP, 5, "lr_out_egr_loop") \ >>> + PIPELINE_STAGE(ROUTER, OUT, DELIVERY, 6, "lr_out_delivery") >>> >>> #define PIPELINE_STAGE(DP_TYPE, PIPELINE, STAGE, TABLE, NAME) \ >>> S_##DP_TYPE##_##PIPELINE##_##STAGE \ >>> @@ -210,6 +213,7 @@ enum ovn_stage { >>> #define REGBIT_PKT_LARGER "reg9[1]" >>> #define REGBIT_LOOKUP_NEIGHBOR_RESULT "reg9[2]" >>> #define REGBIT_LOOKUP_NEIGHBOR_IP_RESULT "reg9[3]" >>> +#define REGBIT_DST_NAT_IP_LOCAL "reg9[4]" >>> >>> /* Register to store the eth address associated to a router port for packets >>> * received in S_ROUTER_IN_ADMISSION. >>> @@ -9568,9 +9572,10 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, >>> undnat_match_p, est_actions, >>> &lb->nlb->header_); >>> } else { >>> - ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 120, >>> - undnat_match_p, "ct_dnat;", >>> - &lb->nlb->header_); >>> + ovn_lflow_add_with_hint( >>> + lflows, od, S_ROUTER_OUT_UNDNAT, 120, undnat_match_p, >>> + od->is_gw_router ? "ct_dnat;" : "ct_dnat_in_czone;", >>> + &lb->nlb->header_); >>> } >>> free(undnat_match_p); >>> next: >>> @@ -9865,7 +9870,7 @@ lrouter_nat_add_ext_ip_match(struct ovn_datapath *od, >>> uint16_t priority; >>> >>> /* Priority of logical flows corresponding to exempted_ext_ips is >>> - * +1 of the corresponding regulr NAT rule. >>> + * +2 of the corresponding regular NAT rule. >>> * For example, if we have following NAT rule and we associate >>> * exempted external ips to it: >>> * "ovn-nbctl lr-nat-add router dnat_and_snat 10.15.24.139 50.0.0.11" >>> @@ -9873,17 +9878,17 @@ lrouter_nat_add_ext_ip_match(struct ovn_datapath *od, >>> * And now we associate exempted external ip address set to it. >>> * Now corresponding to above rule we will have following logical >>> * flows: >>> - * lr_out_snat...priority=162, match=(..ip4.dst == $exempt_range), >>> + * lr_out_snat...priority=163, match=(..ip4.dst == $exempt_range), >>> * action=(next;) >>> * lr_out_snat...priority=161, match=(..), action=(ct_snat(....);) >>> * >>> */ >>> if (is_src) { >>> /* S_ROUTER_IN_DNAT uses priority 100 */ >>> - priority = 100 + 1; >>> + priority = 100 + 2; >>> } else { >>> /* S_ROUTER_OUT_SNAT uses priority (mask + 1 + 128 + 1) */ >>> - priority = count_1bits(ntohl(mask)) + 2; >>> + priority = count_1bits(ntohl(mask)) + 3; >> >> I'm having trouble following why these priorities were raised. I looked >> at the changes to ovn-northd.8.xml to see if they were mentioned, but I >> couldn't find anything there that referenced the change. What am I >> missing here? :) > > Hi Mark, > > Thanks for the review. > > Let me try to explain with an example. > > Suppose a logical router - LR has below dnat_and_snat entry > > ovn-nbctl lr-nat-add LR dnat_and_snat 172.16.1.2 50.0.0.11 > > > And It also has the below configured > > ovn-nbctl create Address_Set name=disallowed_range addresses=\"2.2.2.2\" > ovn-nbctl --is-exempted lr-nat-update-ext-ip LR dnat_and_snat > 172.16.1.2 disallowed_range > > Before this patch, below logical flows were programmed in LR_OUT_SNAT stage > > table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == > 50.0.0.11 && outport == "LR-S1" && is_chassis_resident("cr-DR-S1")), > action=(ct_snat_in_czone(172.16.1.1);) > table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == > 50.0.0.11 && outport == "LR-S1" && is_chassis_resident("cr-DR-S1") && > ip4.dst == $disallowed_range), action=(next;) > > The priority-162 flow basically skips the SNAT if the destination ip > belongs to the address set 'disallowed_range' > > Now this patch changes the priority-162 to 163 flow and adds another > flow with the priority - 162. > > table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == > 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), > action=(ct_snat_in_czone(172.16.1.1);) > table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == > 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && > reg9[4] == 1), action=(reg9[4] = 0; ct_snat(172.16.1.1);) > table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == > 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && > ip4.dst == $disallowed_range), action=(next;) > > > If you notice, the priority-162 flow is almost the same as the > prio-161 flow with the extra match - reg9[4] == 1. > > > I'll update the documentation accordingly. > > This patch could also do something like below > > table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == > 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && > reg9[4] == 0), action=(ct_snat_in_czone(172.16.1.1);) > table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == > 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && > reg9[4] == 1), action=(reg9[4] = 0; ct_snat(172.16.1.1);) > table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == > 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && > ip4.dst == $disallowed_range), action=(next;) > > Let me know which one you'd prefer ? I guess both would work. I like the way you've done it here better than your alternate proposal. Thank you for the explanation. > > Thanks > Numan > >> > >>> >>> if (!od->is_gw_router) { >>> priority += 128; >>> @@ -12268,9 +12273,9 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, >>> /* Traffic received on l3dgw_port is subject to NAT. */ >>> ds_clear(match); >>> ds_clear(actions); >>> - ds_put_format(match, "ip && ip%s.dst == %s && inport == %s", >>> - is_v6 ? "6" : "4", nat->external_ip, >>> - od->l3dgw_ports[0]->json_key); >>> + ds_put_format(match, "ip && ip%s.dst == %s && inport == %s && " >>> + "flags.loopback == 0", is_v6 ? "6" : "4", >>> + nat->external_ip, od->l3dgw_ports[0]->json_key); >>> if (!distributed && od->n_l3dgw_ports) { >>> /* Flows for NAT rules that are centralized are only >>> * programmed on the gateway chassis. */ >>> @@ -12282,12 +12287,31 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, >>> ds_put_format(actions, "ip%s.dst=%s; next;", >>> is_v6 ? "6" : "4", nat->logical_ip); >>> } else { >>> - ds_put_cstr(actions, "ct_snat;"); >>> + ds_put_cstr(actions, "ct_snat_in_czone;"); >>> } >>> >>> ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT, >>> 100, ds_cstr(match), ds_cstr(actions), >>> &nat->header_); >>> + >>> + if (!stateless) { >>> + ds_clear(match); >>> + ds_clear(actions); >>> + ds_put_format(match, "ip && ip%s.dst == %s && inport == %s && " >>> + "flags.loopback == 1 && flags.use_snat_zone == 1", >>> + is_v6 ? "6" : "4", nat->external_ip, >>> + od->l3dgw_ports[0]->json_key); >>> + if (!distributed && od->n_l3dgw_ports) { >>> + /* Flows for NAT rules that are centralized are only >>> + * programmed on the gateway chassis. */ >>> + ds_put_format(match, " && is_chassis_resident(%s)", >>> + od->l3dgw_ports[0]->cr_port->json_key); >>> + } >>> + ds_put_cstr(actions, "ct_snat;"); >>> + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT, >>> + 100, ds_cstr(match), ds_cstr(actions), >>> + &nat->header_); >>> + } >>> } >>> } >>> >>> @@ -12364,7 +12388,7 @@ build_lrouter_in_dnat_flow(struct hmap *lflows, struct ovn_datapath *od, >>> ds_put_format(actions, "ip%s.dst=%s; next;", >>> is_v6 ? "6" : "4", nat->logical_ip); >>> } else { >>> - ds_put_format(actions, "ct_dnat(%s", nat->logical_ip); >>> + ds_put_format(actions, "ct_dnat_in_czone(%s", nat->logical_ip); >>> if (nat->external_port_range[0]) { >>> ds_put_format(actions, ",%s", nat->external_port_range); >>> } >>> @@ -12417,7 +12441,8 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od, >>> ds_put_format(actions, "ip%s.src=%s; next;", >>> is_v6 ? "6" : "4", nat->external_ip); >>> } else { >>> - ds_put_format(actions, "ct_dnat;"); >>> + ds_put_format(actions, >>> + od->is_gw_router ? "ct_dnat;" : "ct_dnat_in_czone;"); >>> } >>> >>> ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 100, >>> @@ -12425,6 +12450,36 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od, >>> &nat->header_); >>> } >>> >>> +static void >>> +build_lrouter_out_is_dnat_local(struct hmap *lflows, struct ovn_datapath *od, >>> + const struct nbrec_nat *nat, struct ds *match, >>> + struct ds *actions, bool distributed, >>> + bool is_v6) >>> +{ >>> + /* Note that this only applies for NAT on a distributed router. >>> + */ >>> + if (!od->n_l3dgw_ports) { >>> + return; >>> + } >>> + >>> + ds_clear(match); >>> + ds_put_format(match, "ip && ip%s.dst == %s && ", >>> + is_v6 ? "6" : "4", nat->external_ip); >>> + if (distributed) { >>> + ds_put_format(match, "is_chassis_resident(\"%s\")", nat->logical_port); >>> + } else { >>> + ds_put_format(match, "is_chassis_resident(%s)", >>> + od->l3dgw_ports[0]->cr_port->json_key); >>> + } >>> + >>> + ds_clear(actions); >>> + ds_put_cstr(actions, REGBIT_DST_NAT_IP_LOCAL" = 1; next;"); >>> + >>> + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_CHECK_DNAT_LOCAL, >>> + 50, ds_cstr(match), ds_cstr(actions), >>> + &nat->header_); >>> +} >>> + >>> static void >>> build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, >>> const struct nbrec_nat *nat, struct ds *match, >>> @@ -12478,16 +12533,19 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, >>> ds_put_format(match, "ip && ip%s.src == %s && outport == %s", >>> is_v6 ? "6" : "4", nat->logical_ip, >>> od->l3dgw_ports[0]->json_key); >>> - if (!distributed && od->n_l3dgw_ports) { >>> - /* Flows for NAT rules that are centralized are only >>> - * programmed on the gateway chassis. */ >>> - priority += 128; >>> - ds_put_format(match, " && is_chassis_resident(%s)", >>> - od->l3dgw_ports[0]->cr_port->json_key); >>> - } else if (distributed) { >>> - priority += 128; >>> - ds_put_format(match, " && is_chassis_resident(\"%s\")", >>> - nat->logical_port); >>> + if (od->n_l3dgw_ports) { >>> + if (distributed) { >>> + ovs_assert(nat->logical_port); >>> + priority += 128; >>> + ds_put_format(match, " && is_chassis_resident(\"%s\")", >>> + nat->logical_port); >>> + } else { >>> + /* Flows for NAT rules that are centralized are only >>> + * programmed on the gateway chassis. */ >>> + priority += 128; >>> + ds_put_format(match, " && is_chassis_resident(%s)", >>> + od->l3dgw_ports[0]->cr_port->json_key); >>> + } >>> } >>> ds_clear(actions); >>> >>> @@ -12505,7 +12563,7 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, >>> ds_put_format(actions, "ip%s.src=%s; next;", >>> is_v6 ? "6" : "4", nat->external_ip); >>> } else { >>> - ds_put_format(actions, "ct_snat(%s", >>> + ds_put_format(actions, "ct_snat_in_czone(%s", >>> nat->external_ip); >>> if (nat->external_port_range[0]) { >>> ds_put_format(actions, ",%s", nat->external_port_range); >>> @@ -12519,6 +12577,24 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, >>> ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT, >>> priority, ds_cstr(match), >>> ds_cstr(actions), &nat->header_); >>> + >>> + if (!stateless) { >>> + ds_put_cstr(match, " && "REGBIT_DST_NAT_IP_LOCAL" == 1"); >>> + ds_clear(actions); >>> + if (distributed) { >>> + ds_put_format(actions, "eth.src = "ETH_ADDR_FMT"; ", >>> + ETH_ADDR_ARGS(mac)); >>> + } >>> + ds_put_format(actions, REGBIT_DST_NAT_IP_LOCAL" = 0; ct_snat(%s", >>> + nat->external_ip); >>> + if (nat->external_port_range[0]) { >>> + ds_put_format(actions, ",%s", nat->external_port_range); >>> + } >>> + ds_put_format(actions, ");"); >>> + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT, >>> + priority + 1, ds_cstr(match), >>> + ds_cstr(actions), &nat->header_); >>> + } >>> } >>> } >>> >>> @@ -12749,10 +12825,13 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, >>> /* Packets are allowed by default. */ >>> ovn_lflow_add(lflows, od, S_ROUTER_IN_DEFRAG, 0, "1", "next;"); >>> ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, 0, "1", "next;"); >>> + ovn_lflow_add(lflows, od, S_ROUTER_OUT_CHECK_DNAT_LOCAL, 0, "1", >>> + REGBIT_DST_NAT_IP_LOCAL" = 0; next;"); >>> ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, 0, "1", "next;"); >>> ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 0, "1", "next;"); >>> ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 0, "1", "next;"); >>> ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 0, "1", "next;"); >>> + ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_SNAT, 0, "1", "next;"); >>> 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;"); >>> >>> @@ -12765,8 +12844,7 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, >>> * not committed, it would produce ongoing datapath flows with the ct.new >>> * flag set. Some NICs are unable to offload these flows. >>> */ >>> - if ((od->is_gw_router || od->n_l3dgw_ports) && >>> - (od->nbr->n_nat || od->has_lb_vip)) { >>> + if (od->is_gw_router && (od->nbr->n_nat || od->has_lb_vip)) { >>> ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 50, >>> "ip", "flags.loopback = 1; ct_dnat;"); >>> ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 50, >>> @@ -12839,6 +12917,10 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, >>> } >>> } >>> >>> + /* S_ROUTER_OUT_DNAT_LOCAL */ >>> + build_lrouter_out_is_dnat_local(lflows, od, nat, match, actions, >>> + distributed, is_v6); >>> + >>> /* S_ROUTER_OUT_UNDNAT */ >>> build_lrouter_out_undnat_flow(lflows, od, nat, match, actions, distributed, >>> mac, is_v6); >>> @@ -12912,7 +12994,8 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, >>> "clone { ct_clear; " >>> "inport = outport; outport = \"\"; " >>> "eth.dst <-> eth.src; " >>> - "flags = 0; flags.loopback = 1; "); >>> + "flags = 0; flags.loopback = 1; " >>> + "flags.use_snat_zone = "REGBIT_DST_NAT_IP_LOCAL"; "); >>> for (int j = 0; j < MFF_N_LOG_REGS; j++) { >>> ds_put_format(actions, "reg%d = 0; ", j); >>> } >>> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml >>> index 21d83718c..fc9d51ea7 100644 >>> --- a/northd/ovn-northd.8.xml >>> +++ b/northd/ovn-northd.8.xml >>> @@ -2879,23 +2879,65 @@ icmp6 { >>> <p> >>> For each configuration in the OVN Northbound database, that asks >>> to change the source IP address of a packet from <var>A</var> to >>> - <var>B</var>, a priority-100 flow matches <code>ip && >>> - ip4.dst == <var>B</var> && inport == <var>GW</var></code> or >>> - <code>ip && >>> - ip6.dst == <var>B</var> && inport == <var>GW</var></code> >>> - where <var>GW</var> is the logical router gateway port, with an >>> - action <code>ct_snat;</code>. If the NAT rule is of type >>> - dnat_and_snat and has <code>stateless=true</code> in the >>> - options, then the action would be <code>ip4/6.dst= >>> - (<var>B</var>)</code>. >>> + <var>B</var>, two priority-100 flows are added. >>> </p> >>> >>> <p> >>> If the NAT rule cannot be handled in a distributed manner, then >>> - the priority-100 flow above is only programmed on the >>> + the below priority-100 flows are only programmed on the >>> gateway chassis. >>> </p> >>> >>> + <ul> >>> + <li> >>> + <p> >>> + The first flow matches <code>ip && >>> + ip4.dst == <var>B</var> && inport == <var>GW</var> >>> + && flags.loopback == 0</code> or >>> + <code>ip && >>> + ip6.dst == <var>B</var> && inport == <var>GW</var> >>> + && flags.loopback == 0</code> >>> + where <var>GW</var> is the logical router gateway port, with an >>> + action <code>ct_snat_in_czone;</code> to unSNAT in the common >>> + zone. If the NAT rule is of type dnat_and_snat and has >>> + <code>stateless=true</code> in the options, then the action >>> + would be <code>ip4/6.dst=(<var>B</var>)</code>. >>> + </p> >>> + >>> + <p> >>> + If the NAT entry is of type <code>snat</code>, then there is an >>> + additional match <code>is_chassis_resident(<var>cr-GW</var>) >>> + </code> where <var>cr-GW</var> is the chassis resident port of >>> + <var>GW</var>. >>> + </p> >>> + </li> >>> + >>> + <li> >>> + <p> >>> + The second flow matches <code>ip && >>> + ip4.dst == <var>B</var> && inport == <var>GW</var> >>> + && flags.loopback == 1 && >>> + flags.use_snat_zone == 1</code> or >>> + <code>ip && >>> + ip6.dst == <var>B</var> && inport == <var>GW</var> >>> + && flags.loopback == 0 && >>> + flags.use_snat_zone == 1</code> >>> + where <var>GW</var> is the logical router gateway port, with an >>> + action <code>ct_snat;</code> to unSNAT in the snat zone. If the >>> + NAT rule is of type dnat_and_snat and has >>> + <code>stateless=true</code> in the options, then the action >>> + would be <code>ip4/6.dst=(<var>B</var>)</code>. >>> + </p> >>> + >>> + <p> >>> + If the NAT entry is of type <code>snat</code>, then there is an >>> + additional match <code>is_chassis_resident(<var>cr-GW</var>) >>> + </code> where <var>cr-GW</var> is the chassis resident port of >>> + <var>GW</var>. >>> + </p> >>> + </li> >>> + </ul> >>> + >>> <p> >>> A priority-0 logical flow with match <code>1</code> has actions >>> <code>next;</code>. >>> @@ -4031,7 +4073,43 @@ nd_ns { >>> </li> >>> </ul> >>> >>> - <h3>Egress Table 0: UNDNAT</h3> >>> + <h3>Egress Table 0: Check DNAT local </h3> >>> + >>> + <p> >>> + This table checks if the packet needs to be DNATed in the router ingress >>> + table <code>lr_out_dnat</code> after it is SNATed and looped back >> >> s/lr_out_dnat/lr_in_dnat/ >> >>> + to the ingress pipeline. This check is done only for routers configured >>> + with distributed gateway ports and NAT entries. This check is done >>> + so that SNAT and DNAT is done in different zones instead of a common >>> + zone. >>> + </p> >>> + >>> + <ul> >>> + <li> >>> + <p> >>> + For each NAT rule in the OVN Northbound database on a >>> + distributed router, a priority-50 logical flow with match >>> + <code>ip4.dst == <var>E</var> && >>> + is_chassis_resident(<var>P</var>)</code>, where <var>E</var> is the >>> + external IP address specified in the NAT rule, <var>GW</var> >>> + is the logical router distributed gateway port. For dnat_and_snat >>> + NAT rule, <var>P</var> is the logical port specified in the NAT rule. >>> + If <ref column="logical_port" >>> + table="NAT" db="OVN_Northbound"/> column of >>> + <ref table="NAT" db="OVN_Northbound"/> table is NOT set, then >>> + <var>P</var> is the <code>chassisredirect port</code> of >>> + <var>GW</var> with the actions: >>> + <code>REGBIT_DST_NAT_IP_LOCAL = 1; next; </code> >>> + </p> >>> + </li> >>> + >>> + <li> >>> + A priority-0 logical flow with match <code>1</code> has actions >>> + <code>REGBIT_DST_NAT_IP_LOCAL = 0; next;</code>. >>> + </li> >>> + </ul> >>> + >>> + <h3>Egress Table 1: UNDNAT</h3> >>> >>> <p> >>> This is for already established connections' reverse traffic. >>> @@ -4040,6 +4118,23 @@ nd_ns { >>> is unDNATed here. >>> </p> >>> >>> + <ul> >>> + <li> >>> + A priority-0 logical flow with match <code>1</code> has actions >>> + <code>next;</code>. >>> + </li> >>> + </ul> >>> + >>> + <h3>Egress Table 1: UNDNAT on Gateway Routers</h3> >>> + >>> + <ul> >>> + <li> >>> + For all IP packets, a priority-50 flow with an action >>> + <code>flags.loopback = 1; ct_dnat;</code>. >>> + </li> >>> + </ul> >>> + >>> + <h3>Egress Table 1: UNDNAT on Distributed Routers</h3> >>> <ul> >>> <li> >>> <p> >>> @@ -4050,9 +4145,9 @@ nd_ns { >>> gateway chassis that matches >>> <code>ip && ip4.src == <var>B</var> && >>> outport == <var>GW</var></code>, where <var>GW</var> is the logical >>> - router gateway port with an action <code>ct_dnat;</code>. If the >>> - backend IPv4 address <var>B</var> is also configured with L4 port >>> - <var>PORT</var> of protocol <var>P</var>, then the >>> + router gateway port with an action <code>ct_dnat_in_czone;</code>. >>> + If the backend IPv4 address <var>B</var> is also configured with >>> + L4 port <var>PORT</var> of protocol <var>P</var>, then the >>> match also includes <code>P.src</code> == <var>PORT</var>. These >>> flows are not added for load balancers with IPv6 <var>VIPs</var>. >>> </p> >>> @@ -4072,7 +4167,7 @@ nd_ns { >>> matches <code>ip && ip4.src == <var>B</var> >>> && outport == <var>GW</var></code>, where <var>GW</var> >>> is the logical router gateway port, with an action >>> - <code>ct_dnat;</code>. If the NAT rule is of type >>> + <code>ct_dnat_in_czone;</code>. If the NAT rule is of type >>> dnat_and_snat and has <code>stateless=true</code> in the >>> options, then the action would be <code>ip4/6.src= >>> (<var>B</var>)</code>. >>> @@ -4081,7 +4176,7 @@ nd_ns { >>> <p> >>> If the NAT rule cannot be handled in a distributed manner, then >>> the priority-100 flow above is only programmed on the >>> - gateway chassis. >>> + gateway chassis with the action <code>ct_dnat_in_czone</code>. >>> </p> >>> >>> <p> >>> @@ -4094,26 +4189,17 @@ nd_ns { >>> </p> >>> </li> >>> >>> - <li> >>> - For all IP packets, a priority-50 flow with an action >>> - <code>flags.loopback = 1; ct_dnat;</code>. >>> - </li> >>> - >>> - <li> >>> - A priority-0 logical flow with match <code>1</code> has actions >>> - <code>next;</code>. >>> - </li> >>> </ul> >>> >>> - <h3>Egress Table 1: Post UNDNAT</h3> >>> + <h3>Egress Table 2: Post UNDNAT</h3> >>> >>> <p> >>> <ul> >>> <li> >>> A priority-50 logical flow is added that commits any untracked flows >>> - from the previous table <code>lr_out_undnat</code>. This flow >>> - matches on <code>ct.new && ip</code> with action >>> - <code>ct_commit { } ; next; </code>. >>> + from the previous table <code>lr_out_undnat</code> for Gateway >>> + routers. This flow matches on <code>ct.new && ip</code> >>> + with action <code>ct_commit { } ; next; </code>. >>> </li> >>> >>> <li> >>> @@ -4124,7 +4210,7 @@ nd_ns { >>> </ul> >>> </p> >>> >>> - <h3>Egress Table 2: SNAT</h3> >>> + <h3>Egress Table 3: SNAT</h3> >>> >>> <p> >>> Packets that are configured to be SNATed get their source IP address >>> @@ -4140,7 +4226,7 @@ nd_ns { >>> </li> >>> </ul> >>> >>> - <p>Egress Table 2: SNAT on Gateway Routers</p> >>> + <p>Egress Table 3: SNAT on Gateway Routers</p> >>> >>> <ul> >>> <li> >>> @@ -4239,7 +4325,7 @@ nd_ns { >>> </li> >>> </ul> >>> >>> - <p>Egress Table 2: SNAT on Distributed Routers</p> >>> + <p>Egress Table 3: SNAT on Distributed Routers</p> >>> >>> <ul> >>> <li> >>> @@ -4247,28 +4333,46 @@ nd_ns { >>> For each configuration in the OVN Northbound database, that asks >>> to change the source IP address of a packet from an IP address of >>> <var>A</var> or to change the source IP address of a packet that >>> - belongs to network <var>A</var> to <var>B</var>, a flow matches >>> - <code>ip && ip4.src == <var>A</var> && >>> - outport == <var>GW</var></code>, where <var>GW</var> is the >>> - logical router gateway port, with an action >>> - <code>ct_snat(<var>B</var>);</code>. The priority of the flow >>> - is calculated based on the mask of <var>A</var>, with matches >>> - having larger masks getting higher priorities. If the NAT rule >>> - is of type dnat_and_snat and has <code>stateless=true</code> >>> - in the options, then the action would be <code>ip4/6.src= >>> - (<var>B</var>)</code>. >>> + belongs to network <var>A</var> to <var>B</var>, two flows are >>> + added. The priority of these flows are calculated based on the >>> + mask of <var>A</var>, with matches having larger masks getting >>> + higher priorities. >>> </p> >>> >>> <p> >>> If the NAT rule cannot be handled in a distributed manner, then >>> - the flow above is only programmed on the >>> - gateway chassis increasing flow priority by 128 in >>> - order to be run first >>> + the below flows are only programmed on the gateway chassis increasing >>> + flow priority by 128 in order to be run first. >>> </p> >>> >>> + <ul> >>> + <li> >>> + The first flow is added with the match >>> + <code>ip && ip4.src == <var>A</var> && >>> + outport == <var>GW</var></code>, where <var>GW</var> is the >>> + logical router gateway port, with an action >>> + <code>ct_snat_in_czone(<var>B</var>);</code> to SNATed in the >>> + common zone. If the NAT rule is of type dnat_and_snat and has >>> + <code>stateless=true</code> in the options, then the action >>> + would be <code>ip4/6.src=(<var>B</var>)</code>. >>> + </li> >>> + >>> + <li> >>> + The second flow is added with the match >>> + <code>ip && ip4.src == <var>A</var> && >>> + outport == <var>GW</var> && >>> + REGBIT_DST_NAT_IP_LOCAL == 0</code>, where <var>GW</var> is the >>> + logical router gateway port, with an action >>> + <code>ct_snat(<var>B</var>);</code> to SNAT in the snat zone. >>> + If the NAT rule is of type dnat_and_snat and has >>> + <code>stateless=true</code> in the options, then the action would >>> + be <code>ip4/6.src=(<var>B</var>)</code>. >>> + </li> >>> + </ul> >>> + >>> <p> >>> If the NAT rule can be handled in a distributed manner, then >>> - there is an additional action >>> + there is an additional action (for both the flows) >>> <code>eth.src = <var>EA</var>;</code>, where <var>EA</var> >>> is the ethernet address associated with the IP address >>> <var>A</var> in the NAT rule. This allows upstream MAC >>> @@ -4299,7 +4403,7 @@ nd_ns { >>> </li> >>> </ul> >>> >>> - <h3>Egress Table 3: Egress Loopback</h3> >>> + <h3>Egress Table 4: Egress Loopback</h3> >>> >>> <p> >>> For distributed logical routers where one of the logical router >>> @@ -4344,6 +4448,7 @@ clone { >>> outport = ""; >>> flags = 0; >>> flags.loopback = 1; >>> + flags.use_snat_zone = REGBIT_DST_NAT_IP_LOCAL; >>> reg0 = 0; >>> reg1 = 0; >>> ... >>> @@ -4368,7 +4473,7 @@ clone { >>> </li> >>> </ul> >>> >>> - <h3>Egress Table 4: Delivery</h3> >>> + <h3>Egress Table 5: Delivery</h3> >>> >>> <p> >>> Packets that reach this table are ready for delivery. It contains: >>> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at >>> index 85b47a18f..70ec5e2e3 100644 >>> --- a/tests/ovn-northd.at >>> +++ b/tests/ovn-northd.at >>> @@ -877,25 +877,25 @@ check_flow_match_sets() { >>> echo >>> echo "IPv4: stateful" >>> ovn-nbctl --wait=sb lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 >>> -check_flow_match_sets 2 2 3 0 0 0 0 >>> +check_flow_match_sets 3 4 2 0 0 0 0 >>> ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 >>> >>> echo >>> echo "IPv4: stateless" >>> ovn-nbctl --wait=sb --stateless lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 >>> -check_flow_match_sets 2 0 1 2 2 0 0 >>> +check_flow_match_sets 2 0 0 2 2 0 0 >>> ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 >>> >>> echo >>> echo "IPv6: stateful" >>> ovn-nbctl --wait=sb lr-nat-add R1 dnat_and_snat fd01::1 fd11::2 >>> -check_flow_match_sets 2 2 3 0 0 0 0 >>> +check_flow_match_sets 3 4 2 0 0 0 0 >>> ovn-nbctl lr-nat-del R1 dnat_and_snat fd01::1 >>> >>> echo >>> echo "IPv6: stateless" >>> ovn-nbctl --wait=sb --stateless lr-nat-add R1 dnat_and_snat fd01::1 fd11::2 >>> -check_flow_match_sets 2 0 1 0 0 2 2 >>> +check_flow_match_sets 2 0 0 0 0 2 2 >>> >>> AT_CLEANUP >>> ]) >>> @@ -924,9 +924,9 @@ echo "CR-LRP UUID is: " $uuid >>> ovn-nbctl --portrange lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 1-3000 >>> >>> AT_CAPTURE_FILE([sbflows]) >>> -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows && test 2 = `grep -c lr_in_unsnat sbflows`]) >>> +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows && test 3 = `grep -c lr_in_unsnat sbflows`]) >>> AT_CHECK([grep -c 'ct_snat.*3000' sbflows && grep -c 'ct_dnat.*3000' sbflows], >>> - [0], [1 >>> + [0], [2 >>> 1 >>> ]) >>> >>> @@ -934,9 +934,9 @@ ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 >>> ovn-nbctl --wait=sb --portrange lr-nat-add R1 snat 172.16.1.1 50.0.0.11 1-3000 >>> >>> AT_CAPTURE_FILE([sbflows2]) >>> -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows2 && test 2 = `grep -c lr_in_unsnat sbflows`]) >>> +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows2 && test 3 = `grep -c lr_in_unsnat sbflows`]) >>> AT_CHECK([grep -c 'ct_snat.*3000' sbflows2 && grep -c 'ct_dnat.*3000' sbflows2], >>> - [1], [1 >>> + [1], [2 >>> 0 >>> ]) >>> >>> @@ -944,7 +944,7 @@ ovn-nbctl lr-nat-del R1 snat 172.16.1.1 >>> ovn-nbctl --wait=sb --portrange --stateless lr-nat-add R1 dnat_and_snat 172.16.1.2 50.0.0.12 1-3000 >>> >>> AT_CAPTURE_FILE([sbflows3]) >>> -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows3 && test 3 = `grep -c lr_in_unsnat sbflows3`]) >>> +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows3 && test 4 = `grep -c lr_in_unsnat sbflows3`]) >>> AT_CHECK([grep 'ct_[s]dnat.*172\.16\.1\.2.*3000' sbflows3], [1]) >>> >>> ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 >>> @@ -1008,17 +1008,20 @@ AT_CAPTURE_FILE([drflows]) >>> ovn-sbctl dump-flows CR > crflows >>> AT_CAPTURE_FILE([crflows]) >>> >>> -AT_CHECK([ >>> - grep -c lr_out_snat drflows >>> - grep -c lr_out_snat crflows >>> - grep lr_out_snat drflows | grep "ip4.src == 50.0.0.11" | grep -c "ip4.dst == $allowed_range" >>> - grep lr_out_snat crflows | grep "ip4.src == 50.0.0.11" | grep -c "ip4.dst == $allowed_range"], [0], [dnl >>> -3 >>> -3 >>> -1 >>> -1 >>> +AT_CHECK([grep -e "lr_out_snat" drflows | sed 's/table=../table=??/' | sort], [0], [dnl >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ct_snat_in_czone(172.16.1.1);) >>> + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.1);) >>> +]) >>> + >>> +AT_CHECK([grep -e "lr_out_snat" crflows | sed 's/table=../table=??/' | sort], [0], [dnl >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ct_snat(172.16.1.1);) >>> ]) >>> >>> + >>> # SNAT with DISALLOWED_IPs >>> check ovn-nbctl lr-nat-del DR snat 50.0.0.11 >>> check ovn-nbctl lr-nat-del CR snat 50.0.0.11 >>> @@ -1036,19 +1039,19 @@ AT_CAPTURE_FILE([drflows2]) >>> ovn-sbctl dump-flows CR > crflows2 >>> AT_CAPTURE_FILE([crflows2]) >>> >>> -AT_CHECK([ >>> - grep -c lr_out_snat drflows2 >>> - grep -c lr_out_snat crflows2 >>> - grep lr_out_snat drflows2 | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep -c "priority=162" >>> - grep lr_out_snat drflows2 | grep "ip4.src == 50.0.0.11" | grep -c "priority=161" >>> - grep lr_out_snat crflows2 | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep -c "priority=34" >>> - grep lr_out_snat crflows2 | grep "ip4.src == 50.0.0.11" | grep -c "priority=33"], [0], [dnl >>> -4 >>> -4 >>> -1 >>> -1 >>> -1 >>> -1 >>> +AT_CHECK([grep -e "lr_out_snat" drflows2 | sed 's/table=../table=??/' | sort], [0], [dnl >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ct_snat_in_czone(172.16.1.1);) >>> + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.1);) >>> + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) >>> +]) >>> + >>> +AT_CHECK([grep -e "lr_out_snat" crflows2 | sed 's/table=../table=??/' | sort], [0], [dnl >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ct_snat(172.16.1.1);) >>> + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) >>> ]) >>> >>> # Stateful FIP with ALLOWED_IPs >>> @@ -1059,25 +1062,24 @@ check ovn-nbctl lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11 >>> check ovn-nbctl lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 >>> >>> check ovn-nbctl lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 allowed_range >>> -check ovn-nbctl lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range >>> +check ovn-nbctl --wait=sb lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range >>> >>> -ovn-nbctl show DR >>> -ovn-sbctl dump-flows DR >>> -ovn-nbctl show CR >>> -ovn-sbctl dump-flows CR >>> - >>> -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ >>> -wc -l`]) >>> -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ >>> -wc -l`]) >>> +ovn-sbctl dump-flows DR > drflows3 >>> +AT_CAPTURE_FILE([drflows2]) >>> +ovn-sbctl dump-flows CR > crflows3 >>> +AT_CAPTURE_FILE([crflows2]) >>> >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 >>> +AT_CHECK([grep -e "lr_out_snat" drflows3 | sed 's/table=../table=??/' | sort], [0], [dnl >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ct_snat_in_czone(172.16.1.2);) >>> + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.2);) >>> ]) >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 >>> -]) >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 >>> -]) >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 >>> + >>> +AT_CHECK([grep -e "lr_out_snat" crflows3 | sed 's/table=../table=??/' | sort], [0], [dnl >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ct_snat(172.16.1.2);) >>> ]) >>> >>> # Stateful FIP with DISALLOWED_IPs >>> @@ -1088,26 +1090,26 @@ ovn-nbctl lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11 >>> ovn-nbctl lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 >>> >>> ovn-nbctl --is-exempted lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 disallowed_range >>> -ovn-nbctl --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range >>> +check ovn-nbctl --wait=sb --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range >>> >>> -ovn-nbctl show DR >>> -ovn-sbctl dump-flows DR >>> -ovn-nbctl show CR >>> -ovn-sbctl dump-flows CR >>> - >>> -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ >>> -wc -l`]) >>> -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ >>> -wc -l`]) >>> +ovn-sbctl dump-flows DR > drflows4 >>> +AT_CAPTURE_FILE([drflows2]) >>> +ovn-sbctl dump-flows CR > crflows4 >>> +AT_CAPTURE_FILE([crflows2]) >>> >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=162" | wc -l], [0], [1 >>> -]) >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 >>> +AT_CHECK([grep -e "lr_out_snat" drflows4 | sed 's/table=../table=??/' | sort], [0], [dnl >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ct_snat_in_czone(172.16.1.2);) >>> + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.2);) >>> + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) >>> ]) >>> >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=34" | wc -l], [0], [1 >>> -]) >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 >>> +AT_CHECK([grep -e "lr_out_snat" crflows4 | sed 's/table=../table=??/' | sort], [0], [dnl >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ct_snat(172.16.1.2);) >>> + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) >>> ]) >>> >>> # Stateless FIP with DISALLOWED_IPs >>> @@ -1120,24 +1122,21 @@ ovn-nbctl --stateless lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 >>> ovn-nbctl lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 allowed_range >>> ovn-nbctl lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range >>> >>> -ovn-nbctl show DR >>> -ovn-sbctl dump-flows DR >>> - >>> -ovn-nbctl show CR >>> -ovn-sbctl dump-flows CR >>> - >>> -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ >>> -wc -l`]) >>> -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ >>> -wc -l`]) >>> +ovn-sbctl dump-flows DR > drflows5 >>> +AT_CAPTURE_FILE([drflows2]) >>> +ovn-sbctl dump-flows CR > crflows5 >>> +AT_CAPTURE_FILE([crflows2]) >>> >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 >>> +AT_CHECK([grep -e "lr_out_snat" drflows5 | sed 's/table=../table=??/' | sort], [0], [dnl >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ip4.src=172.16.1.2; next;) >>> ]) >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 >>> -]) >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 >>> -]) >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 >>> + >>> +AT_CHECK([grep -e "lr_out_snat" crflows5 | sed 's/table=../table=??/' | sort], [0], [dnl >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ip4.src=172.16.1.2; next;) >>> ]) >>> >>> # Stateful FIP with DISALLOWED_IPs >>> @@ -1150,23 +1149,25 @@ ovn-nbctl --stateless lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 >>> ovn-nbctl --is-exempted lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 disallowed_range >>> ovn-nbctl --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range >>> >>> -ovn-nbctl show DR >>> -ovn-sbctl dump-flows DR >>> -ovn-nbctl show CR >>> -ovn-sbctl dump-flows CR >>> +ovn-nbctl --wait=sb sync >>> >>> -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ >>> -wc -l`]) >>> -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ >>> -wc -l`]) >>> +ovn-sbctl dump-flows DR > drflows6 >>> +AT_CAPTURE_FILE([drflows2]) >>> +ovn-sbctl dump-flows CR > crflows6 >>> +AT_CAPTURE_FILE([crflows2]) >>> >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=162" | wc -l], [0], [1 >>> -]) >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 >>> +AT_CHECK([grep -e "lr_out_snat" drflows6 | sed 's/table=../table=??/' | sort], [0], [dnl >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ip4.src=172.16.1.2; next;) >>> + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) >>> ]) >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=34" | wc -l], [0], [1 >>> -]) >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 >>> + >>> +AT_CHECK([grep -e "lr_out_snat" crflows6 | sed 's/table=../table=??/' | sort], [0], [dnl >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ip4.src=172.16.1.2; next;) >>> + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) >>> ]) >>> >>> AT_CLEANUP >>> @@ -3475,14 +3476,14 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(ct_lb(backends=10.0.0.40:8080);) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> ]) >>> >>> check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="20.0.0.4 aef0::4" >>> @@ -3511,21 +3512,21 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> - table=2 (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip4), action=(ct_snat(20.0.0.4);) >>> - table=2 (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip6), action=(ct_snat(aef0::4);) >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip4), action=(ct_snat(20.0.0.4);) >>> + table=? (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip6), action=(ct_snat(aef0::4);) >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> ]) >>> >>> check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="router_ip" >>> @@ -3557,22 +3558,22 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> ]) >>> >>> check ovn-nbctl --wait=sb remove logical_router lr0 options chassis >>> @@ -3584,9 +3585,9 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl >>> table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> ]) >>> >>> check ovn-nbctl set logical_router lr0 options:chassis=ch1 >>> @@ -3617,23 +3618,23 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw1"), action=(ct_snat(bef0::1);) >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw1"), action=(ct_snat(bef0::1);) >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> ]) >>> >>> check ovn-nbctl --wait=sb lb-add lb2 10.0.0.20:80 10.0.0.40:8080 >>> @@ -3661,18 +3662,18 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.20 && tcp && reg9[[16..31]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=120 , match=(flags.skip_snat_for_lb == 1 && ip), action=(next;) >>> +AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=120 , match=(flags.skip_snat_for_lb == 1 && ip), action=(next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> ]) >>> >>> AT_CLEANUP >>> @@ -4176,6 +4177,8 @@ check ovn-nbctl lsp-set-options lrp1-attachment router-port=lrp1 >>> check ovn-nbctl lr-nat-add lr0 dnat 42.42.42.42 192.168.0.2 >>> check ovn-nbctl --wait=sb sync >>> >>> +ovn-trace --minimal 'inport == "sw1-port1" && eth.src == 50:54:00:00:00:03 && eth.dst == 00:00:00:00:ff:02 && ip4.dst == 42.42.42.42 && ip4.src == 11.0.0.2 && ip.ttl == 64' >>> + >>> AT_CHECK([ovn-trace --minimal 'inport == "sw1-port1" && eth.src == 50:54:00:00:00:03 && eth.dst == 00:00:00:00:ff:02 && ip4.dst == 42.42.42.42 && ip4.src == 11.0.0.2 && ip.ttl == 64' | grep "output(\"sw0-port1\")"], [0], [ignore]) >>> >>> dnl If we remove the DNAT entry we will be unable to trace to the DNAT address >>> @@ -4761,17 +4764,17 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> ]) >>> >>> # Create few dnat_and_snat entries >>> @@ -4797,17 +4800,21 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> +]) >>> + >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> ]) >>> >>> ovn-sbctl chassis-add gw1 geneve 127.0.0.1 >>> @@ -4828,9 +4835,12 @@ AT_CAPTURE_FILE([lr0flows]) >>> >>> AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl >>> table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) >>> - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) >>> - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) >>> - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) >>> ]) >>> >>> AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl >>> @@ -4839,26 +4849,34 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl >>> >>> AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) >>> - table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);) >>> + table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone(10.0.0.3);) >>> +]) >>> + >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) >>> + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.10 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) >>> + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.20 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) >>> + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.30 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> - table=0 (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> - table=2 (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.10);) >>> - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.30);) >>> - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.20);) >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=? (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.10);) >>> + table=? (lr_out_snat ), priority=154 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.10);) >>> + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.30);) >>> + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.20);) >>> + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.30);) >>> + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.20);) >>> ]) >>> >>> # Associate load balancer to lr0 >>> @@ -4879,9 +4897,12 @@ AT_CAPTURE_FILE([lr0flows]) >>> >>> AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl >>> table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) >>> - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) >>> - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) >>> - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) >>> ]) >>> >>> AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl >>> @@ -4894,7 +4915,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl >>> >>> AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) >>> - table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);) >>> + table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone(10.0.0.3);) >>> table=6 (lr_in_dnat ), priority=110 , match=(ct.est && ip4 && reg0 == 172.168.0.200 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) >>> table=6 (lr_in_dnat ), priority=110 , match=(ct.new && ip4 && reg0 == 172.168.0.200 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.80,10.0.0.81);) >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.est && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) >>> @@ -4905,27 +4926,35 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> - table=0 (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) >>> - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.4 && tcp.src == 8080)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) >>> - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && tcp.src == 82) || (ip4.src == 10.0.0.60 && tcp.src == 82)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) >>> - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && udp.src == 6062) || (ip4.src == 10.0.0.60 && udp.src == 6062)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) >>> - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.80) || (ip4.src == 10.0.0.81)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) >>> + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.10 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) >>> + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.20 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) >>> + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.30 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) >>> +]) >>> + >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) >>> + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.4 && tcp.src == 8080)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) >>> + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && tcp.src == 82) || (ip4.src == 10.0.0.60 && tcp.src == 82)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) >>> + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && udp.src == 6062) || (ip4.src == 10.0.0.60 && udp.src == 6062)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) >>> + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.80) || (ip4.src == 10.0.0.81)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> - table=2 (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.10);) >>> - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.30);) >>> - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.20);) >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=? (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.10);) >>> + table=? (lr_out_snat ), priority=154 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.10);) >>> + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.30);) >>> + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.20);) >>> + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.30);) >>> + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.20);) >>> ]) >>> >>> # Make the logical router as Gateway router >>> @@ -4965,22 +4994,26 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +]) >>> + >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) >>> ]) >>> >>> # Set lb force snat logical router. >>> @@ -5020,24 +5053,28 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) >>> +]) >>> + >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) >>> ]) >>> >>> # Add a LB VIP same as router ip. >>> @@ -5081,24 +5118,28 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +]) >>> + >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) >>> ]) >>> >>> # Add IPv6 router port and LB. >>> @@ -5155,26 +5196,30 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip6 && xxreg0 == def0::2 && tcp && reg9[[16..31]] == 8000), action=(flags.force_snat_for_lb = 1; ct_lb(backends=[[aef0::2]]:80,[[aef0::3]]:80);) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) >>> +]) >>> + >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-public"), action=(ct_snat(def0::10);) >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw0"), action=(ct_snat(aef0::1);) >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-public"), action=(ct_snat(def0::10);) >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw0"), action=(ct_snat(aef0::1);) >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) >>> ]) >>> >>> check ovn-nbctl lrp-del lr0-sw0 >>> @@ -5209,19 +5254,23 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) >>> +]) >>> + >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) >>> ]) >>> >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) >>> ]) >>> >>> AT_CLEANUP >>> diff --git a/tests/ovn.at b/tests/ovn.at >>> index 0d606b42f..ae5744407 100644 >>> --- a/tests/ovn.at >>> +++ b/tests/ovn.at >>> @@ -21604,7 +21604,7 @@ AT_CAPTURE_FILE([sbflows]) >>> AT_CHECK([for regex in ct_snat ct_dnat ip4.dst= ip4.src=; do >>> grep -c "$regex" sbflows; >>> done], [0], [0 >>> -1 >>> +0 >>> 2 >>> 2 >>> ]) >>> diff --git a/tests/system-ovn.at b/tests/system-ovn.at >>> index c9f5771c9..7f6cb32dc 100644 >>> --- a/tests/system-ovn.at >>> +++ b/tests/system-ovn.at >>> @@ -2224,7 +2224,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=42 | \ >>> +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. >>> @@ -2262,7 +2262,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=42 | \ >>> +OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=43 | \ >>> grep 'nat(src=20.0.0.2)']) >>> >>> rm -f wget*.log >>> @@ -3711,17 +3711,24 @@ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl >>> icmpv6,orig=(src=fd20::2,dst=fd20::3,id=<cleared>,type=128,code=0),reply=(src=fd11::2,dst=fd20::2,id=<cleared>,type=129,code=0),zone=<cleared> >>> ]) >>> >>> +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) >>> + >>> # South-North SNAT: 'foo2' pings 'alice1'. But 'alice1' receives traffic >>> -# from 172.16.1.4 >>> +# from fd20::4 >>> NS_CHECK_EXEC([foo2], [ping6 -q -c 3 -i 0.3 -w 2 fd20::2 | FORMAT_PING], \ >>> [0], [dnl >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms >>> ]) >>> >>> -# We verify that SNAT indeed happened via 'dump-conntrack' command. >>> +ovs-appctl dpctl/dump-conntrack | grep icmpv6 >>> AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd11::3) | \ >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl >>> -icmpv6,orig=(src=fd11::3,dst=fd20::2,id=<cleared>,type=128,code=0),reply=(src=fd20::2,dst=fd11::3,id=<cleared>,type=129,code=0),zone=<cleared> >>> +]) >>> + >>> +# We verify that SNAT indeed happened via 'dump-conntrack' command. >>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::4) | \ >>> +sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl >>> +icmpv6,orig=(src=fd11::3,dst=fd20::2,id=<cleared>,type=128,code=0),reply=(src=fd20::2,dst=fd20::4,id=<cleared>,type=129,code=0),zone=<cleared> >>> ]) >>> >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) >>> @@ -3861,11 +3868,9 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \ >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms >>> ]) >>> >>> -# We verify that the connection is tracked but not NATted. This is due to the >>> -# unDNAT table in the egress router pipeline >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ >>> +# We verify that the connection is not tracked. >>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl >>> -icmp,orig=(src=192.168.1.2,dst=192.168.2.2,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> >>> ]) >>> >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) >>> @@ -3875,11 +3880,9 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \ >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms >>> ]) >>> >>> -# We verify that the connection is tracked but not NATted. This is due to the >>> -# unDNAT table in the egress router pipeline >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ >>> +# We verify that the connection is not tracked. >>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl >>> -icmp,orig=(src=192.168.1.3,dst=192.168.2.2,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=192.168.1.3,id=<cleared>,type=0,code=0),zone=<cleared> >>> ]) >>> >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) >>> @@ -3889,14 +3892,13 @@ NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.3 | FORMAT_PING], \ >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms >>> ]) >>> >>> -# We verify that the connection is tracked but not NATted. This is due to the >>> -# unDNAT table in the egress router pipeline >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ >>> +# We verify that the connection is not tracked. >>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl >>> -icmp,orig=(src=192.168.2.2,dst=192.168.1.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.3,dst=192.168.2.2,id=<cleared>,type=0,code=0),zone=<cleared> >>> ]) >>> >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) >>> + >>> # East-West NAT: 'foo1' pings 'bar1' using 172.16.1.4. >>> NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ >>> [0], [dnl >>> @@ -3905,11 +3907,10 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ >>> >>> # Check conntrack entries. First SNAT of 'foo1' address happens. >>> # Then DNAT of 'bar1' address happens (listed first below). >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) | \ >>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(172.16.1.4) | \ >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl >>> icmp,orig=(src=172.16.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared> >>> icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared> >>> -icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> >>> ]) >>> >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) >>> @@ -3922,7 +3923,7 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ >>> >>> # Check conntrack entries. First SNAT of 'foo2' address happens. >>> # Then DNAT of 'bar1' address happens (listed first below). >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \ >>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(172.16.1.1) | \ >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl >>> icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> >>> icmp,orig=(src=192.168.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> >>> @@ -4055,13 +4056,6 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms >>> ]) >>> >>> -# We verify that the connection is tracked but not NATted. This is due to the >>> -# unDNAT table in the egress router pipeline >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ >>> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl >>> -icmpv6,orig=(src=fd11::2,dst=fd12::2,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd11::2,id=<cleared>,type=129,code=0),zone=<cleared> >>> -]) >>> - >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) >>> # East-West No NAT: 'foo2' pings 'bar1' using fd12::2. >>> NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ >>> @@ -4069,13 +4063,6 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms >>> ]) >>> >>> -# We verify that the connection is tracked but not NATted. This is due to the >>> -# unDNAT table in the egress router pipeline >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ >>> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl >>> -icmpv6,orig=(src=fd11::3,dst=fd12::2,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd11::3,id=<cleared>,type=129,code=0),zone=<cleared> >>> -]) >>> - >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) >>> # East-West No NAT: 'bar1' pings 'foo2' using fd11::3. >>> NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 fd11::3 | FORMAT_PING], \ >>> @@ -4083,13 +4070,6 @@ NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 fd11::3 | FORMAT_PING], \ >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms >>> ]) >>> >>> -# We verify that the connection is tracked but not NATted. This is due to the >>> -# unDNAT table in the egress router pipeline >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ >>> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl >>> -icmpv6,orig=(src=fd12::2,dst=fd11::3,id=<cleared>,type=128,code=0),reply=(src=fd11::3,dst=fd12::2,id=<cleared>,type=129,code=0),zone=<cleared> >>> -]) >>> - >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) >>> # East-West NAT: 'foo1' pings 'bar1' using fd20::4. >>> NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd20::4 | FORMAT_PING], \ >>> @@ -4101,7 +4081,6 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd20::4 | FORMAT_PING], \ >>> # Then DNAT of 'bar1' address happens (listed first below). >>> AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::4) | \ >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl >>> -icmpv6,orig=(src=fd11::2,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd20::4,dst=fd11::2,id=<cleared>,type=129,code=0),zone=<cleared> >>> icmpv6,orig=(src=fd11::2,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd20::4,dst=fd20::3,id=<cleared>,type=129,code=0),zone=<cleared> >>> icmpv6,orig=(src=fd20::3,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd20::3,id=<cleared>,type=129,code=0),zone=<cleared> >>> ]) >>> @@ -6037,7 +6016,6 @@ NS_CHECK_EXEC([sw01-x], [ping -q -c 3 -i 0.3 -w 2 172.16.1.100 | FORMAT_PING], \ >>> AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.100) | \ >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl >>> icmp,orig=(src=192.168.1.2,dst=172.16.1.100,id=<cleared>,type=8,code=0),reply=(src=172.16.1.100,dst=172.16.1.20,id=<cleared>,type=0,code=0),zone=<cleared> >>> -icmp,orig=(src=192.168.1.2,dst=172.16.1.100,id=<cleared>,type=8,code=0),reply=(src=172.16.1.100,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> >>> ]) >>> >>> OVS_APP_EXIT_AND_WAIT([ovn-controller]) >>> >> >> _______________________________________________ >> dev mailing list >> dev@openvswitch.org >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev >> >
On Fri, Nov 19, 2021 at 11:16 AM Mark Michelson <mmichels@redhat.com> wrote: > > On 11/18/21 18:42, Numan Siddique wrote: > > On Thu, Nov 18, 2021 at 4:49 PM Mark Michelson <mmichels@redhat.com> wrote: > >> > >> Hi Numan, > >> > >> I had one question in the code and then one small finding in the > >> documentation. See below: > >> > >> On 11/18/21 13:13, numans@ovn.org wrote: > >>> From: Numan Siddique <numans@ovn.org> > >>> > >>> Make of use of these new actions for the distributed routers > >>> for NAT. These new actions ensure that both sNAT and dNAT > >>> happens in the same zone. This approach solves a couple of > >>> problems: > >>> > >>> - The datapath flows generated for external traffic which requires > >>> dNAT (N -> S) or sNAT (S -> N) are completely HWOL'able. > >>> > >>> - Since there is only one zone, it would avoid multiple recirculations > >>> (improving the performance). > >>> > >>> If the packet needs to be both sNATted and dNATted (for hairpin traffic > >>> with source and destination on the same chassis), then sNAT is done > >>> in a separate zone. To detect this scenario, this patch adds a few > >>> extra logical flows. For each dnat_and_snat entry prior to this patch > >>> ovn-northd was generating 9 logical flows and with this patch it now > >>> generates 12 logical flows. > >>> > >>> Similar approach can be taken for gateway routers. > >>> > >>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1984953 > >>> Signed-off-by: Numan Siddique <numans@ovn.org> > >>> --- > >>> > >>> v1 -> v2 > >>> ------ > >>> * Rebased and resolved conflicts. > >>> > >>> include/ovn/logical-fields.h | 1 + > >>> lib/logical-fields.c | 4 + > >>> northd/northd.c | 147 +++++++-- > >>> northd/ovn-northd.8.xml | 201 +++++++++--- > >>> tests/ovn-northd.at | 575 +++++++++++++++++++---------------- > >>> tests/ovn.at | 2 +- > >>> tests/system-ovn.at | 64 ++-- > >>> 7 files changed, 607 insertions(+), 387 deletions(-) > >>> > >>> diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h > >>> index c9675f81c..2118f7933 100644 > >>> --- a/include/ovn/logical-fields.h > >>> +++ b/include/ovn/logical-fields.h > >>> @@ -70,6 +70,7 @@ enum mff_log_flags_bits { > >>> MLF_LOOKUP_FDB_BIT = 8, > >>> MLF_SKIP_SNAT_FOR_LB_BIT = 9, > >>> MLF_LOCALPORT_BIT = 10, > >>> + MLF_USE_SNAT_ZONE = 11, > >>> }; > >>> > >>> /* MFF_LOG_FLAGS_REG flag assignments */ > >>> diff --git a/lib/logical-fields.c b/lib/logical-fields.c > >>> index 7b3d431e0..352a48c89 100644 > >>> --- a/lib/logical-fields.c > >>> +++ b/lib/logical-fields.c > >>> @@ -125,6 +125,10 @@ ovn_init_symtab(struct shash *symtab) > >>> MLF_SKIP_SNAT_FOR_LB_BIT); > >>> expr_symtab_add_subfield(symtab, "flags.skip_snat_for_lb", NULL, > >>> flags_str); > >>> + snprintf(flags_str, sizeof flags_str, "flags[%d]", > >>> + MLF_USE_SNAT_ZONE); > >>> + expr_symtab_add_subfield(symtab, "flags.use_snat_zone", NULL, > >>> + flags_str); > >>> > >>> /* Connection tracking state. */ > >>> expr_symtab_add_field_scoped(symtab, "ct_mark", MFF_CT_MARK, NULL, false, > >>> diff --git a/northd/northd.c b/northd/northd.c > >>> index 0ff61deec..e4d051a94 100644 > >>> --- a/northd/northd.c > >>> +++ b/northd/northd.c > >>> @@ -159,11 +159,14 @@ enum ovn_stage { > >>> PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 18, "lr_in_arp_request") \ > >>> \ > >>> /* Logical router egress stages. */ \ > >>> - PIPELINE_STAGE(ROUTER, OUT, UNDNAT, 0, "lr_out_undnat") \ > >>> - PIPELINE_STAGE(ROUTER, OUT, POST_UNDNAT, 1, "lr_out_post_undnat") \ > >>> - PIPELINE_STAGE(ROUTER, OUT, SNAT, 2, "lr_out_snat") \ > >>> - PIPELINE_STAGE(ROUTER, OUT, EGR_LOOP, 3, "lr_out_egr_loop") \ > >>> - PIPELINE_STAGE(ROUTER, OUT, DELIVERY, 4, "lr_out_delivery") > >>> + PIPELINE_STAGE(ROUTER, OUT, CHECK_DNAT_LOCAL, 0, \ > >>> + "lr_out_chk_dnat_local") \ > >>> + PIPELINE_STAGE(ROUTER, OUT, UNDNAT, 1, "lr_out_undnat") \ > >>> + PIPELINE_STAGE(ROUTER, OUT, POST_UNDNAT, 2, "lr_out_post_undnat") \ > >>> + PIPELINE_STAGE(ROUTER, OUT, SNAT, 3, "lr_out_snat") \ > >>> + PIPELINE_STAGE(ROUTER, OUT, POST_SNAT, 4, "lr_out_post_snat") \ > >>> + PIPELINE_STAGE(ROUTER, OUT, EGR_LOOP, 5, "lr_out_egr_loop") \ > >>> + PIPELINE_STAGE(ROUTER, OUT, DELIVERY, 6, "lr_out_delivery") > >>> > >>> #define PIPELINE_STAGE(DP_TYPE, PIPELINE, STAGE, TABLE, NAME) \ > >>> S_##DP_TYPE##_##PIPELINE##_##STAGE \ > >>> @@ -210,6 +213,7 @@ enum ovn_stage { > >>> #define REGBIT_PKT_LARGER "reg9[1]" > >>> #define REGBIT_LOOKUP_NEIGHBOR_RESULT "reg9[2]" > >>> #define REGBIT_LOOKUP_NEIGHBOR_IP_RESULT "reg9[3]" > >>> +#define REGBIT_DST_NAT_IP_LOCAL "reg9[4]" > >>> > >>> /* Register to store the eth address associated to a router port for packets > >>> * received in S_ROUTER_IN_ADMISSION. > >>> @@ -9568,9 +9572,10 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, > >>> undnat_match_p, est_actions, > >>> &lb->nlb->header_); > >>> } else { > >>> - ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 120, > >>> - undnat_match_p, "ct_dnat;", > >>> - &lb->nlb->header_); > >>> + ovn_lflow_add_with_hint( > >>> + lflows, od, S_ROUTER_OUT_UNDNAT, 120, undnat_match_p, > >>> + od->is_gw_router ? "ct_dnat;" : "ct_dnat_in_czone;", > >>> + &lb->nlb->header_); > >>> } > >>> free(undnat_match_p); > >>> next: > >>> @@ -9865,7 +9870,7 @@ lrouter_nat_add_ext_ip_match(struct ovn_datapath *od, > >>> uint16_t priority; > >>> > >>> /* Priority of logical flows corresponding to exempted_ext_ips is > >>> - * +1 of the corresponding regulr NAT rule. > >>> + * +2 of the corresponding regular NAT rule. > >>> * For example, if we have following NAT rule and we associate > >>> * exempted external ips to it: > >>> * "ovn-nbctl lr-nat-add router dnat_and_snat 10.15.24.139 50.0.0.11" > >>> @@ -9873,17 +9878,17 @@ lrouter_nat_add_ext_ip_match(struct ovn_datapath *od, > >>> * And now we associate exempted external ip address set to it. > >>> * Now corresponding to above rule we will have following logical > >>> * flows: > >>> - * lr_out_snat...priority=162, match=(..ip4.dst == $exempt_range), > >>> + * lr_out_snat...priority=163, match=(..ip4.dst == $exempt_range), > >>> * action=(next;) > >>> * lr_out_snat...priority=161, match=(..), action=(ct_snat(....);) > >>> * > >>> */ > >>> if (is_src) { > >>> /* S_ROUTER_IN_DNAT uses priority 100 */ > >>> - priority = 100 + 1; > >>> + priority = 100 + 2; > >>> } else { > >>> /* S_ROUTER_OUT_SNAT uses priority (mask + 1 + 128 + 1) */ > >>> - priority = count_1bits(ntohl(mask)) + 2; > >>> + priority = count_1bits(ntohl(mask)) + 3; > >> > >> I'm having trouble following why these priorities were raised. I looked > >> at the changes to ovn-northd.8.xml to see if they were mentioned, but I > >> couldn't find anything there that referenced the change. What am I > >> missing here? :) > > > > Hi Mark, > > > > Thanks for the review. > > > > Let me try to explain with an example. > > > > Suppose a logical router - LR has below dnat_and_snat entry > > > > ovn-nbctl lr-nat-add LR dnat_and_snat 172.16.1.2 50.0.0.11 > > > > > > And It also has the below configured > > > > ovn-nbctl create Address_Set name=disallowed_range addresses=\"2.2.2.2\" > > ovn-nbctl --is-exempted lr-nat-update-ext-ip LR dnat_and_snat > > 172.16.1.2 disallowed_range > > > > Before this patch, below logical flows were programmed in LR_OUT_SNAT stage > > > > table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == > > 50.0.0.11 && outport == "LR-S1" && is_chassis_resident("cr-DR-S1")), > > action=(ct_snat_in_czone(172.16.1.1);) > > table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == > > 50.0.0.11 && outport == "LR-S1" && is_chassis_resident("cr-DR-S1") && > > ip4.dst == $disallowed_range), action=(next;) > > > > The priority-162 flow basically skips the SNAT if the destination ip > > belongs to the address set 'disallowed_range' > > > > Now this patch changes the priority-162 to 163 flow and adds another > > flow with the priority - 162. > > > > table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == > > 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), > > action=(ct_snat_in_czone(172.16.1.1);) > > table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == > > 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && > > reg9[4] == 1), action=(reg9[4] = 0; ct_snat(172.16.1.1);) > > table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == > > 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && > > ip4.dst == $disallowed_range), action=(next;) > > > > > > If you notice, the priority-162 flow is almost the same as the > > prio-161 flow with the extra match - reg9[4] == 1. > > > > > > I'll update the documentation accordingly. > > > > This patch could also do something like below > > > > table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == > > 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && > > reg9[4] == 0), action=(ct_snat_in_czone(172.16.1.1);) > > table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == > > 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && > > reg9[4] == 1), action=(reg9[4] = 0; ct_snat(172.16.1.1);) > > table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == > > 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && > > ip4.dst == $disallowed_range), action=(next;) > > > > Let me know which one you'd prefer ? I guess both would work. > > I like the way you've done it here better than your alternate proposal. > Thank you for the explanation. Thanks. I've submitted v3 updating the documentation. Numan > > > > > Thanks > > Numan > > > >> > > > >>> > >>> if (!od->is_gw_router) { > >>> priority += 128; > >>> @@ -12268,9 +12273,9 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, > >>> /* Traffic received on l3dgw_port is subject to NAT. */ > >>> ds_clear(match); > >>> ds_clear(actions); > >>> - ds_put_format(match, "ip && ip%s.dst == %s && inport == %s", > >>> - is_v6 ? "6" : "4", nat->external_ip, > >>> - od->l3dgw_ports[0]->json_key); > >>> + ds_put_format(match, "ip && ip%s.dst == %s && inport == %s && " > >>> + "flags.loopback == 0", is_v6 ? "6" : "4", > >>> + nat->external_ip, od->l3dgw_ports[0]->json_key); > >>> if (!distributed && od->n_l3dgw_ports) { > >>> /* Flows for NAT rules that are centralized are only > >>> * programmed on the gateway chassis. */ > >>> @@ -12282,12 +12287,31 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, > >>> ds_put_format(actions, "ip%s.dst=%s; next;", > >>> is_v6 ? "6" : "4", nat->logical_ip); > >>> } else { > >>> - ds_put_cstr(actions, "ct_snat;"); > >>> + ds_put_cstr(actions, "ct_snat_in_czone;"); > >>> } > >>> > >>> ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT, > >>> 100, ds_cstr(match), ds_cstr(actions), > >>> &nat->header_); > >>> + > >>> + if (!stateless) { > >>> + ds_clear(match); > >>> + ds_clear(actions); > >>> + ds_put_format(match, "ip && ip%s.dst == %s && inport == %s && " > >>> + "flags.loopback == 1 && flags.use_snat_zone == 1", > >>> + is_v6 ? "6" : "4", nat->external_ip, > >>> + od->l3dgw_ports[0]->json_key); > >>> + if (!distributed && od->n_l3dgw_ports) { > >>> + /* Flows for NAT rules that are centralized are only > >>> + * programmed on the gateway chassis. */ > >>> + ds_put_format(match, " && is_chassis_resident(%s)", > >>> + od->l3dgw_ports[0]->cr_port->json_key); > >>> + } > >>> + ds_put_cstr(actions, "ct_snat;"); > >>> + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT, > >>> + 100, ds_cstr(match), ds_cstr(actions), > >>> + &nat->header_); > >>> + } > >>> } > >>> } > >>> > >>> @@ -12364,7 +12388,7 @@ build_lrouter_in_dnat_flow(struct hmap *lflows, struct ovn_datapath *od, > >>> ds_put_format(actions, "ip%s.dst=%s; next;", > >>> is_v6 ? "6" : "4", nat->logical_ip); > >>> } else { > >>> - ds_put_format(actions, "ct_dnat(%s", nat->logical_ip); > >>> + ds_put_format(actions, "ct_dnat_in_czone(%s", nat->logical_ip); > >>> if (nat->external_port_range[0]) { > >>> ds_put_format(actions, ",%s", nat->external_port_range); > >>> } > >>> @@ -12417,7 +12441,8 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od, > >>> ds_put_format(actions, "ip%s.src=%s; next;", > >>> is_v6 ? "6" : "4", nat->external_ip); > >>> } else { > >>> - ds_put_format(actions, "ct_dnat;"); > >>> + ds_put_format(actions, > >>> + od->is_gw_router ? "ct_dnat;" : "ct_dnat_in_czone;"); > >>> } > >>> > >>> ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 100, > >>> @@ -12425,6 +12450,36 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od, > >>> &nat->header_); > >>> } > >>> > >>> +static void > >>> +build_lrouter_out_is_dnat_local(struct hmap *lflows, struct ovn_datapath *od, > >>> + const struct nbrec_nat *nat, struct ds *match, > >>> + struct ds *actions, bool distributed, > >>> + bool is_v6) > >>> +{ > >>> + /* Note that this only applies for NAT on a distributed router. > >>> + */ > >>> + if (!od->n_l3dgw_ports) { > >>> + return; > >>> + } > >>> + > >>> + ds_clear(match); > >>> + ds_put_format(match, "ip && ip%s.dst == %s && ", > >>> + is_v6 ? "6" : "4", nat->external_ip); > >>> + if (distributed) { > >>> + ds_put_format(match, "is_chassis_resident(\"%s\")", nat->logical_port); > >>> + } else { > >>> + ds_put_format(match, "is_chassis_resident(%s)", > >>> + od->l3dgw_ports[0]->cr_port->json_key); > >>> + } > >>> + > >>> + ds_clear(actions); > >>> + ds_put_cstr(actions, REGBIT_DST_NAT_IP_LOCAL" = 1; next;"); > >>> + > >>> + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_CHECK_DNAT_LOCAL, > >>> + 50, ds_cstr(match), ds_cstr(actions), > >>> + &nat->header_); > >>> +} > >>> + > >>> static void > >>> build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, > >>> const struct nbrec_nat *nat, struct ds *match, > >>> @@ -12478,16 +12533,19 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, > >>> ds_put_format(match, "ip && ip%s.src == %s && outport == %s", > >>> is_v6 ? "6" : "4", nat->logical_ip, > >>> od->l3dgw_ports[0]->json_key); > >>> - if (!distributed && od->n_l3dgw_ports) { > >>> - /* Flows for NAT rules that are centralized are only > >>> - * programmed on the gateway chassis. */ > >>> - priority += 128; > >>> - ds_put_format(match, " && is_chassis_resident(%s)", > >>> - od->l3dgw_ports[0]->cr_port->json_key); > >>> - } else if (distributed) { > >>> - priority += 128; > >>> - ds_put_format(match, " && is_chassis_resident(\"%s\")", > >>> - nat->logical_port); > >>> + if (od->n_l3dgw_ports) { > >>> + if (distributed) { > >>> + ovs_assert(nat->logical_port); > >>> + priority += 128; > >>> + ds_put_format(match, " && is_chassis_resident(\"%s\")", > >>> + nat->logical_port); > >>> + } else { > >>> + /* Flows for NAT rules that are centralized are only > >>> + * programmed on the gateway chassis. */ > >>> + priority += 128; > >>> + ds_put_format(match, " && is_chassis_resident(%s)", > >>> + od->l3dgw_ports[0]->cr_port->json_key); > >>> + } > >>> } > >>> ds_clear(actions); > >>> > >>> @@ -12505,7 +12563,7 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, > >>> ds_put_format(actions, "ip%s.src=%s; next;", > >>> is_v6 ? "6" : "4", nat->external_ip); > >>> } else { > >>> - ds_put_format(actions, "ct_snat(%s", > >>> + ds_put_format(actions, "ct_snat_in_czone(%s", > >>> nat->external_ip); > >>> if (nat->external_port_range[0]) { > >>> ds_put_format(actions, ",%s", nat->external_port_range); > >>> @@ -12519,6 +12577,24 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, > >>> ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT, > >>> priority, ds_cstr(match), > >>> ds_cstr(actions), &nat->header_); > >>> + > >>> + if (!stateless) { > >>> + ds_put_cstr(match, " && "REGBIT_DST_NAT_IP_LOCAL" == 1"); > >>> + ds_clear(actions); > >>> + if (distributed) { > >>> + ds_put_format(actions, "eth.src = "ETH_ADDR_FMT"; ", > >>> + ETH_ADDR_ARGS(mac)); > >>> + } > >>> + ds_put_format(actions, REGBIT_DST_NAT_IP_LOCAL" = 0; ct_snat(%s", > >>> + nat->external_ip); > >>> + if (nat->external_port_range[0]) { > >>> + ds_put_format(actions, ",%s", nat->external_port_range); > >>> + } > >>> + ds_put_format(actions, ");"); > >>> + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT, > >>> + priority + 1, ds_cstr(match), > >>> + ds_cstr(actions), &nat->header_); > >>> + } > >>> } > >>> } > >>> > >>> @@ -12749,10 +12825,13 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, > >>> /* Packets are allowed by default. */ > >>> ovn_lflow_add(lflows, od, S_ROUTER_IN_DEFRAG, 0, "1", "next;"); > >>> ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, 0, "1", "next;"); > >>> + ovn_lflow_add(lflows, od, S_ROUTER_OUT_CHECK_DNAT_LOCAL, 0, "1", > >>> + REGBIT_DST_NAT_IP_LOCAL" = 0; next;"); > >>> ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, 0, "1", "next;"); > >>> ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 0, "1", "next;"); > >>> ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 0, "1", "next;"); > >>> ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 0, "1", "next;"); > >>> + ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_SNAT, 0, "1", "next;"); > >>> 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;"); > >>> > >>> @@ -12765,8 +12844,7 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, > >>> * not committed, it would produce ongoing datapath flows with the ct.new > >>> * flag set. Some NICs are unable to offload these flows. > >>> */ > >>> - if ((od->is_gw_router || od->n_l3dgw_ports) && > >>> - (od->nbr->n_nat || od->has_lb_vip)) { > >>> + if (od->is_gw_router && (od->nbr->n_nat || od->has_lb_vip)) { > >>> ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 50, > >>> "ip", "flags.loopback = 1; ct_dnat;"); > >>> ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 50, > >>> @@ -12839,6 +12917,10 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, > >>> } > >>> } > >>> > >>> + /* S_ROUTER_OUT_DNAT_LOCAL */ > >>> + build_lrouter_out_is_dnat_local(lflows, od, nat, match, actions, > >>> + distributed, is_v6); > >>> + > >>> /* S_ROUTER_OUT_UNDNAT */ > >>> build_lrouter_out_undnat_flow(lflows, od, nat, match, actions, distributed, > >>> mac, is_v6); > >>> @@ -12912,7 +12994,8 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, > >>> "clone { ct_clear; " > >>> "inport = outport; outport = \"\"; " > >>> "eth.dst <-> eth.src; " > >>> - "flags = 0; flags.loopback = 1; "); > >>> + "flags = 0; flags.loopback = 1; " > >>> + "flags.use_snat_zone = "REGBIT_DST_NAT_IP_LOCAL"; "); > >>> for (int j = 0; j < MFF_N_LOG_REGS; j++) { > >>> ds_put_format(actions, "reg%d = 0; ", j); > >>> } > >>> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > >>> index 21d83718c..fc9d51ea7 100644 > >>> --- a/northd/ovn-northd.8.xml > >>> +++ b/northd/ovn-northd.8.xml > >>> @@ -2879,23 +2879,65 @@ icmp6 { > >>> <p> > >>> For each configuration in the OVN Northbound database, that asks > >>> to change the source IP address of a packet from <var>A</var> to > >>> - <var>B</var>, a priority-100 flow matches <code>ip && > >>> - ip4.dst == <var>B</var> && inport == <var>GW</var></code> or > >>> - <code>ip && > >>> - ip6.dst == <var>B</var> && inport == <var>GW</var></code> > >>> - where <var>GW</var> is the logical router gateway port, with an > >>> - action <code>ct_snat;</code>. If the NAT rule is of type > >>> - dnat_and_snat and has <code>stateless=true</code> in the > >>> - options, then the action would be <code>ip4/6.dst= > >>> - (<var>B</var>)</code>. > >>> + <var>B</var>, two priority-100 flows are added. > >>> </p> > >>> > >>> <p> > >>> If the NAT rule cannot be handled in a distributed manner, then > >>> - the priority-100 flow above is only programmed on the > >>> + the below priority-100 flows are only programmed on the > >>> gateway chassis. > >>> </p> > >>> > >>> + <ul> > >>> + <li> > >>> + <p> > >>> + The first flow matches <code>ip && > >>> + ip4.dst == <var>B</var> && inport == <var>GW</var> > >>> + && flags.loopback == 0</code> or > >>> + <code>ip && > >>> + ip6.dst == <var>B</var> && inport == <var>GW</var> > >>> + && flags.loopback == 0</code> > >>> + where <var>GW</var> is the logical router gateway port, with an > >>> + action <code>ct_snat_in_czone;</code> to unSNAT in the common > >>> + zone. If the NAT rule is of type dnat_and_snat and has > >>> + <code>stateless=true</code> in the options, then the action > >>> + would be <code>ip4/6.dst=(<var>B</var>)</code>. > >>> + </p> > >>> + > >>> + <p> > >>> + If the NAT entry is of type <code>snat</code>, then there is an > >>> + additional match <code>is_chassis_resident(<var>cr-GW</var>) > >>> + </code> where <var>cr-GW</var> is the chassis resident port of > >>> + <var>GW</var>. > >>> + </p> > >>> + </li> > >>> + > >>> + <li> > >>> + <p> > >>> + The second flow matches <code>ip && > >>> + ip4.dst == <var>B</var> && inport == <var>GW</var> > >>> + && flags.loopback == 1 && > >>> + flags.use_snat_zone == 1</code> or > >>> + <code>ip && > >>> + ip6.dst == <var>B</var> && inport == <var>GW</var> > >>> + && flags.loopback == 0 && > >>> + flags.use_snat_zone == 1</code> > >>> + where <var>GW</var> is the logical router gateway port, with an > >>> + action <code>ct_snat;</code> to unSNAT in the snat zone. If the > >>> + NAT rule is of type dnat_and_snat and has > >>> + <code>stateless=true</code> in the options, then the action > >>> + would be <code>ip4/6.dst=(<var>B</var>)</code>. > >>> + </p> > >>> + > >>> + <p> > >>> + If the NAT entry is of type <code>snat</code>, then there is an > >>> + additional match <code>is_chassis_resident(<var>cr-GW</var>) > >>> + </code> where <var>cr-GW</var> is the chassis resident port of > >>> + <var>GW</var>. > >>> + </p> > >>> + </li> > >>> + </ul> > >>> + > >>> <p> > >>> A priority-0 logical flow with match <code>1</code> has actions > >>> <code>next;</code>. > >>> @@ -4031,7 +4073,43 @@ nd_ns { > >>> </li> > >>> </ul> > >>> > >>> - <h3>Egress Table 0: UNDNAT</h3> > >>> + <h3>Egress Table 0: Check DNAT local </h3> > >>> + > >>> + <p> > >>> + This table checks if the packet needs to be DNATed in the router ingress > >>> + table <code>lr_out_dnat</code> after it is SNATed and looped back > >> > >> s/lr_out_dnat/lr_in_dnat/ > >> > >>> + to the ingress pipeline. This check is done only for routers configured > >>> + with distributed gateway ports and NAT entries. This check is done > >>> + so that SNAT and DNAT is done in different zones instead of a common > >>> + zone. > >>> + </p> > >>> + > >>> + <ul> > >>> + <li> > >>> + <p> > >>> + For each NAT rule in the OVN Northbound database on a > >>> + distributed router, a priority-50 logical flow with match > >>> + <code>ip4.dst == <var>E</var> && > >>> + is_chassis_resident(<var>P</var>)</code>, where <var>E</var> is the > >>> + external IP address specified in the NAT rule, <var>GW</var> > >>> + is the logical router distributed gateway port. For dnat_and_snat > >>> + NAT rule, <var>P</var> is the logical port specified in the NAT rule. > >>> + If <ref column="logical_port" > >>> + table="NAT" db="OVN_Northbound"/> column of > >>> + <ref table="NAT" db="OVN_Northbound"/> table is NOT set, then > >>> + <var>P</var> is the <code>chassisredirect port</code> of > >>> + <var>GW</var> with the actions: > >>> + <code>REGBIT_DST_NAT_IP_LOCAL = 1; next; </code> > >>> + </p> > >>> + </li> > >>> + > >>> + <li> > >>> + A priority-0 logical flow with match <code>1</code> has actions > >>> + <code>REGBIT_DST_NAT_IP_LOCAL = 0; next;</code>. > >>> + </li> > >>> + </ul> > >>> + > >>> + <h3>Egress Table 1: UNDNAT</h3> > >>> > >>> <p> > >>> This is for already established connections' reverse traffic. > >>> @@ -4040,6 +4118,23 @@ nd_ns { > >>> is unDNATed here. > >>> </p> > >>> > >>> + <ul> > >>> + <li> > >>> + A priority-0 logical flow with match <code>1</code> has actions > >>> + <code>next;</code>. > >>> + </li> > >>> + </ul> > >>> + > >>> + <h3>Egress Table 1: UNDNAT on Gateway Routers</h3> > >>> + > >>> + <ul> > >>> + <li> > >>> + For all IP packets, a priority-50 flow with an action > >>> + <code>flags.loopback = 1; ct_dnat;</code>. > >>> + </li> > >>> + </ul> > >>> + > >>> + <h3>Egress Table 1: UNDNAT on Distributed Routers</h3> > >>> <ul> > >>> <li> > >>> <p> > >>> @@ -4050,9 +4145,9 @@ nd_ns { > >>> gateway chassis that matches > >>> <code>ip && ip4.src == <var>B</var> && > >>> outport == <var>GW</var></code>, where <var>GW</var> is the logical > >>> - router gateway port with an action <code>ct_dnat;</code>. If the > >>> - backend IPv4 address <var>B</var> is also configured with L4 port > >>> - <var>PORT</var> of protocol <var>P</var>, then the > >>> + router gateway port with an action <code>ct_dnat_in_czone;</code>. > >>> + If the backend IPv4 address <var>B</var> is also configured with > >>> + L4 port <var>PORT</var> of protocol <var>P</var>, then the > >>> match also includes <code>P.src</code> == <var>PORT</var>. These > >>> flows are not added for load balancers with IPv6 <var>VIPs</var>. > >>> </p> > >>> @@ -4072,7 +4167,7 @@ nd_ns { > >>> matches <code>ip && ip4.src == <var>B</var> > >>> && outport == <var>GW</var></code>, where <var>GW</var> > >>> is the logical router gateway port, with an action > >>> - <code>ct_dnat;</code>. If the NAT rule is of type > >>> + <code>ct_dnat_in_czone;</code>. If the NAT rule is of type > >>> dnat_and_snat and has <code>stateless=true</code> in the > >>> options, then the action would be <code>ip4/6.src= > >>> (<var>B</var>)</code>. > >>> @@ -4081,7 +4176,7 @@ nd_ns { > >>> <p> > >>> If the NAT rule cannot be handled in a distributed manner, then > >>> the priority-100 flow above is only programmed on the > >>> - gateway chassis. > >>> + gateway chassis with the action <code>ct_dnat_in_czone</code>. > >>> </p> > >>> > >>> <p> > >>> @@ -4094,26 +4189,17 @@ nd_ns { > >>> </p> > >>> </li> > >>> > >>> - <li> > >>> - For all IP packets, a priority-50 flow with an action > >>> - <code>flags.loopback = 1; ct_dnat;</code>. > >>> - </li> > >>> - > >>> - <li> > >>> - A priority-0 logical flow with match <code>1</code> has actions > >>> - <code>next;</code>. > >>> - </li> > >>> </ul> > >>> > >>> - <h3>Egress Table 1: Post UNDNAT</h3> > >>> + <h3>Egress Table 2: Post UNDNAT</h3> > >>> > >>> <p> > >>> <ul> > >>> <li> > >>> A priority-50 logical flow is added that commits any untracked flows > >>> - from the previous table <code>lr_out_undnat</code>. This flow > >>> - matches on <code>ct.new && ip</code> with action > >>> - <code>ct_commit { } ; next; </code>. > >>> + from the previous table <code>lr_out_undnat</code> for Gateway > >>> + routers. This flow matches on <code>ct.new && ip</code> > >>> + with action <code>ct_commit { } ; next; </code>. > >>> </li> > >>> > >>> <li> > >>> @@ -4124,7 +4210,7 @@ nd_ns { > >>> </ul> > >>> </p> > >>> > >>> - <h3>Egress Table 2: SNAT</h3> > >>> + <h3>Egress Table 3: SNAT</h3> > >>> > >>> <p> > >>> Packets that are configured to be SNATed get their source IP address > >>> @@ -4140,7 +4226,7 @@ nd_ns { > >>> </li> > >>> </ul> > >>> > >>> - <p>Egress Table 2: SNAT on Gateway Routers</p> > >>> + <p>Egress Table 3: SNAT on Gateway Routers</p> > >>> > >>> <ul> > >>> <li> > >>> @@ -4239,7 +4325,7 @@ nd_ns { > >>> </li> > >>> </ul> > >>> > >>> - <p>Egress Table 2: SNAT on Distributed Routers</p> > >>> + <p>Egress Table 3: SNAT on Distributed Routers</p> > >>> > >>> <ul> > >>> <li> > >>> @@ -4247,28 +4333,46 @@ nd_ns { > >>> For each configuration in the OVN Northbound database, that asks > >>> to change the source IP address of a packet from an IP address of > >>> <var>A</var> or to change the source IP address of a packet that > >>> - belongs to network <var>A</var> to <var>B</var>, a flow matches > >>> - <code>ip && ip4.src == <var>A</var> && > >>> - outport == <var>GW</var></code>, where <var>GW</var> is the > >>> - logical router gateway port, with an action > >>> - <code>ct_snat(<var>B</var>);</code>. The priority of the flow > >>> - is calculated based on the mask of <var>A</var>, with matches > >>> - having larger masks getting higher priorities. If the NAT rule > >>> - is of type dnat_and_snat and has <code>stateless=true</code> > >>> - in the options, then the action would be <code>ip4/6.src= > >>> - (<var>B</var>)</code>. > >>> + belongs to network <var>A</var> to <var>B</var>, two flows are > >>> + added. The priority of these flows are calculated based on the > >>> + mask of <var>A</var>, with matches having larger masks getting > >>> + higher priorities. > >>> </p> > >>> > >>> <p> > >>> If the NAT rule cannot be handled in a distributed manner, then > >>> - the flow above is only programmed on the > >>> - gateway chassis increasing flow priority by 128 in > >>> - order to be run first > >>> + the below flows are only programmed on the gateway chassis increasing > >>> + flow priority by 128 in order to be run first. > >>> </p> > >>> > >>> + <ul> > >>> + <li> > >>> + The first flow is added with the match > >>> + <code>ip && ip4.src == <var>A</var> && > >>> + outport == <var>GW</var></code>, where <var>GW</var> is the > >>> + logical router gateway port, with an action > >>> + <code>ct_snat_in_czone(<var>B</var>);</code> to SNATed in the > >>> + common zone. If the NAT rule is of type dnat_and_snat and has > >>> + <code>stateless=true</code> in the options, then the action > >>> + would be <code>ip4/6.src=(<var>B</var>)</code>. > >>> + </li> > >>> + > >>> + <li> > >>> + The second flow is added with the match > >>> + <code>ip && ip4.src == <var>A</var> && > >>> + outport == <var>GW</var> && > >>> + REGBIT_DST_NAT_IP_LOCAL == 0</code>, where <var>GW</var> is the > >>> + logical router gateway port, with an action > >>> + <code>ct_snat(<var>B</var>);</code> to SNAT in the snat zone. > >>> + If the NAT rule is of type dnat_and_snat and has > >>> + <code>stateless=true</code> in the options, then the action would > >>> + be <code>ip4/6.src=(<var>B</var>)</code>. > >>> + </li> > >>> + </ul> > >>> + > >>> <p> > >>> If the NAT rule can be handled in a distributed manner, then > >>> - there is an additional action > >>> + there is an additional action (for both the flows) > >>> <code>eth.src = <var>EA</var>;</code>, where <var>EA</var> > >>> is the ethernet address associated with the IP address > >>> <var>A</var> in the NAT rule. This allows upstream MAC > >>> @@ -4299,7 +4403,7 @@ nd_ns { > >>> </li> > >>> </ul> > >>> > >>> - <h3>Egress Table 3: Egress Loopback</h3> > >>> + <h3>Egress Table 4: Egress Loopback</h3> > >>> > >>> <p> > >>> For distributed logical routers where one of the logical router > >>> @@ -4344,6 +4448,7 @@ clone { > >>> outport = ""; > >>> flags = 0; > >>> flags.loopback = 1; > >>> + flags.use_snat_zone = REGBIT_DST_NAT_IP_LOCAL; > >>> reg0 = 0; > >>> reg1 = 0; > >>> ... > >>> @@ -4368,7 +4473,7 @@ clone { > >>> </li> > >>> </ul> > >>> > >>> - <h3>Egress Table 4: Delivery</h3> > >>> + <h3>Egress Table 5: Delivery</h3> > >>> > >>> <p> > >>> Packets that reach this table are ready for delivery. It contains: > >>> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > >>> index 85b47a18f..70ec5e2e3 100644 > >>> --- a/tests/ovn-northd.at > >>> +++ b/tests/ovn-northd.at > >>> @@ -877,25 +877,25 @@ check_flow_match_sets() { > >>> echo > >>> echo "IPv4: stateful" > >>> ovn-nbctl --wait=sb lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 > >>> -check_flow_match_sets 2 2 3 0 0 0 0 > >>> +check_flow_match_sets 3 4 2 0 0 0 0 > >>> ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 > >>> > >>> echo > >>> echo "IPv4: stateless" > >>> ovn-nbctl --wait=sb --stateless lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 > >>> -check_flow_match_sets 2 0 1 2 2 0 0 > >>> +check_flow_match_sets 2 0 0 2 2 0 0 > >>> ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 > >>> > >>> echo > >>> echo "IPv6: stateful" > >>> ovn-nbctl --wait=sb lr-nat-add R1 dnat_and_snat fd01::1 fd11::2 > >>> -check_flow_match_sets 2 2 3 0 0 0 0 > >>> +check_flow_match_sets 3 4 2 0 0 0 0 > >>> ovn-nbctl lr-nat-del R1 dnat_and_snat fd01::1 > >>> > >>> echo > >>> echo "IPv6: stateless" > >>> ovn-nbctl --wait=sb --stateless lr-nat-add R1 dnat_and_snat fd01::1 fd11::2 > >>> -check_flow_match_sets 2 0 1 0 0 2 2 > >>> +check_flow_match_sets 2 0 0 0 0 2 2 > >>> > >>> AT_CLEANUP > >>> ]) > >>> @@ -924,9 +924,9 @@ echo "CR-LRP UUID is: " $uuid > >>> ovn-nbctl --portrange lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 1-3000 > >>> > >>> AT_CAPTURE_FILE([sbflows]) > >>> -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows && test 2 = `grep -c lr_in_unsnat sbflows`]) > >>> +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows && test 3 = `grep -c lr_in_unsnat sbflows`]) > >>> AT_CHECK([grep -c 'ct_snat.*3000' sbflows && grep -c 'ct_dnat.*3000' sbflows], > >>> - [0], [1 > >>> + [0], [2 > >>> 1 > >>> ]) > >>> > >>> @@ -934,9 +934,9 @@ ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 > >>> ovn-nbctl --wait=sb --portrange lr-nat-add R1 snat 172.16.1.1 50.0.0.11 1-3000 > >>> > >>> AT_CAPTURE_FILE([sbflows2]) > >>> -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows2 && test 2 = `grep -c lr_in_unsnat sbflows`]) > >>> +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows2 && test 3 = `grep -c lr_in_unsnat sbflows`]) > >>> AT_CHECK([grep -c 'ct_snat.*3000' sbflows2 && grep -c 'ct_dnat.*3000' sbflows2], > >>> - [1], [1 > >>> + [1], [2 > >>> 0 > >>> ]) > >>> > >>> @@ -944,7 +944,7 @@ ovn-nbctl lr-nat-del R1 snat 172.16.1.1 > >>> ovn-nbctl --wait=sb --portrange --stateless lr-nat-add R1 dnat_and_snat 172.16.1.2 50.0.0.12 1-3000 > >>> > >>> AT_CAPTURE_FILE([sbflows3]) > >>> -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows3 && test 3 = `grep -c lr_in_unsnat sbflows3`]) > >>> +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows3 && test 4 = `grep -c lr_in_unsnat sbflows3`]) > >>> AT_CHECK([grep 'ct_[s]dnat.*172\.16\.1\.2.*3000' sbflows3], [1]) > >>> > >>> ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 > >>> @@ -1008,17 +1008,20 @@ AT_CAPTURE_FILE([drflows]) > >>> ovn-sbctl dump-flows CR > crflows > >>> AT_CAPTURE_FILE([crflows]) > >>> > >>> -AT_CHECK([ > >>> - grep -c lr_out_snat drflows > >>> - grep -c lr_out_snat crflows > >>> - grep lr_out_snat drflows | grep "ip4.src == 50.0.0.11" | grep -c "ip4.dst == $allowed_range" > >>> - grep lr_out_snat crflows | grep "ip4.src == 50.0.0.11" | grep -c "ip4.dst == $allowed_range"], [0], [dnl > >>> -3 > >>> -3 > >>> -1 > >>> -1 > >>> +AT_CHECK([grep -e "lr_out_snat" drflows | sed 's/table=../table=??/' | sort], [0], [dnl > >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ct_snat_in_czone(172.16.1.1);) > >>> + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.1);) > >>> +]) > >>> + > >>> +AT_CHECK([grep -e "lr_out_snat" crflows | sed 's/table=../table=??/' | sort], [0], [dnl > >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ct_snat(172.16.1.1);) > >>> ]) > >>> > >>> + > >>> # SNAT with DISALLOWED_IPs > >>> check ovn-nbctl lr-nat-del DR snat 50.0.0.11 > >>> check ovn-nbctl lr-nat-del CR snat 50.0.0.11 > >>> @@ -1036,19 +1039,19 @@ AT_CAPTURE_FILE([drflows2]) > >>> ovn-sbctl dump-flows CR > crflows2 > >>> AT_CAPTURE_FILE([crflows2]) > >>> > >>> -AT_CHECK([ > >>> - grep -c lr_out_snat drflows2 > >>> - grep -c lr_out_snat crflows2 > >>> - grep lr_out_snat drflows2 | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep -c "priority=162" > >>> - grep lr_out_snat drflows2 | grep "ip4.src == 50.0.0.11" | grep -c "priority=161" > >>> - grep lr_out_snat crflows2 | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep -c "priority=34" > >>> - grep lr_out_snat crflows2 | grep "ip4.src == 50.0.0.11" | grep -c "priority=33"], [0], [dnl > >>> -4 > >>> -4 > >>> -1 > >>> -1 > >>> -1 > >>> -1 > >>> +AT_CHECK([grep -e "lr_out_snat" drflows2 | sed 's/table=../table=??/' | sort], [0], [dnl > >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ct_snat_in_czone(172.16.1.1);) > >>> + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.1);) > >>> + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) > >>> +]) > >>> + > >>> +AT_CHECK([grep -e "lr_out_snat" crflows2 | sed 's/table=../table=??/' | sort], [0], [dnl > >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ct_snat(172.16.1.1);) > >>> + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) > >>> ]) > >>> > >>> # Stateful FIP with ALLOWED_IPs > >>> @@ -1059,25 +1062,24 @@ check ovn-nbctl lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11 > >>> check ovn-nbctl lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 > >>> > >>> check ovn-nbctl lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 allowed_range > >>> -check ovn-nbctl lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range > >>> +check ovn-nbctl --wait=sb lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range > >>> > >>> -ovn-nbctl show DR > >>> -ovn-sbctl dump-flows DR > >>> -ovn-nbctl show CR > >>> -ovn-sbctl dump-flows CR > >>> - > >>> -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ > >>> -wc -l`]) > >>> -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ > >>> -wc -l`]) > >>> +ovn-sbctl dump-flows DR > drflows3 > >>> +AT_CAPTURE_FILE([drflows2]) > >>> +ovn-sbctl dump-flows CR > crflows3 > >>> +AT_CAPTURE_FILE([crflows2]) > >>> > >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 > >>> +AT_CHECK([grep -e "lr_out_snat" drflows3 | sed 's/table=../table=??/' | sort], [0], [dnl > >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ct_snat_in_czone(172.16.1.2);) > >>> + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.2);) > >>> ]) > >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 > >>> -]) > >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 > >>> -]) > >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 > >>> + > >>> +AT_CHECK([grep -e "lr_out_snat" crflows3 | sed 's/table=../table=??/' | sort], [0], [dnl > >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ct_snat(172.16.1.2);) > >>> ]) > >>> > >>> # Stateful FIP with DISALLOWED_IPs > >>> @@ -1088,26 +1090,26 @@ ovn-nbctl lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11 > >>> ovn-nbctl lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 > >>> > >>> ovn-nbctl --is-exempted lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 disallowed_range > >>> -ovn-nbctl --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range > >>> +check ovn-nbctl --wait=sb --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range > >>> > >>> -ovn-nbctl show DR > >>> -ovn-sbctl dump-flows DR > >>> -ovn-nbctl show CR > >>> -ovn-sbctl dump-flows CR > >>> - > >>> -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ > >>> -wc -l`]) > >>> -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ > >>> -wc -l`]) > >>> +ovn-sbctl dump-flows DR > drflows4 > >>> +AT_CAPTURE_FILE([drflows2]) > >>> +ovn-sbctl dump-flows CR > crflows4 > >>> +AT_CAPTURE_FILE([crflows2]) > >>> > >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=162" | wc -l], [0], [1 > >>> -]) > >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 > >>> +AT_CHECK([grep -e "lr_out_snat" drflows4 | sed 's/table=../table=??/' | sort], [0], [dnl > >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ct_snat_in_czone(172.16.1.2);) > >>> + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.2);) > >>> + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) > >>> ]) > >>> > >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=34" | wc -l], [0], [1 > >>> -]) > >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 > >>> +AT_CHECK([grep -e "lr_out_snat" crflows4 | sed 's/table=../table=??/' | sort], [0], [dnl > >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ct_snat(172.16.1.2);) > >>> + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) > >>> ]) > >>> > >>> # Stateless FIP with DISALLOWED_IPs > >>> @@ -1120,24 +1122,21 @@ ovn-nbctl --stateless lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 > >>> ovn-nbctl lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 allowed_range > >>> ovn-nbctl lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range > >>> > >>> -ovn-nbctl show DR > >>> -ovn-sbctl dump-flows DR > >>> - > >>> -ovn-nbctl show CR > >>> -ovn-sbctl dump-flows CR > >>> - > >>> -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ > >>> -wc -l`]) > >>> -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ > >>> -wc -l`]) > >>> +ovn-sbctl dump-flows DR > drflows5 > >>> +AT_CAPTURE_FILE([drflows2]) > >>> +ovn-sbctl dump-flows CR > crflows5 > >>> +AT_CAPTURE_FILE([crflows2]) > >>> > >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 > >>> +AT_CHECK([grep -e "lr_out_snat" drflows5 | sed 's/table=../table=??/' | sort], [0], [dnl > >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ip4.src=172.16.1.2; next;) > >>> ]) > >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 > >>> -]) > >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 > >>> -]) > >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 > >>> + > >>> +AT_CHECK([grep -e "lr_out_snat" crflows5 | sed 's/table=../table=??/' | sort], [0], [dnl > >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ip4.src=172.16.1.2; next;) > >>> ]) > >>> > >>> # Stateful FIP with DISALLOWED_IPs > >>> @@ -1150,23 +1149,25 @@ ovn-nbctl --stateless lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 > >>> ovn-nbctl --is-exempted lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 disallowed_range > >>> ovn-nbctl --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range > >>> > >>> -ovn-nbctl show DR > >>> -ovn-sbctl dump-flows DR > >>> -ovn-nbctl show CR > >>> -ovn-sbctl dump-flows CR > >>> +ovn-nbctl --wait=sb sync > >>> > >>> -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ > >>> -wc -l`]) > >>> -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ > >>> -wc -l`]) > >>> +ovn-sbctl dump-flows DR > drflows6 > >>> +AT_CAPTURE_FILE([drflows2]) > >>> +ovn-sbctl dump-flows CR > crflows6 > >>> +AT_CAPTURE_FILE([crflows2]) > >>> > >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=162" | wc -l], [0], [1 > >>> -]) > >>> -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 > >>> +AT_CHECK([grep -e "lr_out_snat" drflows6 | sed 's/table=../table=??/' | sort], [0], [dnl > >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ip4.src=172.16.1.2; next;) > >>> + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) > >>> ]) > >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=34" | wc -l], [0], [1 > >>> -]) > >>> -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 > >>> + > >>> +AT_CHECK([grep -e "lr_out_snat" crflows6 | sed 's/table=../table=??/' | sort], [0], [dnl > >>> + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ip4.src=172.16.1.2; next;) > >>> + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) > >>> ]) > >>> > >>> AT_CLEANUP > >>> @@ -3475,14 +3476,14 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(ct_lb(backends=10.0.0.40:8080);) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> ]) > >>> > >>> check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="20.0.0.4 aef0::4" > >>> @@ -3511,21 +3512,21 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> - table=2 (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip4), action=(ct_snat(20.0.0.4);) > >>> - table=2 (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip6), action=(ct_snat(aef0::4);) > >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip4), action=(ct_snat(20.0.0.4);) > >>> + table=? (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip6), action=(ct_snat(aef0::4);) > >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> ]) > >>> > >>> check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="router_ip" > >>> @@ -3557,22 +3558,22 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) > >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) > >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> ]) > >>> > >>> check ovn-nbctl --wait=sb remove logical_router lr0 options chassis > >>> @@ -3584,9 +3585,9 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl > >>> table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> ]) > >>> > >>> check ovn-nbctl set logical_router lr0 options:chassis=ch1 > >>> @@ -3617,23 +3618,23 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw1"), action=(ct_snat(bef0::1);) > >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw1"), action=(ct_snat(bef0::1);) > >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> ]) > >>> > >>> check ovn-nbctl --wait=sb lb-add lb2 10.0.0.20:80 10.0.0.40:8080 > >>> @@ -3661,18 +3662,18 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.20 && tcp && reg9[[16..31]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=120 , match=(flags.skip_snat_for_lb == 1 && ip), action=(next;) > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=120 , match=(flags.skip_snat_for_lb == 1 && ip), action=(next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> ]) > >>> > >>> AT_CLEANUP > >>> @@ -4176,6 +4177,8 @@ check ovn-nbctl lsp-set-options lrp1-attachment router-port=lrp1 > >>> check ovn-nbctl lr-nat-add lr0 dnat 42.42.42.42 192.168.0.2 > >>> check ovn-nbctl --wait=sb sync > >>> > >>> +ovn-trace --minimal 'inport == "sw1-port1" && eth.src == 50:54:00:00:00:03 && eth.dst == 00:00:00:00:ff:02 && ip4.dst == 42.42.42.42 && ip4.src == 11.0.0.2 && ip.ttl == 64' > >>> + > >>> AT_CHECK([ovn-trace --minimal 'inport == "sw1-port1" && eth.src == 50:54:00:00:00:03 && eth.dst == 00:00:00:00:ff:02 && ip4.dst == 42.42.42.42 && ip4.src == 11.0.0.2 && ip.ttl == 64' | grep "output(\"sw0-port1\")"], [0], [ignore]) > >>> > >>> dnl If we remove the DNAT entry we will be unable to trace to the DNAT address > >>> @@ -4761,17 +4764,17 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> ]) > >>> > >>> # Create few dnat_and_snat entries > >>> @@ -4797,17 +4800,21 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> +]) > >>> + > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> ]) > >>> > >>> ovn-sbctl chassis-add gw1 geneve 127.0.0.1 > >>> @@ -4828,9 +4835,12 @@ AT_CAPTURE_FILE([lr0flows]) > >>> > >>> AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl > >>> table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) > >>> - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > >>> - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > >>> - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > >>> ]) > >>> > >>> AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl > >>> @@ -4839,26 +4849,34 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl > >>> > >>> AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) > >>> - table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);) > >>> + table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone(10.0.0.3);) > >>> +]) > >>> + > >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > >>> + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.10 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > >>> + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.20 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > >>> + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.30 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=0 (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> - table=2 (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.10);) > >>> - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.30);) > >>> - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.20);) > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=? (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.10);) > >>> + table=? (lr_out_snat ), priority=154 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.10);) > >>> + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.30);) > >>> + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.20);) > >>> + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.30);) > >>> + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.20);) > >>> ]) > >>> > >>> # Associate load balancer to lr0 > >>> @@ -4879,9 +4897,12 @@ AT_CAPTURE_FILE([lr0flows]) > >>> > >>> AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl > >>> table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) > >>> - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > >>> - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > >>> - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) > >>> + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) > >>> ]) > >>> > >>> AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl > >>> @@ -4894,7 +4915,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl > >>> > >>> AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) > >>> - table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);) > >>> + table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone(10.0.0.3);) > >>> table=6 (lr_in_dnat ), priority=110 , match=(ct.est && ip4 && reg0 == 172.168.0.200 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) > >>> table=6 (lr_in_dnat ), priority=110 , match=(ct.new && ip4 && reg0 == 172.168.0.200 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.80,10.0.0.81);) > >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.est && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) > >>> @@ -4905,27 +4926,35 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=0 (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > >>> - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.4 && tcp.src == 8080)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > >>> - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && tcp.src == 82) || (ip4.src == 10.0.0.60 && tcp.src == 82)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > >>> - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && udp.src == 6062) || (ip4.src == 10.0.0.60 && udp.src == 6062)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > >>> - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.80) || (ip4.src == 10.0.0.81)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) > >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > >>> + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.10 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > >>> + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.20 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > >>> + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.30 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) > >>> +]) > >>> + > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > >>> + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.4 && tcp.src == 8080)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > >>> + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && tcp.src == 82) || (ip4.src == 10.0.0.60 && tcp.src == 82)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > >>> + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && udp.src == 6062) || (ip4.src == 10.0.0.60 && udp.src == 6062)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > >>> + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.80) || (ip4.src == 10.0.0.81)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> - table=2 (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.10);) > >>> - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.30);) > >>> - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.20);) > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=? (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.10);) > >>> + table=? (lr_out_snat ), priority=154 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.10);) > >>> + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.30);) > >>> + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.20);) > >>> + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.30);) > >>> + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.20);) > >>> ]) > >>> > >>> # Make the logical router as Gateway router > >>> @@ -4965,22 +4994,26 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +]) > >>> + > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > >>> ]) > >>> > >>> # Set lb force snat logical router. > >>> @@ -5020,24 +5053,28 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > >>> +]) > >>> + > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > >>> ]) > >>> > >>> # Add a LB VIP same as router ip. > >>> @@ -5081,24 +5118,28 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +]) > >>> + > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > >>> ]) > >>> > >>> # Add IPv6 router port and LB. > >>> @@ -5155,26 +5196,30 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip6 && xxreg0 == def0::2 && tcp && reg9[[16..31]] == 8000), action=(flags.force_snat_for_lb = 1; ct_lb(backends=[[aef0::2]]:80,[[aef0::3]]:80);) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > >>> +]) > >>> + > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-public"), action=(ct_snat(def0::10);) > >>> - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw0"), action=(ct_snat(aef0::1);) > >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > >>> - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-public"), action=(ct_snat(def0::10);) > >>> + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw0"), action=(ct_snat(aef0::1);) > >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) > >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) > >>> + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) > >>> ]) > >>> > >>> check ovn-nbctl lrp-del lr0-sw0 > >>> @@ -5209,19 +5254,23 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl > >>> table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl > >>> - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) > >>> +]) > >>> + > >>> +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl > >>> - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) > >>> ]) > >>> > >>> -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl > >>> - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl > >>> + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) > >>> + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) > >>> ]) > >>> > >>> AT_CLEANUP > >>> diff --git a/tests/ovn.at b/tests/ovn.at > >>> index 0d606b42f..ae5744407 100644 > >>> --- a/tests/ovn.at > >>> +++ b/tests/ovn.at > >>> @@ -21604,7 +21604,7 @@ AT_CAPTURE_FILE([sbflows]) > >>> AT_CHECK([for regex in ct_snat ct_dnat ip4.dst= ip4.src=; do > >>> grep -c "$regex" sbflows; > >>> done], [0], [0 > >>> -1 > >>> +0 > >>> 2 > >>> 2 > >>> ]) > >>> diff --git a/tests/system-ovn.at b/tests/system-ovn.at > >>> index c9f5771c9..7f6cb32dc 100644 > >>> --- a/tests/system-ovn.at > >>> +++ b/tests/system-ovn.at > >>> @@ -2224,7 +2224,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=42 | \ > >>> +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. > >>> @@ -2262,7 +2262,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=42 | \ > >>> +OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=43 | \ > >>> grep 'nat(src=20.0.0.2)']) > >>> > >>> rm -f wget*.log > >>> @@ -3711,17 +3711,24 @@ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > >>> icmpv6,orig=(src=fd20::2,dst=fd20::3,id=<cleared>,type=128,code=0),reply=(src=fd11::2,dst=fd20::2,id=<cleared>,type=129,code=0),zone=<cleared> > >>> ]) > >>> > >>> +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > >>> + > >>> # South-North SNAT: 'foo2' pings 'alice1'. But 'alice1' receives traffic > >>> -# from 172.16.1.4 > >>> +# from fd20::4 > >>> NS_CHECK_EXEC([foo2], [ping6 -q -c 3 -i 0.3 -w 2 fd20::2 | FORMAT_PING], \ > >>> [0], [dnl > >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms > >>> ]) > >>> > >>> -# We verify that SNAT indeed happened via 'dump-conntrack' command. > >>> +ovs-appctl dpctl/dump-conntrack | grep icmpv6 > >>> AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd11::3) | \ > >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > >>> -icmpv6,orig=(src=fd11::3,dst=fd20::2,id=<cleared>,type=128,code=0),reply=(src=fd20::2,dst=fd11::3,id=<cleared>,type=129,code=0),zone=<cleared> > >>> +]) > >>> + > >>> +# We verify that SNAT indeed happened via 'dump-conntrack' command. > >>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::4) | \ > >>> +sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > >>> +icmpv6,orig=(src=fd11::3,dst=fd20::2,id=<cleared>,type=128,code=0),reply=(src=fd20::2,dst=fd20::4,id=<cleared>,type=129,code=0),zone=<cleared> > >>> ]) > >>> > >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > >>> @@ -3861,11 +3868,9 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \ > >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms > >>> ]) > >>> > >>> -# We verify that the connection is tracked but not NATted. This is due to the > >>> -# unDNAT table in the egress router pipeline > >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ > >>> +# We verify that the connection is not tracked. > >>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ > >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > >>> -icmp,orig=(src=192.168.1.2,dst=192.168.2.2,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> > >>> ]) > >>> > >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > >>> @@ -3875,11 +3880,9 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \ > >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms > >>> ]) > >>> > >>> -# We verify that the connection is tracked but not NATted. This is due to the > >>> -# unDNAT table in the egress router pipeline > >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ > >>> +# We verify that the connection is not tracked. > >>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ > >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > >>> -icmp,orig=(src=192.168.1.3,dst=192.168.2.2,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=192.168.1.3,id=<cleared>,type=0,code=0),zone=<cleared> > >>> ]) > >>> > >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > >>> @@ -3889,14 +3892,13 @@ NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.3 | FORMAT_PING], \ > >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms > >>> ]) > >>> > >>> -# We verify that the connection is tracked but not NATted. This is due to the > >>> -# unDNAT table in the egress router pipeline > >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ > >>> +# We verify that the connection is not tracked. > >>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ > >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > >>> -icmp,orig=(src=192.168.2.2,dst=192.168.1.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.3,dst=192.168.2.2,id=<cleared>,type=0,code=0),zone=<cleared> > >>> ]) > >>> > >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > >>> + > >>> # East-West NAT: 'foo1' pings 'bar1' using 172.16.1.4. > >>> NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ > >>> [0], [dnl > >>> @@ -3905,11 +3907,10 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ > >>> > >>> # Check conntrack entries. First SNAT of 'foo1' address happens. > >>> # Then DNAT of 'bar1' address happens (listed first below). > >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) | \ > >>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(172.16.1.4) | \ > >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > >>> icmp,orig=(src=172.16.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared> > >>> icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared> > >>> -icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> > >>> ]) > >>> > >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > >>> @@ -3922,7 +3923,7 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ > >>> > >>> # Check conntrack entries. First SNAT of 'foo2' address happens. > >>> # Then DNAT of 'bar1' address happens (listed first below). > >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \ > >>> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(172.16.1.1) | \ > >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > >>> icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> > >>> icmp,orig=(src=192.168.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> > >>> @@ -4055,13 +4056,6 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ > >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms > >>> ]) > >>> > >>> -# We verify that the connection is tracked but not NATted. This is due to the > >>> -# unDNAT table in the egress router pipeline > >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ > >>> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > >>> -icmpv6,orig=(src=fd11::2,dst=fd12::2,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd11::2,id=<cleared>,type=129,code=0),zone=<cleared> > >>> -]) > >>> - > >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > >>> # East-West No NAT: 'foo2' pings 'bar1' using fd12::2. > >>> NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ > >>> @@ -4069,13 +4063,6 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ > >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms > >>> ]) > >>> > >>> -# We verify that the connection is tracked but not NATted. This is due to the > >>> -# unDNAT table in the egress router pipeline > >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ > >>> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > >>> -icmpv6,orig=(src=fd11::3,dst=fd12::2,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd11::3,id=<cleared>,type=129,code=0),zone=<cleared> > >>> -]) > >>> - > >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > >>> # East-West No NAT: 'bar1' pings 'foo2' using fd11::3. > >>> NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 fd11::3 | FORMAT_PING], \ > >>> @@ -4083,13 +4070,6 @@ NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 fd11::3 | FORMAT_PING], \ > >>> 3 packets transmitted, 3 received, 0% packet loss, time 0ms > >>> ]) > >>> > >>> -# We verify that the connection is tracked but not NATted. This is due to the > >>> -# unDNAT table in the egress router pipeline > >>> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ > >>> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > >>> -icmpv6,orig=(src=fd12::2,dst=fd11::3,id=<cleared>,type=128,code=0),reply=(src=fd11::3,dst=fd12::2,id=<cleared>,type=129,code=0),zone=<cleared> > >>> -]) > >>> - > >>> AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > >>> # East-West NAT: 'foo1' pings 'bar1' using fd20::4. > >>> NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd20::4 | FORMAT_PING], \ > >>> @@ -4101,7 +4081,6 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd20::4 | FORMAT_PING], \ > >>> # Then DNAT of 'bar1' address happens (listed first below). > >>> AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::4) | \ > >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > >>> -icmpv6,orig=(src=fd11::2,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd20::4,dst=fd11::2,id=<cleared>,type=129,code=0),zone=<cleared> > >>> icmpv6,orig=(src=fd11::2,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd20::4,dst=fd20::3,id=<cleared>,type=129,code=0),zone=<cleared> > >>> icmpv6,orig=(src=fd20::3,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd20::3,id=<cleared>,type=129,code=0),zone=<cleared> > >>> ]) > >>> @@ -6037,7 +6016,6 @@ NS_CHECK_EXEC([sw01-x], [ping -q -c 3 -i 0.3 -w 2 172.16.1.100 | FORMAT_PING], \ > >>> AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.100) | \ > >>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > >>> icmp,orig=(src=192.168.1.2,dst=172.16.1.100,id=<cleared>,type=8,code=0),reply=(src=172.16.1.100,dst=172.16.1.20,id=<cleared>,type=0,code=0),zone=<cleared> > >>> -icmp,orig=(src=192.168.1.2,dst=172.16.1.100,id=<cleared>,type=8,code=0),reply=(src=172.16.1.100,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> > >>> ]) > >>> > >>> OVS_APP_EXIT_AND_WAIT([ovn-controller]) > >>> > >> > >> _______________________________________________ > >> dev mailing list > >> dev@openvswitch.org > >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev > >> > > > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev >
diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h index c9675f81c..2118f7933 100644 --- a/include/ovn/logical-fields.h +++ b/include/ovn/logical-fields.h @@ -70,6 +70,7 @@ enum mff_log_flags_bits { MLF_LOOKUP_FDB_BIT = 8, MLF_SKIP_SNAT_FOR_LB_BIT = 9, MLF_LOCALPORT_BIT = 10, + MLF_USE_SNAT_ZONE = 11, }; /* MFF_LOG_FLAGS_REG flag assignments */ diff --git a/lib/logical-fields.c b/lib/logical-fields.c index 7b3d431e0..352a48c89 100644 --- a/lib/logical-fields.c +++ b/lib/logical-fields.c @@ -125,6 +125,10 @@ ovn_init_symtab(struct shash *symtab) MLF_SKIP_SNAT_FOR_LB_BIT); expr_symtab_add_subfield(symtab, "flags.skip_snat_for_lb", NULL, flags_str); + snprintf(flags_str, sizeof flags_str, "flags[%d]", + MLF_USE_SNAT_ZONE); + expr_symtab_add_subfield(symtab, "flags.use_snat_zone", NULL, + flags_str); /* Connection tracking state. */ expr_symtab_add_field_scoped(symtab, "ct_mark", MFF_CT_MARK, NULL, false, diff --git a/northd/northd.c b/northd/northd.c index 0ff61deec..e4d051a94 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -159,11 +159,14 @@ enum ovn_stage { PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 18, "lr_in_arp_request") \ \ /* Logical router egress stages. */ \ - PIPELINE_STAGE(ROUTER, OUT, UNDNAT, 0, "lr_out_undnat") \ - PIPELINE_STAGE(ROUTER, OUT, POST_UNDNAT, 1, "lr_out_post_undnat") \ - PIPELINE_STAGE(ROUTER, OUT, SNAT, 2, "lr_out_snat") \ - PIPELINE_STAGE(ROUTER, OUT, EGR_LOOP, 3, "lr_out_egr_loop") \ - PIPELINE_STAGE(ROUTER, OUT, DELIVERY, 4, "lr_out_delivery") + PIPELINE_STAGE(ROUTER, OUT, CHECK_DNAT_LOCAL, 0, \ + "lr_out_chk_dnat_local") \ + PIPELINE_STAGE(ROUTER, OUT, UNDNAT, 1, "lr_out_undnat") \ + PIPELINE_STAGE(ROUTER, OUT, POST_UNDNAT, 2, "lr_out_post_undnat") \ + PIPELINE_STAGE(ROUTER, OUT, SNAT, 3, "lr_out_snat") \ + PIPELINE_STAGE(ROUTER, OUT, POST_SNAT, 4, "lr_out_post_snat") \ + PIPELINE_STAGE(ROUTER, OUT, EGR_LOOP, 5, "lr_out_egr_loop") \ + PIPELINE_STAGE(ROUTER, OUT, DELIVERY, 6, "lr_out_delivery") #define PIPELINE_STAGE(DP_TYPE, PIPELINE, STAGE, TABLE, NAME) \ S_##DP_TYPE##_##PIPELINE##_##STAGE \ @@ -210,6 +213,7 @@ enum ovn_stage { #define REGBIT_PKT_LARGER "reg9[1]" #define REGBIT_LOOKUP_NEIGHBOR_RESULT "reg9[2]" #define REGBIT_LOOKUP_NEIGHBOR_IP_RESULT "reg9[3]" +#define REGBIT_DST_NAT_IP_LOCAL "reg9[4]" /* Register to store the eth address associated to a router port for packets * received in S_ROUTER_IN_ADMISSION. @@ -9568,9 +9572,10 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, undnat_match_p, est_actions, &lb->nlb->header_); } else { - ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 120, - undnat_match_p, "ct_dnat;", - &lb->nlb->header_); + ovn_lflow_add_with_hint( + lflows, od, S_ROUTER_OUT_UNDNAT, 120, undnat_match_p, + od->is_gw_router ? "ct_dnat;" : "ct_dnat_in_czone;", + &lb->nlb->header_); } free(undnat_match_p); next: @@ -9865,7 +9870,7 @@ lrouter_nat_add_ext_ip_match(struct ovn_datapath *od, uint16_t priority; /* Priority of logical flows corresponding to exempted_ext_ips is - * +1 of the corresponding regulr NAT rule. + * +2 of the corresponding regular NAT rule. * For example, if we have following NAT rule and we associate * exempted external ips to it: * "ovn-nbctl lr-nat-add router dnat_and_snat 10.15.24.139 50.0.0.11" @@ -9873,17 +9878,17 @@ lrouter_nat_add_ext_ip_match(struct ovn_datapath *od, * And now we associate exempted external ip address set to it. * Now corresponding to above rule we will have following logical * flows: - * lr_out_snat...priority=162, match=(..ip4.dst == $exempt_range), + * lr_out_snat...priority=163, match=(..ip4.dst == $exempt_range), * action=(next;) * lr_out_snat...priority=161, match=(..), action=(ct_snat(....);) * */ if (is_src) { /* S_ROUTER_IN_DNAT uses priority 100 */ - priority = 100 + 1; + priority = 100 + 2; } else { /* S_ROUTER_OUT_SNAT uses priority (mask + 1 + 128 + 1) */ - priority = count_1bits(ntohl(mask)) + 2; + priority = count_1bits(ntohl(mask)) + 3; if (!od->is_gw_router) { priority += 128; @@ -12268,9 +12273,9 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, /* Traffic received on l3dgw_port is subject to NAT. */ ds_clear(match); ds_clear(actions); - ds_put_format(match, "ip && ip%s.dst == %s && inport == %s", - is_v6 ? "6" : "4", nat->external_ip, - od->l3dgw_ports[0]->json_key); + ds_put_format(match, "ip && ip%s.dst == %s && inport == %s && " + "flags.loopback == 0", is_v6 ? "6" : "4", + nat->external_ip, od->l3dgw_ports[0]->json_key); if (!distributed && od->n_l3dgw_ports) { /* Flows for NAT rules that are centralized are only * programmed on the gateway chassis. */ @@ -12282,12 +12287,31 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, ds_put_format(actions, "ip%s.dst=%s; next;", is_v6 ? "6" : "4", nat->logical_ip); } else { - ds_put_cstr(actions, "ct_snat;"); + ds_put_cstr(actions, "ct_snat_in_czone;"); } ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT, 100, ds_cstr(match), ds_cstr(actions), &nat->header_); + + if (!stateless) { + ds_clear(match); + ds_clear(actions); + ds_put_format(match, "ip && ip%s.dst == %s && inport == %s && " + "flags.loopback == 1 && flags.use_snat_zone == 1", + is_v6 ? "6" : "4", nat->external_ip, + od->l3dgw_ports[0]->json_key); + if (!distributed && od->n_l3dgw_ports) { + /* Flows for NAT rules that are centralized are only + * programmed on the gateway chassis. */ + ds_put_format(match, " && is_chassis_resident(%s)", + od->l3dgw_ports[0]->cr_port->json_key); + } + ds_put_cstr(actions, "ct_snat;"); + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT, + 100, ds_cstr(match), ds_cstr(actions), + &nat->header_); + } } } @@ -12364,7 +12388,7 @@ build_lrouter_in_dnat_flow(struct hmap *lflows, struct ovn_datapath *od, ds_put_format(actions, "ip%s.dst=%s; next;", is_v6 ? "6" : "4", nat->logical_ip); } else { - ds_put_format(actions, "ct_dnat(%s", nat->logical_ip); + ds_put_format(actions, "ct_dnat_in_czone(%s", nat->logical_ip); if (nat->external_port_range[0]) { ds_put_format(actions, ",%s", nat->external_port_range); } @@ -12417,7 +12441,8 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od, ds_put_format(actions, "ip%s.src=%s; next;", is_v6 ? "6" : "4", nat->external_ip); } else { - ds_put_format(actions, "ct_dnat;"); + ds_put_format(actions, + od->is_gw_router ? "ct_dnat;" : "ct_dnat_in_czone;"); } ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 100, @@ -12425,6 +12450,36 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od, &nat->header_); } +static void +build_lrouter_out_is_dnat_local(struct hmap *lflows, struct ovn_datapath *od, + const struct nbrec_nat *nat, struct ds *match, + struct ds *actions, bool distributed, + bool is_v6) +{ + /* Note that this only applies for NAT on a distributed router. + */ + if (!od->n_l3dgw_ports) { + return; + } + + ds_clear(match); + ds_put_format(match, "ip && ip%s.dst == %s && ", + is_v6 ? "6" : "4", nat->external_ip); + if (distributed) { + ds_put_format(match, "is_chassis_resident(\"%s\")", nat->logical_port); + } else { + ds_put_format(match, "is_chassis_resident(%s)", + od->l3dgw_ports[0]->cr_port->json_key); + } + + ds_clear(actions); + ds_put_cstr(actions, REGBIT_DST_NAT_IP_LOCAL" = 1; next;"); + + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_CHECK_DNAT_LOCAL, + 50, ds_cstr(match), ds_cstr(actions), + &nat->header_); +} + static void build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, const struct nbrec_nat *nat, struct ds *match, @@ -12478,16 +12533,19 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, ds_put_format(match, "ip && ip%s.src == %s && outport == %s", is_v6 ? "6" : "4", nat->logical_ip, od->l3dgw_ports[0]->json_key); - if (!distributed && od->n_l3dgw_ports) { - /* Flows for NAT rules that are centralized are only - * programmed on the gateway chassis. */ - priority += 128; - ds_put_format(match, " && is_chassis_resident(%s)", - od->l3dgw_ports[0]->cr_port->json_key); - } else if (distributed) { - priority += 128; - ds_put_format(match, " && is_chassis_resident(\"%s\")", - nat->logical_port); + if (od->n_l3dgw_ports) { + if (distributed) { + ovs_assert(nat->logical_port); + priority += 128; + ds_put_format(match, " && is_chassis_resident(\"%s\")", + nat->logical_port); + } else { + /* Flows for NAT rules that are centralized are only + * programmed on the gateway chassis. */ + priority += 128; + ds_put_format(match, " && is_chassis_resident(%s)", + od->l3dgw_ports[0]->cr_port->json_key); + } } ds_clear(actions); @@ -12505,7 +12563,7 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, ds_put_format(actions, "ip%s.src=%s; next;", is_v6 ? "6" : "4", nat->external_ip); } else { - ds_put_format(actions, "ct_snat(%s", + ds_put_format(actions, "ct_snat_in_czone(%s", nat->external_ip); if (nat->external_port_range[0]) { ds_put_format(actions, ",%s", nat->external_port_range); @@ -12519,6 +12577,24 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT, priority, ds_cstr(match), ds_cstr(actions), &nat->header_); + + if (!stateless) { + ds_put_cstr(match, " && "REGBIT_DST_NAT_IP_LOCAL" == 1"); + ds_clear(actions); + if (distributed) { + ds_put_format(actions, "eth.src = "ETH_ADDR_FMT"; ", + ETH_ADDR_ARGS(mac)); + } + ds_put_format(actions, REGBIT_DST_NAT_IP_LOCAL" = 0; ct_snat(%s", + nat->external_ip); + if (nat->external_port_range[0]) { + ds_put_format(actions, ",%s", nat->external_port_range); + } + ds_put_format(actions, ");"); + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT, + priority + 1, ds_cstr(match), + ds_cstr(actions), &nat->header_); + } } } @@ -12749,10 +12825,13 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, /* Packets are allowed by default. */ ovn_lflow_add(lflows, od, S_ROUTER_IN_DEFRAG, 0, "1", "next;"); ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, 0, "1", "next;"); + ovn_lflow_add(lflows, od, S_ROUTER_OUT_CHECK_DNAT_LOCAL, 0, "1", + REGBIT_DST_NAT_IP_LOCAL" = 0; next;"); ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, 0, "1", "next;"); ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 0, "1", "next;"); ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 0, "1", "next;"); ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 0, "1", "next;"); + ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_SNAT, 0, "1", "next;"); 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;"); @@ -12765,8 +12844,7 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, * not committed, it would produce ongoing datapath flows with the ct.new * flag set. Some NICs are unable to offload these flows. */ - if ((od->is_gw_router || od->n_l3dgw_ports) && - (od->nbr->n_nat || od->has_lb_vip)) { + if (od->is_gw_router && (od->nbr->n_nat || od->has_lb_vip)) { ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 50, "ip", "flags.loopback = 1; ct_dnat;"); ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 50, @@ -12839,6 +12917,10 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, } } + /* S_ROUTER_OUT_DNAT_LOCAL */ + build_lrouter_out_is_dnat_local(lflows, od, nat, match, actions, + distributed, is_v6); + /* S_ROUTER_OUT_UNDNAT */ build_lrouter_out_undnat_flow(lflows, od, nat, match, actions, distributed, mac, is_v6); @@ -12912,7 +12994,8 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, "clone { ct_clear; " "inport = outport; outport = \"\"; " "eth.dst <-> eth.src; " - "flags = 0; flags.loopback = 1; "); + "flags = 0; flags.loopback = 1; " + "flags.use_snat_zone = "REGBIT_DST_NAT_IP_LOCAL"; "); for (int j = 0; j < MFF_N_LOG_REGS; j++) { ds_put_format(actions, "reg%d = 0; ", j); } diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index 21d83718c..fc9d51ea7 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -2879,23 +2879,65 @@ icmp6 { <p> For each configuration in the OVN Northbound database, that asks to change the source IP address of a packet from <var>A</var> to - <var>B</var>, a priority-100 flow matches <code>ip && - ip4.dst == <var>B</var> && inport == <var>GW</var></code> or - <code>ip && - ip6.dst == <var>B</var> && inport == <var>GW</var></code> - where <var>GW</var> is the logical router gateway port, with an - action <code>ct_snat;</code>. If the NAT rule is of type - dnat_and_snat and has <code>stateless=true</code> in the - options, then the action would be <code>ip4/6.dst= - (<var>B</var>)</code>. + <var>B</var>, two priority-100 flows are added. </p> <p> If the NAT rule cannot be handled in a distributed manner, then - the priority-100 flow above is only programmed on the + the below priority-100 flows are only programmed on the gateway chassis. </p> + <ul> + <li> + <p> + The first flow matches <code>ip && + ip4.dst == <var>B</var> && inport == <var>GW</var> + && flags.loopback == 0</code> or + <code>ip && + ip6.dst == <var>B</var> && inport == <var>GW</var> + && flags.loopback == 0</code> + where <var>GW</var> is the logical router gateway port, with an + action <code>ct_snat_in_czone;</code> to unSNAT in the common + zone. If the NAT rule is of type dnat_and_snat and has + <code>stateless=true</code> in the options, then the action + would be <code>ip4/6.dst=(<var>B</var>)</code>. + </p> + + <p> + If the NAT entry is of type <code>snat</code>, then there is an + additional match <code>is_chassis_resident(<var>cr-GW</var>) + </code> where <var>cr-GW</var> is the chassis resident port of + <var>GW</var>. + </p> + </li> + + <li> + <p> + The second flow matches <code>ip && + ip4.dst == <var>B</var> && inport == <var>GW</var> + && flags.loopback == 1 && + flags.use_snat_zone == 1</code> or + <code>ip && + ip6.dst == <var>B</var> && inport == <var>GW</var> + && flags.loopback == 0 && + flags.use_snat_zone == 1</code> + where <var>GW</var> is the logical router gateway port, with an + action <code>ct_snat;</code> to unSNAT in the snat zone. If the + NAT rule is of type dnat_and_snat and has + <code>stateless=true</code> in the options, then the action + would be <code>ip4/6.dst=(<var>B</var>)</code>. + </p> + + <p> + If the NAT entry is of type <code>snat</code>, then there is an + additional match <code>is_chassis_resident(<var>cr-GW</var>) + </code> where <var>cr-GW</var> is the chassis resident port of + <var>GW</var>. + </p> + </li> + </ul> + <p> A priority-0 logical flow with match <code>1</code> has actions <code>next;</code>. @@ -4031,7 +4073,43 @@ nd_ns { </li> </ul> - <h3>Egress Table 0: UNDNAT</h3> + <h3>Egress Table 0: Check DNAT local </h3> + + <p> + This table checks if the packet needs to be DNATed in the router ingress + table <code>lr_out_dnat</code> after it is SNATed and looped back + to the ingress pipeline. This check is done only for routers configured + with distributed gateway ports and NAT entries. This check is done + so that SNAT and DNAT is done in different zones instead of a common + zone. + </p> + + <ul> + <li> + <p> + For each NAT rule in the OVN Northbound database on a + distributed router, a priority-50 logical flow with match + <code>ip4.dst == <var>E</var> && + is_chassis_resident(<var>P</var>)</code>, where <var>E</var> is the + external IP address specified in the NAT rule, <var>GW</var> + is the logical router distributed gateway port. For dnat_and_snat + NAT rule, <var>P</var> is the logical port specified in the NAT rule. + If <ref column="logical_port" + table="NAT" db="OVN_Northbound"/> column of + <ref table="NAT" db="OVN_Northbound"/> table is NOT set, then + <var>P</var> is the <code>chassisredirect port</code> of + <var>GW</var> with the actions: + <code>REGBIT_DST_NAT_IP_LOCAL = 1; next; </code> + </p> + </li> + + <li> + A priority-0 logical flow with match <code>1</code> has actions + <code>REGBIT_DST_NAT_IP_LOCAL = 0; next;</code>. + </li> + </ul> + + <h3>Egress Table 1: UNDNAT</h3> <p> This is for already established connections' reverse traffic. @@ -4040,6 +4118,23 @@ nd_ns { is unDNATed here. </p> + <ul> + <li> + A priority-0 logical flow with match <code>1</code> has actions + <code>next;</code>. + </li> + </ul> + + <h3>Egress Table 1: UNDNAT on Gateway Routers</h3> + + <ul> + <li> + For all IP packets, a priority-50 flow with an action + <code>flags.loopback = 1; ct_dnat;</code>. + </li> + </ul> + + <h3>Egress Table 1: UNDNAT on Distributed Routers</h3> <ul> <li> <p> @@ -4050,9 +4145,9 @@ nd_ns { gateway chassis that matches <code>ip && ip4.src == <var>B</var> && outport == <var>GW</var></code>, where <var>GW</var> is the logical - router gateway port with an action <code>ct_dnat;</code>. If the - backend IPv4 address <var>B</var> is also configured with L4 port - <var>PORT</var> of protocol <var>P</var>, then the + router gateway port with an action <code>ct_dnat_in_czone;</code>. + If the backend IPv4 address <var>B</var> is also configured with + L4 port <var>PORT</var> of protocol <var>P</var>, then the match also includes <code>P.src</code> == <var>PORT</var>. These flows are not added for load balancers with IPv6 <var>VIPs</var>. </p> @@ -4072,7 +4167,7 @@ nd_ns { matches <code>ip && ip4.src == <var>B</var> && outport == <var>GW</var></code>, where <var>GW</var> is the logical router gateway port, with an action - <code>ct_dnat;</code>. If the NAT rule is of type + <code>ct_dnat_in_czone;</code>. If the NAT rule is of type dnat_and_snat and has <code>stateless=true</code> in the options, then the action would be <code>ip4/6.src= (<var>B</var>)</code>. @@ -4081,7 +4176,7 @@ nd_ns { <p> If the NAT rule cannot be handled in a distributed manner, then the priority-100 flow above is only programmed on the - gateway chassis. + gateway chassis with the action <code>ct_dnat_in_czone</code>. </p> <p> @@ -4094,26 +4189,17 @@ nd_ns { </p> </li> - <li> - For all IP packets, a priority-50 flow with an action - <code>flags.loopback = 1; ct_dnat;</code>. - </li> - - <li> - A priority-0 logical flow with match <code>1</code> has actions - <code>next;</code>. - </li> </ul> - <h3>Egress Table 1: Post UNDNAT</h3> + <h3>Egress Table 2: Post UNDNAT</h3> <p> <ul> <li> A priority-50 logical flow is added that commits any untracked flows - from the previous table <code>lr_out_undnat</code>. This flow - matches on <code>ct.new && ip</code> with action - <code>ct_commit { } ; next; </code>. + from the previous table <code>lr_out_undnat</code> for Gateway + routers. This flow matches on <code>ct.new && ip</code> + with action <code>ct_commit { } ; next; </code>. </li> <li> @@ -4124,7 +4210,7 @@ nd_ns { </ul> </p> - <h3>Egress Table 2: SNAT</h3> + <h3>Egress Table 3: SNAT</h3> <p> Packets that are configured to be SNATed get their source IP address @@ -4140,7 +4226,7 @@ nd_ns { </li> </ul> - <p>Egress Table 2: SNAT on Gateway Routers</p> + <p>Egress Table 3: SNAT on Gateway Routers</p> <ul> <li> @@ -4239,7 +4325,7 @@ nd_ns { </li> </ul> - <p>Egress Table 2: SNAT on Distributed Routers</p> + <p>Egress Table 3: SNAT on Distributed Routers</p> <ul> <li> @@ -4247,28 +4333,46 @@ nd_ns { For each configuration in the OVN Northbound database, that asks to change the source IP address of a packet from an IP address of <var>A</var> or to change the source IP address of a packet that - belongs to network <var>A</var> to <var>B</var>, a flow matches - <code>ip && ip4.src == <var>A</var> && - outport == <var>GW</var></code>, where <var>GW</var> is the - logical router gateway port, with an action - <code>ct_snat(<var>B</var>);</code>. The priority of the flow - is calculated based on the mask of <var>A</var>, with matches - having larger masks getting higher priorities. If the NAT rule - is of type dnat_and_snat and has <code>stateless=true</code> - in the options, then the action would be <code>ip4/6.src= - (<var>B</var>)</code>. + belongs to network <var>A</var> to <var>B</var>, two flows are + added. The priority of these flows are calculated based on the + mask of <var>A</var>, with matches having larger masks getting + higher priorities. </p> <p> If the NAT rule cannot be handled in a distributed manner, then - the flow above is only programmed on the - gateway chassis increasing flow priority by 128 in - order to be run first + the below flows are only programmed on the gateway chassis increasing + flow priority by 128 in order to be run first. </p> + <ul> + <li> + The first flow is added with the match + <code>ip && ip4.src == <var>A</var> && + outport == <var>GW</var></code>, where <var>GW</var> is the + logical router gateway port, with an action + <code>ct_snat_in_czone(<var>B</var>);</code> to SNATed in the + common zone. If the NAT rule is of type dnat_and_snat and has + <code>stateless=true</code> in the options, then the action + would be <code>ip4/6.src=(<var>B</var>)</code>. + </li> + + <li> + The second flow is added with the match + <code>ip && ip4.src == <var>A</var> && + outport == <var>GW</var> && + REGBIT_DST_NAT_IP_LOCAL == 0</code>, where <var>GW</var> is the + logical router gateway port, with an action + <code>ct_snat(<var>B</var>);</code> to SNAT in the snat zone. + If the NAT rule is of type dnat_and_snat and has + <code>stateless=true</code> in the options, then the action would + be <code>ip4/6.src=(<var>B</var>)</code>. + </li> + </ul> + <p> If the NAT rule can be handled in a distributed manner, then - there is an additional action + there is an additional action (for both the flows) <code>eth.src = <var>EA</var>;</code>, where <var>EA</var> is the ethernet address associated with the IP address <var>A</var> in the NAT rule. This allows upstream MAC @@ -4299,7 +4403,7 @@ nd_ns { </li> </ul> - <h3>Egress Table 3: Egress Loopback</h3> + <h3>Egress Table 4: Egress Loopback</h3> <p> For distributed logical routers where one of the logical router @@ -4344,6 +4448,7 @@ clone { outport = ""; flags = 0; flags.loopback = 1; + flags.use_snat_zone = REGBIT_DST_NAT_IP_LOCAL; reg0 = 0; reg1 = 0; ... @@ -4368,7 +4473,7 @@ clone { </li> </ul> - <h3>Egress Table 4: Delivery</h3> + <h3>Egress Table 5: Delivery</h3> <p> Packets that reach this table are ready for delivery. It contains: diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 85b47a18f..70ec5e2e3 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -877,25 +877,25 @@ check_flow_match_sets() { echo echo "IPv4: stateful" ovn-nbctl --wait=sb lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 -check_flow_match_sets 2 2 3 0 0 0 0 +check_flow_match_sets 3 4 2 0 0 0 0 ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 echo echo "IPv4: stateless" ovn-nbctl --wait=sb --stateless lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 -check_flow_match_sets 2 0 1 2 2 0 0 +check_flow_match_sets 2 0 0 2 2 0 0 ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 echo echo "IPv6: stateful" ovn-nbctl --wait=sb lr-nat-add R1 dnat_and_snat fd01::1 fd11::2 -check_flow_match_sets 2 2 3 0 0 0 0 +check_flow_match_sets 3 4 2 0 0 0 0 ovn-nbctl lr-nat-del R1 dnat_and_snat fd01::1 echo echo "IPv6: stateless" ovn-nbctl --wait=sb --stateless lr-nat-add R1 dnat_and_snat fd01::1 fd11::2 -check_flow_match_sets 2 0 1 0 0 2 2 +check_flow_match_sets 2 0 0 0 0 2 2 AT_CLEANUP ]) @@ -924,9 +924,9 @@ echo "CR-LRP UUID is: " $uuid ovn-nbctl --portrange lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 1-3000 AT_CAPTURE_FILE([sbflows]) -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows && test 2 = `grep -c lr_in_unsnat sbflows`]) +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows && test 3 = `grep -c lr_in_unsnat sbflows`]) AT_CHECK([grep -c 'ct_snat.*3000' sbflows && grep -c 'ct_dnat.*3000' sbflows], - [0], [1 + [0], [2 1 ]) @@ -934,9 +934,9 @@ ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 ovn-nbctl --wait=sb --portrange lr-nat-add R1 snat 172.16.1.1 50.0.0.11 1-3000 AT_CAPTURE_FILE([sbflows2]) -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows2 && test 2 = `grep -c lr_in_unsnat sbflows`]) +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows2 && test 3 = `grep -c lr_in_unsnat sbflows`]) AT_CHECK([grep -c 'ct_snat.*3000' sbflows2 && grep -c 'ct_dnat.*3000' sbflows2], - [1], [1 + [1], [2 0 ]) @@ -944,7 +944,7 @@ ovn-nbctl lr-nat-del R1 snat 172.16.1.1 ovn-nbctl --wait=sb --portrange --stateless lr-nat-add R1 dnat_and_snat 172.16.1.2 50.0.0.12 1-3000 AT_CAPTURE_FILE([sbflows3]) -OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows3 && test 3 = `grep -c lr_in_unsnat sbflows3`]) +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 > sbflows3 && test 4 = `grep -c lr_in_unsnat sbflows3`]) AT_CHECK([grep 'ct_[s]dnat.*172\.16\.1\.2.*3000' sbflows3], [1]) ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 @@ -1008,17 +1008,20 @@ AT_CAPTURE_FILE([drflows]) ovn-sbctl dump-flows CR > crflows AT_CAPTURE_FILE([crflows]) -AT_CHECK([ - grep -c lr_out_snat drflows - grep -c lr_out_snat crflows - grep lr_out_snat drflows | grep "ip4.src == 50.0.0.11" | grep -c "ip4.dst == $allowed_range" - grep lr_out_snat crflows | grep "ip4.src == 50.0.0.11" | grep -c "ip4.dst == $allowed_range"], [0], [dnl -3 -3 -1 -1 +AT_CHECK([grep -e "lr_out_snat" drflows | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ct_snat_in_czone(172.16.1.1);) + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.1);) +]) + +AT_CHECK([grep -e "lr_out_snat" crflows | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ct_snat(172.16.1.1);) ]) + # SNAT with DISALLOWED_IPs check ovn-nbctl lr-nat-del DR snat 50.0.0.11 check ovn-nbctl lr-nat-del CR snat 50.0.0.11 @@ -1036,19 +1039,19 @@ AT_CAPTURE_FILE([drflows2]) ovn-sbctl dump-flows CR > crflows2 AT_CAPTURE_FILE([crflows2]) -AT_CHECK([ - grep -c lr_out_snat drflows2 - grep -c lr_out_snat crflows2 - grep lr_out_snat drflows2 | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep -c "priority=162" - grep lr_out_snat drflows2 | grep "ip4.src == 50.0.0.11" | grep -c "priority=161" - grep lr_out_snat crflows2 | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep -c "priority=34" - grep lr_out_snat crflows2 | grep "ip4.src == 50.0.0.11" | grep -c "priority=33"], [0], [dnl -4 -4 -1 -1 -1 -1 +AT_CHECK([grep -e "lr_out_snat" drflows2 | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ct_snat_in_czone(172.16.1.1);) + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.1);) + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) +]) + +AT_CHECK([grep -e "lr_out_snat" crflows2 | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ct_snat(172.16.1.1);) + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) ]) # Stateful FIP with ALLOWED_IPs @@ -1059,25 +1062,24 @@ check ovn-nbctl lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11 check ovn-nbctl lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 check ovn-nbctl lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 allowed_range -check ovn-nbctl lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range +check ovn-nbctl --wait=sb lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range -ovn-nbctl show DR -ovn-sbctl dump-flows DR -ovn-nbctl show CR -ovn-sbctl dump-flows CR - -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ -wc -l`]) -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ -wc -l`]) +ovn-sbctl dump-flows DR > drflows3 +AT_CAPTURE_FILE([drflows2]) +ovn-sbctl dump-flows CR > crflows3 +AT_CAPTURE_FILE([crflows2]) -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 +AT_CHECK([grep -e "lr_out_snat" drflows3 | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ct_snat_in_czone(172.16.1.2);) + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.2);) ]) -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 -]) -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 -]) -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 + +AT_CHECK([grep -e "lr_out_snat" crflows3 | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ct_snat(172.16.1.2);) ]) # Stateful FIP with DISALLOWED_IPs @@ -1088,26 +1090,26 @@ ovn-nbctl lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11 ovn-nbctl lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 ovn-nbctl --is-exempted lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 disallowed_range -ovn-nbctl --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range +check ovn-nbctl --wait=sb --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range -ovn-nbctl show DR -ovn-sbctl dump-flows DR -ovn-nbctl show CR -ovn-sbctl dump-flows CR - -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ -wc -l`]) -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ -wc -l`]) +ovn-sbctl dump-flows DR > drflows4 +AT_CAPTURE_FILE([drflows2]) +ovn-sbctl dump-flows CR > crflows4 +AT_CAPTURE_FILE([crflows2]) -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=162" | wc -l], [0], [1 -]) -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 +AT_CHECK([grep -e "lr_out_snat" drflows4 | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ct_snat_in_czone(172.16.1.2);) + table=??(lr_out_snat ), priority=162 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.16.1.2);) + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) ]) -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=34" | wc -l], [0], [1 -]) -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 +AT_CHECK([grep -e "lr_out_snat" crflows4 | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ct_snat(172.16.1.2);) + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) ]) # Stateless FIP with DISALLOWED_IPs @@ -1120,24 +1122,21 @@ ovn-nbctl --stateless lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 ovn-nbctl lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 allowed_range ovn-nbctl lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range -ovn-nbctl show DR -ovn-sbctl dump-flows DR - -ovn-nbctl show CR -ovn-sbctl dump-flows CR - -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ -wc -l`]) -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ -wc -l`]) +ovn-sbctl dump-flows DR > drflows5 +AT_CAPTURE_FILE([drflows2]) +ovn-sbctl dump-flows CR > crflows5 +AT_CAPTURE_FILE([crflows2]) -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 +AT_CHECK([grep -e "lr_out_snat" drflows5 | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $allowed_range), action=(ip4.src=172.16.1.2; next;) ]) -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 -]) -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1 -]) -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1 + +AT_CHECK([grep -e "lr_out_snat" crflows5 | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $allowed_range), action=(ip4.src=172.16.1.2; next;) ]) # Stateful FIP with DISALLOWED_IPs @@ -1150,23 +1149,25 @@ ovn-nbctl --stateless lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11 ovn-nbctl --is-exempted lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 disallowed_range ovn-nbctl --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range -ovn-nbctl show DR -ovn-sbctl dump-flows DR -ovn-nbctl show CR -ovn-sbctl dump-flows CR +ovn-nbctl --wait=sb sync -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \ -wc -l`]) -OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \ -wc -l`]) +ovn-sbctl dump-flows DR > drflows6 +AT_CAPTURE_FILE([drflows2]) +ovn-sbctl dump-flows CR > crflows6 +AT_CAPTURE_FILE([crflows2]) -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=162" | wc -l], [0], [1 -]) -AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 +AT_CHECK([grep -e "lr_out_snat" drflows6 | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1")), action=(ip4.src=172.16.1.2; next;) + table=??(lr_out_snat ), priority=163 , match=(ip && ip4.src == 50.0.0.11 && outport == "DR-S1" && is_chassis_resident("cr-DR-S1") && ip4.dst == $disallowed_range), action=(next;) ]) -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=34" | wc -l], [0], [1 -]) -AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1 + +AT_CHECK([grep -e "lr_out_snat" crflows6 | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_out_snat ), priority=0 , match=(1), action=(next;) + table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=??(lr_out_snat ), priority=33 , match=(ip && ip4.src == 50.0.0.11), action=(ip4.src=172.16.1.2; next;) + table=??(lr_out_snat ), priority=35 , match=(ip && ip4.src == 50.0.0.11 && ip4.dst == $disallowed_range), action=(next;) ]) AT_CLEANUP @@ -3475,14 +3476,14 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(ct_lb(backends=10.0.0.40:8080);) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) ]) check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="20.0.0.4 aef0::4" @@ -3511,21 +3512,21 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) - table=2 (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip4), action=(ct_snat(20.0.0.4);) - table=2 (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip6), action=(ct_snat(aef0::4);) - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip4), action=(ct_snat(20.0.0.4);) + table=? (lr_out_snat ), priority=100 , match=(flags.force_snat_for_lb == 1 && ip6), action=(ct_snat(aef0::4);) + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) ]) check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="router_ip" @@ -3557,22 +3558,22 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) ]) check ovn-nbctl --wait=sb remove logical_router lr0 options chassis @@ -3584,9 +3585,9 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) ]) check ovn-nbctl set logical_router lr0 options:chassis=ch1 @@ -3617,23 +3618,23 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw1"), action=(ct_snat(bef0::1);) - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw1"), action=(ct_snat(20.0.0.1);) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw1"), action=(ct_snat(bef0::1);) + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) ]) check ovn-nbctl --wait=sb lb-add lb2 10.0.0.20:80 10.0.0.40:8080 @@ -3661,18 +3662,18 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 10.0.0.20 && tcp && reg9[[16..31]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl - table=2 (lr_out_snat ), priority=120 , match=(flags.skip_snat_for_lb == 1 && ip), action=(next;) +AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=120 , match=(flags.skip_snat_for_lb == 1 && ip), action=(next;) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) ]) AT_CLEANUP @@ -4176,6 +4177,8 @@ check ovn-nbctl lsp-set-options lrp1-attachment router-port=lrp1 check ovn-nbctl lr-nat-add lr0 dnat 42.42.42.42 192.168.0.2 check ovn-nbctl --wait=sb sync +ovn-trace --minimal 'inport == "sw1-port1" && eth.src == 50:54:00:00:00:03 && eth.dst == 00:00:00:00:ff:02 && ip4.dst == 42.42.42.42 && ip4.src == 11.0.0.2 && ip.ttl == 64' + AT_CHECK([ovn-trace --minimal 'inport == "sw1-port1" && eth.src == 50:54:00:00:00:03 && eth.dst == 00:00:00:00:ff:02 && ip4.dst == 42.42.42.42 && ip4.src == 11.0.0.2 && ip.ttl == 64' | grep "output(\"sw0-port1\")"], [0], [ignore]) dnl If we remove the DNAT entry we will be unable to trace to the DNAT address @@ -4761,17 +4764,17 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) ]) # Create few dnat_and_snat entries @@ -4797,17 +4800,21 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) +]) + +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) ]) ovn-sbctl chassis-add gw1 geneve 127.0.0.1 @@ -4828,9 +4835,12 @@ AT_CAPTURE_FILE([lr0flows]) AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) ]) AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl @@ -4839,26 +4849,34 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);) + table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone(10.0.0.3);) +]) + +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.10 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.20 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.30 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) - table=0 (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) - table=2 (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.10);) - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.30);) - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.20);) +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=? (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.10);) + table=? (lr_out_snat ), priority=154 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.10);) + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.30);) + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.20);) + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.30);) + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.20);) ]) # Associate load balancer to lr0 @@ -4879,9 +4897,12 @@ AT_CAPTURE_FILE([lr0flows]) AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl table=4 (lr_in_unsnat ), priority=0 , match=(1), action=(next;) - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) - table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.10 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 0 && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone;) + table=4 (lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.30 && inport == "lr0-public" && flags.loopback == 1 && flags.use_snat_zone == 1 && is_chassis_resident("cr-lr0-public")), action=(ct_snat;) ]) AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl @@ -4894,7 +4915,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);) + table=6 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone(10.0.0.3);) table=6 (lr_in_dnat ), priority=110 , match=(ct.est && ip4 && reg0 == 172.168.0.200 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) table=6 (lr_in_dnat ), priority=110 , match=(ct.new && ip4 && reg0 == 172.168.0.200 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.80,10.0.0.81);) table=6 (lr_in_dnat ), priority=120 , match=(ct.est && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) @@ -4905,27 +4926,35 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) - table=0 (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.4 && tcp.src == 8080)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && tcp.src == 82) || (ip4.src == 10.0.0.60 && tcp.src == 82)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && udp.src == 6062) || (ip4.src == 10.0.0.60 && udp.src == 6062)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) - table=0 (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.80) || (ip4.src == 10.0.0.81)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;) - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.10 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.20 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) + table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.30 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;) +]) + +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.4 && tcp.src == 8080)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && tcp.src == 82) || (ip4.src == 10.0.0.60 && tcp.src == 82)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.50 && udp.src == 6062) || (ip4.src == 10.0.0.60 && udp.src == 6062)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) + table=? (lr_out_undnat ), priority=120 , match=(ip4 && ((ip4.src == 10.0.0.80) || (ip4.src == 10.0.0.81)) && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) - table=2 (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.10);) - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.30);) - table=2 (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat(172.168.0.20);) +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=? (lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.10);) + table=? (lr_out_snat ), priority=154 , match=(ip && ip4.src == 10.0.0.0/24 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.10);) + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.30);) + table=? (lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat_in_czone(172.168.0.20);) + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.10 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.30);) + table=? (lr_out_snat ), priority=162 , match=(ip && ip4.src == 10.0.0.3 && outport == "lr0-public" && is_chassis_resident("cr-lr0-public") && reg9[[4]] == 1), action=(reg9[[4]] = 0; ct_snat(172.168.0.20);) ]) # Make the logical router as Gateway router @@ -4965,22 +4994,26 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +]) + +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) ]) # Set lb force snat logical router. @@ -5020,24 +5053,28 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) +]) + +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) ]) # Add a LB VIP same as router ip. @@ -5081,24 +5118,28 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +]) + +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) ]) # Add IPv6 router port and LB. @@ -5155,26 +5196,30 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip6 && xxreg0 == def0::2 && tcp && reg9[[16..31]] == 8000), action=(flags.force_snat_for_lb = 1; ct_lb(backends=[[aef0::2]]:80,[[aef0::3]]:80);) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) +]) + +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-public"), action=(ct_snat(def0::10);) - table=2 (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw0"), action=(ct_snat(aef0::1);) - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) - table=2 (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) - table=2 (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.10);) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0"), action=(ct_snat(10.0.0.1);) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-public"), action=(ct_snat(def0::10);) + table=? (lr_out_snat ), priority=110 , match=(flags.force_snat_for_lb == 1 && ip6 && outport == "lr0-sw0"), action=(ct_snat(aef0::1);) + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) + table=? (lr_out_snat ), priority=25 , match=(ip && ip4.src == 10.0.0.0/24), action=(ct_snat(172.168.0.10);) + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.10), action=(ct_snat(172.168.0.30);) + table=? (lr_out_snat ), priority=33 , match=(ip && ip4.src == 10.0.0.3), action=(ct_snat(172.168.0.20);) ]) check ovn-nbctl lrp-del lr0-sw0 @@ -5209,19 +5254,23 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);) ]) -AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl - table=0 (lr_out_undnat ), priority=0 , match=(1), action=(next;) - table=0 (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) +AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;) +]) + +AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) ]) -AT_CHECK([grep "lr_out_post_undnat" lr0flows | sort], [0], [dnl - table=1 (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) - table=1 (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) +AT_CHECK([grep "lr_out_post_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_post_undnat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_post_undnat ), priority=50 , match=(ip && ct.new), action=(ct_commit { } ; next; ) ]) -AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl - table=2 (lr_out_snat ), priority=0 , match=(1), action=(next;) - table=2 (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) +AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl + table=? (lr_out_snat ), priority=0 , match=(1), action=(next;) + table=? (lr_out_snat ), priority=120 , match=(nd_ns), action=(next;) ]) AT_CLEANUP diff --git a/tests/ovn.at b/tests/ovn.at index 0d606b42f..ae5744407 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -21604,7 +21604,7 @@ AT_CAPTURE_FILE([sbflows]) AT_CHECK([for regex in ct_snat ct_dnat ip4.dst= ip4.src=; do grep -c "$regex" sbflows; done], [0], [0 -1 +0 2 2 ]) diff --git a/tests/system-ovn.at b/tests/system-ovn.at index c9f5771c9..7f6cb32dc 100644 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -2224,7 +2224,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=42 | \ +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. @@ -2262,7 +2262,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=42 | \ +OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=43 | \ grep 'nat(src=20.0.0.2)']) rm -f wget*.log @@ -3711,17 +3711,24 @@ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl icmpv6,orig=(src=fd20::2,dst=fd20::3,id=<cleared>,type=128,code=0),reply=(src=fd11::2,dst=fd20::2,id=<cleared>,type=129,code=0),zone=<cleared> ]) +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) + # South-North SNAT: 'foo2' pings 'alice1'. But 'alice1' receives traffic -# from 172.16.1.4 +# from fd20::4 NS_CHECK_EXEC([foo2], [ping6 -q -c 3 -i 0.3 -w 2 fd20::2 | FORMAT_PING], \ [0], [dnl 3 packets transmitted, 3 received, 0% packet loss, time 0ms ]) -# We verify that SNAT indeed happened via 'dump-conntrack' command. +ovs-appctl dpctl/dump-conntrack | grep icmpv6 AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd11::3) | \ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl -icmpv6,orig=(src=fd11::3,dst=fd20::2,id=<cleared>,type=128,code=0),reply=(src=fd20::2,dst=fd11::3,id=<cleared>,type=129,code=0),zone=<cleared> +]) + +# We verify that SNAT indeed happened via 'dump-conntrack' command. +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::4) | \ +sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl +icmpv6,orig=(src=fd11::3,dst=fd20::2,id=<cleared>,type=128,code=0),reply=(src=fd20::2,dst=fd20::4,id=<cleared>,type=129,code=0),zone=<cleared> ]) AT_CHECK([ovs-appctl dpctl/flush-conntrack]) @@ -3861,11 +3868,9 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \ 3 packets transmitted, 3 received, 0% packet loss, time 0ms ]) -# We verify that the connection is tracked but not NATted. This is due to the -# unDNAT table in the egress router pipeline -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ +# We verify that the connection is not tracked. +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl -icmp,orig=(src=192.168.1.2,dst=192.168.2.2,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> ]) AT_CHECK([ovs-appctl dpctl/flush-conntrack]) @@ -3875,11 +3880,9 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \ 3 packets transmitted, 3 received, 0% packet loss, time 0ms ]) -# We verify that the connection is tracked but not NATted. This is due to the -# unDNAT table in the egress router pipeline -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ +# We verify that the connection is not tracked. +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl -icmp,orig=(src=192.168.1.3,dst=192.168.2.2,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=192.168.1.3,id=<cleared>,type=0,code=0),zone=<cleared> ]) AT_CHECK([ovs-appctl dpctl/flush-conntrack]) @@ -3889,14 +3892,13 @@ NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.3 | FORMAT_PING], \ 3 packets transmitted, 3 received, 0% packet loss, time 0ms ]) -# We verify that the connection is tracked but not NATted. This is due to the -# unDNAT table in the egress router pipeline -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \ +# We verify that the connection is not tracked. +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(192.168.2.2) | \ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl -icmp,orig=(src=192.168.2.2,dst=192.168.1.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.3,dst=192.168.2.2,id=<cleared>,type=0,code=0),zone=<cleared> ]) AT_CHECK([ovs-appctl dpctl/flush-conntrack]) + # East-West NAT: 'foo1' pings 'bar1' using 172.16.1.4. NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ [0], [dnl @@ -3905,11 +3907,10 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ # Check conntrack entries. First SNAT of 'foo1' address happens. # Then DNAT of 'bar1' address happens (listed first below). -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) | \ +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(172.16.1.4) | \ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl icmp,orig=(src=172.16.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared> icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared> -icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> ]) AT_CHECK([ovs-appctl dpctl/flush-conntrack]) @@ -3922,7 +3923,7 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \ # Check conntrack entries. First SNAT of 'foo2' address happens. # Then DNAT of 'bar1' address happens (listed first below). -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \ +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep icmp | FORMAT_CT(172.16.1.1) | \ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> icmp,orig=(src=192.168.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> @@ -4055,13 +4056,6 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ 3 packets transmitted, 3 received, 0% packet loss, time 0ms ]) -# We verify that the connection is tracked but not NATted. This is due to the -# unDNAT table in the egress router pipeline -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl -icmpv6,orig=(src=fd11::2,dst=fd12::2,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd11::2,id=<cleared>,type=129,code=0),zone=<cleared> -]) - AT_CHECK([ovs-appctl dpctl/flush-conntrack]) # East-West No NAT: 'foo2' pings 'bar1' using fd12::2. NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ @@ -4069,13 +4063,6 @@ NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 fd12::2 | FORMAT_PING], \ 3 packets transmitted, 3 received, 0% packet loss, time 0ms ]) -# We verify that the connection is tracked but not NATted. This is due to the -# unDNAT table in the egress router pipeline -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl -icmpv6,orig=(src=fd11::3,dst=fd12::2,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd11::3,id=<cleared>,type=129,code=0),zone=<cleared> -]) - AT_CHECK([ovs-appctl dpctl/flush-conntrack]) # East-West No NAT: 'bar1' pings 'foo2' using fd11::3. NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 fd11::3 | FORMAT_PING], \ @@ -4083,13 +4070,6 @@ NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 fd11::3 | FORMAT_PING], \ 3 packets transmitted, 3 received, 0% packet loss, time 0ms ]) -# We verify that the connection is tracked but not NATted. This is due to the -# unDNAT table in the egress router pipeline -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd12::2) | \ -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl -icmpv6,orig=(src=fd12::2,dst=fd11::3,id=<cleared>,type=128,code=0),reply=(src=fd11::3,dst=fd12::2,id=<cleared>,type=129,code=0),zone=<cleared> -]) - AT_CHECK([ovs-appctl dpctl/flush-conntrack]) # East-West NAT: 'foo1' pings 'bar1' using fd20::4. NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd20::4 | FORMAT_PING], \ @@ -4101,7 +4081,6 @@ NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 fd20::4 | FORMAT_PING], \ # Then DNAT of 'bar1' address happens (listed first below). AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::4) | \ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl -icmpv6,orig=(src=fd11::2,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd20::4,dst=fd11::2,id=<cleared>,type=129,code=0),zone=<cleared> icmpv6,orig=(src=fd11::2,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd20::4,dst=fd20::3,id=<cleared>,type=129,code=0),zone=<cleared> icmpv6,orig=(src=fd20::3,dst=fd20::4,id=<cleared>,type=128,code=0),reply=(src=fd12::2,dst=fd20::3,id=<cleared>,type=129,code=0),zone=<cleared> ]) @@ -6037,7 +6016,6 @@ NS_CHECK_EXEC([sw01-x], [ping -q -c 3 -i 0.3 -w 2 172.16.1.100 | FORMAT_PING], \ AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.100) | \ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl icmp,orig=(src=192.168.1.2,dst=172.16.1.100,id=<cleared>,type=8,code=0),reply=(src=172.16.1.100,dst=172.16.1.20,id=<cleared>,type=0,code=0),zone=<cleared> -icmp,orig=(src=192.168.1.2,dst=172.16.1.100,id=<cleared>,type=8,code=0),reply=(src=172.16.1.100,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared> ]) OVS_APP_EXIT_AND_WAIT([ovn-controller])