diff --git a/.ci/ovn-kubernetes/Dockerfile b/.ci/ovn-kubernetes/Dockerfile index e74b620be..1884724ec 100644 --- a/.ci/ovn-kubernetes/Dockerfile +++ b/.ci/ovn-kubernetes/Dockerfile @@ -1,5 +1,5 @@ ARG OVNKUBE_COMMIT=master -ARG LIBOVSDB_COMMIT=8081fe24e48f +ARG LIBOVSDB_COMMIT=a6a173993830 FROM fedora:35 AS ovnbuilder @@ -47,9 +47,17 @@ RUN GO111MODULE=on go install github.com/ovn-org/libovsdb/cmd/modelgen@${LIBOVSD # Clone OVN Kubernetes and build the binary based on the commit passed as argument WORKDIR /root RUN git clone https://github.com/ovn-org/ovn-kubernetes.git -WORKDIR /root/ovn-kubernetes/go-controller +WORKDIR /root/ovn-kubernetes RUN git checkout ${OVNKUBE_COMMIT} && git log -n 1 +# Copy the ovn-kubernetes scripts from the OVN sources and apply any +# custom changes if needed. +RUN mkdir -p /tmp/ovn/.ci/ovn-kubernetes +COPY .ci/ovn-kubernetes /tmp/ovn/.ci/ovn-kubernetes +WORKDIR /tmp/ovn +RUN .ci/ovn-kubernetes/prepare.sh /root/ovn-kubernetes + +WORKDIR /root/ovn-kubernetes/go-controller # Make sure we use the OVN NB/SB schema from the local code. COPY --from=ovnbuilder /tmp/ovn/ovn-nb.ovsschema pkg/nbdb/ovn-nb.ovsschema COPY --from=ovnbuilder /tmp/ovn/ovn-sb.ovsschema pkg/sbdb/ovn-sb.ovsschema diff --git a/.ci/ovn-kubernetes/custom.patch b/.ci/ovn-kubernetes/custom.patch new file mode 100644 index 000000000..e69de29bb diff --git a/.ci/ovn-kubernetes/prepare.sh b/.ci/ovn-kubernetes/prepare.sh new file mode 100755 index 000000000..8fc9652af --- /dev/null +++ b/.ci/ovn-kubernetes/prepare.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +set -ev + +ovnk8s_path=$1 +topdir=$PWD + +pushd ${ovnk8s_path} + +# Add here any custom operations that need to performed on the +# ovn-kubernetes cloned repo, e.g., custom patches. + +# git apply --allow-empty is too new so not all git versions from major +# distros support it, just check if the custom patch file is not empty +# before applying it. +[ -s ${topdir}/.ci/ovn-kubernetes/custom.patch ] && \ + git apply -v ${topdir}/.ci/ovn-kubernetes/custom.patch + +popd # ${ovnk8s_path} +exit 0 diff --git a/.github/workflows/ovn-kubernetes.yml b/.github/workflows/ovn-kubernetes.yml index 344937e53..840ecd1e0 100644 --- a/.github/workflows/ovn-kubernetes.yml +++ b/.github/workflows/ovn-kubernetes.yml @@ -16,7 +16,7 @@ env: GO_VERSION: "1.18.4" K8S_VERSION: v1.24.0 OVNKUBE_COMMIT: "master" - LIBOVSDB_COMMIT: "98c0bad3cff1" + LIBOVSDB_COMMIT: "a6a173993830" KIND_CLUSTER_NAME: ovn KIND_INSTALL_INGRESS: true KIND_ALLOW_SYSTEM_WRITES: true @@ -73,6 +73,7 @@ jobs: env: JOB_NAME: "${{ matrix.target }}-${{ matrix.ha }}-${{ matrix.gateway-mode }}-${{ matrix.ipfamily }}-${{ matrix.disable-snat-multiple-gws }}-${{ matrix.second-bridge }}" OVN_HYBRID_OVERLAY_ENABLE: "${{ matrix.target == 'control-plane' }}" + KIND_INSTALL_METALLB: "${{ matrix.target == 'control-plane' }}" OVN_MULTICAST_ENABLE: "${{ matrix.target == 'control-plane' }}" OVN_EMPTY_LB_EVENTS: "${{ matrix.target == 'control-plane' }}" OVN_HA: "true" @@ -91,12 +92,19 @@ jobs: go-version: ${{ env.GO_VERSION }} id: go + - name: Check out ovn + uses: actions/checkout@v3 + - name: Check out ovn-kubernetes uses: actions/checkout@v3 with: path: src/github.com/ovn-org/ovn-kubernetes repository: ovn-org/ovn-kubernetes + - name: Prepare + run: | + .ci/ovn-kubernetes/prepare.sh src/github.com/ovn-org/ovn-kubernetes + - name: Set up environment run: | export GOPATH=$(go env GOPATH) diff --git a/Makefile.am b/Makefile.am index c8f770146..f7758d114 100644 --- a/Makefile.am +++ b/Makefile.am @@ -90,6 +90,8 @@ EXTRA_DIST = \ .ci/osx-build.sh \ .ci/osx-prepare.sh \ .ci/ovn-kubernetes/Dockerfile \ + .ci/ovn-kubernetes/prepare.sh \ + .ci/ovn-kubernetes/custom.patch \ .github/workflows/test.yml \ .github/workflows/ovn-kubernetes.yml \ boot.sh \ diff --git a/NEWS b/NEWS index 0920b44e2..acb8065bc 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,6 @@ +OVN v22.12.1 - xx xxx xxxx +-------------------------- + OVN v22.12.0 - 16 Dec 2022 -------------------------- - Add load balancer "affinity_timeout" option to configure load balancing diff --git a/build-aux/sodepends.py b/build-aux/sodepends.py index 343fda1af..7b1f9c840 100755 --- a/build-aux/sodepends.py +++ b/build-aux/sodepends.py @@ -63,7 +63,8 @@ def sodepends(include_info, filenames, dst): continue # Open file. - include_dirs = [info[0] for info in include_info] + include_dirs = [info[1] if len(info) == 2 else info[0] + for info in include_info] fn = soutil.find_file(include_dirs, toplevel) if not fn: ok = False diff --git a/configure.ac b/configure.ac index 101467253..357758e0c 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ # limitations under the License. AC_PREREQ(2.63) -AC_INIT(ovn, 22.12.0, bugs@openvswitch.org) +AC_INIT(ovn, 22.12.1, bugs@openvswitch.org) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) diff --git a/controller/chassis.c b/controller/chassis.c index 685d9b2ae..98f8da2be 100644 --- a/controller/chassis.c +++ b/controller/chassis.c @@ -352,6 +352,7 @@ chassis_build_other_config(const struct ovs_chassis_cfg *ovs_cfg, smap_replace(config, OVN_FEATURE_PORT_UP_NOTIF, "true"); smap_replace(config, OVN_FEATURE_CT_NO_MASKED_LABEL, "true"); smap_replace(config, OVN_FEATURE_MAC_BINDING_TIMESTAMP, "true"); + smap_replace(config, OVN_FEATURE_CT_LB_RELATED, "true"); } /* @@ -469,6 +470,12 @@ chassis_other_config_changed(const struct ovs_chassis_cfg *ovs_cfg, return true; } + if (!smap_get_bool(&chassis_rec->other_config, + OVN_FEATURE_CT_LB_RELATED, + false)) { + return true; + } + return false; } diff --git a/controller/lflow.c b/controller/lflow.c index bb47bb0c7..4b1cfe318 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -1567,9 +1567,6 @@ add_lb_vip_hairpin_reply_action(struct in6_addr *vip6, ovs_be32 vip, /* Hairpin replies have the same nw_proto as packets that created the * session. */ - union mf_value imm_proto = { - .u8 = lb_proto, - }; ol_spec = ofpbuf_put_zeros(ofpacts, sizeof *ol_spec); ol_spec->dst.field = mf_from_id(MFF_IP_PROTO); ol_spec->src.field = mf_from_id(MFF_IP_PROTO); @@ -1577,16 +1574,21 @@ add_lb_vip_hairpin_reply_action(struct in6_addr *vip6, ovs_be32 vip, ol_spec->dst.n_bits = ol_spec->dst.field->n_bits; ol_spec->n_bits = ol_spec->dst.n_bits; ol_spec->dst_type = NX_LEARN_DST_MATCH; - ol_spec->src_type = NX_LEARN_SRC_IMMEDIATE; - mf_write_subfield_value(&ol_spec->dst, &imm_proto, &match); - - /* Push value last, as this may reallocate 'ol_spec' */ - imm_bytes = DIV_ROUND_UP(ol_spec->dst.n_bits, 8); - src_imm = ofpbuf_put_zeros(ofpacts, OFPACT_ALIGN(imm_bytes)); - memcpy(src_imm, &imm_proto, imm_bytes); /* Hairpin replies have source port == . */ if (has_l4_port) { + union mf_value imm_proto = { + .u8 = lb_proto, + }; + + ol_spec->src_type = NX_LEARN_SRC_IMMEDIATE; + mf_write_subfield_value(&ol_spec->dst, &imm_proto, &match); + + /* Push value last, as this may reallocate 'ol_spec' */ + imm_bytes = DIV_ROUND_UP(ol_spec->dst.n_bits, 8); + src_imm = ofpbuf_put_zeros(ofpacts, OFPACT_ALIGN(imm_bytes)); + memcpy(src_imm, &imm_proto, imm_bytes); + ol_spec = ofpbuf_put_zeros(ofpacts, sizeof *ol_spec); switch (lb_proto) { case IPPROTO_TCP: @@ -1610,6 +1612,8 @@ add_lb_vip_hairpin_reply_action(struct in6_addr *vip6, ovs_be32 vip, ol_spec->n_bits = ol_spec->dst.n_bits; ol_spec->dst_type = NX_LEARN_DST_MATCH; ol_spec->src_type = NX_LEARN_SRC_FIELD; + } else { + ol_spec->src_type = NX_LEARN_SRC_FIELD; } /* Set MLF_LOOKUP_LB_HAIRPIN_BIT for hairpin replies. */ diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 73c33a6bf..c899283dc 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -755,6 +755,11 @@ update_ct_zones(const struct shash *binding_lports, } bitmap_set1(ct_zone_bitmap, snat_req_node->data); node->data = snat_req_node->data; + } else { + add_pending_ct_zone_entry(pending_ct_zones, CT_ZONE_OF_QUEUED, + snat_req_node->data, true, snat_req_node->name); + bitmap_set1(ct_zone_bitmap, snat_req_node->data); + simap_put(ct_zones, snat_req_node->name, snat_req_node->data); } } diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 82da6ae73..e4d530138 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -1419,7 +1419,6 @@ prepare_ipv6_prefixd(struct ovsdb_idl_txn *ovnsb_idl_txn, struct buffer_info { struct ofpbuf ofpacts; - ofp_port_t ofp_port; struct dp_packet *p; }; @@ -1495,7 +1494,6 @@ buffered_push_packet(struct buffered_packets *bp, union mf_value pkt_mark_value; mf_get_value(pkt_mark_field, &md->flow, &pkt_mark_value); ofpact_put_set_field(&bi->ofpacts, pkt_mark_field, &pkt_mark_value, NULL); - bi->ofp_port = md->flow.in_port.ofp_port; struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&bi->ofpacts); resubmit->in_port = OFPP_CONTROLLER; @@ -1531,7 +1529,7 @@ buffered_send_packets(struct rconn *swconn, struct buffered_packets *bp, .ofpacts = bi->ofpacts.data, .ofpacts_len = bi->ofpacts.size, }; - match_set_in_port(&po.flow_metadata, bi->ofp_port); + match_set_in_port(&po.flow_metadata, OFPP_CONTROLLER); queue_msg(swconn, ofputil_encode_packet_out(&po, proto)); ofpbuf_uninit(&bi->ofpacts); diff --git a/debian/changelog b/debian/changelog index 6f5a9ac2a..d658774f6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +OVN (22.12.1-1) unstable; urgency=low + [ OVN team ] + * New upstream version + + -- OVN team Fri, 16 Dec 2022 09:52:44 -0500 + ovn (22.12.0-1) unstable; urgency=low * New upstream version diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 73ce77e5c..9a80a7f68 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -1911,13 +1911,112 @@ main(int argc, char *argv[]) struct ovsdb_idl_loop ovnisb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER( ovsdb_idl_create(ovn_ic_sb_db, &icsbrec_idl_class, true, true)); - /* ovn-nb db. XXX: add only needed tables and columns */ + /* ovn-nb db. */ struct ovsdb_idl_loop ovnnb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER( - ovsdb_idl_create(ovnnb_db, &nbrec_idl_class, true, true)); - - /* ovn-sb db. XXX: add only needed tables and columns */ + ovsdb_idl_create(ovnnb_db, &nbrec_idl_class, false, true)); + + ovsdb_idl_add_table(ovnnb_idl_loop.idl, &nbrec_table_nb_global); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, &nbrec_nb_global_col_name); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, &nbrec_nb_global_col_options); + + ovsdb_idl_add_table(ovnnb_idl_loop.idl, + &nbrec_table_logical_router_static_route); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_static_route_col_route_table); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_static_route_col_ip_prefix); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_static_route_col_nexthop); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_static_route_col_external_ids); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_static_route_col_options); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_static_route_col_policy); + + ovsdb_idl_add_table(ovnnb_idl_loop.idl, &nbrec_table_logical_router); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_col_static_routes); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_col_ports); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_col_options); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_col_external_ids); + + ovsdb_idl_add_table(ovnnb_idl_loop.idl, &nbrec_table_logical_router_port); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_port_col_name); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_port_col_networks); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_port_col_external_ids); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_router_port_col_options); + + ovsdb_idl_add_table(ovnnb_idl_loop.idl, &nbrec_table_logical_switch); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_switch_col_ports); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_switch_col_other_config); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_switch_col_external_ids); + + ovsdb_idl_add_table(ovnnb_idl_loop.idl, &nbrec_table_logical_switch_port); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_switch_port_col_addresses); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_switch_port_col_options); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_switch_port_col_type); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_switch_port_col_up); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_switch_port_col_addresses); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_switch_port_col_enabled); + ovsdb_idl_add_column(ovnnb_idl_loop.idl, + &nbrec_logical_switch_port_col_external_ids); + + /* ovn-sb db. */ struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER( - ovsdb_idl_create(ovnsb_db, &sbrec_idl_class, true, true)); + ovsdb_idl_create(ovnsb_db, &sbrec_idl_class, false, true)); + + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_chassis); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_encaps); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_name); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_hostname); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_other_config); + + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_encap); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_encap_col_chassis_name); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_encap_col_type); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_encap_col_ip); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_encap_col_options); + + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_datapath_binding); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_datapath_binding_col_external_ids); + + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_port_binding); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_port_binding_col_datapath); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_port_binding_col_mac); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_port_binding_col_options); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_port_binding_col_logical_port); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_port_binding_col_external_ids); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_port_binding_col_chassis); /* Create IDL indexes */ struct ovsdb_idl_index *nbrec_ls_by_name diff --git a/include/ovn/features.h b/include/ovn/features.h index 679f67457..5bcd68739 100644 --- a/include/ovn/features.h +++ b/include/ovn/features.h @@ -24,6 +24,7 @@ #define OVN_FEATURE_PORT_UP_NOTIF "port-up-notif" #define OVN_FEATURE_CT_NO_MASKED_LABEL "ct-no-masked-label" #define OVN_FEATURE_MAC_BINDING_TIMESTAMP "mac-binding-timestamp" +#define OVN_FEATURE_CT_LB_RELATED "ovn-ct-lb-related" /* OVS datapath supported features. Based on availability OVN might generate * different types of openflows. diff --git a/include/ovn/lex.h b/include/ovn/lex.h index 9159b7a26..64d33361f 100644 --- a/include/ovn/lex.h +++ b/include/ovn/lex.h @@ -29,6 +29,8 @@ struct ds; +#define LEX_TEMPLATE_PREFIX '^' + /* Token type. */ enum lex_type { LEX_T_END, /* end of input */ diff --git a/lib/lb.c b/lib/lb.c index 43628bba7..c13d07b99 100644 --- a/lib/lb.c +++ b/lib/lb.c @@ -314,11 +314,10 @@ ovn_lb_vip_destroy(struct ovn_lb_vip *vip) free(vip->backends); } -void -ovn_lb_vip_format(const struct ovn_lb_vip *vip, struct ds *s, bool template) +static void +ovn_lb_vip_format__(const struct ovn_lb_vip *vip, struct ds *s, + bool needs_brackets) { - bool needs_brackets = vip->address_family == AF_INET6 && vip->port_str - && !template; if (needs_brackets) { ds_put_char(s, '['); } @@ -331,6 +330,30 @@ ovn_lb_vip_format(const struct ovn_lb_vip *vip, struct ds *s, bool template) } } +/* Formats the VIP in the way the ovn-controller expects it, that is, + * template IPv6 variables need to be between brackets too. + */ +static char * +ovn_lb_vip6_template_format_internal(const struct ovn_lb_vip *vip) +{ + struct ds s = DS_EMPTY_INITIALIZER; + + if (vip->vip_str && *vip->vip_str == LEX_TEMPLATE_PREFIX) { + ovn_lb_vip_format__(vip, &s, true); + } else { + ovn_lb_vip_format(vip, &s, !!vip->port_str); + } + return ds_steal_cstr(&s); +} + +void +ovn_lb_vip_format(const struct ovn_lb_vip *vip, struct ds *s, bool template) +{ + bool needs_brackets = vip->address_family == AF_INET6 && vip->port_str + && !template; + ovn_lb_vip_format__(vip, s, needs_brackets); +} + void ovn_lb_vip_backends_format(const struct ovn_lb_vip *vip, struct ds *s, bool template) @@ -512,6 +535,7 @@ ovn_northd_lb_create(const struct nbrec_load_balancer *nbrec_lb) lb->n_vips = smap_count(&nbrec_lb->vips); lb->vips = xcalloc(lb->n_vips, sizeof *lb->vips); lb->vips_nb = xcalloc(lb->n_vips, sizeof *lb->vips_nb); + smap_init(&lb->template_vips); lb->controller_event = smap_get_bool(&nbrec_lb->options, "event", false); bool routable = smap_get_bool(&nbrec_lb->options, "add_route", false); @@ -560,6 +584,12 @@ ovn_northd_lb_create(const struct nbrec_load_balancer *nbrec_lb) } else { sset_add(&lb->ips_v6, lb_vip->vip_str); } + + if (lb->template && address_family == AF_INET6) { + smap_add_nocopy(&lb->template_vips, + ovn_lb_vip6_template_format_internal(lb_vip), + xstrdup(node->value)); + } n_vips++; } @@ -604,6 +634,15 @@ ovn_northd_lb_find(const struct hmap *lbs, const struct uuid *uuid) return NULL; } +const struct smap * +ovn_northd_lb_get_vips(const struct ovn_northd_lb *lb) +{ + if (!smap_is_empty(&lb->template_vips)) { + return &lb->template_vips; + } + return &lb->nlb->vips; +} + void ovn_northd_lb_add_lr(struct ovn_northd_lb *lb, size_t n, struct ovn_datapath **ods) @@ -637,6 +676,7 @@ ovn_northd_lb_destroy(struct ovn_northd_lb *lb) } free(lb->vips); free(lb->vips_nb); + smap_destroy(&lb->template_vips); sset_destroy(&lb->ips_v4); sset_destroy(&lb->ips_v6); free(lb->selection_fields); diff --git a/lib/lb.h b/lib/lb.h index 55a41ae0b..55becc1bf 100644 --- a/lib/lb.h +++ b/lib/lb.h @@ -19,6 +19,7 @@ #include #include +#include "lib/smap.h" #include "openvswitch/hmap.h" #include "ovn-util.h" #include "sset.h" @@ -62,6 +63,9 @@ struct ovn_northd_lb { char *selection_fields; struct ovn_lb_vip *vips; struct ovn_northd_lb_vip *vips_nb; + struct smap template_vips; /* Slightly changed template VIPs, populated + * if needed. Until now it's only required + * for IPv6 template load balancers. */ size_t n_vips; enum lb_neighbor_responder_mode neigh_mode; @@ -130,6 +134,7 @@ struct ovn_northd_lb_backend { struct ovn_northd_lb *ovn_northd_lb_create(const struct nbrec_load_balancer *); struct ovn_northd_lb *ovn_northd_lb_find(const struct hmap *, const struct uuid *); +const struct smap *ovn_northd_lb_get_vips(const struct ovn_northd_lb *); void ovn_northd_lb_destroy(struct ovn_northd_lb *); void ovn_northd_lb_add_lr(struct ovn_northd_lb *lb, size_t n, struct ovn_datapath **ods); diff --git a/lib/lex.c b/lib/lex.c index 5251868b5..a8b9812bb 100644 --- a/lib/lex.c +++ b/lib/lex.c @@ -782,7 +782,7 @@ next: p = lex_parse_port_group(p, token); break; - case '^': + case LEX_TEMPLATE_PREFIX: p = lex_parse_template(p, token); break; @@ -1061,7 +1061,7 @@ lexer_parse_template_string(const char *s, const struct smap *template_vars, struct sset *template_vars_ref) { /* No '^' means no templates. */ - if (!strchr(s, '^')) { + if (!strchr(s, LEX_TEMPLATE_PREFIX)) { return lex_str_use(s); } diff --git a/lib/ovn-util.c b/lib/ovn-util.c index 86b98acf7..69ab56423 100644 --- a/lib/ovn-util.c +++ b/lib/ovn-util.c @@ -825,24 +825,6 @@ ovn_get_internal_version(void) N_OVNACTS, OVN_INTERNAL_MINOR_VER); } -unsigned int -ovn_parse_internal_version_minor(const char *ver) -{ - const char *p = ver + strlen(ver); - for (int i = 0; i < strlen(ver); i++) { - if (*p == '.') { - break; - } - p--; - } - - unsigned int minor; - if (ovs_scan(p, ".%u", &minor)) { - return minor; - } - return 0; -} - #ifdef DDLOG /* Callbacks used by the ddlog northd code to print warnings and errors. */ void diff --git a/lib/ovn-util.h b/lib/ovn-util.h index 809ff1d36..48dc846ad 100644 --- a/lib/ovn-util.h +++ b/lib/ovn-util.h @@ -70,6 +70,23 @@ struct lport_addresses { struct ipv6_netaddr *ipv6_addrs; }; +static inline bool +ipv6_is_all_router(const struct in6_addr *addr) +{ + return ipv6_addr_equals(addr, &in6addr_all_routers); +} + +static const struct in6_addr in6addr_all_site_routers = {{{ + 0xff,0x05,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 +}}}; + +static inline bool +ipv6_is_all_site_router(const struct in6_addr *addr) +{ + return ipv6_addr_equals(addr, &in6addr_all_site_routers); +} + bool is_dynamic_lsp_address(const char *address); bool extract_addresses(const char *address, struct lport_addresses *, int *ofs); @@ -248,11 +265,6 @@ bool ip_address_and_port_from_lb_key(const char *key, char **ip_address, * value. */ char *ovn_get_internal_version(void); -/* Parse the provided internal version string and return the "minor" part which - * is expected to be an unsigned integer followed by the last "." in the - * string. Returns 0 if the string can't be parsed. */ -unsigned int ovn_parse_internal_version_minor(const char *ver); - /* OVN Packet definitions. These may eventually find a home in OVS's * packets.h file. For the time being, they live here because OVN uses them * and OVS does not. diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c index 363e384bd..a7b735333 100644 --- a/northd/inc-proc-northd.c +++ b/northd/inc-proc-northd.c @@ -34,10 +34,13 @@ #include "en-lflow.h" #include "en-northd-output.h" #include "en-sync-sb.h" +#include "unixctl.h" #include "util.h" VLOG_DEFINE_THIS_MODULE(inc_proc_northd); +static unixctl_cb_func chassis_features_list; + #define NB_NODES \ NB_NODE(nb_global, "nb_global") \ NB_NODE(copp, "copp") \ @@ -306,6 +309,12 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, engine_ovsdb_node_add_index(&en_sb_address_set, "sbrec_address_set_by_name", sbrec_address_set_by_name); + + struct northd_data *northd_data = + engine_get_internal_data(&en_northd); + unixctl_command_register("debug/chassis-features-list", "", 0, 0, + chassis_features_list, + &northd_data->features); } void inc_proc_northd_run(struct ovsdb_idl_txn *ovnnb_txn, @@ -354,3 +363,20 @@ void inc_proc_northd_cleanup(void) engine_cleanup(); engine_set_context(NULL); } + +static void +chassis_features_list(struct unixctl_conn *conn, int argc OVS_UNUSED, + const char *argv[] OVS_UNUSED, void *features_) +{ + struct chassis_features *features = features_; + struct ds ds = DS_EMPTY_INITIALIZER; + + ds_put_format(&ds, "ct_no_masked_label: %s\n", + features->ct_no_masked_label ? "true" : "false"); + ds_put_format(&ds, "ct_lb_related: %s\n", + features->ct_lb_related ? "true" : "false"); + ds_put_format(&ds, "mac_binding_timestamp: %s\n", + features->mac_binding_timestamp ? "true" : "false"); + unixctl_command_reply(conn, ds_cstr(&ds)); + ds_destroy(&ds); +} diff --git a/northd/northd.c b/northd/northd.c index 841ae9cc5..9cedec909 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -125,11 +125,11 @@ enum ovn_stage { PIPELINE_STAGE(SWITCH, IN, LB_AFF_CHECK, 11, "ls_in_lb_aff_check") \ PIPELINE_STAGE(SWITCH, IN, LB, 12, "ls_in_lb") \ PIPELINE_STAGE(SWITCH, IN, LB_AFF_LEARN, 13, "ls_in_lb_aff_learn") \ - PIPELINE_STAGE(SWITCH, IN, ACL_AFTER_LB, 14, "ls_in_acl_after_lb") \ - PIPELINE_STAGE(SWITCH, IN, STATEFUL, 15, "ls_in_stateful") \ - PIPELINE_STAGE(SWITCH, IN, PRE_HAIRPIN, 16, "ls_in_pre_hairpin") \ - PIPELINE_STAGE(SWITCH, IN, NAT_HAIRPIN, 17, "ls_in_nat_hairpin") \ - PIPELINE_STAGE(SWITCH, IN, HAIRPIN, 18, "ls_in_hairpin") \ + PIPELINE_STAGE(SWITCH, IN, PRE_HAIRPIN, 14, "ls_in_pre_hairpin") \ + PIPELINE_STAGE(SWITCH, IN, NAT_HAIRPIN, 15, "ls_in_nat_hairpin") \ + PIPELINE_STAGE(SWITCH, IN, HAIRPIN, 16, "ls_in_hairpin") \ + PIPELINE_STAGE(SWITCH, IN, ACL_AFTER_LB, 17, "ls_in_acl_after_lb") \ + PIPELINE_STAGE(SWITCH, IN, STATEFUL, 18, "ls_in_stateful") \ PIPELINE_STAGE(SWITCH, IN, ARP_ND_RSP, 19, "ls_in_arp_rsp") \ PIPELINE_STAGE(SWITCH, IN, DHCP_OPTIONS, 20, "ls_in_dhcp_options") \ PIPELINE_STAGE(SWITCH, IN, DHCP_RESPONSE, 21, "ls_in_dhcp_response") \ @@ -215,6 +215,7 @@ enum ovn_stage { #define REGBIT_ACL_LABEL "reg0[13]" #define REGBIT_FROM_RAMP "reg0[14]" #define REGBIT_PORT_SEC_DROP "reg0[15]" +#define REGBIT_ACL_HINT_ALLOW_REL "reg0[17]" #define REG_ORIG_DIP_IPV4 "reg1" #define REG_ORIG_DIP_IPV6 "xxreg1" @@ -430,6 +431,13 @@ build_chassis_features(const struct northd_input *input_data, const struct sbrec_chassis *chassis; SBREC_CHASSIS_TABLE_FOR_EACH (chassis, input_data->sbrec_chassis) { + /* Only consider local AZ chassis. Remote ones don't install + * flows generated by the local northd. + */ + if (smap_get_bool(&chassis->other_config, "is-remote", false)) { + continue; + } + bool ct_no_masked_label = smap_get_bool(&chassis->other_config, OVN_FEATURE_CT_NO_MASKED_LABEL, @@ -446,6 +454,15 @@ build_chassis_features(const struct northd_input *input_data, chassis_features->mac_binding_timestamp) { chassis_features->mac_binding_timestamp = false; } + + bool ct_lb_related = + smap_get_bool(&chassis->other_config, + OVN_FEATURE_CT_LB_RELATED, + false); + if (!ct_lb_related && + chassis_features->ct_lb_related) { + chassis_features->ct_lb_related = false; + } } } @@ -4410,7 +4427,7 @@ sync_lbs(struct northd_input *input_data, struct ovsdb_idl_txn *ovnsb_txn, /* Update columns. */ sbrec_load_balancer_set_name(lb->slb, lb->nlb->name); - sbrec_load_balancer_set_vips(lb->slb, &lb->nlb->vips); + sbrec_load_balancer_set_vips(lb->slb, ovn_northd_lb_get_vips(lb)); sbrec_load_balancer_set_protocol(lb->slb, lb->nlb->protocol); sbrec_load_balancer_set_datapath_group(lb->slb, dpg->dp_group); sbrec_load_balancer_set_options(lb->slb, &options); @@ -4849,7 +4866,7 @@ ovn_igmp_group_get_ports(const struct sbrec_igmp_group *sb_igmp_group, struct ovn_port *port = ovn_port_find(ovn_ports, sb_igmp_group->ports[i]->logical_port); - if (!port) { + if (!port || !port->nbsp) { continue; } @@ -6758,7 +6775,8 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features, ct_blocked_match); ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, UINT16_MAX - 3, ds_cstr(&match), REGBIT_ACL_HINT_DROP" = 0; " - REGBIT_ACL_HINT_BLOCK" = 0; next;"); + REGBIT_ACL_HINT_BLOCK" = 0; " + REGBIT_ACL_HINT_ALLOW_REL" = 1; next;"); ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX - 3, ds_cstr(&match), "next;"); @@ -6774,14 +6792,21 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features, * a dynamically negotiated FTP data channel), but will allow * related traffic such as an ICMP Port Unreachable through * that's generated from a non-listening UDP port. */ + const char *ct_in_acl_action = + features->ct_lb_related + ? REGBIT_ACL_HINT_ALLOW_REL" = 1; ct_commit_nat;" + : REGBIT_ACL_HINT_ALLOW_REL" = 1; next;"; + const char *ct_out_acl_action = features->ct_lb_related + ? "ct_commit_nat;" + : "next;"; ds_clear(&match); ds_put_format(&match, "!ct.est && ct.rel && !ct.new%s && %s == 0", use_ct_inv_match ? " && !ct.inv" : "", ct_blocked_match); ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, UINT16_MAX - 3, - ds_cstr(&match), "ct_commit_nat;"); + ds_cstr(&match), ct_in_acl_action); ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX - 3, - ds_cstr(&match), "ct_commit_nat;"); + ds_cstr(&match), ct_out_acl_action); /* Ingress and Egress ACL Table (Priority 65532). * @@ -6790,6 +6815,11 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features, "nd || nd_ra || nd_rs || mldv1 || mldv2", "next;"); ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX - 3, "nd || nd_ra || nd_rs || mldv1 || mldv2", "next;"); + + /* Reply and related traffic matched by an "allow-related" ACL + * should be allowed in the ls_in_acl_after_lb stage too. */ + ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL_AFTER_LB, UINT16_MAX - 3, + REGBIT_ACL_HINT_ALLOW_REL" == 1", "next;"); } /* Ingress or Egress ACL Table (Various priorities). */ @@ -7838,7 +7868,7 @@ build_lrouter_groups(struct hmap *ports, struct ovs_list *lr_list) } /* - * Ingress table 24: Flows that flood self originated ARP/RARP/ND packets in + * Ingress table 25: Flows that flood self originated ARP/RARP/ND packets in * the switching domain. */ static void @@ -7952,7 +7982,7 @@ lrouter_port_ipv6_reachable(const struct ovn_port *op, } /* - * Ingress table 24: Flows that forward ARP/ND requests only to the routers + * Ingress table 25: Flows that forward ARP/ND requests only to the routers * that own the addresses. Other ARP/ND packets are still flooded in the * switching domain as regular broadcast. */ @@ -7989,7 +8019,7 @@ build_lswitch_rport_arp_req_flow(const char *ips, } /* - * Ingress table 24: Flows that forward ARP/ND requests only to the routers + * Ingress table 25: Flows that forward ARP/ND requests only to the routers * that own the addresses. * Priorities: * - 80: self originated GARPs that need to follow regular processing. @@ -8318,7 +8348,8 @@ build_lswitch_flows(const struct hmap *datapaths, struct ovn_datapath *od; - /* Ingress table 25: Destination lookup for unknown MACs (priority 0). */ + /* Ingress table 25/26: Destination lookup for unknown MACs + * (priority 0). */ HMAP_FOR_EACH (od, key_node, datapaths) { if (!od->nbs) { continue; @@ -8393,7 +8424,7 @@ build_lswitch_lflows_admission_control(struct ovn_datapath *od, } } -/* Ingress table 18: ARP/ND responder, skip requests coming from localnet +/* Ingress table 19: ARP/ND responder, skip requests coming from localnet * ports. (priority 100); see ovn-northd.8.xml for the rationale. */ static void @@ -8411,7 +8442,7 @@ build_lswitch_arp_nd_responder_skip_local(struct ovn_port *op, } } -/* Ingress table 18: ARP/ND responder, reply for known IPs. +/* Ingress table 19: ARP/ND responder, reply for known IPs. * (priority 50). */ static void build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op, @@ -8671,7 +8702,7 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op, } } -/* Ingress table 18: ARP/ND responder, by default goto next. +/* Ingress table 19: ARP/ND responder, by default goto next. * (priority 0)*/ static void build_lswitch_arp_nd_responder_default(struct ovn_datapath *od, @@ -8682,7 +8713,7 @@ build_lswitch_arp_nd_responder_default(struct ovn_datapath *od, } } -/* Ingress table 18: ARP/ND responder for service monitor source ip. +/* Ingress table 19: ARP/ND responder for service monitor source ip. * (priority 110)*/ static void build_lswitch_arp_nd_service_monitor(struct ovn_northd_lb *lb, @@ -8730,7 +8761,7 @@ build_lswitch_arp_nd_service_monitor(struct ovn_northd_lb *lb, } -/* Logical switch ingress table 19 and 20: DHCP options and response +/* Logical switch ingress table 20 and 21: DHCP options and response * priority 100 flows. */ static void build_lswitch_dhcp_options_and_response(struct ovn_port *op, @@ -8782,11 +8813,11 @@ build_lswitch_dhcp_options_and_response(struct ovn_port *op, } } -/* Ingress table 19 and 20: DHCP options and response, by default goto +/* Ingress table 20 and 21: DHCP options and response, by default goto * next. (priority 0). - * Ingress table 21 and 22: DNS lookup and response, by default goto next. + * Ingress table 22 and 23: DNS lookup and response, by default goto next. * (priority 0). - * Ingress table 23 - External port handling, by default goto next. + * Ingress table 24 - External port handling, by default goto next. * (priority 0). */ static void build_lswitch_dhcp_and_dns_defaults(struct ovn_datapath *od, @@ -8801,7 +8832,7 @@ build_lswitch_dhcp_and_dns_defaults(struct ovn_datapath *od, } } -/* Logical switch ingress table 21 and 22: DNS lookup and response +/* Logical switch ingress table 22 and 23: DNS lookup and response * priority 100 flows. */ static void @@ -8829,7 +8860,7 @@ build_lswitch_dns_lookup_and_response(struct ovn_datapath *od, } } -/* Table 23: External port. Drop ARP request for router ips from +/* Table 24: External port. Drop ARP request for router ips from * external ports on chassis not binding those ports. * This makes the router pipeline to be run only on the chassis * binding the external ports. */ @@ -8846,7 +8877,7 @@ build_lswitch_external_port(struct ovn_port *op, } } -/* Ingress table 24: Destination lookup, broadcast and multicast handling +/* Ingress table 25: Destination lookup, broadcast and multicast handling * (priority 70 - 100). */ static void build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od, @@ -8931,7 +8962,7 @@ build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od, } -/* Ingress table 24: Add IP multicast flows learnt from IGMP/MLD +/* Ingress table 25: Add IP multicast flows learnt from IGMP/MLD * (priority 90). */ static void build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, @@ -8973,9 +9004,11 @@ build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, igmp_group->mcgroup.name); } else { /* RFC 4291, section 2.7.1: Skip groups that correspond to all - * hosts. + * hosts, all link-local routers and all site routers. */ - if (ipv6_is_all_hosts(&igmp_group->address)) { + if (ipv6_is_all_hosts(&igmp_group->address) || + ipv6_is_all_router(&igmp_group->address) || + ipv6_is_all_site_router(&igmp_group->address)) { return; } if (atomic_compare_exchange_strong( @@ -9013,7 +9046,7 @@ build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, static struct ovs_mutex mcgroup_mutex = OVS_MUTEX_INITIALIZER; -/* Ingress table 24: Destination lookup, unicast handling (priority 50), */ +/* Ingress table 25: Destination lookup, unicast handling (priority 50), */ static void build_lswitch_ip_unicast_lookup(struct ovn_port *op, struct hmap *lflows, @@ -10471,9 +10504,11 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, struct hmap *lflows, struct ds *match, struct ds *action, const struct shash *meter_groups, - bool ct_lb_mark) + const struct chassis_features *features) { - const char *ct_natted = ct_lb_mark ? "ct_mark.natted" : "ct_label.natted"; + const char *ct_natted = features->ct_no_masked_label + ? "ct_mark.natted" + : "ct_label.natted"; char *skip_snat_new_action = NULL; char *skip_snat_est_action = NULL; char *new_match; @@ -10484,7 +10519,7 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, bool reject = build_lb_vip_actions(lb_vip, vips_nb, action, lb->selection_fields, false, - ct_lb_mark); + features->ct_no_masked_label); bool drop = !!strncmp(ds_cstr(action), "ct_lb", strlen("ct_lb")); if (!drop) { /* Remove the trailing ");". */ @@ -10506,9 +10541,11 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, } if (lb->skip_snat) { - skip_snat_new_action = xasprintf("flags.skip_snat_for_lb = 1; %s%s", - ds_cstr(action), - drop ? "" : "; skip_snat);"); + const char *skip_snat = features->ct_lb_related && !drop + ? "; skip_snat" + : ""; + skip_snat_new_action = xasprintf("flags.skip_snat_for_lb = 1; %s%s);", + ds_cstr(action), skip_snat); skip_snat_est_action = xasprintf("flags.skip_snat_for_lb = 1; " "next;"); } @@ -10641,9 +10678,11 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, skip_snat_new_action, est_match, skip_snat_est_action, lflows, prio, meter_groups); - char *new_actions = xasprintf("flags.force_snat_for_lb = 1; %s%s", - ds_cstr(action), - drop ? "" : "; force_snat);"); + const char *force_snat = features->ct_lb_related && !drop + ? "; force_snat" + : ""; + char *new_actions = xasprintf("flags.force_snat_for_lb = 1; %s%s);", + ds_cstr(action), force_snat); build_gw_lrouter_nat_flows_for_lb(lb, gw_router_force_snat, n_gw_router_force_snat, reject, new_match, new_actions, est_match, @@ -10898,7 +10937,7 @@ build_lrouter_flows_for_lb(struct ovn_northd_lb *lb, struct hmap *lflows, build_lrouter_nat_flows_for_lb(lb_vip, lb, &lb->vips_nb[i], lflows, match, action, meter_groups, - features->ct_no_masked_label); + features); if (!build_empty_lb_event_flow(lb_vip, lb, match, action)) { continue; @@ -14208,7 +14247,7 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, const struct hmap *ports, struct ds *match, struct ds *actions, const struct shash *meter_groups, - bool ct_lb_mark) + const struct chassis_features *features) { if (!od->nbr) { return; @@ -14239,9 +14278,11 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, * a dynamically negotiated FTP data channel), but will allow * related traffic such as an ICMP Port Unreachable through * that's generated from a non-listening UDP port. */ - if (od->has_lb_vip) { + if (od->has_lb_vip && features->ct_lb_related) { ds_clear(match); - const char *ct_flag_reg = ct_lb_mark ? "ct_mark" : "ct_label"; + const char *ct_flag_reg = features->ct_no_masked_label + ? "ct_mark" + : "ct_label"; ds_put_cstr(match, "ct.rel && !ct.est && !ct.new"); size_t match_len = match->length; @@ -14328,6 +14369,23 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, sset_add(&nat_entries, nat->external_ip); } else { if (!sset_contains(&nat_entries, nat->external_ip)) { + /* Drop packets coming in from external that still has + * destination IP equals to the NAT external IP, to avoid loop. + * The packets must have gone through DNAT/unSNAT stage but + * failed to convert the destination. */ + ds_clear(match); + ds_put_format( + match, "inport == %s && outport == %s && ip%s.dst == %s", + l3dgw_port->json_key, l3dgw_port->json_key, + is_v6 ? "6" : "4", nat->external_ip); + ovn_lflow_add_with_hint(lflows, od, + S_ROUTER_IN_ARP_RESOLVE, + 150, ds_cstr(match), + debug_drop_action(), + &nat->header_); + /* Now for packets coming from other (downlink) LRPs, allow ARP + * resolve for the NAT IP, so that such packets can be + * forwarded for E/W NAT. */ ds_clear(match); ds_put_format( match, "outport == %s && %s == %s", @@ -14464,7 +14522,7 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, if (od->nbr->n_nat) { ds_clear(match); - const char *ct_natted = ct_lb_mark ? + const char *ct_natted = features->ct_no_masked_label ? "ct_mark.natted" : "ct_label.natted"; ds_put_format(match, "ip && %s == 1", ct_natted); @@ -14581,7 +14639,7 @@ build_lswitch_and_lrouter_iterate_by_od(struct ovn_datapath *od, build_lrouter_arp_nd_for_datapath(od, lsi->lflows, lsi->meter_groups); build_lrouter_nat_defrag_and_lb(od, lsi->lflows, lsi->ports, &lsi->match, &lsi->actions, lsi->meter_groups, - lsi->features->ct_no_masked_label); + lsi->features); build_lb_affinity_default_flows(od, lsi->lflows); } @@ -16073,6 +16131,7 @@ northd_init(struct northd_data *data) data->features = (struct chassis_features) { .ct_no_masked_label = true, .mac_binding_timestamp = true, + .ct_lb_related = true, }; data->ovn_internal_version_changed = false; } diff --git a/northd/northd.h b/northd/northd.h index ff8727cb7..4d9055296 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -71,6 +71,7 @@ struct northd_input { struct chassis_features { bool ct_no_masked_label; bool mac_binding_timestamp; + bool ct_lb_related; }; struct northd_data { diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index 058cbf71a..4de015e40 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -790,8 +790,9 @@ policy, ct_mark.blocked will get set and packets in the reply direction will no longer be allowed, either. This flow also clears the register bits reg0[9] and - reg0[10]. If ACL logging and logging of related packets - is enabled, then a companion priority-65533 flow will be installed that + reg0[10] and sets register bit reg0[17]. + If ACL logging and logging of related packets is enabled, then a + companion priority-65533 flow will be installed that accomplishes the same thing but also logs the traffic. @@ -1028,92 +1029,7 @@ -

Ingress table 14: from-lport ACLs after LB

- -

- Logical flows in this table closely reproduce those in the - ACL table in the OVN_Northbound database - for the from-lport direction with the option - apply-after-lb set to true. - The priority values from the ACL table have a - limited range and have 1000 added to them to leave room for OVN default - flows at both higher and lower priorities. -

- -
    -
  • - allow apply-after-lb ACLs translate into logical flows - with the next; action. If there are any stateful ACLs - (including both before-lb and after-lb ACLs) - on this datapath, then allow ACLs translate to - ct_commit; next; (which acts as a hint for the next tables - to commit the connection to conntrack). In case the ACL - has a label then reg3 is loaded with the label value and - reg0[13] bit is set to 1 (which acts as a hint for the - next tables to commit the label to conntrack). -
  • -
  • - allow-related apply-after-lb ACLs translate into logical - flows with the ct_commit(ct_label=0/1); next; actions - for new connections and reg0[1] = 1; next; for existing - connections. In case the ACL has a label then - reg3 is loaded with the label value and - reg0[13] bit is set to 1 (which acts as a hint for the - next tables to commit the label to conntrack). -
  • -
  • - allow-stateless apply-after-lb ACLs translate into logical - flows with the next; action. -
  • -
  • - reject apply-after-lb ACLs translate into logical - flows with the - tcp_reset { output <-> inport; - next(pipeline=egress,table=5);} - action for TCP connections,icmp4/icmp6 action - for UDP connections, and sctp_abort {output <-%gt; inport; - next(pipeline=egress,table=5);} action for SCTP associations. -
  • -
  • - Other apply-after-lb ACLs translate to drop; for new - or untracked connections and ct_commit(ct_label=1/1); for - known connections. Setting ct_label marks a connection - as one that was previously allowed, but should no longer be - allowed due to a policy change. -
  • -
- -
    -
  • - One priority-0 fallback flow that matches all packets and advances to - the next table. -
  • -
- -

Ingress Table 15: Stateful

- -
    -
  • - A priority 100 flow is added which commits the packet to the conntrack - and sets the most significant 32-bits of ct_label with the - reg3 value based on the hint provided by previous tables - (with a match for reg0[1] == 1 && reg0[13] == 1). - This is used by the ACLs with label to commit the label - value to conntrack. -
  • - -
  • - For ACLs without label, a second priority-100 flow commits - packets to connection tracker using ct_commit; next; - action based on a hint provided by the previous tables (with a match - for reg0[1] == 1 && reg0[13] == 0). -
  • -
  • - A priority-0 flow that simply moves traffic to the next table. -
  • -
- -

Ingress Table 16: Pre-Hairpin

+

Ingress Table 14: Pre-Hairpin

  • If the logical switch has load balancer(s) configured, then a @@ -1131,7 +1047,7 @@
-

Ingress Table 17: Nat-Hairpin

+

Ingress Table 15: Nat-Hairpin

  • If the logical switch has load balancer(s) configured, then a @@ -1166,7 +1082,7 @@
-

Ingress Table 18: Hairpin

+

Ingress Table 16: Hairpin

  • @@ -1200,6 +1116,100 @@

+

Ingress table 17: from-lport ACLs after LB

+ +

+ Logical flows in this table closely reproduce those in the + ACL table in the OVN_Northbound database + for the from-lport direction with the option + apply-after-lb set to true. + The priority values from the ACL table have a + limited range and have 1000 added to them to leave room for OVN default + flows at both higher and lower priorities. +

+ +
    +
  • + allow apply-after-lb ACLs translate into logical flows + with the next; action. If there are any stateful ACLs + (including both before-lb and after-lb ACLs) + on this datapath, then allow ACLs translate to + ct_commit; next; (which acts as a hint for the next tables + to commit the connection to conntrack). In case the ACL + has a label then reg3 is loaded with the label value and + reg0[13] bit is set to 1 (which acts as a hint for the + next tables to commit the label to conntrack). +
  • +
  • + allow-related apply-after-lb ACLs translate into logical + flows with the ct_commit(ct_label=0/1); next; actions + for new connections and reg0[1] = 1; next; for existing + connections. In case the ACL has a label then + reg3 is loaded with the label value and + reg0[13] bit is set to 1 (which acts as a hint for the + next tables to commit the label to conntrack). +
  • +
  • + allow-stateless apply-after-lb ACLs translate into logical + flows with the next; action. +
  • +
  • + reject apply-after-lb ACLs translate into logical + flows with the + tcp_reset { output <-> inport; + next(pipeline=egress,table=5);} + action for TCP connections,icmp4/icmp6 action + for UDP connections, and sctp_abort {output <-%gt; inport; + next(pipeline=egress,table=5);} action for SCTP associations. +
  • +
  • + Other apply-after-lb ACLs translate to drop; for new + or untracked connections and ct_commit(ct_label=1/1); for + known connections. Setting ct_label marks a connection + as one that was previously allowed, but should no longer be + allowed due to a policy change. +
  • +
+ +
    +
  • + One priority-65532 flow matching packets with reg0[17] + set (either replies to existing sessions or traffic related to + existing sessions) and allows these by advancing to the next + table. +
  • +
+ +
    +
  • + One priority-0 fallback flow that matches all packets and advances to + the next table. +
  • +
+ +

Ingress Table 18: Stateful

+ +
    +
  • + A priority 100 flow is added which commits the packet to the conntrack + and sets the most significant 32-bits of ct_label with the + reg3 value based on the hint provided by previous tables + (with a match for reg0[1] == 1 && reg0[13] == 1). + This is used by the ACLs with label to commit the label + value to conntrack. +
  • + +
  • + For ACLs without label, a second priority-100 flow commits + packets to connection tracker using ct_commit; next; + action based on a hint provided by the previous tables (with a match + for reg0[1] == 1 && reg0[13] == 0). +
  • +
  • + A priority-0 flow that simply moves traffic to the next table. +
  • +
+

Ingress Table 19: ARP/ND responder

@@ -4257,13 +4267,17 @@ outport = P For each row in the NAT table with IPv4 address A in the column of - table, a priority-100 - flow with the match outport === P && - reg0 == A has actions eth.dst = E; - next;, where P is the distributed logical router - port, E is the Ethernet address if set in the - column - of table for of type + table, below two flows are + programmed: +

+ +

+ A priority-100 flow with the match outport == P + && reg0 == A has actions eth.dst = + E; next;, where P is the distributed + logical router port, E is the Ethernet address if set in + the + column of table for of type dnat_and_snat, otherwise the Ethernet address of the distributed logical router port. Note that if the is not @@ -4273,9 +4287,18 @@ outport = P will be added.

+

+ Corresponding to the above flow, a priority-150 flow with the match + inport == P && outport == P + && ip4.dst == A has actions + drop; to exclude packets that have gone through + DNAT/unSNAT stage but failed to convert the destination, to avoid + loop. +

+

For IPv6 NAT entries, same flows are added, but using the register - xxreg0 for the match. + xxreg0 and field ip6 for the match.

diff --git a/ovn-architecture.7.xml b/ovn-architecture.7.xml index b2e00d6e4..cb1064f71 100644 --- a/ovn-architecture.7.xml +++ b/ovn-architecture.7.xml @@ -2832,8 +2832,7 @@ The maximum number of networks is reduced to 4096.
  • - The maximum number of ports per network is reduced to 4096. (Including - multicast group ports.) + The maximum number of ports per network is reduced to 2048.
  • ACLs matching against logical ingress port identifiers are not supported. diff --git a/tests/atlocal.in b/tests/atlocal.in index 0b9a31276..02e9ce9bb 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -166,6 +166,9 @@ fi # Set HAVE_TCPDUMP find_command tcpdump +# Set HAVE_XXD +find_command xxd + # Set HAVE_LFTP find_command lftp diff --git a/tests/network-functions.at b/tests/network-functions.at index c583bc31e..a2481c55c 100644 --- a/tests/network-functions.at +++ b/tests/network-functions.at @@ -128,12 +128,18 @@ OVS_START_SHELL_HELPERS # hex_to_binary HEXDIGITS # # Converts the pairs of HEXDIGITS into bytes and prints them on stdout. -hex_to_binary() { - printf $(while test -n "$1"; do - printf '\\%03o' 0x$(expr "$1" : '\(..\)') - set -- "${1##??}" - done) -} +if test x$HAVE_XXD = xno; then + hex_to_binary() { + printf $(while test -n "$1"; do + printf '\\%03o' 0x$(expr "$1" : '\(..\)') + set -- "${1##??}" + done) + } +else + hex_to_binary() { + echo $1 | xxd -r -p + } +fi # tcpdump_hex TITLE PACKET # diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at index 6bc9ba75d..e2f4fc85c 100644 --- a/tests/ovn-controller.at +++ b/tests/ovn-controller.at @@ -2499,3 +2499,30 @@ AT_CHECK([GET_LOCAL_TEMPLATE_VARS], [1], []) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn-controller - Requested SNAT Zone in router creation transaction]) +ovn_start + +net_add n1 +sim_add hv1 +as hv1 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 + +dnl This is key. Add the snat-ct-zone when creating the logical router and then +dnl do not make any further changes to the logical router settings. +check ovn-nbctl lr-add lr0 -- set Logical_Router lr0 options:snat-ct-zone=666 +check ovn-nbctl lrp-add lr0 lrp-gw 01:00:00:00:00:01 172.16.0.1 +check ovn-nbctl lrp-set-gateway-chassis lrp-gw hv1 + +check ovn-nbctl --wait=hv sync + +lr_uuid=$(fetch_column Datapath_Binding _uuid external_ids:name=lr0) +ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list) +zone_num=$(printf "$ct_zones" | grep ${lr_uuid}_snat | cut -d ' ' -f 2) + +check test "$zone_num" -eq 666 + +AT_CLEANUP +]) diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index c25d1122c..072102f36 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -2232,9 +2232,9 @@ check ovn-nbctl acl-add sw0 to-lport 1002 'outport == "sw0-p1" && ip4.src == 10. check ovn-nbctl acl-add sw0 to-lport 1002 'outport == "sw0-p1" && ip4.src == 10.0.0.13' allow check ovn-nbctl acl-add pg0 to-lport 1002 'outport == "pg0" && ip4.src == 10.0.0.11' drop -acl1=$(ovn-nbctl --bare --column _uuid,match find acl | grep -B1 '10.0.0.12' | head -1) -acl2=$(ovn-nbctl --bare --column _uuid,match find acl | grep -B1 '10.0.0.13' | head -1) -acl3=$(ovn-nbctl --bare --column _uuid,match find acl | grep -B1 '10.0.0.11' | head -1) +acl1=$(ovn-nbctl --bare --column _uuid,match find acl | grep -F -B1 '10.0.0.12' | head -1) +acl2=$(ovn-nbctl --bare --column _uuid,match find acl | grep -F -B1 '10.0.0.13' | head -1) +acl3=$(ovn-nbctl --bare --column _uuid,match find acl | grep -F -B1 '10.0.0.11' | head -1) check ovn-nbctl set acl $acl1 log=true severity=alert meter=meter_me name=acl_one check ovn-nbctl set acl $acl2 log=true severity=info meter=meter_me name=acl_two check ovn-nbctl set acl $acl3 log=true severity=info meter=meter_me name=acl_three @@ -2472,8 +2472,8 @@ AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e table=7 (ls_in_acl_hint ), priority=7 , match=(ct.new && !ct.est), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;) table=8 (ls_in_acl ), priority=1 , match=(ip && !ct.est), action=(reg0[[1]] = 1; next;) table=8 (ls_in_acl ), priority=1 , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;) - table=8 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) - table=8 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=8 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) + table=8 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) table=8 (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) ]) @@ -2485,7 +2485,8 @@ check ovn-nbctl --wait=sb \ -- ls-lb-add ls lb AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e ls_in_acl -e ls_out_acl | sort], [0], [dnl - table=14(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) + table=17(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) + table=17(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) table=3 (ls_out_acl_hint ), priority=0 , match=(1), action=(next;) table=3 (ls_out_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) table=3 (ls_out_acl_hint ), priority=2 , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;) @@ -2518,8 +2519,8 @@ AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e table=8 (ls_in_acl ), priority=1001 , match=(reg0[[7]] == 1 && (ip)), action=(reg0[[1]] = 1; next;) table=8 (ls_in_acl ), priority=1001 , match=(reg0[[8]] == 1 && (ip)), action=(next;) table=8 (ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) - table=8 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) - table=8 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=8 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) + table=8 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) table=8 (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=8 (ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) ]) @@ -2528,7 +2529,7 @@ ovn-nbctl --wait=sb clear logical_switch ls acls ovn-nbctl --wait=sb clear logical_switch ls load_balancer AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e ls_in_acl -e ls_out_acl | sort], [0], [dnl - table=14(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) + table=17(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) table=3 (ls_out_acl_hint ), priority=65535, match=(1), action=(next;) table=4 (ls_out_acl ), priority=65535, match=(1), action=(next;) table=7 (ls_in_acl_hint ), priority=65535, match=(1), action=(next;) @@ -4360,8 +4361,8 @@ ovn-sbctl dump-flows sw0 > sw0flows AT_CAPTURE_FILE([sw0flows]) AT_CHECK([grep -w "ls_in_acl" sw0flows | grep 6553 | sort | sed 's/table=./table=?/'], [0], [dnl - table=? (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) - table=? (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=? (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) + table=? (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) table=? (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=? (ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) ]) @@ -4380,9 +4381,9 @@ ovn-sbctl dump-flows sw0 > sw0flows AT_CAPTURE_FILE([sw0flows]) AT_CHECK([grep -w "ls_in_acl" sw0flows | grep 6553 | sort | sed 's/table=./table=?/'], [0], [dnl - table=? (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && ct_mark.blocked == 0), action=(ct_commit_nat;) + table=? (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) table=? (ls_in_acl ), priority=65532, match=((ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) - table=? (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=? (ls_in_acl ), 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; next;) table=? (ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) ]) @@ -4404,8 +4405,8 @@ ovn-sbctl dump-flows sw0 > sw0flows AT_CAPTURE_FILE([sw0flows]) AT_CHECK([grep -w "ls_in_acl" sw0flows | grep 6553 | sort | sed 's/table=./table=?/'], [0], [dnl - table=? (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) - table=? (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=? (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) + table=? (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) table=? (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=? (ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) ]) @@ -5139,7 +5140,8 @@ AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [ ]) check ovn-sbctl chassis-add gw1 geneve 127.0.0.1 \ - -- set chassis gw1 other_config:ct-no-masked-label="true" + -- set chassis gw1 other_config:ct-no-masked-label="true" \ + -- set chassis gw1 other_config:ovn-ct-lb-related="true" # Create a distributed gw port on lr0 check ovn-nbctl ls-add public @@ -6685,11 +6687,12 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], table=??(ls_in_acl ), priority=2004 , match=(reg0[[10]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(ct_commit { ct_mark.blocked = 1; }; /* drop */) table=??(ls_in_acl ), priority=2004 , match=(reg0[[9]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(/* drop */) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) - table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) + table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) + table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) table=??(ls_in_acl_hint ), priority=2 , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;) @@ -6730,8 +6733,8 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], table=??(ls_in_acl ), priority=1 , match=(ip && !ct.est), action=(reg0[[1]] = 1; next;) table=??(ls_in_acl ), priority=1 , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) - table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) + table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) @@ -6743,6 +6746,7 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], table=??(ls_in_acl_after_lb ), priority=2003 , match=(reg0[[8]] == 1 && (ip4 && icmp)), action=(next;) table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[10]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(ct_commit { ct_mark.blocked = 1; }; /* drop */) table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[9]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(/* drop */) + table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) table=??(ls_in_acl_hint ), priority=2 , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;) @@ -6787,8 +6791,8 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], table=??(ls_in_acl ), priority=2003 , match=(reg0[[7]] == 1 && (ip4 && icmp)), action=(reg0[[1]] = 1; next;) table=??(ls_in_acl ), priority=2003 , match=(reg0[[8]] == 1 && (ip4 && icmp)), action=(next;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) - table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) + table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) @@ -6796,6 +6800,7 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], table=??(ls_in_acl_after_lb ), priority=2001 , match=(reg0[[9]] == 1 && (ip4)), action=(/* drop */) table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[10]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(ct_commit { ct_mark.blocked = 1; }; /* drop */) table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[9]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(/* drop */) + table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) table=??(ls_in_acl_hint ), priority=2 , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;) @@ -7219,11 +7224,12 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ table=??(ls_in_acl ), priority=1001 , match=(reg0[[7]] == 1 && (ip4 && tcp)), action=(reg0[[1]] = 1; next;) table=??(ls_in_acl ), priority=1001 , match=(reg0[[8]] == 1 && (ip4 && tcp)), action=(next;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) - table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) + table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(drop;) + table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) table=??(ls_in_acl_hint ), priority=2 , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;) @@ -7342,13 +7348,14 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ table=??(ls_in_acl ), priority=1 , match=(ip && !ct.est), action=(drop;) table=??(ls_in_acl ), priority=1 , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) - table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) + table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(drop;) table=??(ls_in_acl_after_lb ), priority=1001 , match=(reg0[[7]] == 1 && (ip4 && tcp)), action=(reg0[[1]] = 1; next;) table=??(ls_in_acl_after_lb ), priority=1001 , match=(reg0[[8]] == 1 && (ip4 && tcp)), action=(next;) + table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) table=??(ls_in_acl_hint ), priority=2 , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;) @@ -7467,11 +7474,12 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ table=??(ls_in_acl ), priority=1 , match=(ip && !ct.est), action=(drop;) table=??(ls_in_acl ), priority=1 , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;) table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) - table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) + table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(drop;) + table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) table=??(ls_in_acl_hint ), priority=2 , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;) @@ -7775,7 +7783,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl table=??(ls_in_check_port_sec), priority=100 , match=(vlan.present), action=(drop;) table=??(ls_in_check_port_sec), priority=50 , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;) table=??(ls_in_check_port_sec), priority=70 , match=(inport == "localnetport"), action=(set_queue(10); reg0[[15]] = check_in_port_sec(); next;) - table=??(ls_in_check_port_sec), priority=70 , match=(inport == "sw0p1"), action=(reg0[[14]] = 1; next(pipeline=ingress, table=18);) + table=??(ls_in_check_port_sec), priority=70 , match=(inport == "sw0p1"), action=(reg0[[14]] = 1; next(pipeline=ingress, table=16);) table=??(ls_in_check_port_sec), priority=70 , match=(inport == "sw0p2"), action=(set_queue(10); reg0[[15]] = check_in_port_sec(); next;) table=??(ls_in_apply_port_sec), priority=0 , match=(1), action=(next;) table=??(ls_in_apply_port_sec), priority=50 , match=(reg0[[15]] == 1), action=(drop;) @@ -7832,6 +7840,22 @@ AT_CHECK([ovn-sbctl lflow-list | grep -e natted -e ct_lb], [0], [dnl table=2 (ls_out_pre_stateful), priority=110 , match=(reg0[[2]] == 1), action=(ct_lb;) ]) +check ovn-nbctl --wait=sb set logical_router lr options:lb_force_snat_ip="42.42.42.1" +AT_CHECK([ovn-sbctl lflow-list | grep lr_in_dnat], [0], [dnl + table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 66.66.66.66 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;) + table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 66.66.66.66), action=(flags.force_snat_for_lb = 1; ct_lb(backends=42.42.42.2);) + table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) +]) +check ovn-nbctl remove logical_router lr options lb_force_snat_ip + +check ovn-nbctl --wait=sb set load_balancer lb-test options:skip_snat="true" +AT_CHECK([ovn-sbctl lflow-list | grep lr_in_dnat], [0], [dnl + table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 66.66.66.66 && ct_label.natted == 1), action=(flags.skip_snat_for_lb = 1; next;) + table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 66.66.66.66), action=(flags.skip_snat_for_lb = 1; ct_lb(backends=42.42.42.2);) + table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) +]) +check ovn-nbctl remove load_balancer lb-test options skip_snat + AS_BOX([Chassis upgrades and supports ct_lb_mark - use ct_lb_mark and ct_mark.natted]) check ovn-sbctl set chassis hv other_config:ct-no-masked-label=true check ovn-nbctl --wait=sb sync @@ -7865,8 +7889,8 @@ AT_CHECK([ovn-sbctl lflow-list | grep 'ls.*acl.*blocked' ], [0], [dnl table=7 (ls_in_acl_hint ), priority=4 , match=(!ct.new && ct.est && !ct.rpl && ct_mark.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;) table=7 (ls_in_acl_hint ), priority=2 , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;) table=7 (ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) - table=8 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) - table=8 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=8 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) + table=8 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) table=8 (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=8 (ls_in_acl ), priority=1 , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;) table=3 (ls_out_acl_hint ), priority=6 , match=(!ct.new && ct.est && !ct.rpl && ct_mark.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;) @@ -7887,15 +7911,15 @@ AT_CHECK([ovn-sbctl lflow-list | grep 'ls.*acl.*blocked' ], [0], [dnl table=7 (ls_in_acl_hint ), priority=4 , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;) table=7 (ls_in_acl_hint ), priority=2 , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;) table=7 (ls_in_acl_hint ), priority=1 , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;) - table=8 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(ct_commit_nat;) - table=8 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=8 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(reg0[[17]] = 1; next;) + table=8 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) table=8 (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) table=8 (ls_in_acl ), priority=1 , match=(ip && ct.est && ct_label.blocked == 1), action=(reg0[[1]] = 1; next;) table=3 (ls_out_acl_hint ), priority=6 , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;) table=3 (ls_out_acl_hint ), priority=4 , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;) table=3 (ls_out_acl_hint ), priority=2 , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;) table=3 (ls_out_acl_hint ), priority=1 , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;) - table=4 (ls_out_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(ct_commit_nat;) + table=4 (ls_out_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;) table=4 (ls_out_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;) table=4 (ls_out_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) table=4 (ls_out_acl ), priority=1 , match=(ip && ct.est && ct_label.blocked == 1), action=(reg0[[1]] = 1; next;) @@ -7909,15 +7933,15 @@ AT_CHECK([ovn-sbctl lflow-list | grep 'ls.*acl.*blocked' ], [0], [dnl table=7 (ls_in_acl_hint ), priority=4 , match=(!ct.new && ct.est && !ct.rpl && ct_mark.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;) table=7 (ls_in_acl_hint ), priority=2 , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;) table=7 (ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) - table=8 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) - table=8 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=8 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; next;) + table=8 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) table=8 (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=8 (ls_in_acl ), priority=1 , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;) table=3 (ls_out_acl_hint ), priority=6 , match=(!ct.new && ct.est && !ct.rpl && ct_mark.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;) table=3 (ls_out_acl_hint ), priority=4 , match=(!ct.new && ct.est && !ct.rpl && ct_mark.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;) table=3 (ls_out_acl_hint ), priority=2 , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;) table=3 (ls_out_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) - table=4 (ls_out_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) + table=4 (ls_out_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(next;) table=4 (ls_out_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;) table=4 (ls_out_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) table=4 (ls_out_acl ), priority=1 , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;) @@ -8437,3 +8461,156 @@ check_row_count sb:Chassis_Template_Var 0 AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD_NO_HV([ +AT_SETUP([Load balancer CT related backwards compatibility]) +AT_KEYWORDS([lb]) +ovn_start + +check ovn-nbctl \ + -- ls-add ls \ + -- lr-add lr -- set logical_router lr options:chassis=local \ + -- lb-add lb-test 192.168.0.1 192.168.1.10 \ + -- ls-lb-add ls lb-test \ + -- lr-lb-add lr lb-test + +m4_define([DUMP_FLOWS_SORTED], [sed 's/table=[[0-9]]\{1,2\}/table=?/' | sort]) + +AS_BOX([No chassis registered - CT related flows should be installed]) +check ovn-nbctl --wait=sb sync +ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows0 + +AT_CHECK([grep -e "lr_in_defrag" -e "lr_in_dnat" lflows0], [0], [dnl + table=? (lr_in_defrag ), priority=0 , match=(1), action=(next;) + table=? (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 192.168.0.1), action=(reg0 = 192.168.0.1; ct_dnat;) + table=? (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) + table=? (lr_in_dnat ), priority=0 , match=(1), action=(next;) + table=? (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 192.168.0.1 && ct_mark.natted == 1), action=(next;) + table=? (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 192.168.0.1), action=(ct_lb_mark(backends=192.168.1.10);) + table=? (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) + table=? (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) + table=? (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) +]) + +AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows0 | grep "priority=65532"], [0], [dnl + table=? (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) + table=? (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) + table=? (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) + table=? (ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) + table=? (ls_out_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) + table=? (ls_out_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;) + table=? (ls_out_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) + table=? (ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) + table=?(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) +]) + + +AS_BOX([Chassis registered that doesn't support CT related]) +check ovn-sbctl chassis-add hv geneve 127.0.0.1 +check ovn-nbctl --wait=sb sync +ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows1 + +AT_CHECK([grep -e "lr_in_defrag" -e "lr_in_dnat" lflows1], [0], [dnl + table=? (lr_in_defrag ), priority=0 , match=(1), action=(next;) + table=? (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 192.168.0.1), action=(reg0 = 192.168.0.1; ct_dnat;) + table=? (lr_in_dnat ), priority=0 , match=(1), action=(next;) + table=? (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 192.168.0.1 && ct_label.natted == 1), action=(next;) + table=? (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 192.168.0.1), action=(ct_lb(backends=192.168.1.10);) +]) + +check ovn-nbctl --wait=sb set logical_router lr options:lb_force_snat_ip="192.168.1.1" +AT_CHECK([ovn-sbctl lflow-list | grep lr_in_dnat], [0], [dnl + table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 192.168.0.1 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;) + table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 192.168.0.1), action=(flags.force_snat_for_lb = 1; ct_lb(backends=192.168.1.10);) + table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) +]) +check ovn-nbctl remove logical_router lr options lb_force_snat_ip + +check ovn-nbctl --wait=sb set load_balancer lb-test options:skip_snat="true" +AT_CHECK([ovn-sbctl lflow-list | grep lr_in_dnat], [0], [dnl + table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 192.168.0.1 && ct_label.natted == 1), action=(flags.skip_snat_for_lb = 1; next;) + table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 192.168.0.1), action=(flags.skip_snat_for_lb = 1; ct_lb(backends=192.168.1.10);) + table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) +]) +check ovn-nbctl remove load_balancer lb-test options skip_snat + +AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows1 | grep "priority=65532"], [0], [dnl + table=? (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(reg0[[17]] = 1; next;) + table=? (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) + table=? (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) + table=? (ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) + table=? (ls_out_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;) + table=? (ls_out_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;) + table=? (ls_out_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) + table=? (ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) + table=?(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) +]) + +AS_BOX([Chassis upgrades and supports CT related]) +check ovn-sbctl set chassis hv other_config:ct-no-masked-label=true +check ovn-sbctl set chassis hv other_config:ovn-ct-lb-related=true +check ovn-nbctl --wait=sb sync +ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows2 + +AT_CHECK([grep -e "lr_in_defrag" -e "lr_in_dnat" lflows2], [0], [dnl + table=? (lr_in_defrag ), priority=0 , match=(1), action=(next;) + table=? (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 192.168.0.1), action=(reg0 = 192.168.0.1; ct_dnat;) + table=? (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) + table=? (lr_in_dnat ), priority=0 , match=(1), action=(next;) + table=? (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 192.168.0.1 && ct_mark.natted == 1), action=(next;) + table=? (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 192.168.0.1), action=(ct_lb_mark(backends=192.168.1.10);) + table=? (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) + table=? (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) + table=? (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) +]) + +AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows2 | grep "priority=65532"], [0], [dnl + table=? (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;) + table=? (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;) + table=? (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) + table=? (ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) + table=? (ls_out_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;) + table=? (ls_out_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;) + table=? (ls_out_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) + table=? (ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) + table=?(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) +]) + +AT_CLEANUP +]) + +OVN_FOR_EACH_NORTHD_NO_HV([ +AT_SETUP([Chassis-feature compatibitility - remote chassis]) +ovn_start + +AS_BOX([Local chassis]) +check ovn-sbctl chassis-add hv1 geneve 127.0.0.1 \ + -- set chassis hv1 other_config:ct-no-masked-label=true \ + -- set chassis hv1 other_config:ovn-ct-lb-related=true \ + -- set chassis hv1 other_config:mac-binding-timestamp=true + +check ovn-nbctl --wait=sb sync + +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE debug/chassis-features-list], [0], [dnl +ct_no_masked_label: true +ct_lb_related: true +mac_binding_timestamp: true +]) + +AS_BOX([Remote chassis]) +check ovn-sbctl chassis-add hv2 geneve 127.0.0.2 \ + -- set chassis hv2 other_config:is-remote=true \ + -- set chassis hv2 other_config:ct-no-masked-label=false \ + -- set chassis hv2 other_config:ovn-ct-lb-related=false \ + -- set chassis hv2 other_config:mac-binding-timestamp=false + +check ovn-nbctl --wait=sb sync + +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE debug/chassis-features-list], [0], [dnl +ct_no_masked_label: true +ct_lb_related: true +mac_binding_timestamp: true +]) + +AT_CLEANUP +]) diff --git a/tests/ovn.at b/tests/ovn.at index ad2014de6..f77a4983d 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -4461,7 +4461,12 @@ for i in 1 2 3; do done # Gracefully terminate daemons -OVN_CLEANUP([hv1],[hv2],[vtep]) + +OVN_CLEANUP_SBOX([hv1]) +OVN_CLEANUP_SBOX([hv2]) +OVS_WAIT_UNTIL([test `as vtep ovs-vsctl list-ports vtep_bfd | wc -l` -eq 0]) +OVN_CLEANUP([vtep]) + OVN_CLEANUP_VSWITCH([hv3]) AT_CLEANUP @@ -25064,8 +25069,10 @@ OVN_FOR_EACH_NORTHD([ AT_SETUP([interconnection]) ovn_init_ic_db -n_az=5 -n_ts=5 +# The number needs to stay relatively low due to high memory consumption +# with address sanitizers enabled. +n_az=3 +n_ts=3 for i in `seq 1 $n_az`; do ovn_start az$i done @@ -28416,24 +28423,39 @@ wait_row_count Port_Binding 1 logical_port=lsp-cont1 chassis=$ch OVN_CLEANUP([hv1]) AT_CLEANUP +# TEST_LR_DROP_TRAFFIC_FOR_OWN_IPS [ DGP | GR ] # Test dropping traffic destined to router owned IPs. -OVN_FOR_EACH_NORTHD([ -AT_SETUP([gateway router drop traffic for own IPs]) +m4_define([TEST_LR_DROP_TRAFFIC_FOR_OWN_IPS], [ ovn_start -ovn-nbctl lr-add r1 -- set logical_router r1 options:chassis=hv1 -ovn-nbctl ls-add s1 - -# Connnect r1 to s1. -ovn-nbctl lrp-add r1 lrp-r1-s1 00:00:00:00:01:01 10.0.1.1/24 -ovn-nbctl lsp-add s1 lsp-s1-r1 -- set Logical_Switch_Port lsp-s1-r1 type=router \ - options:router-port=lrp-r1-s1 addresses=router - -# Create logical port p1 in s1 -ovn-nbctl lsp-add s1 p1 \ +ovn-nbctl lr-add r1 # Gateway router or LR with DGP on the ext side +ovn-nbctl ls-add ext # simulate external LS +ovn-nbctl ls-add s2 # simulate internal LS + +# Connnect r1 to ext. +ovn-nbctl lrp-add r1 lrp-r1-ext 00:00:00:00:01:01 10.0.1.1/24 +if test X"$1" = X"DGP"; then + ovn-nbctl lrp-set-gateway-chassis lrp-r1-ext hv1 1 +else + ovn-nbctl set logical_router r1 options:chassis=hv1 +fi +ovn-nbctl lsp-add ext lsp-ext-r1 -- set Logical_Switch_Port lsp-ext-r1 type=router \ + options:router-port=lrp-r1-ext addresses=router + +# Connnect r1 to s2. +ovn-nbctl lrp-add r1 lrp-r1-s2 00:00:00:00:02:01 10.0.2.1/24 +ovn-nbctl lsp-add s2 lsp-s2-r1 -- set Logical_Switch_Port lsp-s2-r1 type=router \ + options:router-port=lrp-r1-s2 addresses=router + +# Create logical port p1 in ext +ovn-nbctl lsp-add ext p1 \ -- lsp-set-addresses p1 "f0:00:00:00:01:02 10.0.1.2" \ -- lsp-set-port-security p1 "f0:00:00:00:01:02 10.0.1.2" +# Create logical port p2 in s2 +ovn-nbctl lsp-add s2 p2 \ +-- lsp-set-addresses p2 "f0:00:00:00:02:02 10.0.2.2" + # Create two hypervisor and create OVS ports corresponding to logical ports. net_add n1 @@ -28447,6 +28469,12 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \ options:rxq_pcap=hv1/vif1-rx.pcap \ ofport-request=1 +ovs-vsctl -- add-port br-int hv1-vif2 -- \ + set interface hv1-vif2 external-ids:iface-id=p2 \ + options:tx_pcap=hv1/vif2-tx.pcap \ + options:rxq_pcap=hv1/vif2-rx.pcap \ + ofport-request=2 + # Pre-populate the hypervisors' ARP tables so that we don't lose any # packets for ARP resolution (native tunneling doesn't queue packets # for ARP resolution). @@ -28457,9 +28485,10 @@ ovn-nbctl --wait=hv sync sw_key=$(ovn-sbctl --bare --columns tunnel_key list datapath_binding r1) +echo sw_key: $sw_key AT_CHECK([ovn-sbctl lflow-list | grep lr_in_arp_resolve | grep 10.0.1.1], [1], []) -# Send ip packets from p1 to lrp-r1-s1 +# Send ip packets from p1 to lrp-r1-ext src_mac="f00000000102" dst_mac="000000000101" src_ip=`ip_to_hex 10 0 1 2` @@ -28478,10 +28507,10 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=11, n_packets=1,.* ]) # Use the router IP as SNAT IP. -ovn-nbctl set logical_router r1 options:lb_force_snat_ip=10.0.1.1 +ovn-nbctl lr-nat-add r1 snat 10.0.1.1 10.8.8.0/24 ovn-nbctl --wait=hv sync -# Send ip packets from p1 to lrp-r1-s1 +# Send ip packets from p1 to lrp-r1-ext src_mac="f00000000102" dst_mac="000000000101" src_ip=`ip_to_hex 10 0 1 2` @@ -28496,11 +28525,53 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep "actions=controller" | grep ]) # The packet should've been dropped in the lr_in_arp_resolve stage. -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=25, n_packets=1,.* priority=2,ip,metadata=0x${sw_key},nw_dst=10.0.1.1 actions=drop" -c], [0], [dnl +if test X"$1" = X"DGP"; then + prio=150 + inport=reg14 + outport=reg15 +else + prio=2 +fi +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=25, n_packets=1,.* priority=$prio,ip,$inport.*$outport.*metadata=0x${sw_key},nw_dst=10.0.1.1 actions=drop" -c], [0], [dnl 1 ]) +# Send ip packets from p2 to lrp-r1-ext +src_mac="f00000000202" +dst_mac="000000000201" +src_ip=`ip_to_hex 10 0 2 2` +dst_ip=`ip_to_hex 10 0 1 1` +packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 +as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet + +# Still no packet-ins should reach ovn-controller. +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep "actions=controller" | grep -v n_packets=0 -c], [1], [dnl +0 +]) + +if test X"$1" = X"DGP"; then + # The packet dst should be resolved once for E/W centralized NAT purpose. + AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=25, n_packets=1,.* priority=100,reg0=0xa000101,reg15=.*metadata=0x${sw_key} actions=mod_dl_dst:00:00:00:00:01:01,resubmit" -c], [0], [dnl +1 +]) +fi + +# The packet should've been finally dropped in the lr_in_arp_resolve stage. +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=25, n_packets=2,.* priority=$prio,ip,$inport.*$outport.*metadata=0x${sw_key},nw_dst=10.0.1.1 actions=drop" -c], [0], [dnl +1 +]) OVN_CLEANUP([hv1]) +]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([gateway router drop traffic for own IPs]) +TEST_LR_DROP_TRAFFIC_FOR_OWN_IPS(GR) +AT_CLEANUP +]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([distributed gateway port drop traffic for own IPs]) +TEST_LR_DROP_TRAFFIC_FOR_OWN_IPS(DGP) AT_CLEANUP ]) diff --git a/tests/system-ovn.at b/tests/system-ovn.at index 99ad14aa5..1e6767846 100644 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -1618,8 +1618,8 @@ OVS_WAIT_UNTIL([ ovn-nbctl --reject lb-add lb3 30.0.0.10:80 "" ovn-nbctl ls-lb-add foo lb3 # Filter reset segments -NS_CHECK_EXEC([foo1], [tcpdump -c 1 -neei foo1 ip[[33:1]]=0x14 > rst.pcap 2>/dev/null &]) -sleep 1 +NS_CHECK_EXEC([foo1], [tcpdump -l -c 1 -neei foo1 ip[[33:1]]=0x14 > rst.pcap 2>tcpdump_err &]) +OVS_WAIT_UNTIL([grep "listening" tcpdump_err]) NS_CHECK_EXEC([foo1], [wget -q 30.0.0.10],[4]) OVS_WAIT_UNTIL([ @@ -1734,13 +1734,11 @@ OVS_START_L7([bar2], [http6]) OVS_START_L7([bar3], [http6]) dnl Should work with the virtual IP fd03::1 address through NAT -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([foo1], [wget http://[[fd03::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log || (ovs-ofctl -O OpenFlow13 dump-flows br-int && false)]) +OVS_WAIT_FOR_OUTPUT([ +for i in `seq 1 10`; do + NS_EXEC([foo1], [wget http://[[fd03::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log || (ovs-ofctl -O OpenFlow13 dump-flows br-int && false)]) done - -dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::1) | grep -v fe80 | \ +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::1) | grep -v fe80 | \ sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=fd01::2,dst=fd03::1,sport=,dport=),reply=(src=fd02::2,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=fd01::2,dst=fd03::1,sport=,dport=),reply=(src=fd02::3,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) @@ -1748,27 +1746,25 @@ tcp,orig=(src=fd01::2,dst=fd03::1,sport=,dport=),reply=(src=fd ]) dnl Should work with the virtual IP fd03::3 address through NAT -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([foo1], [wget http://[[fd03::3]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +OVS_WAIT_FOR_OUTPUT([ +for i in `seq 1 10`; do + NS_EXEC([foo1], [wget http://[[fd03::3]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done - dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::3) | grep -v fe80 | \ +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::3) | grep -v fe80 | \ sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=fd01::2,dst=fd03::3,sport=,dport=),reply=(src=fd02::2,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=fd01::2,dst=fd03::3,sport=,dport=),reply=(src=fd02::3,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=fd01::2,dst=fd03::3,sport=,dport=),reply=(src=fd02::4,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) ]) +OVS_WAIT_FOR_OUTPUT([ dnl Test load-balancing that includes L4 ports in NAT. -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([foo1], [wget http://[[fd03::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +for i in `seq 1 10`; do + NS_EXEC([foo1], [wget http://[[fd03::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done - dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::2) | grep -v fe80 | \ +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::2) | grep -v fe80 | \ sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=fd01::2,dst=fd03::2,sport=,dport=),reply=(src=fd02::2,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=fd01::2,dst=fd03::2,sport=,dport=),reply=(src=fd02::3,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) @@ -1784,14 +1780,14 @@ OVS_WAIT_UNTIL([ AT_CHECK([ovs-appctl dpctl/flush-conntrack]) +OVS_WAIT_FOR_OUTPUT([ dnl Test load-balancing that includes L4 ports in NAT. -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([foo1], [wget http://[[fd03::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +for i in `seq 1 10`; do + NS_EXEC([foo1], [wget http://[[fd03::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::2) | grep -v fe80 | \ +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::2) | grep -v fe80 | \ sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=fd01::2,dst=fd03::2,sport=,dport=),reply=(src=fd02::2,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=fd01::2,dst=fd03::2,sport=,dport=),reply=(src=fd02::3,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) @@ -1933,13 +1929,13 @@ OVS_START_L7([foo3], [http]) OVS_START_L7([foo4], [http]) dnl Should work with the virtual IP address through NAT -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +OVS_WAIT_FOR_OUTPUT([ +for i in `seq 1 10`; do + NS_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \ +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \ sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=,dport=),reply=(src=192.168.1.3,dst=192.168.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=,dport=),reply=(src=192.168.1.4,dst=192.168.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) @@ -1947,20 +1943,19 @@ tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=,dport=),reply=(s ]) dnl Test load-balancing that includes L4 ports in NAT. -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +OVS_WAIT_FOR_OUTPUT([ +for i in `seq 1 10`; do + NS_EXEC([foo1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \ +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \ sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=,dport=),reply=(src=192.168.1.3,dst=192.168.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=,dport=),reply=(src=192.168.1.4,dst=192.168.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=,dport=),reply=(src=192.168.1.5,dst=192.168.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) ]) - OVS_APP_EXIT_AND_WAIT([ovn-controller]) as ovn-sb @@ -2044,13 +2039,13 @@ OVS_START_L7([foo3], [http6]) OVS_START_L7([foo4], [http6]) dnl Should work with the virtual IP address through NAT -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([foo1], [wget http://[[fd03::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +OVS_WAIT_FOR_OUTPUT([ +for i in `seq 1 10`; do + NS_EXEC([foo1], [wget http://[[fd03::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::1) | grep -v fe80 | \ +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::1) | grep -v fe80 | \ sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=fd01::2,dst=fd03::1,sport=,dport=),reply=(src=fd01::3,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=fd01::2,dst=fd03::1,sport=,dport=),reply=(src=fd01::4,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) @@ -2058,20 +2053,19 @@ tcp,orig=(src=fd01::2,dst=fd03::1,sport=,dport=),reply=(src=fd ]) dnl Test load-balancing that includes L4 ports in NAT. -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([foo1], [wget http://[[fd03::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +OVS_WAIT_FOR_OUTPUT([ +for i in `seq 1 10`; do + NS_EXEC([foo1], [wget http://[[fd03::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::2) | grep -v fe80 | \ +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::2) | grep -v fe80 | \ sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=fd01::2,dst=fd03::2,sport=,dport=),reply=(src=fd01::3,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=fd01::2,dst=fd03::2,sport=,dport=),reply=(src=fd01::4,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=fd01::2,dst=fd03::2,sport=,dport=),reply=(src=fd01::5,dst=fd01::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) ]) - OVS_APP_EXIT_AND_WAIT([ovn-controller]) as ovn-sb @@ -2199,27 +2193,27 @@ OVS_START_L7([bar1], [http]) check ovs-appctl dpctl/flush-conntrack dnl Should work with the virtual IP address through NAT -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +OVS_WAIT_FOR_OUTPUT([ +for i in `seq 1 10`; do + NS_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=,dport=),reply=(src=192.168.1.2,dst=172.16.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=,dport=),reply=(src=192.168.2.2,dst=172.16.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) ]) check ovs-appctl dpctl/flush-conntrack +OVS_WAIT_FOR_OUTPUT([ dnl Test load-balancing that includes L4 ports in NAT. -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +for i in `seq 1 10`; do + NS_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=,dport=),reply=(src=192.168.1.2,dst=172.16.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=,dport=),reply=(src=192.168.2.2,dst=172.16.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) @@ -2256,23 +2250,23 @@ OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=43 | \ grep 'nat(src=20.0.0.2)']) check ovs-appctl dpctl/flush-conntrack +exp_ct1="tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=,dport=),reply=(src=192.168.1.2,dst=172.16.1.2,sport=,dport=),zone=,mark=10,protoinfo=(state=) +tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=,dport=),reply=(src=192.168.2.2,dst=172.16.1.2,sport=,dport=),zone=,mark=10,protoinfo=(state=)" +exp_ct2="tcp,orig=(src=172.16.1.2,dst=192.168.1.2,sport=,dport=),reply=(src=192.168.1.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=) +tcp,orig=(src=172.16.1.2,dst=192.168.2.2,sport=,dport=),reply=(src=192.168.2.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=)" + dnl Test load-balancing that includes L4 ports in NAT. -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ +for i in `seq 1 10`; do + NS_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | -sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=,dport=),reply=(src=192.168.1.2,dst=172.16.1.2,sport=,dport=),zone=,mark=10,protoinfo=(state=) -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=,dport=),reply=(src=192.168.2.2,dst=172.16.1.2,sport=,dport=),zone=,mark=10,protoinfo=(state=) -]) +ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | sed -e 's/zone=[[0-9]]*/zone=/') +ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) | sed -e 's/zone=[[0-9]]*/zone=/') -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) | -sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -tcp,orig=(src=172.16.1.2,dst=192.168.1.2,sport=,dport=),reply=(src=192.168.1.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=) -tcp,orig=(src=172.16.1.2,dst=192.168.2.2,sport=,dport=),reply=(src=192.168.2.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=) +test "x$ct1 = x$exp_ct1" && test "x$ct2 = x$exp_ct2" +], [0], [dnl ]) OVS_WAIT_UNTIL([check_est_flows], [check established flows]) @@ -2298,22 +2292,21 @@ rm -f wget*.log check ovs-appctl dpctl/flush-conntrack dnl Test load-balancing that includes L4 ports in NAT. -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +exp_ct1="tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=,dport=),reply=(src=192.168.1.2,dst=172.16.1.2,sport=,dport=),zone=,mark=10,protoinfo=(state=) +tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=,dport=),reply=(src=192.168.2.2,dst=172.16.1.2,sport=,dport=),zone=,mark=10,protoinfo=(state=)" +exp_ct2="tcp,orig=(src=172.16.1.2,dst=192.168.1.2,sport=,dport=),reply=(src=192.168.1.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=) +tcp,orig=(src=172.16.1.2,dst=192.168.2.2,sport=,dport=),reply=(src=192.168.2.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=)" + +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ +for i in `seq 1 10`; do + NS_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | -sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=,dport=),reply=(src=192.168.1.2,dst=172.16.1.2,sport=,dport=),zone=,mark=10,protoinfo=(state=) -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=,dport=),reply=(src=192.168.2.2,dst=172.16.1.2,sport=,dport=),zone=,mark=10,protoinfo=(state=) -]) - -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) | -sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -tcp,orig=(src=172.16.1.2,dst=192.168.1.2,sport=,dport=),reply=(src=192.168.1.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=) -tcp,orig=(src=172.16.1.2,dst=192.168.2.2,sport=,dport=),reply=(src=192.168.2.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=) +ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | sed -e 's/zone=[[0-9]]*/zone=/') +ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) | sed -e 's/zone=[[0-9]]*/zone=/') +test "x$ct1 = x$exp_ct1" && test "x$ct2 = x$exp_ct2" +], [0], [dnl ]) OVS_WAIT_UNTIL([check_est_flows], [check established flows]) @@ -2549,26 +2542,26 @@ OVS_START_L7([foo1], [http6]) OVS_START_L7([bar1], [http6]) dnl Should work with the virtual IP address through NAT -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([alice1], [wget http://[[fd30::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ +for i in `seq 1 10`; do + NS_EXEC([alice1], [wget http://[[fd30::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 | +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=fd72::2,dst=fd30::1,sport=,dport=),reply=(src=fd11::2,dst=fd72::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=fd72::2,dst=fd30::1,sport=,dport=),reply=(src=fd12::2,dst=fd72::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) ]) dnl Test load-balancing that includes L4 ports in NAT. -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([alice1], [wget http://[[fd30::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ +for i in `seq 1 10`; do + NS_EXEC([alice1], [wget http://[[fd30::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::2) | grep -v fe80 | +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::2) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=fd72::2,dst=fd30::2,sport=,dport=),reply=(src=fd11::2,dst=fd72::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=fd72::2,dst=fd30::2,sport=,dport=),reply=(src=fd12::2,dst=fd72::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) @@ -2727,24 +2720,24 @@ OVS_START_L7([foo1], [http]) OVS_START_L7([bar1], [http]) dnl Should work with the virtual IP address through NAT -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +exp_ct1="tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=,dport=),reply=(src=192.168.1.2,dst=172.16.1.3,sport=,dport=),zone=,mark=10,protoinfo=(state=) +tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=,dport=),reply=(src=192.168.2.2,dst=172.16.1.3,sport=,dport=),zone=,mark=10,protoinfo=(state=)" +exp_ct2="tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=,dport=),reply=(src=192.168.1.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=) +tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=,dport=),reply=(src=192.168.2.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=)" + +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ +for i in `seq 1 10`; do + NS_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | -sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=,dport=),reply=(src=192.168.1.2,dst=172.16.1.3,sport=,dport=),zone=,mark=10,protoinfo=(state=) -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=,dport=),reply=(src=192.168.2.2,dst=172.16.1.3,sport=,dport=),zone=,mark=10,protoinfo=(state=) -]) - +ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | sed -e 's/zone=[[0-9]]*/zone=/') dnl Force SNAT should have worked. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) | -sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=,dport=),reply=(src=192.168.1.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=) -tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=,dport=),reply=(src=192.168.2.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=) +ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) | sed -e 's/zone=[[0-9]]*/zone=/') +test "x$ct1 = x$exp_ct1" && test "x$ct2 = x$exp_ct2" +], [0], [dnl ]) + OVS_APP_EXIT_AND_WAIT([ovn-controller]) as ovn-sb @@ -2900,24 +2893,24 @@ OVS_START_L7([foo1], [http6]) OVS_START_L7([bar1], [http6]) dnl Should work with the virtual IP address through NAT -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([alice1], [wget http://[[fd30::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +exp_ct1="tcp,orig=(src=fd72::3,dst=fd30::1,sport=,dport=),reply=(src=fd11::2,dst=fd72::3,sport=,dport=),zone=,mark=10,protoinfo=(state=) +tcp,orig=(src=fd72::3,dst=fd30::1,sport=,dport=),reply=(src=fd12::2,dst=fd72::3,sport=,dport=),zone=,mark=10,protoinfo=(state=) +exp_ct2=tcp,orig=(src=fd72::3,dst=fd11::2,sport=,dport=),reply=(src=fd11::2,dst=fd20::2,sport=,dport=),zone=,protoinfo=(state=) +tcp,orig=(src=fd72::3,dst=fd12::2,sport=,dport=),reply=(src=fd12::2,dst=fd20::2,sport=,dport=),zone=,protoinfo=(state=)" + +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ +for i in `seq 1 10`; do + NS_EXEC([alice1], [wget http://[[fd30::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 | -sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -tcp,orig=(src=fd72::3,dst=fd30::1,sport=,dport=),reply=(src=fd11::2,dst=fd72::3,sport=,dport=),zone=,mark=10,protoinfo=(state=) -tcp,orig=(src=fd72::3,dst=fd30::1,sport=,dport=),reply=(src=fd12::2,dst=fd72::3,sport=,dport=),zone=,mark=10,protoinfo=(state=) -]) - +ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=/') dnl Force SNAT should have worked. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::2) | grep -v fe80 | -sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -tcp,orig=(src=fd72::3,dst=fd11::2,sport=,dport=),reply=(src=fd11::2,dst=fd20::2,sport=,dport=),zone=,protoinfo=(state=) -tcp,orig=(src=fd72::3,dst=fd12::2,sport=,dport=),reply=(src=fd12::2,dst=fd20::2,sport=,dport=),zone=,protoinfo=(state=) +ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::2) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=/') +test "x$ct1 = x$exp_ct1" && test "x$ct2 = x$exp_ct2" +], [0], [dnl ]) + OVS_APP_EXIT_AND_WAIT([ovn-controller]) as ovn-sb @@ -3111,39 +3104,32 @@ OVS_START_L7([foo16], [http6]) OVS_START_L7([bar16], [http6]) dnl Should work with the virtual IP address through NAT -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) -done - -for i in `seq 1 20`; do - echo Request ${i}_6 - NS_CHECK_EXEC([alice16], [wget http://[[fd30::1]] -t 5 -T 1 --retry-connrefused -v -o wget${i}_6.log]) +exp_ct1="tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=,dport=),reply=(src=192.168.1.2,dst=172.16.1.3,sport=,dport=),zone=,mark=10,protoinfo=(state=) +tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=,dport=),reply=(src=192.168.2.2,dst=172.16.1.3,sport=,dport=),zone=,mark=10,protoinfo=(state=)" +exp_ct2="tcp,orig=(src=fd72::3,dst=fd30::1,sport=,dport=),reply=(src=fd11::2,dst=fd72::3,sport=,dport=),zone=,mark=10,protoinfo=(state=) +tcp,orig=(src=fd72::3,dst=fd30::1,sport=,dport=),reply=(src=fd12::2,dst=fd72::3,sport=,dport=),zone=,mark=10,protoinfo=(state=)" +exp_ct3="tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=,dport=),reply=(src=192.168.1.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=) +tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=,dport=),reply=(src=192.168.2.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=)" +exp_ct4="tcp,orig=(src=fd72::3,dst=fd11::2,sport=,dport=),reply=(src=fd11::2,dst=fd20::2,sport=,dport=),zone=,protoinfo=(state=) +tcp,orig=(src=fd72::3,dst=fd12::2,sport=,dport=),reply=(src=fd12::2,dst=fd20::2,sport=,dport=),zone=,protoinfo=(state=)" + +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ +for i in `seq 1 10`; do + NS_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) + NS_EXEC([alice16], [wget http://[[fd30::1]] -t 5 -T 1 --retry-connrefused -v -o wget${i}_6.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | -sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=,dport=),reply=(src=192.168.1.2,dst=172.16.1.3,sport=,dport=),zone=,mark=10,protoinfo=(state=) -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=,dport=),reply=(src=192.168.2.2,dst=172.16.1.3,sport=,dport=),zone=,mark=10,protoinfo=(state=) -]) -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 | -sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -tcp,orig=(src=fd72::3,dst=fd30::1,sport=,dport=),reply=(src=fd11::2,dst=fd72::3,sport=,dport=),zone=,mark=10,protoinfo=(state=) -tcp,orig=(src=fd72::3,dst=fd30::1,sport=,dport=),reply=(src=fd12::2,dst=fd72::3,sport=,dport=),zone=,mark=10,protoinfo=(state=) -]) +ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | sed -e 's/zone=[[0-9]]*/zone=/') +ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=/') dnl Force SNAT should have worked. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) | -sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=,dport=),reply=(src=192.168.1.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=) -tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=,dport=),reply=(src=192.168.2.2,dst=20.0.0.2,sport=,dport=),zone=,protoinfo=(state=) -]) -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::2) | grep -v fe80 | -sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -tcp,orig=(src=fd72::3,dst=fd11::2,sport=,dport=),reply=(src=fd11::2,dst=fd20::2,sport=,dport=),zone=,protoinfo=(state=) -tcp,orig=(src=fd72::3,dst=fd12::2,sport=,dport=),reply=(src=fd12::2,dst=fd20::2,sport=,dport=),zone=,protoinfo=(state=) +ct3=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) | sed -e 's/zone=[[0-9]]*/zone=/') +ct4=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::2) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=/') +test "x$ct1 = x$exp_ct1" && test "x$ct2 = x$exp_ct2" && test "x$ct3 = x$exp_ct3" && test "x$ct4 = x$exp_ct4" +], [0], [dnl ]) + OVS_APP_EXIT_AND_WAIT([ovn-controller]) as ovn-sb @@ -3262,26 +3248,26 @@ OVS_START_L7([foo1], [http]) OVS_START_L7([bar1], [http]) dnl Should work with the virtual IP address through NAT -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([alice1], [wget 172.16.1.10 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ +for i in `seq 1 10`; do + NS_EXEC([alice1], [wget 172.16.1.10 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.10) | +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.10) | sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=,dport=),reply=(src=192.168.1.2,dst=172.16.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=,dport=),reply=(src=192.168.2.2,dst=172.16.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) ]) dnl Test load-balancing that includes L4 ports in NAT. -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([alice1], [wget 172.16.1.11:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ +for i in `seq 1 10`; do + NS_EXEC([alice1], [wget 172.16.1.11:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.11) | +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.11) | sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=,dport=),reply=(src=192.168.1.2,dst=172.16.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=,dport=),reply=(src=192.168.2.2,dst=172.16.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) @@ -3405,26 +3391,26 @@ OVS_START_L7([foo1], [http6]) OVS_START_L7([bar1], [http6]) dnl Should work with the virtual IP address through NAT -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([alice1], [wget http://[[fd72::10]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ +for i in `seq 1 10`; do + NS_EXEC([alice1], [wget http://[[fd72::10]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd72::10) | grep -v fe80 | +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd72::10) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=fd72::2,dst=fd72::10,sport=,dport=),reply=(src=fd01::2,dst=fd72::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=fd72::2,dst=fd72::10,sport=,dport=),reply=(src=fd02::2,dst=fd72::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) ]) dnl Test load-balancing that includes L4 ports in NAT. -for i in `seq 1 20`; do - echo Request $i - NS_CHECK_EXEC([alice1], [wget http://[[fd72::11]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) +OVS_WAIT_FOR_OUTPUT_UNQUOTED([ +for i in `seq 1 10`; do + NS_EXEC([alice1], [wget http://[[fd72::11]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd72::11) | grep -v fe80 | +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd72::11) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=fd72::2,dst=fd72::11,sport=,dport=),reply=(src=fd01::2,dst=fd72::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=fd72::2,dst=fd72::11,sport=,dport=),reply=(src=fd02::2,dst=fd72::2,sport=,dport=),zone=,mark=2,protoinfo=(state=) @@ -3598,8 +3584,8 @@ icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=,type=8,code=0),reply=(src ]) # Try to ping external network -NS_CHECK_EXEC([ext-net], [tcpdump -n -c 3 -i ext-veth dst 172.16.1.3 and icmp > ext-net.pcap &]) -sleep 1 +NS_CHECK_EXEC([ext-net], [tcpdump -l -n -c 3 -i ext-veth dst 172.16.1.3 and icmp > ext-net.pcap 2>tcpdump_err &]) +OVS_WAIT_UNTIL([grep "listening" tcpdump_err]) AT_CHECK([ovn-nbctl lr-nat-del R1 snat]) NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.1 | FORMAT_PING], \ [0], [dnl @@ -4507,17 +4493,15 @@ OVS_WAIT_UNTIL( [ovn-sbctl dump-flows sw0 | grep ct_lb_mark | grep priority=120 | grep "ip4.dst == 10.0.0.10" > lflows.txt test 1 = `cat lflows.txt | grep "ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80)" | wc -l`] ) - # From sw0-p2 send traffic to vip - 10.0.0.10 -for i in `seq 1 20`; do - echo Request $i - ovn-sbctl list service_monitor - NS_CHECK_EXEC([sw0-p2], [wget 10.0.0.10 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) -done +#dnl Each server should have at least one connection. +OVS_WAIT_FOR_OUTPUT([ + for i in `seq 1 10`; do + NS_EXEC([sw0-p2], [wget 10.0.0.10 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) + done -dnl Each server should have at least one connection. -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.0.0.10) | \ -sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl + ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.0.0.10) | \ + sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl tcp,orig=(src=10.0.0.4,dst=10.0.0.10,sport=,dport=),reply=(src=10.0.0.3,dst=10.0.0.4,sport=,dport=),zone=,mark=2,protoinfo=(state=) tcp,orig=(src=10.0.0.4,dst=10.0.0.10,sport=,dport=),reply=(src=20.0.0.3,dst=10.0.0.4,sport=,dport=),zone=,mark=2,protoinfo=(state=) ]) @@ -4649,10 +4633,12 @@ ovn-nbctl lb-add lb-ipv4-tcp 88.88.88.88:8080 42.42.42.1:4041 tcp ovn-nbctl lb-add lb-ipv4-tcp-dup 88.88.88.89:8080 42.42.42.1:4041 tcp ovn-nbctl lb-add lb-ipv4-udp 88.88.88.88:4040 42.42.42.1:2021 udp ovn-nbctl lb-add lb-ipv4-udp-dup 88.88.88.89:4040 42.42.42.1:2021 udp +ovn-nbctl lb-add lb-ipv4 88.88.88.90 42.42.42.1 ovn-nbctl ls-lb-add sw lb-ipv4-tcp ovn-nbctl ls-lb-add sw lb-ipv4-tcp-dup ovn-nbctl ls-lb-add sw lb-ipv4-udp ovn-nbctl ls-lb-add sw lb-ipv4-udp-dup +ovn-nbctl ls-lb-add sw lb-ipv4 ovn-nbctl lr-add rtr ovn-nbctl lrp-add rtr rtr-sw 00:00:00:00:01:00 42.42.42.254/24 @@ -4668,28 +4654,39 @@ ADD_VETH(lsp, lsp, br-int, "42.42.42.1/24", "00:00:00:00:00:01", \ ovn-nbctl --wait=hv -t 3 sync # Start IPv4 TCP server on lsp. -NS_CHECK_EXEC([lsp], [timeout 2s nc -k -l 42.42.42.1 4041 &], [0]) +NETNS_DAEMONIZE([lsp], [nc -l -k 42.42.42.1 4041], [lsp0.pid]) # Check that IPv4 TCP hairpin connection succeeds on both VIPs. NS_CHECK_EXEC([lsp], [nc 88.88.88.88 8080 -z], [0], [ignore], [ignore]) NS_CHECK_EXEC([lsp], [nc 88.88.88.89 8080 -z], [0], [ignore], [ignore]) +NS_CHECK_EXEC([lsp], [nc 88.88.88.90 4041 -z], [0], [ignore], [ignore]) # Capture IPv4 UDP hairpinned packets. filter="dst 42.42.42.1 and dst port 2021 and udp" -NS_CHECK_EXEC([lsp], [tcpdump -nn -c 2 -i lsp ${filter} > lsp.pcap &]) - -sleep 1 +NS_CHECK_EXEC([lsp], [tcpdump -l -nn -c 3 -i lsp ${filter} > lsp.pcap 2>tcpdump_err &]) +OVS_WAIT_UNTIL([grep "listening" tcpdump_err]) # Generate IPv4 UDP hairpin traffic. NS_CHECK_EXEC([lsp], [echo a | nc -u 88.88.88.88 4040 &], [0]) NS_CHECK_EXEC([lsp], [echo a | nc -u 88.88.88.89 4040 &], [0]) +NS_CHECK_EXEC([lsp], [echo a | nc -u 88.88.88.90 2021 &], [0]) # Check hairpin traffic. OVS_WAIT_UNTIL([ total_pkts=$(cat lsp.pcap | wc -l) - test "${total_pkts}" = "2" + test "${total_pkts}" = "3" ]) +ovn-nbctl pg-add pg0 lsp +ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1004 "ip4 && ip4.dst == 10.0.0.2" drop +ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip4 && tcp" allow-related +ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip4 && udp" allow +ovn-nbctl --wait=hv sync + +## Check that IPv4 TCP hairpin connection succeeds on both VIPs. +NS_CHECK_EXEC([lsp], [nc 88.88.88.88 8080 -z], [0], [ignore], [ignore]) +NS_CHECK_EXEC([lsp], [nc 88.88.88.89 8080 -z], [0], [ignore], [ignore]) + OVS_APP_EXIT_AND_WAIT([ovn-controller]) as ovn-sb @@ -4736,10 +4733,12 @@ ovn-nbctl lb-add lb-ipv6-tcp [[8800::0088]]:8080 [[4200::1]]:4041 tcp ovn-nbctl lb-add lb-ipv6-tcp-dup [[8800::0089]]:8080 [[4200::1]]:4041 tcp ovn-nbctl lb-add lb-ipv6-udp [[8800::0088]]:4040 [[4200::1]]:2021 udp ovn-nbctl lb-add lb-ipv6-udp-dup [[8800::0089]]:4040 [[4200::1]]:2021 udp +ovn-nbctl lb-add lb-ipv6 8800::0090 4200::1 ovn-nbctl ls-lb-add sw lb-ipv6-tcp ovn-nbctl ls-lb-add sw lb-ipv6-tcp-dup ovn-nbctl ls-lb-add sw lb-ipv6-udp ovn-nbctl ls-lb-add sw lb-ipv6-udp-dup +ovn-nbctl ls-lb-add sw lb-ipv6 ovn-nbctl lr-add rtr ovn-nbctl lrp-add rtr rtr-sw 00:00:00:00:01:00 4200::00ff/64 @@ -4754,28 +4753,39 @@ OVS_WAIT_UNTIL([test "$(ip netns exec lsp ip a | grep 4200::1 | grep tentative)" ovn-nbctl --wait=hv -t 3 sync # Start IPv6 TCP server on lsp. -NS_CHECK_EXEC([lsp], [timeout 2s nc -k -l 4200::1 4041 &], [0]) +NETNS_DAEMONIZE([lsp], [nc -l -k 4200::1 4041], [lsp0.pid]) # Check that IPv6 TCP hairpin connection succeeds on both VIPs. NS_CHECK_EXEC([lsp], [nc 8800::0088 8080 -z], [0], [ignore], [ignore]) NS_CHECK_EXEC([lsp], [nc 8800::0089 8080 -z], [0], [ignore], [ignore]) +NS_CHECK_EXEC([lsp], [nc 8800::0090 4041 -z], [0], [ignore], [ignore]) # Capture IPv6 UDP hairpinned packets. filter="dst 4200::1 and dst port 2021 and udp" -NS_CHECK_EXEC([lsp], [tcpdump -nn -c 2 -i lsp $filter > lsp.pcap &]) - -sleep 1 +NS_CHECK_EXEC([lsp], [tcpdump -l -nn -c 3 -i lsp $filter > lsp.pcap 2>tcpdump_err &]) +OVS_WAIT_UNTIL([grep "listening" tcpdump_err]) # Generate IPv6 UDP hairpin traffic. NS_CHECK_EXEC([lsp], [echo a | nc -u 8800::0088 4040 &], [0]) NS_CHECK_EXEC([lsp], [echo a | nc -u 8800::0089 4040 &], [0]) +NS_CHECK_EXEC([lsp], [echo a | nc -u 8800::0090 2021 &], [0]) # Check hairpin traffic. OVS_WAIT_UNTIL([ total_pkts=$(cat lsp.pcap | wc -l) - test "${total_pkts}" = "2" + test "${total_pkts}" = "3" ]) +ovn-nbctl pg-add pg0 lsp +ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip6 && tcp" allow-related +ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip6 && udp" allow +ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1000 "ip6" drop +ovn-nbctl --wait=hv sync + +# Check that IPv6 TCP hairpin connection succeeds on both VIPs. +NS_CHECK_EXEC([lsp], [nc 8800::0088 8080 -z], [0], [ignore], [ignore]) +NS_CHECK_EXEC([lsp], [nc 8800::0089 8080 -z], [0], [ignore], [ignore]) + OVS_APP_EXIT_AND_WAIT([ovn-controller]) as ovn-sb @@ -4938,7 +4948,7 @@ OVS_WAIT_UNTIL([ ip netns exec sw0-p1-rej nc -u 10.0.0.4 90 < foo c=$(cat sw0-p1-rej-icmp.pcap | grep \ "10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 90 unreachable" | uniq | wc -l) - test $c -eq 1 + test $c -ge 1 ]) rm -f *.pcap @@ -4950,7 +4960,7 @@ OVS_WAIT_UNTIL([ ip netns exec sw0-p1-rej nc -u 10.0.0.4 94 < foo c=$(cat sw0-p1-rej-icmp.pcap | grep \ "10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 94 unreachable" | uniq | wc -l) - test $c -eq 1 + test $c -ge 1 ]) # Now test for IPv6 UDP. @@ -4962,7 +4972,7 @@ OVS_WAIT_UNTIL([ c=$(cat sw0-p2-rej-icmp6.pcap | grep \ "IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \ aef0::3 udp port 90" | uniq | wc -l) - test $c -eq 1 + test $c -ge 1 ]) rm -f *.pcap @@ -4975,7 +4985,7 @@ OVS_WAIT_UNTIL([ c=$(cat sw0-p2-rej-icmp6.pcap | grep \ "IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \ aef0::3 udp port 94" | uniq | wc -l) - test $c -eq 1 + test $c -ge 1 ]) # Delete all the ACLs of pg0 and add the ACL with a generic match with reject action. @@ -5000,7 +5010,7 @@ OVS_WAIT_UNTIL([ ip netns exec sw0-p1-rej nc -u 10.0.0.4 90 < foo c=$(cat sw0-p1-rej-icmp.pcap | grep \ "10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 90 unreachable" | uniq | wc -l) - test $c -eq 1 + test $c -ge 1 ]) rm -f *.pcap @@ -5012,7 +5022,7 @@ OVS_WAIT_UNTIL([ c=$(cat sw0-p2-rej-icmp6.pcap | grep \ "IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \ aef0::3 udp port 90" | uniq | wc -l) - test $c -eq 1 + test $c -ge 1 ]) @@ -5179,7 +5189,7 @@ OVS_WAIT_UNTIL([ ip netns exec sw0-p1-rej nc -u 10.0.0.4 90 < foo c=$(cat sw0-p1-rej-icmp.pcap | grep \ "10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 90 unreachable" | uniq | wc -l) - test $c -eq 1 + test $c -ge 1 ]) rm -f *.pcap @@ -5191,7 +5201,7 @@ OVS_WAIT_UNTIL([ ip netns exec sw0-p1-rej nc -u 10.0.0.4 94 < foo c=$(cat sw0-p1-rej-icmp.pcap | grep \ "10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 94 unreachable" | uniq | wc -l) - test $c -eq 1 + test $c -ge 1 ]) # Now test for IPv6 UDP. @@ -5203,7 +5213,7 @@ OVS_WAIT_UNTIL([ c=$(cat sw0-p2-rej-icmp6.pcap | grep \ "IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \ aef0::3 udp port 90" | uniq | wc -l) - test $c -eq 1 + test $c -ge 1 ]) rm -f *.pcap @@ -5216,7 +5226,7 @@ OVS_WAIT_UNTIL([ c=$(cat sw0-p2-rej-icmp6.pcap | grep \ "IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \ aef0::3 udp port 94" | uniq | wc -l) - test $c -eq 1 + test $c -ge 1 ]) # Delete all the ACLs of pg0 and add the ACL with a generic match with reject action. @@ -5241,7 +5251,7 @@ OVS_WAIT_UNTIL([ ip netns exec sw0-p1-rej nc -u 10.0.0.4 90 < foo c=$(cat sw0-p1-rej-icmp.pcap | grep \ "10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 90 unreachable" | uniq | wc -l) - test $c -eq 1 + test $c -ge 1 ]) rm -f *.pcap @@ -5253,7 +5263,7 @@ OVS_WAIT_UNTIL([ c=$(cat sw0-p2-rej-icmp6.pcap | grep \ "IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \ aef0::3 udp port 90" | uniq | wc -l) - test $c -eq 1 + test $c -ge 1 ]) @@ -9277,13 +9287,15 @@ test_related_traffic() { check ovs-appctl dpctl/flush-conntrack - NETNS_DAEMONIZE([client], [tcpdump -U -i client -w client.pcap], [tcpdump0.pid]) - NETNS_DAEMONIZE([server], [tcpdump -U -i server -w server.pcap], [tcpdump1.pid]) + NETNS_DAEMONIZE([client], [tcpdump -l -U -i client -w client.pcap 2>client_err], [tcpdump0.pid]) + NETNS_DAEMONIZE([server], [tcpdump -l -U -i server -w server.pcap 2>server_err], [tcpdump1.pid]) # Setup a dummy UDP listeners so we don't get "port unreachable". NETNS_DAEMONIZE([client], [nc -l -u 1], [nc0.pid]) NETNS_DAEMONIZE([server], [nc -l -u 2], [nc1.pid]) - sleep 1 + + OVS_WAIT_UNTIL([grep "listening" client_err]) + OVS_WAIT_UNTIL([grep "listening" server_err]) # Send UDP client -> server check ovs-ofctl packet-out br-int "in_port=ovs-client,packet=$client_udp,actions=resubmit(,0)" @@ -9479,7 +9491,8 @@ name: 'vport' value: '666' # Start IPv4 TCP server on vm1. NETNS_DAEMONIZE([vm1], [nc -k -l 42.42.42.2 4242], [nc-vm1.pid]) -# Make sure connecting to the VIP works. +# Make sure connecting to the VIP works (hairpin, via ls and via lr). +NS_CHECK_EXEC([vm1], [nc 66.66.66.66 666 -z], [0], [ignore], [ignore]) NS_CHECK_EXEC([vm2], [nc 66.66.66.66 666 -z], [0], [ignore], [ignore]) NS_CHECK_EXEC([vm3], [nc 66.66.66.66 666 -z], [0], [ignore], [ignore]) @@ -9572,9 +9585,263 @@ name: 'vport' value: '666' # Start IPv6 TCP server on vm1. NETNS_DAEMONIZE([vm1], [nc -k -l 4242::2 4242], [nc-vm1.pid]) -# Make sure connecting to the VIP works. +# Make sure connecting to the VIP works (hairpin, via ls and via lr). +NS_CHECK_EXEC([vm1], [nc 6666::1 666 -z], [0], [ignore], [ignore]) NS_CHECK_EXEC([vm2], [nc 6666::1 666 -z], [0], [ignore], [ignore]) NS_CHECK_EXEC([vm3], [nc 6666::1 666 -z], [0], [ignore], [ignore]) AT_CLEANUP ]) + +########################################################### +## ls1 -- cluster-router -- join - gr1 -- public1 -- ln1 ## +########################################################### +OVN_FOR_EACH_NORTHD([ +AT_SETUP([Gateway router with dynamic_neigh_routers]) + +CHECK_CONNTRACK() +CHECK_CONNTRACK_NAT() +ovn_start +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-int]) +ADD_BR([br-ex], [set Bridge br-ex fail-mode=standalone]) + +check ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=provider:br-ex + +# 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 + +# Add routers +check ovn-nbctl lr-add gr1 +check ovn-nbctl lr-add cluster-router + +# Add switches +check ovn-nbctl ls-add join +check ovn-nbctl ls-add public1 +check ovn-nbctl ls-add ls1 + +# Add ls1 ports +check ovn-nbctl lsp-add ls1 ls1p1 \ + -- lsp-set-addresses ls1p1 "00:00:00:00:01:11 10.244.2.11" + +check ovn-nbctl lsp-add ls1 ls1-to-cluster-router \ + -- lsp-set-type ls1-to-cluster-router router \ + -- lsp-set-options ls1-to-cluster-router router-port=cluster-router-to-ls1 \ + -- lsp-set-addresses ls1-to-cluster-router router + +# Add cluster-router ports +check ovn-nbctl lrp-add cluster-router cluster-router-to-ls1 "00:00:00:0f:01:01" 10.244.2.1/24 \ + -- lrp-add cluster-router cluster-router-to-join "00:00:00:0f:02:01" 100.64.0.1/16 \ + -- lrp-set-gateway-chassis cluster-router-to-ls1 hv1 10 \ + -- --policy=src-ip lr-route-add cluster-router 10.244.2.0/24 100.64.0.3 + +# Add join ports +check ovn-nbctl lsp-add join join-to-cluster-router \ + -- lsp-set-type join-to-cluster-router router \ + -- lsp-set-options join-to-cluster-router router-port=cluster-router-to-join \ + -- lsp-set-addresses join-to-cluster-router router \ + -- lsp-add join join-to-gr1 \ + -- lsp-set-type join-to-gr1 router \ + -- lsp-set-options join-to-gr1 router-port=gr1-to-join \ + -- lsp-set-addresses join-to-gr1 router + +check ovn-nbctl set logical_router gr1 options:lb_force_snat_ip=router_ip \ + -- set logical_router gr1 options:snat-ct-zone=0 \ + -- set logical_router gr1 options:dynamic_neigh_routers=true + +# Add gr1 ports and set natting +check ovn-nbctl lrp-add gr1 gr1-to-join "00:00:00:0f:02:03" 100.64.0.3/16 \ + -- lr-route-add gr1 10.244.0.0/16 100.64.0.1 \ + -- lr-nat-add gr1 snat 10.89.189.12 10.244.0.0/16 \ + -- lrp-add gr1 gr1-to-public1 "0a:0a:b6:fc:03:12" 10.89.189.12/24 \ + -- set logical_router gr1 options:chassis=hv1 + +# Add public1 ports +check ovn-nbctl lsp-add public1 public1-to-gr1 \ + -- lsp-set-type public1-to-gr1 router \ + -- lsp-set-options public1-to-gr1 router-port=gr1-to-public1 \ + -- lsp-set-addresses public1-to-gr1 router \ + -- lsp-add public1 ln1 \ + -- lsp-set-type ln1 localnet \ + -- lsp-set-options ln1 network_name=provider \ + -- lsp-set-addresses ln1 unknown + +check ovn-nbctl --wait=hv sync + +ADD_NAMESPACES(ns_ls1p1) +ADD_VETH(ls1p1, ns_ls1p1, br-int, "10.244.2.11/24", "00:00:00:00:01:11", "10.244.2.1") + +ADD_NAMESPACES(ns_ext1) +ADD_VETH(ln1, ns_ext1, br-ex, "10.89.189.1/24", "0a:0a:b6:fc:03:01") + +NS_CHECK_EXEC([ns_ls1p1], [ping -q -c 3 -i 0.3 -w 2 10.89.189.1 | FORMAT_PING], \ +[0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +OVS_APP_EXIT_AND_WAIT([ovn-controller]) + +as ovn-sb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as ovn-nb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as northd +OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) + +as +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d +/connection dropped.*/d"]) +AT_CLEANUP +]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ACL default_acl_drop]) +AT_KEYWORDS([acl default_acl_drop]) + +CHECK_CONNTRACK() +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 + +ovn-nbctl ls-add sw + +# Logical port 'vm1' in switch 'sw'. +ADD_NAMESPACES(vm1) +ADD_VETH(vm1, vm1, br-int, "10.0.0.1/24", "f0:00:00:01:02:03", \ + "10.0.0.254") +check ovn-nbctl lsp-add sw vm1 \ +-- lsp-set-addresses vm1 "f0:00:00:01:02:03 10.0.0.1" + +# Logical port 'vm2' in switch 'sw'. +ADD_NAMESPACES(vm2) +ADD_VETH(vm2, vm2, br-int, "10.0.0.2/24", "f0:00:00:01:02:05", \ +"10.0.0.254") +check ovn-nbctl lsp-add sw vm2 \ +-- lsp-set-addresses vm2 "f0:00:00:01:02:05 10.0.0.2" + +# Wait for ovn-controller to catch up. +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +AS_BOX([from-lport acl, default_acl_drop false]) +check ovn-nbctl acl-del sw +check ovn-nbctl set NB_Global . options:default_acl_drop=false \ + -- acl-add sw from-lport 20 "ip4 && icmp" allow-related \ + -- acl-add sw from-lport 10 "ip4" drop +check ovn-nbctl --wait=hv sync + +# 'vm1' should be able to ping 'vm2' directly. +NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.2 | FORMAT_PING], \ +[0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +AS_BOX([from-lport acl, default_acl_drop true]) +check ovn-nbctl acl-del sw +check ovn-nbctl set NB_Global . options:default_acl_drop=true \ + -- acl-add sw from-lport 20 "ip4 && icmp" allow-related \ + -- acl-add sw from-lport 10 "arp" allow \ + -- --apply-after-lb acl-add sw from-lport 1 1 allow \ + -- acl-add sw to-lport 1 1 allow +check ovn-nbctl --wait=hv sync + +# 'vm1' should be able to ping 'vm2' directly. +NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.2 | FORMAT_PING], \ +[0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +AS_BOX([from-lport acl, after LB, default_acl_drop false]) +check ovn-nbctl acl-del sw +check ovn-nbctl set NB_Global . options:default_acl_drop=false \ + -- --apply-after-lb acl-add sw from-lport 20 "ip4 && icmp" allow-related \ + -- --apply-after-lb acl-add sw from-lport 10 "ip4" drop +check ovn-nbctl --wait=hv sync + +# 'vm1' should be able to ping 'vm2' directly. +NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.2 | FORMAT_PING], \ +[0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +AS_BOX([from-lport acl, after LB, default_acl_drop true]) +check ovn-nbctl acl-del sw +check ovn-nbctl set NB_Global . options:default_acl_drop=true \ + -- acl-add sw from-lport 1 1 allow \ + -- --apply-after-lb acl-add sw from-lport 20 "ip4 && icmp" allow-related \ + -- --apply-after-lb acl-add sw from-lport 20 "arp" allow-related \ + -- acl-add sw to-lport 1 1 allow +check ovn-nbctl --wait=hv sync + +# 'vm1' should be able to ping 'vm2' directly. +NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.2 | FORMAT_PING], \ +[0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +AS_BOX([to-lport acl, default_acl_drop false]) +check ovn-nbctl acl-del sw +check ovn-nbctl set NB_Global . options:default_acl_drop=false \ + -- acl-add sw to-lport 20 "ip4 && icmp" allow-related \ + -- acl-add sw to-lport 10 "ip4" drop +check ovn-nbctl --wait=hv sync + +# 'vm1' should be able to ping 'vm2' directly. +NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.2 | FORMAT_PING], \ +[0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +AS_BOX([to-lport acl, default_acl_drop true]) +check ovn-nbctl acl-del sw +check ovn-nbctl set NB_Global . options:default_acl_drop=true \ + -- acl-add sw from-lport 1 1 allow \ + -- --apply-after-lb acl-add sw from-lport 1 1 allow \ + -- acl-add sw to-lport 20 "ip4 && icmp" allow-related \ + -- acl-add sw to-lport 20 "arp" allow +check ovn-nbctl --wait=hv sync + +# 'vm1' should be able to ping 'vm2' directly. +NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.2 | FORMAT_PING], \ +[0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +OVS_APP_EXIT_AND_WAIT([ovn-controller]) + +as ovn-sb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as ovn-nb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as northd +OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) + +as +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d +/connection dropped.*/d"]) +AT_CLEANUP +]) diff --git a/utilities/ovn-dbctl.c b/utilities/ovn-dbctl.c index a850c2f31..5edb82e7f 100644 --- a/utilities/ovn-dbctl.c +++ b/utilities/ovn-dbctl.c @@ -109,6 +109,15 @@ static void server_loop(const struct ovn_dbctl_options *dbctl_options, struct ovsdb_idl *idl, int argc, char *argv[]); static void ovn_dbctl_exit(int status); +static void +destroy_argv(int argc, char **argv) +{ + for (int i = 0; i < argc; i++) { + free(argv[i]); + } + free(argv); +} + int ovn_dbctl_main(int argc, char *argv[], const struct ovn_dbctl_options *dbctl_options) @@ -151,6 +160,7 @@ ovn_dbctl_main(int argc, char *argv[], char *error_s = ovs_cmdl_parse_all(argc, argv_, get_all_options(), &parsed_options, &n_parsed_options); if (error_s) { + destroy_argv(argc, argv_); ctl_fatal("%s", error_s); } @@ -179,6 +189,7 @@ ovn_dbctl_main(int argc, char *argv[], bool daemon_mode = false; if (get_detach()) { if (argc != optind) { + destroy_argv(argc, argv_); ctl_fatal("non-option arguments not supported with --detach " "(use --help for help)"); } @@ -204,11 +215,8 @@ ovn_dbctl_main(int argc, char *argv[], if (error) { ovsdb_idl_destroy(idl); idl = the_idl = NULL; + destroy_argv(argc, argv_); - for (int i = 0; i < argc; i++) { - free(argv_[i]); - } - free(argv_); ctl_fatal("%s", error); } @@ -237,21 +245,15 @@ cleanup: } free(commands); if (error) { - for (int i = 0; i < argc; i++) { - free(argv_[i]); - } - free(argv_); + destroy_argv(argc, argv_); ctl_fatal("%s", error); } } ovsdb_idl_destroy(idl); idl = the_idl = NULL; + destroy_argv(argc, argv_); - for (int i = 0; i < argc; i++) { - free(argv_[i]); - } - free(argv_); exit(EXIT_SUCCESS); } @@ -1238,40 +1240,53 @@ dbctl_client(const struct ovn_dbctl_options *dbctl_options, ctl_timeout_setup(timeout); + char *cmd_result = NULL; + char *cmd_error = NULL; struct jsonrpc *client; + int exit_status; + char *error_str; + int error = unixctl_client_create(socket_name, &client); if (error) { - ctl_fatal("%s: could not connect to %s daemon (%s); " - "unset %s to avoid using daemon", - socket_name, program_name, ovs_strerror(error), - dbctl_options->daemon_env_var_name); + error_str = xasprintf("%s: could not connect to %s daemon (%s); " + "unset %s to avoid using daemon", + socket_name, program_name, ovs_strerror(error), + dbctl_options->daemon_env_var_name); + goto log_error; } - char *cmd_result; - char *cmd_error; error = unixctl_client_transact(client, "run", args.n, args.names, &cmd_result, &cmd_error); if (error) { - ctl_fatal("%s: transaction error (%s)", - socket_name, ovs_strerror(error)); + error_str = xasprintf("%s: transaction error (%s)", + socket_name, ovs_strerror(error)); + goto log_error; } - svec_destroy(&args); - int exit_status; if (cmd_error) { - exit_status = EXIT_FAILURE; fprintf(stderr, "%s: %s", program_name, cmd_error); - } else { - exit_status = EXIT_SUCCESS; - fputs(cmd_result, stdout); + goto error; } + + exit_status = EXIT_SUCCESS; + fputs(cmd_result, stdout); + goto cleanup; + +log_error: + VLOG_ERR("%s", error_str); + ovs_error(0, "%s", error_str); + free(error_str); + +error: + exit_status = EXIT_FAILURE; + +cleanup: free(cmd_result); free(cmd_error); jsonrpc_close(client); - for (int i = 0; i < argc; i++) { - free(argv[i]); - } - free(argv); + svec_destroy(&args); + destroy_argv(argc, argv); + exit(exit_status); } diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml index 92e10c012..72d4088f0 100644 --- a/utilities/ovn-nbctl.8.xml +++ b/utilities/ovn-nbctl.8.xml @@ -814,7 +814,7 @@ Attaches the mirror m to the logical port port. -
    lsp-dettach-mirror port m
    +
    lsp-detach-mirror port m
    Detaches the mirror m from the logical port port.
    diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c index 07ebac5e5..e5766ed67 100644 --- a/utilities/ovn-trace.c +++ b/utilities/ovn-trace.c @@ -1486,9 +1486,8 @@ ovntrace_node_prune_hard(struct ovs_list *nodes) } static void -execute_load(const struct ovnact_load *load, - const struct ovntrace_datapath *dp, struct flow *uflow, - struct ovs_list *super OVS_UNUSED) +execute_load(const struct ovnact *ovnact, const struct ovntrace_datapath *dp, + struct flow *uflow, struct ovs_list *super OVS_UNUSED) { const struct ovnact_encode_params ep = { .lookup_port = ovntrace_lookup_port, @@ -1498,7 +1497,7 @@ execute_load(const struct ovnact_load *load, uint64_t stub[512 / 8]; struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub); - ovnacts_encode(&load->ovnact, sizeof *load, &ep, &ofpacts); + ovnacts_encode(ovnact, OVNACT_ALIGN(ovnact->len), &ep, &ofpacts); struct ofpact *a; OFPACT_FOR_EACH (a, ofpacts.data, ofpacts.size) { @@ -1506,12 +1505,11 @@ execute_load(const struct ovnact_load *load, if (!mf_is_register(sf->field->id)) { struct ds s = DS_EMPTY_INITIALIZER; - ovnacts_format(&load->ovnact, OVNACT_LOAD_SIZE, &s); - ds_chomp(&s, ';'); - char *friendly = ovntrace_make_names_friendly(ds_cstr(&s)); - ovntrace_node_append(super, OVNTRACE_NODE_MODIFY, "%s", friendly); - free(friendly); + ovnacts_format(ovnact, OVNACT_ALIGN(ovnact->len), &s); + ds_chomp(&s, ';'); + ovntrace_node_append(super, OVNTRACE_NODE_MODIFY, "%s", + ds_cstr(&s)); ds_destroy(&s); } @@ -3057,7 +3055,7 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, const struct ovnact *a; OVNACT_FOR_EACH (a, ovnacts, ovnacts_len) { ds_clear(&s); - ovnacts_format(a, sizeof *a * (ovnact_next(a) - a), &s); + ovnacts_format(a, OVNACT_ALIGN(a->len), &s); char *friendly = ovntrace_make_names_friendly(ds_cstr(&s)); ovntrace_node_append(super, OVNTRACE_NODE_ACTION, "%s", friendly); free(friendly); @@ -3072,7 +3070,7 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, break; case OVNACT_LOAD: - execute_load(ovnact_get_LOAD(a), dp, uflow, super); + execute_load(a, dp, uflow, super); break; case OVNACT_MOVE: