On 5/15/25 1:59 PM, Alexandra Rukomoinikova wrote:
> [0] Removed support for using load balancers in conjunction with stateless
> ACL.
> This commit adds an option enable-stateless-acl-with-lb for logical switch to
> make load balancers work.
>
> [0] -
> https://github.com/ovn-org/ovn/commit/a0f82efdd9dfd3ef2d9606c1890e353df1097a51
>
> Signed-off-by: Alexandra Rukomoinikova <[email protected]>
> ---
> v4 --> v5: 1) made this functionality optional on the logical switch.
> 2) moved snat_ip to ovn_northd_lb structure from lb_vip bc
> it's seems to be more correct.
> 3) added ls_lb_with_stateless_mode hmapx in ovn_lb_datapaths
> because the flows for the load balancer are added to the datapath
> group,
> and I would like to separately add the flows needed for the balancers
> to work with stateless acl only for datapath with enabled option.
> 4) added doc and NEWS.
> ---
Hi Alexandra,
Thanks for v5!
> NEWS | 3 +
> northd/lb.c | 18 +++++-
> northd/lb.h | 5 ++
> northd/northd.c | 62 +++++++++++++++++++-
> northd/northd.h | 4 ++
> northd/ovn-northd.8.xml | 8 +++
> ovn-nb.xml | 8 +++
> tests/ovn-northd.at | 123 ++++++++++++++++++++++++++++++++++++++++
> tests/system-ovn.at | 91 +++++++++++++++++++++++++++++
> 9 files changed, 318 insertions(+), 4 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index f82f25754..52c829e83 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -20,6 +20,9 @@ Post v25.03.0
> - Introduce exclude-router-ips-from-garp in logical_switch_port column
> so that the router port IPs are not advertised in the GARPs.
> - Added support for port mirroring in OVN overlay.
> + - Add a new logical switch option - enable-stateless-acl-lb with default
> + value of false. This option should be set to true for logical switch
Nit: s/switch/switches/
> + with stateless ACL to work with load balancer.
>
> OVN v25.03.0 - 07 Mar 2025
> --------------------------
> diff --git a/northd/lb.c b/northd/lb.c
> index ffd21c5bc..b11896cf1 100644
> --- a/northd/lb.c
> +++ b/northd/lb.c
> @@ -257,6 +257,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)
> @@ -297,6 +305,12 @@ ovn_northd_lb_init(struct ovn_northd_lb *lb,
> }
> lb->affinity_timeout = affinity_timeout;
>
> + const char *snat_ip = smap_get(&nbrec_lb->options, "hairpin_snat_ip");
> +
> + if (snat_ip && validate_snap_ip_address(snat_ip)) {
> + lb->hairpin_snat_ip = xstrdup(snat_ip);
> + }
> +
> sset_init(&lb->ips_v4);
> sset_init(&lb->ips_v6);
> struct smap_node *node;
> @@ -413,6 +427,7 @@ ovn_northd_lb_cleanup(struct ovn_northd_lb *lb)
> sset_destroy(&lb->ips_v4);
> sset_destroy(&lb->ips_v6);
> free(lb->selection_fields);
> + free(lb->hairpin_snat_ip);
> lb->selection_fields = NULL;
> lb->health_checks = false;
> }
> @@ -566,7 +581,7 @@ ovn_lb_datapaths_create(const struct ovn_northd_lb *lb,
> size_t n_ls_datapaths,
> lb_dps->nb_ls_map = bitmap_allocate(n_ls_datapaths);
> lb_dps->nb_lr_map = bitmap_allocate(n_lr_datapaths);
> lb_dps->lflow_ref = lflow_ref_create();
> -
> + hmapx_init(&lb_dps->ls_lb_with_stateless_mode);
> return lb_dps;
> }
>
> @@ -576,6 +591,7 @@ ovn_lb_datapaths_destroy(struct ovn_lb_datapaths *lb_dps)
> bitmap_free(lb_dps->nb_lr_map);
> bitmap_free(lb_dps->nb_ls_map);
> lflow_ref_destroy(lb_dps->lflow_ref);
> + hmapx_destroy(&lb_dps->ls_lb_with_stateless_mode);
> free(lb_dps);
> }
>
> diff --git a/northd/lb.h b/northd/lb.h
> index aa6616af4..eb1942bd4 100644
> --- a/northd/lb.h
> +++ b/northd/lb.h
> @@ -18,6 +18,7 @@
> #define OVN_NORTHD_LB_H 1
>
> #include "openvswitch/hmap.h"
> +#include "hmapx.h"
> #include "uuid.h"
>
> #include "lib/lb.h"
> @@ -72,6 +73,8 @@ struct ovn_northd_lb {
>
> /* Indicates if the load balancer has health checks configured. */
> bool health_checks;
> +
> + char *hairpin_snat_ip;
> };
>
> /* ovn-northd specific backend information. */
> @@ -139,6 +142,8 @@ struct ovn_lb_datapaths {
> size_t n_nb_lr;
> unsigned long *nb_lr_map;
>
> + struct hmapx ls_lb_with_stateless_mode;
> +
> /* Reference of lflows generated for this load balancer.
> *
> * This data is initialized and destroyed by the en_northd node, but
> diff --git a/northd/northd.c b/northd/northd.c
> index 7b05147b4..85a1fcc58 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -503,6 +503,7 @@ ovn_datapath_create(struct hmap *datapaths, const struct
> uuid *key,
> od->router_ports = VECTOR_EMPTY_INITIALIZER(struct ovn_port *);
> od->l3dgw_ports = VECTOR_EMPTY_INITIALIZER(struct ovn_port *);
> od->localnet_ports = VECTOR_EMPTY_INITIALIZER(struct ovn_port *);
> + od->lb_with_stateless_mode = false;
> return od;
> }
>
> @@ -942,6 +943,12 @@ join_datapaths(const struct nbrec_logical_switch_table
> *nbrec_ls_table,
> if (smap_get_bool(&nbs->other_config, "ic-vxlan_mode", false)) {
> vxlan_ic_mode = true;
> }
> +
> + if (smap_get_bool(&nbs->other_config,
> + "enable-stateless-acl-with-lb", false)) {
Nit: indentation is a bit off.
> + VLOG_WARN("set option to true");
This VLOG_WARN should be removed.
> + od->lb_with_stateless_mode = true;
> + }
> }
>
> const struct nbrec_logical_router *nbr;
> @@ -3965,6 +3972,9 @@ build_lb_datapaths(const struct hmap *lbs, const struct
> hmap *lb_groups,
> lb_dps = ovn_lb_datapaths_find(lb_datapaths_map, lb_uuid);
> ovs_assert(lb_dps);
> ovn_lb_datapaths_add_ls(lb_dps, 1, &od);
> + if (od->lb_with_stateless_mode) {
> + hmapx_add(&lb_dps->ls_lb_with_stateless_mode, od);
> + }
> }
>
> for (size_t i = 0; i < od->nbs->n_load_balancer_group; i++) {
> @@ -5534,6 +5544,10 @@ northd_handle_lb_data_changes(struct tracked_lb_data
> *trk_lb_data,
> ovs_assert(lb_dps);
> ovn_lb_datapaths_add_ls(lb_dps, 1, &od);
>
> + if (od->lb_with_stateless_mode) {
> + hmapx_add(&lb_dps->ls_lb_with_stateless_mode, od);
> + }
> +
> /* Add the lb to the northd tracked data. */
> hmapx_add(&nd_changes->trk_lbs.crupdated, lb_dps);
> }
> @@ -6215,7 +6229,7 @@ build_stateless_filter(const struct ovn_datapath *od,
> action,
> &acl->header_,
> lflow_ref);
> - } else {
> + } else if (!od->lb_with_stateless_mode) {
> ovn_lflow_add_with_hint(lflows, od, S_SWITCH_OUT_PRE_ACL,
> acl->priority + OVN_ACL_PRI_OFFSET,
> acl->match,
> @@ -7780,8 +7794,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 && !od->lb_with_stateless_mode) {
> + 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);
> @@ -8086,6 +8106,42 @@ 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);
> +
> + struct lflow_ref *lflow_ref = lb_dps->lflow_ref;
> + struct hmapx_node *hmapx_node;
> + struct ovn_datapath *od;
> + HMAPX_FOR_EACH (hmapx_node, &lb_dps->ls_lb_with_stateless_mode) {
> + od = hmapx_node->data;
> +
> + ds_clear(action);
> + ds_clear(match);
> +
> + 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);
Nit: indentation is a bit off.
> + }
> +
> + ds_put_cstr(action, "ct_lb_mark;");
> +
> + ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_STATEFUL, 150,
> + ds_cstr(match), ds_cstr(action), lflow_ref);
> +
> + if (lb->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->hairpin_snat_ip ? lb->hairpin_snat_ip
> + : lb_vip->vip_str);
I think this matches our style better:
ds_put_format(match, "%s && %s.dst == %s", lb->proto, ip_match,
lb->hairpin_snat_ip
? lb->hairpin_snat_ip
: lb_vip->vip_str);
> +
> + ds_put_cstr(action, "ct_lb_mark;");
> +
> + ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_STATEFUL, 105,
> + ds_cstr(match), ds_cstr(action), lflow_ref);
> + }
> + }
> }
> }
>
> diff --git a/northd/northd.h b/northd/northd.h
> index 5a698458f..f32ff1e2e 100644
> --- a/northd/northd.h
> +++ b/northd/northd.h
> @@ -379,6 +379,10 @@ struct ovn_datapath {
> bool has_vtep_lports;
> bool has_arp_proxy_port;
>
> + /* Set to true if the option 'enable-stateless-acl-with-lb' is enabled
> + * on the logical switch. */
> + bool lb_with_stateless_mode;
> +
> /* IPAM data. */
> struct ipam_info ipam_info;
>
> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
> index 96e102eeb..5d00cff89 100644
> --- a/northd/ovn-northd.8.xml
> +++ b/northd/ovn-northd.8.xml
> @@ -652,6 +652,12 @@
> <code>ct_lb_mark;</code> action.
> </li>
>
> + <li>
> + A priority-105 added enabled when enable-stateless-acl-with-lb and
> + send all packet directed to VIP that don't match the above flows to
> + connection tracker.
> + </li>
> +
> <li>
> A priority-100 flow sends the packets to connection tracker based
> on a hint provided by the previous tables
> @@ -2331,6 +2337,8 @@ output;
> <p>
> This is similar to ingress table <code>Pre-ACLs</code> except for
> <code>to-lport</code> traffic.
> + Except when the option enable-stateless-acl-with-lbis enabled:
Typo: enable-stateless-acl-with-lbis enabled
> + REGBIT_ACL_STATELESS ignored.
> </p>
>
> <p>
> diff --git a/ovn-nb.xml b/ovn-nb.xml
> index 4396023a4..94ee92b9c 100644
> --- a/ovn-nb.xml
> +++ b/ovn-nb.xml
> @@ -839,6 +839,14 @@
> is not set and the zone limit is derived from OvS default datapath
> limit.
> </column>
> +
> + <column name="other_config" key="enable-stateless-acl-with-lb"
> + type='{"type": "boolean"}'>
> + This option must be set to true for stateless ACL to work with load
> + balancers. When enabled, packets with the ct.inv flag will not be
> + dropped, even if use_ct_inv_match is set to true.
> + Default: <code>false</code>.
> + </column>
> </group>
>
> <group title="IP Multicast Snooping Options">
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index 69b75fe9d..0eca60fdb 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -17290,3 +17290,126 @@ AT_CHECK([cat trace | grep output], [0], [dnl
>
> AT_CLEANUP
> ])
> +
> +OVN_FOR_EACH_NORTHD_NO_HV([
> +AT_SETUP([enable-stateless-acl-with-lb usage])
> +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 --wait=sb acl-add sw0 from-lport 1001 "ip" allow-stateless
> +check ovn-nbctl --wait=sb 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 --wait=sb acl-add sw0 from-lport 1000 "ip" allow-related
> +check ovn-nbctl --wait=sb acl-add sw0 to-lport 1000 "ip" allow-related
> +
> +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;)
> + 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;)
This part needs a small rebase since:
8828b6120ea1 ("northd: Remove redundant ct state matches.")
https://github.com/ovn-org/ovn/commit/8828b61
> + 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([Enable enable-stateless-acl-with-lb option.])
> +check ovn-nbctl --wait=sb set logical_switch sw0
> other_config:enable-stateless-acl-with-lb=true
> +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.
Typo: invalide
> +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.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.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=(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=(reg0[[2]] == 1 &&
> ip4.dst == 10.0.0.4 && tcp.dst == 80), action=(reg4 = 10.0.0.4; reg2[[0..15]]
> = 80; ct_lb_mark;)
> + table=??(ls_in_pre_stateful ), priority=150 , match=(ip4.dst == 10.0.0.4
> && tcp.dst == 80), action=(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=(reg0[[2]] == 1 &&
> ip4.dst == 10.0.0.5), action=(reg4 = 10.0.0.5; ct_lb_mark;)
> + table=??(ls_in_pre_stateful ), priority=150 , match=(ip4.dst ==
> 10.0.0.5), action=(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=(reg0[[2]] == 1 &&
> ip4.dst == 10.0.0.5), action=(reg4 = 10.0.0.5; ct_lb_mark;)
> + table=??(ls_in_pre_stateful ), priority=150 , match=(ip4.dst ==
> 10.0.0.5), action=(ct_lb_mark;)
> +])
> +
> +AS_BOX([Create one more logical switch with load balancer.])
> +# Check if load balancer is attached to multiple logical switches:
> +# the lflows for the load balancer will only change on the switch
> +# where the option is enabled.
> +check ovn-nbctl ls-add sw1
> +check ovn-nbctl ls-lb-add sw1 lb2
> +
> +ovn-sbctl dump-flows sw1 > sw1flows
> +AT_CHECK([grep -E 'ls_in_pre_stateful' sw1flows | 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=(reg0[[2]] == 1 &&
> ip4.dst == 10.0.0.5), action=(reg4 = 10.0.0.5; ct_lb_mark;)
> +])
> +
> +AT_CLEANUP
> +])
> +
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index 1dccefb09..dbd129e3b 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -5184,6 +5184,97 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port
> patch-.*/d
> AT_CLEANUP
> ])
>
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([system enable-stateless-acl-with-lb usage])
Nit: We should add a "AT_SKIP_IF([test $HAVE_NC = no])" here.
> +
> +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")
> +
> +# Wait for ovn-controller to catch up.
> +wait_for_ports_up
> +check ovn-nbctl --wait=hv sync
> +
> +# 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 --wait=hv acl-add sw to-lport 2000 'ip' allow-stateless
> +check ovn-nbctl --wait=hv acl-add sw from-lport 2000 'ip' allow-stateless
> +
> +# To provide work of load balancer with stateless ACL this is necessary
> +# to set enable-stateless-acl-lb to true.
> +check ovn-nbctl set logical_switch sw
> other_config:enable-stateless-acl-with-lb=true
> +
> +check ovn-nbctl --wait=hv sync
> +
> +# 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 --wait=hv acl-add sw to-lport 2001 'ip' allow-related
> +check ovn-nbctl --wait=hv acl-add sw from-lport 2001 'ip' allow-related
> +
> +# 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])
To avoid a v6, I took care of the minor comments I had and pushed the patch to
main.
Thanks a lot for your patience in driving this change to completion!
Regards,
Dumitru
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev