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 == <backend-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 <dev@openvswitch.org> 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 <sys/types.h>
#include <netinet/in.h>
+#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, <code>ct_mark.blocked</code> will get set and packets in the
reply direction will no longer be allowed, either. This flow also
clears the register bits <code>reg0[9]</code> and
- <code>reg0[10]</code>. If ACL logging and logging of related packets
- is enabled, then a companion priority-65533 flow will be installed that
+ <code>reg0[10]</code> and sets register bit <code>reg0[17]</code>.
+ 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.
</li>
@@ -1028,92 +1029,7 @@
</li>
</ul>
- <h3>Ingress table 14: <code>from-lport</code> ACLs after LB</h3>
-
- <p>
- Logical flows in this table closely reproduce those in the
- <code>ACL</code> table in the <code>OVN_Northbound</code> database
- for the <code>from-lport</code> direction with the option
- <code>apply-after-lb</code> set to <code>true</code>.
- The <code>priority</code> values from the <code>ACL</code> table have a
- limited range and have 1000 added to them to leave room for OVN default
- flows at both higher and lower priorities.
- </p>
-
- <ul>
- <li>
- <code>allow</code> apply-after-lb ACLs translate into logical flows
- with the <code>next;</code> action. If there are any stateful ACLs
- (including both before-lb and after-lb ACLs)
- on this datapath, then <code>allow</code> ACLs translate to
- <code>ct_commit; next;</code> (which acts as a hint for the next tables
- to commit the connection to conntrack). In case the <code>ACL</code>
- has a label then <code>reg3</code> is loaded with the label value and
- <code>reg0[13]</code> bit is set to 1 (which acts as a hint for the
- next tables to commit the label to conntrack).
- </li>
- <li>
- <code>allow-related</code> apply-after-lb ACLs translate into logical
- flows with the <code>ct_commit(ct_label=0/1); next;</code> actions
- for new connections and <code>reg0[1] = 1; next;</code> for existing
- connections. In case the <code>ACL</code> has a label then
- <code>reg3</code> is loaded with the label value and
- <code>reg0[13]</code> bit is set to 1 (which acts as a hint for the
- next tables to commit the label to conntrack).
- </li>
- <li>
- <code>allow-stateless</code> apply-after-lb ACLs translate into logical
- flows with the <code>next;</code> action.
- </li>
- <li>
- <code>reject</code> apply-after-lb ACLs translate into logical
- flows with the
- <code>tcp_reset { output <-> inport;
- next(pipeline=egress,table=5);}</code>
- action for TCP connections,<code>icmp4/icmp6</code> action
- for UDP connections, and <code>sctp_abort {output <-%gt; inport;
- next(pipeline=egress,table=5);}</code> action for SCTP associations.
- </li>
- <li>
- Other apply-after-lb ACLs translate to <code>drop;</code> for new
- or untracked connections and <code>ct_commit(ct_label=1/1);</code> for
- known connections. Setting <code>ct_label</code> marks a connection
- as one that was previously allowed, but should no longer be
- allowed due to a policy change.
- </li>
- </ul>
-
- <ul>
- <li>
- One priority-0 fallback flow that matches all packets and advances to
- the next table.
- </li>
- </ul>
-
- <h3>Ingress Table 15: Stateful</h3>
-
- <ul>
- <li>
- A priority 100 flow is added which commits the packet to the conntrack
- and sets the most significant 32-bits of <code>ct_label</code> with the
- <code>reg3</code> value based on the hint provided by previous tables
- (with a match for <code>reg0[1] == 1 && reg0[13] == 1</code>).
- This is used by the <code>ACLs</code> with label to commit the label
- value to conntrack.
- </li>
-
- <li>
- For <code>ACLs</code> without label, a second priority-100 flow commits
- packets to connection tracker using <code>ct_commit; next;</code>
- action based on a hint provided by the previous tables (with a match
- for <code>reg0[1] == 1 && reg0[13] == 0</code>).
- </li>
- <li>
- A priority-0 flow that simply moves traffic to the next table.
- </li>
- </ul>
-
- <h3>Ingress Table 16: Pre-Hairpin</h3>
+ <h3>Ingress Table 14: Pre-Hairpin</h3>
<ul>
<li>
If the logical switch has load balancer(s) configured, then a
@@ -1131,7 +1047,7 @@
</li>
</ul>
- <h3>Ingress Table 17: Nat-Hairpin</h3>
+ <h3>Ingress Table 15: Nat-Hairpin</h3>
<ul>
<li>
If the logical switch has load balancer(s) configured, then a
@@ -1166,7 +1082,7 @@
</li>
</ul>
- <h3>Ingress Table 18: Hairpin</h3>
+ <h3>Ingress Table 16: Hairpin</h3>
<ul>
<li>
<p>
@@ -1200,6 +1116,100 @@
</li>
</ul>
+ <h3>Ingress table 17: <code>from-lport</code> ACLs after LB</h3>
+
+ <p>
+ Logical flows in this table closely reproduce those in the
+ <code>ACL</code> table in the <code>OVN_Northbound</code> database
+ for the <code>from-lport</code> direction with the option
+ <code>apply-after-lb</code> set to <code>true</code>.
+ The <code>priority</code> values from the <code>ACL</code> table have a
+ limited range and have 1000 added to them to leave room for OVN default
+ flows at both higher and lower priorities.
+ </p>
+
+ <ul>
+ <li>
+ <code>allow</code> apply-after-lb ACLs translate into logical flows
+ with the <code>next;</code> action. If there are any stateful ACLs
+ (including both before-lb and after-lb ACLs)
+ on this datapath, then <code>allow</code> ACLs translate to
+ <code>ct_commit; next;</code> (which acts as a hint for the next tables
+ to commit the connection to conntrack). In case the <code>ACL</code>
+ has a label then <code>reg3</code> is loaded with the label value and
+ <code>reg0[13]</code> bit is set to 1 (which acts as a hint for the
+ next tables to commit the label to conntrack).
+ </li>
+ <li>
+ <code>allow-related</code> apply-after-lb ACLs translate into logical
+ flows with the <code>ct_commit(ct_label=0/1); next;</code> actions
+ for new connections and <code>reg0[1] = 1; next;</code> for existing
+ connections. In case the <code>ACL</code> has a label then
+ <code>reg3</code> is loaded with the label value and
+ <code>reg0[13]</code> bit is set to 1 (which acts as a hint for the
+ next tables to commit the label to conntrack).
+ </li>
+ <li>
+ <code>allow-stateless</code> apply-after-lb ACLs translate into logical
+ flows with the <code>next;</code> action.
+ </li>
+ <li>
+ <code>reject</code> apply-after-lb ACLs translate into logical
+ flows with the
+ <code>tcp_reset { output <-> inport;
+ next(pipeline=egress,table=5);}</code>
+ action for TCP connections,<code>icmp4/icmp6</code> action
+ for UDP connections, and <code>sctp_abort {output <-%gt; inport;
+ next(pipeline=egress,table=5);}</code> action for SCTP associations.
+ </li>
+ <li>
+ Other apply-after-lb ACLs translate to <code>drop;</code> for new
+ or untracked connections and <code>ct_commit(ct_label=1/1);</code> for
+ known connections. Setting <code>ct_label</code> marks a connection
+ as one that was previously allowed, but should no longer be
+ allowed due to a policy change.
+ </li>
+ </ul>
+
+ <ul>
+ <li>
+ One priority-65532 flow matching packets with <code>reg0[17]</code>
+ set (either replies to existing sessions or traffic related to
+ existing sessions) and allows these by advancing to the next
+ table.
+ </li>
+ </ul>
+
+ <ul>
+ <li>
+ One priority-0 fallback flow that matches all packets and advances to
+ the next table.
+ </li>
+ </ul>
+
+ <h3>Ingress Table 18: Stateful</h3>
+
+ <ul>
+ <li>
+ A priority 100 flow is added which commits the packet to the conntrack
+ and sets the most significant 32-bits of <code>ct_label</code> with the
+ <code>reg3</code> value based on the hint provided by previous tables
+ (with a match for <code>reg0[1] == 1 && reg0[13] == 1</code>).
+ This is used by the <code>ACLs</code> with label to commit the label
+ value to conntrack.
+ </li>
+
+ <li>
+ For <code>ACLs</code> without label, a second priority-100 flow commits
+ packets to connection tracker using <code>ct_commit; next;</code>
+ action based on a hint provided by the previous tables (with a match
+ for <code>reg0[1] == 1 && reg0[13] == 0</code>).
+ </li>
+ <li>
+ A priority-0 flow that simply moves traffic to the next table.
+ </li>
+ </ul>
+
<h3>Ingress Table 19: ARP/ND responder</h3>
<p>
@@ -4257,13 +4267,17 @@ outport = <var>P</var>
For each row in the <code>NAT</code> table with IPv4 address
<var>A</var> in the <ref column="external_ip"
table="NAT" db="OVN_Northbound"/> column of
- <ref table="NAT" db="OVN_Northbound"/> table, a priority-100
- flow with the match <code>outport === <var>P</var> &&
- reg0 == <var>A</var></code> has actions <code>eth.dst = <var>E</var>;
- next;</code>, where <code>P</code> is the distributed logical router
- port, <var>E</var> is the Ethernet address if set in the
- <ref column="external_mac" table="NAT" db="OVN_Northbound"/> column
- of <ref table="NAT" db="OVN_Northbound"/> table for of type
+ <ref table="NAT" db="OVN_Northbound"/> table, below two flows are
+ programmed:
+ </p>
+
+ <p>
+ A priority-100 flow with the match <code>outport == <var>P</var>
+ && reg0 == <var>A</var></code> has actions <code>eth.dst =
+ <var>E</var>; next;</code>, where <code>P</code> is the distributed
+ logical router port, <var>E</var> is the Ethernet address if set in
+ the <ref column="external_mac" table="NAT" db="OVN_Northbound"/>
+ column of <ref table="NAT" db="OVN_Northbound"/> table for of type
<code>dnat_and_snat</code>, otherwise the Ethernet address of the
distributed logical router port. Note that if the
<ref column="external_ip" table="NAT" db="OVN_Northbound"/> is not
@@ -4273,9 +4287,18 @@ outport = <var>P</var>
will be added.
</p>
+ <p>
+ Corresponding to the above flow, a priority-150 flow with the match
+ <code>inport == <var>P</var> && outport == <var>P</var>
+ && ip4.dst == <var>A</var></code> has actions
+ <code>drop;</code> to exclude packets that have gone through
+ DNAT/unSNAT stage but failed to convert the destination, to avoid
+ loop.
+ </p>
+
<p>
For IPv6 NAT entries, same flows are added, but using the register
- <code>xxreg0</code> for the match.
+ <code>xxreg0</code> and field <code>ip6</code> for the match.
</p>
</li>
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.
</li>
<li>
- 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.
</li>
<li>
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=<cleared>/'], [0], [dnl
tcp,orig=(src=fd01::2,dst=fd03::1,sport=<cleared>,dport=<cleared>),reply=(src=fd02::2,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=fd01::2,dst=fd03::1,sport=<cleared>,dport=<cleared>),reply=(src=fd02::3,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
@@ -1748,27 +1746,25 @@ tcp,orig=(src=fd01::2,dst=fd03::1,sport=<cleared>,dport=<cleared>),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=<cleared>/'], [0], [dnl
tcp,orig=(src=fd01::2,dst=fd03::3,sport=<cleared>,dport=<cleared>),reply=(src=fd02::2,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=fd01::2,dst=fd03::3,sport=<cleared>,dport=<cleared>),reply=(src=fd02::3,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=fd01::2,dst=fd03::3,sport=<cleared>,dport=<cleared>),reply=(src=fd02::4,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
])
+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=<cleared>/'], [0], [dnl
tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd02::2,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd02::3,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
@@ -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=<cleared>/'], [0], [dnl
tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd02::2,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd02::3,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
@@ -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=<cleared>/'], [0], [dnl
tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
@@ -1947,20 +1943,19 @@ tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),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=<cleared>/'], [0], [dnl
tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
])
-
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=<cleared>/'], [0], [dnl
tcp,orig=(src=fd01::2,dst=fd03::1,sport=<cleared>,dport=<cleared>),reply=(src=fd01::3,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=fd01::2,dst=fd03::1,sport=<cleared>,dport=<cleared>),reply=(src=fd01::4,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
@@ -2058,20 +2053,19 @@ tcp,orig=(src=fd01::2,dst=fd03::1,sport=<cleared>,dport=<cleared>),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=<cleared>/'], [0], [dnl
tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd01::3,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd01::4,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd01::5,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
])
-
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=<cleared>/'], [0], [dnl
tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
])
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=<cleared>/'], [0], [dnl
tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
@@ -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=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
+tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)"
+exp_ct2="tcp,orig=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+tcp,orig=(src=172.16.1.2,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)"
+
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=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
-])
+ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
+ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) |
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.2,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+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=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
+tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)"
+exp_ct2="tcp,orig=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+tcp,orig=(src=172.16.1.2,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)"
+
+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=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
-])
-
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) |
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.2,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
+ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
+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=<cleared>/'], [0], [dnl
tcp,orig=(src=fd72::2,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=fd72::2,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
])
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=<cleared>/'], [0], [dnl
tcp,orig=(src=fd72::2,dst=fd30::2,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=fd72::2,dst=fd30::2,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
@@ -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=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
+tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)"
+exp_ct2="tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)"
+
+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=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
-])
-
+ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
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=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
+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=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
+tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
+exp_ct2=tcp,orig=(src=fd72::3,dst=fd11::2,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+tcp,orig=(src=fd72::3,dst=fd12::2,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)"
+
+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=<cleared>/'], [0], [dnl
-tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
-tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
-])
-
+ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
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=<cleared>/'], [0], [dnl
-tcp,orig=(src=fd72::3,dst=fd11::2,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=fd72::3,dst=fd12::2,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::2) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
+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=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
+tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)"
+exp_ct2="tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
+tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)"
+exp_ct3="tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)"
+exp_ct4="tcp,orig=(src=fd72::3,dst=fd11::2,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+tcp,orig=(src=fd72::3,dst=fd12::2,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)"
+
+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=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
-])
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 |
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
-tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
-])
+ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
+ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
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=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-])
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::2) | grep -v fe80 |
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=fd72::3,dst=fd11::2,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=fd72::3,dst=fd12::2,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
+ct3=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
+ct4=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::2) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
+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=<cleared>/'], [0], [dnl
tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
])
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=<cleared>/'], [0], [dnl
tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
@@ -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=<cleared>/'], [0], [dnl
tcp,orig=(src=fd72::2,dst=fd72::10,sport=<cleared>,dport=<cleared>),reply=(src=fd01::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=fd72::2,dst=fd72::10,sport=<cleared>,dport=<cleared>),reply=(src=fd02::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
])
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=<cleared>/'], [0], [dnl
tcp,orig=(src=fd72::2,dst=fd72::11,sport=<cleared>,dport=<cleared>),reply=(src=fd01::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=fd72::2,dst=fd72::11,sport=<cleared>,dport=<cleared>),reply=(src=fd02::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
@@ -3598,8 +3584,8 @@ icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,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=<cleared>/'], [0], [dnl
+ ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.0.0.10) | \
+ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
tcp,orig=(src=10.0.0.4,dst=10.0.0.10,sport=<cleared>,dport=<cleared>),reply=(src=10.0.0.3,dst=10.0.0.4,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
tcp,orig=(src=10.0.0.4,dst=10.0.0.10,sport=<cleared>,dport=<cleared>),reply=(src=20.0.0.3,dst=10.0.0.4,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
])
@@ -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 <var>m</var> to the logical port <var>port</var>.
</dd>
- <dt><code>lsp-dettach-mirror</code> <var>port</var> <var>m</var></dt>
+ <dt><code>lsp-detach-mirror</code> <var>port</var> <var>m</var></dt>
<dd>
Detaches the mirror <var>m</var> from the logical port <var>port</var>.
</dd>
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: