On Tue, Sep 23, 2025 at 9:41 AM Indrajitt Valsaraj < [email protected]> wrote:
> This commit adds the ability for ovn-ic to deny filter routes > learnt/advertised between AZs. This commit also fixes a documentation > error for the ic-route-filter-adv option. > > Signed-off-by: Indrajitt Valsaraj <[email protected]> > > --- > v1: > - Address review comments from Mark > v2: > - Rebased patch > --- > NEWS | 3 + > ic/ovn-ic.c | 53 +++++++++---- > ovn-nb.xml | 66 ++++++++++++++--- > tests/ovn-ic.at | 193 ++++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 290 insertions(+), 25 deletions(-) > > diff --git a/NEWS b/NEWS > index 4d0c45e4d..4b6742c01 100644 > --- a/NEWS > +++ b/NEWS > @@ -2,6 +2,9 @@ Post v25.09.0 > ------------- > - Added disable_garp_rarp option to logical_router table in order to > disable > GARP/RARP announcements by all the peer ports of this logical router. > + - Added "ic-route-deny-adv" and "ic-route-deny-learn" options to > + the Logical_Router/Logical_Router_Port tables to allow users to > + deny filter advertised/learned IC routes. > > OVN v25.09.0 - xxx xx xxxx > -------------------------- > diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c > index 1462b8043..cea64588b 100644 > --- a/ic/ovn-ic.c > +++ b/ic/ovn-ic.c > @@ -1121,26 +1121,50 @@ prefix_is_filtered(struct in6_addr *prefix, > } > > static bool > -prefix_is_deny_listed(const struct smap *nb_options, > - struct in6_addr *prefix, > - unsigned int plen) > -{ > - const char *filter_name = "ic-route-denylist"; > - const char *denylist = smap_get(nb_options, filter_name); > - if (!denylist || !denylist[0]) { > - denylist = smap_get(nb_options, "ic-route-blacklist"); > - if (!denylist || !denylist[0]) { > - return false; > +prefix_is_deny_filtered(struct in6_addr *prefix, > + unsigned int plen, > + const struct smap *nb_options, > + const struct nbrec_logical_router *nb_lr, > + const struct nbrec_logical_router_port *ts_lrp, > + bool is_advertisement) > +{ > + struct ds deny_list = DS_EMPTY_INITIALIZER; > + const char *deny_key = is_advertisement ? "ic-route-deny-adv" : > + "ic-route-deny-learn"; > + > + if (ts_lrp) { > + const char *lrp_deny_filter = smap_get(&ts_lrp->options, > deny_key); > + if (lrp_deny_filter) { > + ds_put_format(&deny_list, "%s,", lrp_deny_filter); > + } > + } > + > + if (nb_lr) { > + const char *lr_deny_filter = smap_get(&nb_lr->options, deny_key); > + if (lr_deny_filter) { > + ds_put_format(&deny_list, "%s,", lr_deny_filter); > + } > + } > + > + if (nb_options) { > + const char *global_deny = smap_get(nb_options, > "ic-route-denylist"); > + if (!global_deny || !global_deny[0]) { > + global_deny = smap_get(nb_options, "ic-route-blacklist"); > + } > + if (global_deny && global_deny[0]) { > + ds_put_format(&deny_list, "%s,", global_deny); > } > } > > struct sset prefix_set = SSET_INITIALIZER(&prefix_set); > - sset_from_delimited_string(&prefix_set, denylist, ","); > + sset_from_delimited_string(&prefix_set, ds_cstr(&deny_list), ","); > > bool denied = false; > if (!sset_is_empty(&prefix_set)) { > - denied = find_prefix_in_set(prefix, plen, &prefix_set, > filter_name); > + denied = find_prefix_in_set(prefix, plen, &prefix_set, deny_key); > } > + > + ds_destroy(&deny_list); > sset_destroy(&prefix_set); > return denied; > } > @@ -1170,7 +1194,8 @@ route_need_advertise(const char *policy, > return false; > } > > - if (prefix_is_deny_listed(nb_options, prefix, plen)) { > + if (prefix_is_deny_filtered(prefix, plen, nb_options, > + nb_lr, ts_lrp, true)) { > return false; > } > > @@ -1527,7 +1552,7 @@ route_need_learn(const struct nbrec_logical_router > *lr, > return false; > } > > - if (prefix_is_deny_listed(nb_options, prefix, plen)) { > + if (prefix_is_deny_filtered(prefix, plen, nb_options, lr, ts_lrp, > false)) { > return false; > } > > diff --git a/ovn-nb.xml b/ovn-nb.xml > index 1f5c58490..b96d38e6b 100644 > --- a/ovn-nb.xml > +++ b/ovn-nb.xml > @@ -3315,7 +3315,7 @@ or > <column name="options" key="ic-route-filter-adv"> > <p> > This option expects list of CIDRs delimited by "," that's > present > - in the Logical Router. A route will not be advertised if the > + in the Logical Router. A route will be advertised if the > route's prefix belongs to any of the CIDRs listed. > > This allows to filter CIDR prefixes in the process of > advertising > @@ -3324,6 +3324,28 @@ or > </column> > > <column name="options" key="ic-route-filter-learn"> > + <p> > + This option expects list of CIDRs delimited by "," that's > present > + in the Logical Router. A route will be learned if the > + route's prefix belongs to any of the CIDRs listed. > + > + This allows to filter CIDR prefixes in the process of learning > + routes in <code>ovn-ic</code> daemon. > + </p> > + </column> > + > + <column name="options" key="ic-route-deny-adv"> > + <p> > + This option expects list of CIDRs delimited by "," that's > present > + in the Logical Router. A route will not be advertised if the > + route's prefix belongs to any of the CIDRs listed. > + > + This allows to filter CIDR prefixes in the process of > advertising > + routes in <code>ovn-ic</code> daemon. > + </p> > + </column> > + > + <column name="options" key="ic-route-deny-learn"> > <p> > This option expects list of CIDRs delimited by "," that's > present > in the Logical Router. A route will not be learned if the > @@ -4352,18 +4374,40 @@ or > This allows to filter CIDR prefixes in the process of > advertising > routes in <code>ovn-ic</code> daemon. > </p> > - </column> > + </column> > > - <column name="options" key="ic-route-filter-learn"> > - <p> > - This option expects list of CIDRs delimited by "," that's > present > - in the Logical Router Port. A route will be learned if the > - route's prefix belongs to any of the CIDRs listed. > + <column name="options" key="ic-route-filter-learn"> > + <p> > + This option expects list of CIDRs delimited by "," that's > present > + in the Logical Router Port. A route will be learned if the > + route's prefix belongs to any of the CIDRs listed. > > - This allows to filter CIDR prefixes in the process of learning > - routes in <code>ovn-ic</code> daemon. > - </p> > - </column> > + This allows to filter CIDR prefixes in the process of learning > + routes in <code>ovn-ic</code> daemon. > + </p> > + </column> > + > + <column name="options" key="ic-route-deny-adv"> > + <p> > + This option expects list of CIDRs delimited by "," that's > present > + in the Logical Router Port. A route will not be advertised if > the > + route's prefix belongs to any of the CIDRs listed. > + > + This allows to filter CIDR prefixes in the process of > advertising > + routes in <code>ovn-ic</code> daemon. > + </p> > + </column> > + > + <column name="options" key="ic-route-deny-learn"> > + <p> > + This option expects list of CIDRs delimited by "," that's > present in > + the Logical Router Port. A route will not be learned if the > + route's prefix belongs to any of the CIDRs listed. > + > + This allows to filter CIDR prefixes in the process of learning > + routes in <code>ovn-ic</code> daemon. > + </p> > + </column> > </group> > > <group title="Attachment"> > diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at > index 7e2665652..2d92f3adf 100644 > --- a/tests/ovn-ic.at > +++ b/tests/ovn-ic.at > @@ -4058,3 +4058,196 @@ OVN_CLEANUP_IC([az1], [az2], [az3]) > AT_CLEANUP > ]) > > +OVN_FOR_EACH_NORTHD([ > +AT_SETUP([ovn-ic -- prefix filter -- deny route adv]) > +ovn_init_ic_db > +ovn-ic-nbctl ts-add ts1 > +for i in 1 2; do > + ovn_start az$i > + ovn_as az$i > + check ovn-nbctl set nb_global . options:ic-route-learn=true > + check ovn-nbctl set nb_global . options:ic-route-adv=true > +done > + > +# Create routers and connect to transit switch > +for i in 1 2; do > + ovn_as az$i > + lr=lr1$i > + check ovn-nbctl lr-add $lr > + lrp=lrp-$lr-ts1 > + lsp=lsp-ts1-$lr > + check ovn-nbctl lrp-add $lr $lrp aa:aa:aa:aa:ab:0$i 169.254.101.$i/24 > fe80:10::$i/64 > + check ovn-nbctl lsp-add ts1 $lsp \ > + -- lsp-set-addresses $lsp router \ > + -- lsp-set-type $lsp router \ > + -- lsp-set-options $lsp router-port=$lrp > +done > + > +# Add directly connected routes to lr12 (first two test prefixes reused) > +ovn_as az2 check ovn-nbctl lrp-add lr12 lrp-lr12-1 aa:aa:aa:aa:cc:01 " > 192.168.100.1/24" "2001:db12::1/64" > +ovn_as az2 check ovn-nbctl lrp-add lr12 lrp-lr12-2 aa:aa:aa:aa:cc:02 " > 192.168.200.1/24" "2001:db22::1/64" > + > +# Sync IC DB > +check ovn-ic-nbctl --wait=sb sync > + > +# Validate lr11 learns both IPv4 and IPv6 routes from lr12 > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep -E > '192.168|2001' | grep learned | awk '{print $1, $2}' | sort], [0], [dnl > +192.168.100.0/24 169.254.101.2 > +192.168.200.0/24 169.254.101.2 > +2001:db12::/64 fe80:10::2 > +2001:db22::/64 fe80:10::2 > +]) > + > +# Set deny-adv on lrp-lr12-ts1 for 192.168.100.0/24 > +ovn_as az2 check ovn-nbctl set logical_router_port lrp-lr12-ts1 > options:ic-route-deny-adv=192.168.100.0/24 > + > +# Only 192.168.200.0/24 should now be learned > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > 192.168 | grep learned | awk '{print $1, $2}' | sort], [0], [dnl > +192.168.200.0/24 169.254.101.2 > +]) > + > +# Add IPv6 deny prefix too > +ovn_as az2 check ovn-nbctl set logical_router_port lrp-lr12-ts1 > options:ic-route-deny-adv="192.168.100.0/24,2001:db12::/64" > + > +# Only 2001:db22::/64 should be learned now > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 2001 > | grep learned | awk '{print $1, $2}' | sort], [0], [dnl > +2001:db22::/64 fe80:10::2 > +]) > + > +# Remove deny-adv and validate all are learned again > +ovn_as az2 check ovn-nbctl remove logical_router_port lrp-lr12-ts1 > options ic-route-deny-adv > + > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > learned | awk '{print $1, $2}' | sort], [0], [dnl > +192.168.100.0/24 169.254.101.2 > +192.168.200.0/24 169.254.101.2 > +2001:db12::/64 fe80:10::2 > +2001:db22::/64 fe80:10::2 > +]) > + > +# --- Test ic-route-deny-learn --- > + > +# Set deny-learn on lrp-lr11-ts1 for 192.168.200.0/24 and 2001:db22::/64 > +ovn_as az1 check ovn-nbctl set logical_router_port lrp-lr11-ts1 > options:ic-route-deny-learn="192.168.200.0/24,2001:db22::/64" > + > +# Now lr11 should only learn 192.168.100.0/24 and 2001:db12::/64 > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep -E > '192.168|2001' | grep learned | awk '{print $1, $2}' | sort], [0], [dnl > +192.168.100.0/24 169.254.101.2 > +2001:db12::/64 fe80:10::2 > +]) > + > +# Remove deny-learn and confirm full route learning resumes > +ovn_as az1 check ovn-nbctl remove logical_router_port lrp-lr11-ts1 > options ic-route-deny-learn > + > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep -E > '192.168|2001' | grep learned | awk '{print $1, $2}' | sort], [0], [dnl > +192.168.100.0/24 169.254.101.2 > +192.168.200.0/24 169.254.101.2 > +2001:db12::/64 fe80:10::2 > +2001:db22::/64 fe80:10::2 > +]) > + > +# --- Test setting deny options on logical router --- > + > +# Set deny-adv on lr12 for 192.168.100.0/24 > +ovn_as az2 check ovn-nbctl set logical_router lr12 > options:ic-route-deny-adv="192.168.100.0/24" > + > +# Sync again after router option is applied > +check ovn-ic-nbctl --wait=sb sync > + > +# Only 192.168.200.0/24 should now be learned > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > 192.168 | grep learned | awk '{print $1, $2}' | sort], [0], [dnl > +192.168.200.0/24 169.254.101.2 > +]) > + > +# Set deny-learn on lr11 for 2001:db22::/64 > +ovn_as az1 check ovn-nbctl set logical_router lr11 > options:ic-route-deny-learn="2001:db22::/64" > + > +# Only 2001:db12::/64 should now be learned > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 2001 > | grep learned | awk '{print $1, $2}' | sort], [0], [dnl > +2001:db12::/64 fe80:10::2 > +]) > + > +# Clean up router-level options > +ovn_as az2 check ovn-nbctl remove logical_router lr12 options > ic-route-deny-adv > +ovn_as az1 check ovn-nbctl remove logical_router lr11 options > ic-route-deny-learn > + > +# Confirm all routes are back > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > learned | awk '{print $1, $2}' | sort], [0], [dnl > +192.168.100.0/24 169.254.101.2 > +192.168.200.0/24 169.254.101.2 > +2001:db12::/64 fe80:10::2 > +2001:db22::/64 fe80:10::2 > +]) > + > +# --- Test ic-route-denylist (global option) --- > + > +# Set global denylist to block 192.168.100.0/24 and 2001:db12::/64 > +ovn_as az2 check ovn-nbctl set nb_global . options:ic-route-denylist=" > 192.168.100.0/24,2001:db12::/64" > + > +# Now lr11 should only learn 192.168.200.0/24 and 2001:db22::/64 > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep -E > '192.168|2001' | grep learned | awk '{print $1, $2}' | sort], [0], [dnl > +192.168.200.0/24 169.254.101.2 > +2001:db22::/64 fe80:10::2 > +]) > + > +# Remove global denylist > +ovn_as az2 check ovn-nbctl remove nb_global . options ic-route-denylist > + > +# Confirm all routes are learned again > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep -E > '192.168|2001' | grep learned | awk '{print $1, $2}' | sort], [0], [dnl > +192.168.100.0/24 169.254.101.2 > +192.168.200.0/24 169.254.101.2 > +2001:db12::/64 fe80:10::2 > +2001:db22::/64 fe80:10::2 > +]) > + > +# --- Test combination of deny options --- > + > +# Set all deny filters > +ovn_as az2 check ovn-nbctl set logical_router_port lrp-lr12-ts1 > options:ic-route-deny-adv="192.168.100.0/24" > +ovn_as az1 check ovn-nbctl set logical_router_port lrp-lr11-ts1 > options:ic-route-deny-learn="192.168.200.0/24" > +ovn_as az2 check ovn-nbctl set nb_global . > options:ic-route-denylist="2001:db12::/64" > + > +# Validate only 2001:db22::/64 is learned > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep -E > '192.168|2001' | grep learned | awk '{print $1, $2}' | sort], [0], [dnl > +2001:db22::/64 fe80:10::2 > +]) > + > +# Clean up for interaction tests > +ovn_as az2 check ovn-nbctl remove logical_router_port lrp-lr12-ts1 > options ic-route-deny-adv > +ovn_as az1 check ovn-nbctl remove logical_router_port lrp-lr11-ts1 > options ic-route-deny-learn > +ovn_as az2 check ovn-nbctl remove nb_global . options ic-route-denylist > + > +# --- Test interactions between different filter options --- > + > +# Test ic-route-filter-adv vs ic-route-deny-adv precedence > +# Set both filter-adv (allow) and deny-adv (deny) for same CIDR - deny > should take precedence > +ovn_as az2 check ovn-nbctl set logical_router_port lrp-lr12-ts1 > options:ic-route-filter-adv="192.168.100.0/24,192.168.200.0/24" > +ovn_as az2 check ovn-nbctl set logical_router_port lrp-lr12-ts1 > options:ic-route-deny-adv="192.168.100.0/24" > + > +# Only 192.168.200.0/24 should be learned (192.168.100.0/24 denied > despite being in filter-adv) > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > 192.168 | grep learned | awk '{print $1, $2}' | sort], [0], [dnl > +192.168.200.0/24 169.254.101.2 > +]) > + > +# Clean up > +ovn_as az2 check ovn-nbctl remove logical_router_port lrp-lr12-ts1 > options ic-route-filter-adv > +ovn_as az2 check ovn-nbctl remove logical_router_port lrp-lr12-ts1 > options ic-route-deny-adv > + > +# Test cross-router interaction: filter-adv on lr12 vs deny-learn on lr11 > +# lr12 allows advertising 192.168.100.0/24, but lr11 denies learning it > +ovn_as az2 check ovn-nbctl set logical_router_port lrp-lr12-ts1 > options:ic-route-filter-adv="192.168.100.0/24" > +ovn_as az1 check ovn-nbctl set logical_router_port lrp-lr11-ts1 > options:ic-route-deny-learn="192.168.100.0/24" > + > +# 192.168.100.0/24 should not be learned (deny-learn takes precedence > over filter-adv) > +# No routes should be learned since only 192.168.100.0/24 is allowed to > be advertised but it's denied for learning > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > 192.168 | grep learned | wc -l], [0], [0 > +]) > + > +# Clean up interaction tests > +ovn_as az2 check ovn-nbctl remove logical_router_port lrp-lr12-ts1 > options ic-route-filter-adv > +ovn_as az1 check ovn-nbctl remove logical_router_port lrp-lr11-ts1 > options ic-route-deny-learn > + > + > +OVN_CLEANUP_IC([az1], [az2]) > +AT_CLEANUP > +]) > -- > 2.39.3 > _______________________________________________ > dev mailing list > [email protected] > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > Thank you Indrajitt, I have added acks from Mairtin and Lorenzo and merged this into main. Regards, Ales _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
