On 4/28/25 8:32 PM, Alexandra Rukomoinikova wrote: > [0] Removed support for using load balancers in conjunction with stateless > ACL. > This commit removes the ability to use load balancers alongside stateless ACL. > If a load balancer is created, the datapath is no longer fully stateless. > Therefore, to avoid traffic being directed to the contract, it is recommended > to refrain from creating a load balancer entirely. > > Commit [0] ensures the separation of stateful and stateless scenarios > in the absence of load balancers, without altering the functionality > of load balancers themselves. > > When a logical switch is configured with stateless ACL and a load balancer, > the check for the `REGBIT_CONNTRACK_NAT` flag in the `pre_lb` stage of > the ingress pipeline becomes redundant. Traffic directed to the load balancer > must be processed through the conntrack. > > To ensure proper load balancer operation, a rule must be added to match > the load balancer's VIP address and its protocol (if applicable). This rule > is added to the datapath group and does not negatively impact performance. > Packets matching this rule would still be directed to the contract via > lower-priority rules in the absence of stateless ACL. However, with stateless > ACL, > this rule enables load balancing when the client balances traffic to itself. > > In the egress pipeline, the stateless register should only be set if no > load balancers are present on the datapath. This maintains a clear separation > between Stateful and Stateless modes when using ACL. > If a user creates a load balancer on a logical switch, they should be aware > that the traffic will no longer be fully stateless. > > Also in case of lb configured with stateless ACLs we no longer take into > account > ct.inv packets in egress. They will be dropped further, at the hypervisor > level. > > [0] - ovn-org@a0f82ef. > > Signed-off-by: Alexandra Rukomoinikova <arukomoinikova@k2.cloud> > --- > v3 --> v4: fixed Dumitu's comments. >
Hi Alexandra, Thanks for the patch and sorry for the slowness in reviews. > --- > lib/lb.c | 1 + > lib/lb.h | 2 + > northd/en-ls-stateful.c | 4 + > northd/en-ls-stateful.h | 1 + > northd/lb.c | 17 ++++- > northd/northd.c | 71 +++++++++++++++--- > northd/ovn-northd.8.xml | 11 ++- > tests/ovn-northd.at | 143 +++++++++++++++++++++++++++++++++--- > tests/ovn.at | 8 +- > tests/system-ovn.at | 157 ++++++++++++++++++++++++++++++++++++---- > 10 files changed, 372 insertions(+), 43 deletions(-) > > diff --git a/lib/lb.c b/lib/lb.c > index 6e7a4e296..f12373321 100644 > --- a/lib/lb.c > +++ b/lib/lb.c > @@ -304,6 +304,7 @@ ovn_lb_vip_destroy(struct ovn_lb_vip *vip) > { > free(vip->vip_str); > free(vip->port_str); > + free(vip->hairpin_snat_ip); > ovn_lb_backends_destroy(vip); > } > > diff --git a/lib/lb.h b/lib/lb.h > index b1a89d63c..c629e1efd 100644 > --- a/lib/lb.h > +++ b/lib/lb.h > @@ -42,6 +42,8 @@ struct ovn_lb_vip { > > bool empty_backend_rej; > int address_family; > + > + char *hairpin_snat_ip; > }; > > struct ovn_lb_backend { > diff --git a/northd/en-ls-stateful.c b/northd/en-ls-stateful.c > index 69cda5008..6240c1ea8 100644 > --- a/northd/en-ls-stateful.c > +++ b/northd/en-ls-stateful.c > @@ -452,6 +452,10 @@ ls_stateful_record_set_acl_flags_(struct > ls_stateful_record *ls_stateful_rec, > && !strcmp(acl->action, "allow-related")) { > ls_stateful_rec->has_stateful_acl = true; > } > + if (!ls_stateful_rec->has_stateless_acl > + && !strcmp(acl->action, "allow-stateless")) { > + ls_stateful_rec->has_stateless_acl = true; > + } > if (ls_stateful_rec->has_stateful_acl && > ls_acl_tiers_are_maxed_out( > &ls_stateful_rec->max_acl_tier, > diff --git a/northd/en-ls-stateful.h b/northd/en-ls-stateful.h > index 18a7398a6..8516996c5 100644 > --- a/northd/en-ls-stateful.h > +++ b/northd/en-ls-stateful.h > @@ -50,6 +50,7 @@ struct ls_stateful_record { > size_t ls_index; > > bool has_stateful_acl; > + bool has_stateless_acl; > bool has_lb_vip; > bool has_acls; > struct acl_tier max_acl_tier; > diff --git a/northd/lb.c b/northd/lb.c > index af0c92954..3279a8fcd 100644 > --- a/northd/lb.c > +++ b/northd/lb.c > @@ -256,6 +256,14 @@ ovn_lb_get_health_check(const struct nbrec_load_balancer > *nbrec_lb, > return NULL; > } > > +static bool > +validate_snap_ip_address(const char *snat_ip) > +{ > + ovs_be32 ip; > + > + return ip_parse(snat_ip, &ip); > +} > + > static void > ovn_northd_lb_init(struct ovn_northd_lb *lb, > const struct nbrec_load_balancer *nbrec_lb) > @@ -338,7 +346,14 @@ ovn_northd_lb_init(struct ovn_northd_lb *lb, > if (lb_vip_nb->lb_health_check) { > ovn_lb_vip_backends_health_check_init(lb, lb_vip, lb_vip_nb); > } > - } > + > + const char *snat_ip = smap_get(&lb->nlb->options, > + "hairpin_snat_ip"); > + > + if (snat_ip && validate_snap_ip_address(snat_ip)) { > + lb_vip->hairpin_snat_ip = xstrdup(snat_ip); > + } > + } > > /* It's possible that parsing VIPs fails. Update the lb->n_vips to the > * correct value. > diff --git a/northd/northd.c b/northd/northd.c > index 74792e38b..b9f733bd8 100644 > --- a/northd/northd.c > +++ b/northd/northd.c > @@ -5926,7 +5926,8 @@ skip_port_from_conntrack(const struct ovn_datapath *od, > struct ovn_port *op, > } > > static void > -build_stateless_filter(const struct ovn_datapath *od, > +build_stateless_filter(const struct ls_stateful_record *ls_stateful_rec, > + const struct ovn_datapath *od, > const struct nbrec_acl *acl, > struct lflow_table *lflows, > struct lflow_ref *lflow_ref) > @@ -5939,7 +5940,11 @@ build_stateless_filter(const struct ovn_datapath *od, > action, > &acl->header_, > lflow_ref); > - } else { > + } else if (!ls_stateful_rec->has_lb_vip) { > + /* For cases when we have statefull ACLs but no load Uhm, I think you mean "For cases when we have stateless ACLs but no load balancer". > + balancer configured on logical switch - we should > + completely bypass conntrack on egress, otherwise > + it is necessary to check the balanced traffic. */ > ovn_lflow_add_with_hint(lflows, od, S_SWITCH_OUT_PRE_ACL, > acl->priority + OVN_ACL_PRI_OFFSET, > acl->match, However, I've been testing this patch some more and, as I was trying to say on earlier versions, I don't think we can accept it as is. Let's assume we have an user that has the following configuration: VIF2 (42.42.42.2/24) --- LS --- VIF3 (42.42.42.3/24) And a to-lport (egress) stateless ACL: to-lport, prio 1, if "ip4.dst == 42.42.42.0/24", then allow-stateless When there's no load balancer configured all traffic from VIF3 (42.42.42.3) to VIF2 (42.42.42.2) is forwarded without ever being sent to conntrack, in the datapath ct_state=-trk, which is fine. Now let's assume we also have VIFs 4 and 5: VIF2 (42.42.42.2/24) --- LS --- VIF3 (42.42.42.3/24) | VIF4 (42.42.42.4/24) ----+----- VIF5 (42.42.42.5/24) And a TCP load balancer: - VIP: 66.66.66.66:666 - backends: 42.42.42.4:4242 (VIF4) Before your patch: a. traffic from VIF5 to LB VIP (66.66.66.66:666) is not DNATed, LB doesn't work b. all traffic from VIF3 (42.42.42.3) to VIF2 (42.42.42.2) is forwarded without ever being sent to conntrack, in the datapath ct_state=-trk. According to Han and Venu [0], [1], that's as designed: [0] https://github.com/ovn-org/ovn/commit/a0f82efdd9dfd3ef2d9606c1890e353df1097a51 [1] https://mail.openvswitch.org/pipermail/ovs-dev/2022-November/399224.html Now with your patch: a. traffic from VIF5 to LB VIP (66.66.66.66:666) works. BUT b. all traffic between VIF3 (42.42.42.3) and VIF2 (42.42.42.2) is forwarded either on datapath flows that match on: ct_state(+new-est-rel-rpl-inv+trk) OR on flows that match on: ct_state(-new-est-rel-rpl+inv+trk) That means the to-lport allow-stateless ACL has no stateless semantics anymore. It also breaks HW offload for some NVIDIA NICs and it also means (useless?) recirculations in the datapath. I understand that for your use case that's acceptable but other use cases as above get broken. I think we have two options: A. add flows that match on reply traffic that's destined to load balancer backends. This comes with a control plane performance cost because we need to add a flow per backend. It also means we'd have to add the flows from ovn-controller if we want to support template load balancers (for which the backend IPs are potentially not known in ovn-northd). B. add a per switch option to enable the load balancer functionality when stateless ACLs are configured on the switch. The documentation for this option should clearly note that when the option is set allow-stateless ACLs in the egress direction are not stateless anymore if LBs are present. The option should be false by default so we don't break any existing deployments. Something like NB.Logical_Switch.other_config:enable-stateless-acl-lb. Then change the code above to bypass the stateless filter in the egress pipeline only if the option is set to True for the given switch. We'd also need to make sure we change the ct.inv/!ct.inv lflow matches only if the option is set to true. This new option would also need a NEWS file entry. Knobs are not great but in this situation I'm out of ideas so I vote for option B. Please see some more minor comments below. > @@ -5950,15 +5955,17 @@ build_stateless_filter(const struct ovn_datapath *od, > } > > static void > -build_stateless_filters(const struct ovn_datapath *od, > +build_stateless_filters(const struct ls_stateful_record *ls_stateful_rec, > const struct ls_port_group_table *ls_port_groups, > + const struct ovn_datapath *od, > struct lflow_table *lflows, > struct lflow_ref *lflow_ref) > { > for (size_t i = 0; i < od->nbs->n_acls; i++) { > const struct nbrec_acl *acl = od->nbs->acls[i]; > if (!strcmp(acl->action, "allow-stateless")) { > - build_stateless_filter(od, acl, lflows, lflow_ref); > + build_stateless_filter(ls_stateful_rec, od, acl, lflows, > + lflow_ref); > } > } > > @@ -5974,7 +5981,8 @@ build_stateless_filters(const struct ovn_datapath *od, > const struct nbrec_acl *acl = ls_pg_rec->nb_pg->acls[i]; > > if (!strcmp(acl->action, "allow-stateless")) { > - build_stateless_filter(od, acl, lflows, lflow_ref); > + build_stateless_filter(ls_stateful_rec, od, acl, lflows, > + lflow_ref); > } > } > } > @@ -6029,7 +6037,8 @@ build_ls_stateful_rec_pre_acls( > } > > /* stateless filters always take precedence over stateful ACLs. */ > - build_stateless_filters(od, ls_port_groups, lflows, lflow_ref); > + build_stateless_filters(ls_stateful_rec, ls_port_groups, od, lflows, > + lflow_ref); > > /* Ingress and Egress Pre-ACL Table (Priority 110). > * > @@ -6074,7 +6083,8 @@ build_ls_stateful_rec_pre_acls( > } else if (ls_stateful_rec->has_lb_vip) { > /* We'll build stateless filters if there are LB rules so that > * the stateless flows are not tracked in pre-lb. */ > - build_stateless_filters(od, ls_port_groups, lflows, lflow_ref); > + build_stateless_filters(ls_stateful_rec, ls_port_groups, od, lflows, > + lflow_ref); > } > } > > @@ -7400,6 +7410,23 @@ choose_max_acl_tier(const struct ls_stateful_record > *ls_stateful_rec, > } > } > > +/* In the case of stateless ACLs and load balancers, all traffic > + * is passed to conntrack during egress pipeline. Conntrack will > + * mark the packets as 'invalid,' but since stateless systems do > + * not rely on conntrack state, these invalid packets will be > + * discarded during processing on the hypervisor level. > + */ > +static bool > +stateless_inv_match(const struct ls_stateful_record *ls_stateful_rec) > +{ > + if (ls_stateful_rec->has_lb_vip > + && ls_stateful_rec->has_stateless_acl) { Nit: these fit on the same line. > + return false; > + } > + > + return true; > +} > + > static void > build_acls(const struct ls_stateful_record *ls_stateful_rec, > const struct ovn_datapath *od, > @@ -7502,8 +7529,14 @@ build_acls(const struct ls_stateful_record > *ls_stateful_rec, > * > * This is enforced at a higher priority than ACLs can be defined. */ > ds_clear(&match); > - ds_put_format(&match, "%s(ct.est && ct.rpl && ct_mark.blocked == 1)", > - use_ct_inv_match ? "ct.inv || " : ""); > + > + if (use_ct_inv_match && stateless_inv_match(ls_stateful_rec)) { > + ds_put_cstr(&match, "ct.inv || (ct.est && ct.rpl && " > + "ct_mark.blocked == 1)"); > + } else { > + ds_put_cstr(&match, "ct.est && ct.rpl && ct_mark.blocked == 1"); > + } > + > ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL_EVAL, UINT16_MAX - 3, > ds_cstr(&match), REGBIT_ACL_VERDICT_DROP " = 1; next;", > lflow_ref); > @@ -7797,8 +7830,7 @@ build_lb_rules_pre_stateful(struct lflow_table *lflows, > } > ds_put_cstr(action, "ct_lb_mark;"); > > - ds_put_format(match, REGBIT_CONNTRACK_NAT" == 1 && %s.dst == %s", > - ip_match, lb_vip->vip_str); > + ds_put_format(match, "%s.dst == %s", ip_match, lb_vip->vip_str); > if (lb_vip->port_str) { > ds_put_format(match, " && %s.dst == %s", lb->proto, > lb_vip->port_str); > @@ -7808,6 +7840,23 @@ build_lb_rules_pre_stateful(struct lflow_table *lflows, > lflows, lb_dps->nb_ls_map, ods_size(ls_datapaths), > S_SWITCH_IN_PRE_STATEFUL, 120, ds_cstr(match), ds_cstr(action), > &lb->nlb->header_, lb_dps->lflow_ref); > + > + /* Pass all VIP traffic to the conntrack to support load balancers > + in the case of stateless acl. */ > + if (lb_vip->hairpin_snat_ip || lb_vip->port_str) { > + ds_clear(action); > + ds_clear(match); > + > + ds_put_format(match, "%s && %s.dst == %s", lb->proto, ip_match, > + lb_vip->hairpin_snat_ip ? lb_vip->hairpin_snat_ip > + : lb_vip->vip_str); > + ds_put_cstr(action, "ct_lb_mark;"); > + > + ovn_lflow_add_with_dp_group( > + lflows, lb_dps->nb_ls_map, ods_size(ls_datapaths), > + S_SWITCH_IN_PRE_STATEFUL, 105, ds_cstr(match), > ds_cstr(action), > + &lb->nlb->header_, lb_dps->lflow_ref); > + } > } > } > > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > index e087b6f59..08803b4c7 100644 > --- a/northd/ovn-northd.8.xml > +++ b/northd/ovn-northd.8.xml > @@ -507,7 +507,7 @@ > <ref table="Logical_Switch_Port" db="OVN_Northbound"/>. Multicast, > IPv6 > Neighbor Discovery and MLD traffic also skips stateful ACLs. For > "allow-stateless" ACLs, a flow is added to bypass setting the hint for > - connection tracker processing when there are stateful ACLs or LB rules; > + connection tracker processing when there are stateful ACLs without LB; > <code>REGBIT_ACL_STATELESS</code> is set for traffic matching stateless > ACL flows. > </p> > @@ -624,6 +624,12 @@ > <code>ct_lb_mark;</code> action. > </li> > > + <li> > + A priority-105 flow sends all packet directed to VIP that don't > + match the above flows to connection tracker. This allows load > + balancers to work in case of stateless ACLs. > + </li> > + > <li> > A priority-100 flow sends the packets to connection tracker based > on a hint provided by the previous tables > @@ -770,7 +776,8 @@ > </li> > <li> > <code>allow-stateless</code> ACLs translate into logical flows that > set > - the allow bit and advance to the next table. > + the allow bit and advance to the next table. In case of load > balancers > + with stateless ACLs in this table we allow ct.inv packets go further. > </li> > <li> > <code>reject</code> ACLs translate into logical flows with that set > the > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > index 82dfe92fd..63e1fe330 100644 > --- a/tests/ovn-northd.at > +++ b/tests/ovn-northd.at > @@ -3747,10 +3747,18 @@ for direction in from to; do > done > check ovn-nbctl --wait=sb sync > > -# TCP packets should not go to conntrack for load balancing. > +# TCP packets should go to conntrack for load balancing. > flow="inport == \"lsp1\" && ${flow_eth} && ${flow_ip} && ${flow_tcp}" > AT_CHECK_UNQUOTED([ovn_trace --ct new --ct new --minimal ls "${flow}"], [0], > [dnl > -output("lsp2"); > +ct_lb_mark { > + ct_lb_mark { > + reg0[[6]] = 0; > + reg0[[12]] = 0; > + ct_lb_mark /* default (use --ct to customize) */ { > + output("lsp2"); > + }; > + }; > +}; > ]) > > # UDP packets still go to conntrack. > @@ -3883,10 +3891,18 @@ for direction in from to; do > done > check ovn-nbctl --wait=sb sync > > -# TCP packets should not go to conntrack for load balancing. > +# TCP packets should go to conntrack for load balancing. > flow="inport == \"lsp1\" && ${flow_eth} && ${flow_ip} && ${flow_tcp}" > AT_CHECK_UNQUOTED([ovn_trace --ct new --ct new --minimal ls "${flow}"], [0], > [dnl > -output("lsp2"); > +ct_lb_mark { > + ct_lb_mark { > + reg0[[6]] = 0; > + reg0[[12]] = 0; > + ct_lb_mark /* default (use --ct to customize) */ { > + output("lsp2"); > + }; > + }; > +}; > ]) > > # UDP packets still go to conntrack. > @@ -4775,10 +4791,12 @@ check_stateful_flows() { > AT_CHECK([grep "ls_in_pre_stateful" sw0flows | ovn_strip_lflows], [0], > [dnl > table=??(ls_in_pre_stateful ), priority=0 , match=(1), action=(next;) > table=??(ls_in_pre_stateful ), priority=100 , match=(reg0[[0]] == 1), > action=(ct_next;) > + table=??(ls_in_pre_stateful ), priority=105 , match=(tcp && ip4.dst == > 10.0.0.10), action=(ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=105 , match=(tcp && ip4.dst == > 10.0.0.20), action=(ct_lb_mark;) > table=??(ls_in_pre_stateful ), priority=110 , match=(reg0[[2]] == 1), > action=(ct_lb_mark;) > table=??(ls_in_pre_stateful ), priority=115 , match=(reg0[[2]] == 1 && > ip.is_frag), action=(reg0[[19]] = 1; ct_lb_mark;) > - table=??(ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && > ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; > reg2[[0..15]] = 80; ct_lb_mark;) > - table=??(ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && > ip4.dst == 10.0.0.20 && tcp.dst == 80), action=(reg4 = 10.0.0.20; > reg2[[0..15]] = 80; ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=120 , match=(ip4.dst == 10.0.0.10 > && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=120 , match=(ip4.dst == 10.0.0.20 > && tcp.dst == 80), action=(reg4 = 10.0.0.20; reg2[[0..15]] = 80; ct_lb_mark;) > ]) > > AT_CHECK([grep "ls_in_lb " sw0flows | ovn_strip_lflows], [0], [dnl > @@ -5072,16 +5090,16 @@ AT_CAPTURE_FILE([sw0flows]) > > AT_CHECK([grep -w "ls_in_acl_eval" sw0flows | grep 6553 | ovn_strip_lflows], > [0], [dnl > table=??(ls_in_acl_eval ), priority=65532, match=(!ct.est && ct.rel && > !ct.new && ct_mark.blocked == 0), action=(reg0[[17]] = 1; reg8[[16]] = 1; > ct_commit_nat;) > - table=??(ls_in_acl_eval ), priority=65532, match=((ct.est && ct.rpl && > ct_mark.blocked == 1)), action=(reg8[[17]] = 1; next;) > table=??(ls_in_acl_eval ), priority=65532, match=(ct.est && !ct.rel && > !ct.new && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] > = 0; reg0[[17]] = 1; reg8[[16]] = 1; next;) > + table=??(ls_in_acl_eval ), priority=65532, match=(ct.est && ct.rpl && > ct_mark.blocked == 1), action=(reg8[[17]] = 1; next;) > table=??(ls_in_acl_eval ), priority=65532, match=(ct.est && > ct_mark.allow_established == 1), action=(reg0[[21]] = 1; reg8[[16]] = 1; > next;) > table=??(ls_in_acl_eval ), priority=65532, match=(nd || nd_ra || nd_rs > || mldv1 || mldv2), action=(reg8[[16]] = 1; next;) > ]) > > AT_CHECK([grep -w "ls_out_acl_eval" sw0flows | grep 6553 | > ovn_strip_lflows], [0], [dnl > table=??(ls_out_acl_eval ), priority=65532, match=(!ct.est && ct.rel && > !ct.new && ct_mark.blocked == 0), action=(reg8[[16]] = 1; ct_commit_nat;) > - table=??(ls_out_acl_eval ), priority=65532, match=((ct.est && ct.rpl && > ct_mark.blocked == 1)), action=(reg8[[17]] = 1; next;) > table=??(ls_out_acl_eval ), priority=65532, match=(ct.est && !ct.rel && > !ct.new && ct.rpl && ct_mark.blocked == 0), action=(reg8[[16]] = 1; next;) > + table=??(ls_out_acl_eval ), priority=65532, match=(ct.est && ct.rpl && > ct_mark.blocked == 1), action=(reg8[[17]] = 1; next;) > table=??(ls_out_acl_eval ), priority=65532, match=(ct.est && > ct_mark.allow_established == 1), action=(reg8[[16]] = 1; next;) > table=??(ls_out_acl_eval ), priority=65532, match=(nd || nd_ra || nd_rs > || mldv1 || mldv2), action=(reg8[[16]] = 1; next;) > ]) > @@ -14398,7 +14416,7 @@ ovn-sbctl dump-flows s1 > s1flows > AT_CAPTURE_FILE([s1flows]) > > AT_CHECK([grep "ls_in_pre_stateful" s1flows | ovn_strip_lflows | grep > "30.0.0.1"], [0], [dnl > - table=??(ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && > ip4.dst == 30.0.0.1), action=(reg4 = 30.0.0.1; ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=120 , match=(ip4.dst == > 30.0.0.1), action=(reg4 = 30.0.0.1; ct_lb_mark;) > ]) > AT_CHECK([grep "ls_in_lb" s1flows | ovn_strip_lflows | grep "30.0.0.1"], > [0], [dnl > table=??(ls_in_lb ), priority=110 , match=(ct.new && ip4.dst == > 30.0.0.1), action=(reg4 = 30.0.0.1; > ct_lb_mark(backends=172.16.0.103,172.16.0.102,172.16.0.101);) > @@ -14512,7 +14530,7 @@ ovn-sbctl dump-flows s1 > s1flows > AT_CAPTURE_FILE([s1flows]) > > AT_CHECK([grep "ls_in_pre_stateful" s1flows | ovn_strip_lflows | grep > "2001:db8:cccc::1"], [0], [dnl > - table=??(ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && > ip6.dst == 2001:db8:cccc::1), action=(xxreg1 = 2001:db8:cccc::1; ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=120 , match=(ip6.dst == > 2001:db8:cccc::1), action=(xxreg1 = 2001:db8:cccc::1; ct_lb_mark;) > ]) > AT_CHECK([grep "ls_in_lb" s1flows | ovn_strip_lflows | grep > "2001:db8:cccc::1"], [0], [dnl > table=??(ls_in_lb ), priority=110 , match=(ct.new && ip6.dst == > 2001:db8:cccc::1), action=(xxreg1 = 2001:db8:cccc::1; > ct_lb_mark(backends=2001:db8:aaaa:3::103,2001:db8:aaaa:3::102,2001:db8:aaaa:3::101);) > @@ -14623,7 +14641,7 @@ ovn-sbctl dump-flows s1 > s1flows > AT_CAPTURE_FILE([s1flows]) > > AT_CHECK([grep "ls_in_pre_stateful" s1flows | ovn_strip_lflows | grep > "30.0.0.1"], [0], [dnl > - table=??(ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && > ip4.dst == 30.0.0.1), action=(reg4 = 30.0.0.1; ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=120 , match=(ip4.dst == > 30.0.0.1), action=(reg4 = 30.0.0.1; ct_lb_mark;) > ]) > AT_CHECK([grep "ls_in_lb" s1flows | ovn_strip_lflows | grep "30.0.0.1"], > [0], [dnl > table=??(ls_in_lb ), priority=110 , match=(ct.new && ip4.dst == > 30.0.0.1), action=(reg4 = 30.0.0.1; > ct_lb_mark(backends=172.16.0.103,172.16.0.102,172.16.0.101);) > @@ -16960,5 +16978,108 @@ AT_CHECK([ovn_strip_lflows < lrflows | grep > priority=105 | grep -c "flags.force_ > 1 > ]) > > +AT_CLEANUP > +]) > + > +OVN_FOR_EACH_NORTHD_NO_HV([ > +AT_SETUP([Load Balancers with stateless ACLs]) > +ovn_start ovn-northd > + > +AS_BOX([create logical switches and ports]) > +check ovn-nbctl ls-add sw0 > +check ovn-nbctl --wait=sb lsp-add sw0 sw0-p1 -- lsp-set-addresses sw0-p1 \ > +"00:00:00:00:00:02 10.0.0.2" > + > +check ovn-nbctl --wait=sb lsp-add sw0 sw0-p2 -- lsp-set-addresses sw0-p2 \ > +"00:00:00:00:00:03 10.0.0.3" > + > +AS_BOX([create stateless ACLs]) > +check ovn-nbctl acl-add sw0 from-lport 1001 "ip" allow-stateless > +check ovn-nbctl acl-add sw0 to-lport 1001 "ip" allow-stateless > + > +AS_BOX([create stateful ACLs]) > +# check if allow-stateless acls have higher priority we skip conntrack. > +check ovn-nbctl acl-add sw0 from-lport 1000 "ip" allow-related > +check ovn-nbctl acl-add sw0 to-lport 1000 "ip" allow-related > + > +ovn-sbctl dump-flows sw0 > sw0flows > + > +AT_CHECK( > + [grep -E 'ls_(in|out)_pre_acl' sw0flows | grep reg0 | ovn_strip_lflows], > [0], [dnl > + table=??(ls_in_pre_acl ), priority=100 , match=(ip), > action=(reg0[[0]] = 1; next;) > + table=??(ls_in_pre_acl ), priority=2001 , match=(ip), > action=(reg0[[16]] = 1; next;) > + table=??(ls_out_pre_acl ), priority=100 , match=(ip), > action=(reg0[[0]] = 1; next;) > + table=??(ls_out_pre_acl ), priority=2001 , match=(ip), > action=(reg0[[16]] = 1; next;) > +]) > + > +AT_CHECK( > + [grep -E 'ls_out_acl_eval' sw0flows | grep 65532 | ovn_strip_lflows], [0], > [dnl > + table=??(ls_out_acl_eval ), priority=65532, match=(!ct.est && ct.rel && > !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg8[[16]] = 1; > ct_commit_nat;) > + table=??(ls_out_acl_eval ), priority=65532, match=(ct.est && !ct.rel && > !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg8[[16]] = > 1; next;) > + table=??(ls_out_acl_eval ), priority=65532, match=(ct.est && > ct_mark.allow_established == 1), action=(reg8[[16]] = 1; next;) > + table=??(ls_out_acl_eval ), priority=65532, match=(ct.inv || (ct.est && > ct.rpl && ct_mark.blocked == 1)), action=(reg8[[17]] = 1; next;) > + table=??(ls_out_acl_eval ), priority=65532, match=(nd || nd_ra || nd_rs > || mldv1 || mldv2), action=(reg8[[16]] = 1; next;) > +]) > + > +AS_BOX([create Load Balancer]) > +check ovn-nbctl lb-add lb1 10.0.0.4:80 10.0.0.2:80,10.0.0.3:80 > +check ovn-nbctl --wait=sb ls-lb-add sw0 lb1 > + > +ovn-sbctl dump-flows sw0 > sw0flows > + > +AT_CHECK([grep -E 'ls_(in|out)_pre_acl' sw0flows | grep reg0 | > ovn_strip_lflows], [0], [dnl > + table=??(ls_in_pre_acl ), priority=100 , match=(ip), > action=(reg0[[0]] = 1; next;) > + table=??(ls_in_pre_acl ), priority=2001 , match=(ip), > action=(reg0[[16]] = 1; next;) > + table=??(ls_out_pre_acl ), priority=100 , match=(ip), > action=(reg0[[0]] = 1; next;) > +]) > + > +# We do not match conntrack invalide packets in case of load balancers with > stateless ACLs. > +AT_CHECK( > + [grep -E 'ls_out_acl_eval' sw0flows | grep 65532 | ovn_strip_lflows], [0], > [dnl > + table=??(ls_out_acl_eval ), priority=65532, match=(!ct.est && ct.rel && > !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg8[[16]] = 1; > ct_commit_nat;) > + table=??(ls_out_acl_eval ), priority=65532, match=(ct.est && !ct.rel && > !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg8[[16]] = > 1; next;) > + table=??(ls_out_acl_eval ), priority=65532, match=(ct.est && ct.rpl && > ct_mark.blocked == 1), action=(reg8[[17]] = 1; next;) > + table=??(ls_out_acl_eval ), priority=65532, match=(ct.est && > ct_mark.allow_established == 1), action=(reg8[[16]] = 1; next;) > + table=??(ls_out_acl_eval ), priority=65532, match=(nd || nd_ra || nd_rs > || mldv1 || mldv2), action=(reg8[[16]] = 1; next;) > +]) > + > +AT_CHECK([grep -E 'ls_in_pre_stateful' sw0flows | ovn_strip_lflows], [0], > [dnl > + table=??(ls_in_pre_stateful ), priority=0 , match=(1), action=(next;) > + table=??(ls_in_pre_stateful ), priority=100 , match=(reg0[[0]] == 1), > action=(ct_next;) > + table=??(ls_in_pre_stateful ), priority=105 , match=(tcp && ip4.dst == > 10.0.0.4), action=(ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=110 , match=(reg0[[2]] == 1), > action=(ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=115 , match=(reg0[[2]] == 1 && > ip.is_frag), action=(reg0[[19]] = 1; ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=120 , match=(ip4.dst == 10.0.0.4 > && tcp.dst == 80), action=(reg4 = 10.0.0.4; reg2[[0..15]] = 80; ct_lb_mark;) > +]) > + > +AS_BOX([create Load Balancer without port]) > +check ovn-nbctl --wait=sb ls-lb-del sw0 lb1 > +check ovn-nbctl lb-add lb2 10.0.0.5 10.0.0.2,10.0.0.3 > +check ovn-nbctl --wait=sb ls-lb-add sw0 lb2 > + > +ovn-sbctl dump-flows sw0 > sw0flows > + > +AT_CHECK([grep -E 'ls_in_pre_stateful' sw0flows | ovn_strip_lflows], [0], > [dnl > + table=??(ls_in_pre_stateful ), priority=0 , match=(1), action=(next;) > + table=??(ls_in_pre_stateful ), priority=100 , match=(reg0[[0]] == 1), > action=(ct_next;) > + table=??(ls_in_pre_stateful ), priority=110 , match=(reg0[[2]] == 1), > action=(ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=115 , match=(reg0[[2]] == 1 && > ip.is_frag), action=(reg0[[19]] = 1; ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=120 , match=(ip4.dst == > 10.0.0.5), action=(reg4 = 10.0.0.5; ct_lb_mark;) > +]) > + > +AS_BOX([set hairpin_snat_ip to Load Balancer without port]) > +check ovn-nbctl --wait=sb set load_balancer lb2 > options:hairpin_snat_ip="10.0.0.6" > + > +ovn-sbctl dump-flows sw0 > sw0flows > +AT_CHECK([grep -E 'ls_in_pre_stateful' sw0flows | ovn_strip_lflows], [0], > [dnl > + table=??(ls_in_pre_stateful ), priority=0 , match=(1), action=(next;) > + table=??(ls_in_pre_stateful ), priority=100 , match=(reg0[[0]] == 1), > action=(ct_next;) > + table=??(ls_in_pre_stateful ), priority=105 , match=(tcp && ip4.dst == > 10.0.0.6), action=(ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=110 , match=(reg0[[2]] == 1), > action=(ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=115 , match=(reg0[[2]] == 1 && > ip.is_frag), action=(reg0[[19]] = 1; ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=120 , match=(ip4.dst == > 10.0.0.5), action=(reg4 = 10.0.0.5; ct_lb_mark;) > +]) > + > + > AT_CLEANUP > ]) > diff --git a/tests/ovn.at b/tests/ovn.at > index 88c9cabfe..ea5682e00 100644 > --- a/tests/ovn.at > +++ b/tests/ovn.at > @@ -26388,7 +26388,7 @@ OVS_WAIT_FOR_OUTPUT( > [ovn-sbctl dump-flows > sbflows > ovn-sbctl dump-flows sw0 | grep ct_lb_mark | grep priority=120 | sed > 's/table=..//'], 0, > [dnl > - (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip4.dst == > 10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; > ct_lb_mark;) > + (ls_in_pre_stateful ), priority=120 , match=(ip4.dst == 10.0.0.10 && > tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark;) > (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == > 10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; > ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80; > hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");) > ]) > > @@ -26433,7 +26433,7 @@ AT_CHECK( > [grep "ip4.dst == 10.0.0.10 && tcp.dst == 80" sbflows3 | grep priority=120 > |\ > ovn_strip_lflows], [0], [dnl > table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == > 10.0.0.10 && tcp.dst == 80), action=(drop;) > - table=??(ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && > ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; > reg2[[0..15]] = 80; ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=120 , match=(ip4.dst == 10.0.0.10 > && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark;) > ]) > > AT_CAPTURE_FILE([sbflows4]) > @@ -26594,7 +26594,7 @@ OVS_WAIT_FOR_OUTPUT( > [ovn-sbctl dump-flows > sbflows > ovn-sbctl dump-flows sw0 | grep ct_lb_mark | grep priority=120 | sed > 's/table=..//'], 0, > [dnl > - (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip6.dst == > 2002::a && tcp.dst == 80), action=(xxreg1 = 2002::a; reg2[[0..15]] = 80; > ct_lb_mark;) > + (ls_in_pre_stateful ), priority=120 , match=(ip6.dst == 2002::a && > tcp.dst == 80), action=(xxreg1 = 2002::a; reg2[[0..15]] = 80; ct_lb_mark;) > (ls_in_lb ), priority=120 , match=(ct.new && ip6.dst == 2002::a > && tcp.dst == 80), action=(xxreg1 = 2002::a; reg2[[0..15]] = 80; > ct_lb_mark(backends=[[2001::3]]:80,[[2002::3]]:80; > hash_fields="ipv6_dst,ipv6_src,tcp_dst,tcp_src");) > ]) > > @@ -26638,7 +26638,7 @@ AT_CHECK( > [grep "ip6.dst == 2002::a && tcp.dst == 80" sbflows3 | grep priority=120 |\ > ovn_strip_lflows], [0], [dnl > table=??(ls_in_lb ), priority=120 , match=(ct.new && ip6.dst == > 2002::a && tcp.dst == 80), action=(drop;) > - table=??(ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && > ip6.dst == 2002::a && tcp.dst == 80), action=(xxreg1 = 2002::a; reg2[[0..15]] > = 80; ct_lb_mark;) > + table=??(ls_in_pre_stateful ), priority=120 , match=(ip6.dst == 2002::a > && tcp.dst == 80), action=(xxreg1 = 2002::a; reg2[[0..15]] = 80; ct_lb_mark;) > ]) > > AT_CAPTURE_FILE([sbflows4]) > diff --git a/tests/system-ovn.at b/tests/system-ovn.at > index 5fa740cfb..59f6fdefa 100644 > --- a/tests/system-ovn.at > +++ b/tests/system-ovn.at > @@ -5184,6 +5184,88 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port > patch-.*/d > AT_CLEANUP > ]) > > +OVN_FOR_EACH_NORTHD([ > +AT_SETUP([Load Balancer LS hairpin IPv4 with stateless ACLs]) > + > +ovn_start > + > +OVS_TRAFFIC_VSWITCHD_START() > +ADD_BR([br-int]) > + > +# Set external-ids in br-int needed for ovn-controller > +ovs-vsctl \ > + -- set Open_vSwitch . external-ids:system-id=hv1 \ > + -- set Open_vSwitch . > external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ > + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ > + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ > + -- set bridge br-int fail-mode=secure > other-config:disable-in-band=true > + > +# Start ovn-controller > +start_daemon ovn-controller > + > +# Logical network: > +# One logical switch with IPv4 load balancers that hairpin the traffic. > +check ovn-nbctl ls-add sw > +check ovn-nbctl lsp-add sw lsp1 -- lsp-set-addresses lsp1 00:00:00:00:00:01 > +check ovn-nbctl lsp-add sw lsp2 -- lsp-set-addresses lsp2 00:00:00:00:00:02 > +check ovn-nbctl lb-add lb-ipv4-tcp 88.88.88.88:8080 42.42.42.1:4041 tcp > +check ovn-nbctl ls-lb-add sw lb-ipv4-tcp > + > +check ovn-nbctl lr-add rtr > +check ovn-nbctl lrp-add rtr rtr-sw 00:00:00:00:01:00 42.42.42.254/24 > +check ovn-nbctl lsp-add sw sw-rtr \ > + -- lsp-set-type sw-rtr router \ > + -- lsp-set-addresses sw-rtr 00:00:00:00:01:00 \ > + -- lsp-set-options sw-rtr router-port=rtr-sw > + > +ADD_NAMESPACES(lsp1) > +ADD_VETH(lsp1, lsp1, br-int, "42.42.42.1/24", "00:00:00:00:00:01", \ > + "42.42.42.254") > + > +ADD_NAMESPACES(lsp2) > +ADD_VETH(lsp2, lsp2, br-int, "42.42.42.2/24", "00:00:00:00:00:02", \ > + "42.42.42.254") > + > +check ovn-nbctl --wait=hv -t 3 sync > + We shouldn't reduce the default timeout (-t 3), a plain "check ovn-nbctl --wait=hv sync" is enough. We probably want a "wait_for_ports_up" as well here. > +# Start IPv4 TCP server on lsp1. > +NETNS_DAEMONIZE([lsp1], [nc -l -k 42.42.42.1 4041], [lsp1.pid]) > + > +# Send the packet to VIP. > +NS_CHECK_EXEC([lsp1], [nc -z 88.88.88.88 8080], [0], [ignore], [ignore]) > +NS_CHECK_EXEC([lsp2], [nc -z 88.88.88.88 8080], [0], [ignore], [ignore]) > + > +check ovn-nbctl acl-add sw to-lport 2000 'ip' allow-stateless > +check ovn-nbctl acl-add sw from-lport 2000 'ip' allow-stateless > + This is racy, we need a "--wait=hv sync" here. > +# Send the packet to VIP after add stateless acl. > +NS_CHECK_EXEC([lsp1], [nc -z 88.88.88.88 8080], [0], [ignore], [ignore]) > +NS_CHECK_EXEC([lsp2], [nc -z 88.88.88.88 8080], [0], [ignore], [ignore]) > + > +check ovn-nbctl acl-add sw to-lport 2001 'ip' allow-related > +check ovn-nbctl acl-add sw from-lport 2001 'ip' allow-related > + Here too. > +# Send the packet to VIP after add related acls. > +NS_CHECK_EXEC([lsp1], [nc -z 88.88.88.88 8080], [0], [ignore], [ignore]) > +NS_CHECK_EXEC([lsp2], [nc -z 88.88.88.88 8080], [0], [ignore], [ignore]) > + > +OVN_CLEANUP_CONTROLLER([hv1]) > + > +as ovn-sb > +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) > + > +as ovn-nb > +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) > + > +as northd > +OVS_APP_EXIT_AND_WAIT([ovn-northd]) > + > +as > +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d > +/connection dropped.*/d"]) > +AT_CLEANUP > +]) > + > OVN_FOR_EACH_NORTHD([ > AT_SETUP([Load Balancer LS hairpin IPv6]) > AT_SKIP_IF([test $HAVE_NC = no]) > @@ -10071,7 +10153,7 @@ > tcp,orig=(src=192.168.1.2,dst=30.30.30.30,sport=<cleared>,dport=<cleared>),reply > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > -# remove lb > +# Remove Load Balancer. > check ovn-nbctl ls-lb-del foo lb1 > > # add stateless acl > @@ -10088,7 +10170,29 @@ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > -# add lb back > +# Delete ACLs. > +check ovn-nbctl acl-del foo > + > +# Add stateful ACLs. > +check ovn-nbctl acl-add foo from-lport 1 1 allow-related > +check ovn-nbctl --wait=hv acl-add foo to-lport 1 1 allow-related > + > +# Add stateless ACLs. > +check ovn-nbctl acl-add foo from-lport 2 1 allow-stateless > +check ovn-nbctl --wait=hv acl-add foo to-lport 2 1 allow-stateless > + > +AT_CHECK([ip netns exec foo1 wget 192.168.2.2 -t 1 -T 1], [0], [ignore], > [ignore]) > + > +# Check conntrack zone has no entry. > +AT_CHECK([ovs-appctl dpctl/dump-conntrack zone=$zone_id | \ > +FORMAT_CT(192.168.2.2) | \ > +sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > +]) > + > +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > + > +# When lb configured: pass conntrack for vip traffic. > +# Add Load Balancer back. > check ovn-nbctl ls-lb-add foo lb1 > > # Wait for ovn-controller to catch up. > @@ -10097,13 +10201,14 @@ check ovn-nbctl --wait=hv sync > OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \ > grep 'nat(dst=192.168.2.2:80)']) > > -# should not dnat so will not be able to connect > -AT_CHECK([ip netns exec foo1 curl 30.30.30.30 --retry 3 --max-time 1], [28], > [ignore], [ignore]) > +# Now check with VIP. > +AT_CHECK([ip netns exec foo1 wget 30.30.30.30 -t 3 -T 1], [0], [ignore], > [ignore]) > > -# check conntrack zone has no tcp entry > +# Check conntrack zone has tcp entry. > AT_CHECK([ovs-appctl dpctl/dump-conntrack zone=$zone_id | \ > FORMAT_CT(30.30.30.30) | \ > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > +tcp,orig=(src=192.168.1.2,dst=30.30.30.30,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>) > ]) > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > @@ -10203,7 +10308,7 @@ > tcp,orig=(src=fd11::2,dst=fd12::2,sport=<cleared>,dport=<cleared>),reply=(src=fd > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > -# now check with VIP > +# Now check with VIP. > AT_CHECK([ip netns exec foo1 wget http://[[fd30::2]] -t 3 -T 1], [0], > [ignore], [ignore]) > > # check conntrack zone has tcp entry > @@ -10215,16 +10320,39 @@ > tcp,orig=(src=fd11::2,dst=fd30::2,sport=<cleared>,dport=<cleared>),reply=(src=fd > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > -# remove lb > +# Remove Load_Balancer. > check ovn-nbctl ls-lb-del foo lb1 > > -# add stateless acl > +# Delete ACLs. > +check ovn-nbctl acl-del foo > + > +# Add stateful ACLs. > +check ovn-nbctl acl-add foo from-lport 1 1 allow-related > +check ovn-nbctl --wait=hv acl-add foo to-lport 1 1 allow-related > + > +# Add stateless ACLs. > +check ovn-nbctl acl-add foo from-lport 2 1 allow-stateless > +check ovn-nbctl --wait=hv acl-add foo to-lport 2 1 allow-stateless > + > +AT_CHECK([ip netns exec foo1 wget http://[[fd12::2]] -t 1 -T 1], [0], > [ignore], [ignore]) > + > +# Check conntrack zone has no tcp entry. > +AT_CHECK([ovs-appctl dpctl/dump-conntrack zone=$zone_id | \ > +FORMAT_CT(fd12::2) | grep -v fe80 | \ > +sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > +]) > + > +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > + > +check ovn-nbctl acl-del foo > + > +# Add stateless ACLs. > check ovn-nbctl acl-add foo from-lport 1 1 allow-stateless > check ovn-nbctl --wait=hv acl-add foo to-lport 1 1 allow-stateless > > AT_CHECK([ip netns exec foo1 wget http://[[fd12::2]] -t 3 -T 1], [0], > [ignore], [ignore]) > > -# check conntrack zone has no tcp entry > +# Check conntrack zone has no tcp entry. > AT_CHECK([ovs-appctl dpctl/dump-conntrack zone=$zone_id | \ > FORMAT_CT(fd12::2) | grep -v fe80 | \ > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > @@ -10232,7 +10360,7 @@ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > > -# add lb back > +# Add Load Balancer back. > check ovn-nbctl ls-lb-add foo lb1 > > # Wait for ovn-controller to catch up. > @@ -10241,13 +10369,14 @@ check ovn-nbctl --wait=hv sync > OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \ > grep 'nat(dst=\[[fd12::2\]]:80)']) > > -# should not dnat so will not be able to connect > -AT_CHECK([ip netns exec foo1 curl http://[[fd30::2]] --retry 3 --max-time > 1], [28], [ignore], [ignore]) > -# > -# check conntrack zone has no tcp entry > +# Now check with VIP. > +AT_CHECK([ip netns exec foo1 wget http://[[fd30::2]] -t 3 -T 1], [0], > [ignore], [ignore]) > + > +# Check conntrack zone has tcp entry. > AT_CHECK([ovs-appctl dpctl/dump-conntrack zone=$zone_id | \ > FORMAT_CT(fd30::2) | grep -v fe80 | \ > sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl > +tcp,orig=(src=fd11::2,dst=fd30::2,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd11::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>) > ]) > > AT_CHECK([ovs-appctl dpctl/flush-conntrack]) Regards, Dumitru _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev