bgpd: Allow setting attributes over route-maps for conditional advertisements

Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
This commit is contained in:
Donatas Abraitis 2022-02-15 18:08:32 +02:00
parent 5cb526136a
commit cb290e57c7
6 changed files with 59 additions and 52 deletions

View File

@ -82,7 +82,7 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
struct peer_af *paf; struct peer_af *paf;
const struct prefix *dest_p; const struct prefix *dest_p;
struct update_subgroup *subgrp; struct update_subgroup *subgrp;
struct attr dummy_attr = {0}, attr = {0}; struct attr advmap_attr = {0}, attr = {0};
struct bgp_path_info_extra path_extra = {0}; struct bgp_path_info_extra path_extra = {0};
route_map_result_t ret; route_map_result_t ret;
@ -110,22 +110,22 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
assert(dest_p); assert(dest_p);
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
dummy_attr = *pi->attr; advmap_attr = *pi->attr;
/* Fill temp path_info */ /* Fill temp path_info */
prep_for_rmap_apply(&path, &path_extra, dest, pi, prep_for_rmap_apply(&path, &path_extra, dest, pi,
pi->peer, &dummy_attr); pi->peer, &advmap_attr);
RESET_FLAG(dummy_attr.rmap_change_flags); RESET_FLAG(advmap_attr.rmap_change_flags);
ret = route_map_apply(rmap, dest_p, &path); ret = route_map_apply(rmap, dest_p, &path);
bgp_attr_flush(&dummy_attr); if (ret != RMAP_PERMITMATCH ||
!bgp_check_selected(pi, peer, addpath_capable, afi,
if (ret != RMAP_PERMITMATCH)
continue;
if (bgp_check_selected(pi, peer, addpath_capable, afi,
safi)) { safi)) {
bgp_attr_flush(&advmap_attr);
continue;
}
/* Skip route-map checks in /* Skip route-map checks in
* subgroup_announce_check while executing from * subgroup_announce_check while executing from
* the conditional advertise scanner process. * the conditional advertise scanner process.
@ -133,23 +133,21 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
* on same peer, routes in advertise-map may not * on same peer, routes in advertise-map may not
* be advertised as expected. * be advertised as expected.
*/ */
if ((update_type == ADVERTISE) if (update_type == ADVERTISE &&
&& subgroup_announce_check(dest, pi, subgrp, subgroup_announce_check(dest, pi, subgrp, dest_p,
dest_p, &attr, &attr, &advmap_attr)) {
true)) bgp_adj_out_set_subgroup(dest, subgrp, &attr,
bgp_adj_out_set_subgroup(dest, subgrp, pi);
&attr, pi); } else {
else {
/* If default originate is enabled for /* If default originate is enabled for
* the peer, do not send explicit * the peer, do not send explicit
* withdraw. This will prevent deletion * withdraw. This will prevent deletion
* of default route advertised through * of default route advertised through
* default originate. * default originate.
*/ */
if (CHECK_FLAG( if (CHECK_FLAG(peer->af_flags[afi][safi],
peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE) &&
PEER_FLAG_DEFAULT_ORIGINATE) is_default_prefix(dest_p))
&& is_default_prefix(dest_p))
break; break;
bgp_adj_out_unset_subgroup( bgp_adj_out_unset_subgroup(
@ -158,7 +156,7 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
peer, afi, safi, peer, afi, safi,
&pi->tx_addpath)); &pi->tx_addpath));
} }
} bgp_attr_flush(&advmap_attr);
} }
} }
UNSET_FLAG(subgrp->sflags, SUBGRP_STATUS_TABLE_REPARSING); UNSET_FLAG(subgrp->sflags, SUBGRP_STATUS_TABLE_REPARSING);

View File

@ -1836,7 +1836,7 @@ void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
struct update_subgroup *subgrp, struct update_subgroup *subgrp,
const struct prefix *p, struct attr *attr, const struct prefix *p, struct attr *attr,
bool skip_rmap_check) struct attr *post_attr)
{ {
struct bgp_filter *filter; struct bgp_filter *filter;
struct peer *from; struct peer *from;
@ -2067,7 +2067,15 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
} }
} }
/* For modify attribute, copy it to temporary structure. */ /* For modify attribute, copy it to temporary structure.
* post_attr comes from BGP conditional advertisements, where
* attributes are already processed by advertise-map route-map,
* and this needs to be saved instead of overwriting from the
* path attributes.
*/
if (post_attr)
*attr = *post_attr;
else
*attr = *piattr; *attr = *piattr;
/* If local-preference is not set. */ /* If local-preference is not set. */
@ -2162,8 +2170,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
bgp_peer_as_override(bgp, afi, safi, peer, attr); bgp_peer_as_override(bgp, afi, safi, peer, attr);
/* Route map & unsuppress-map apply. */ /* Route map & unsuppress-map apply. */
if (!skip_rmap_check if (!post_attr &&
&& (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) { (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
struct bgp_path_info rmap_path = {0}; struct bgp_path_info rmap_path = {0};
struct bgp_path_info_extra dummy_rmap_path_extra = {0}; struct bgp_path_info_extra dummy_rmap_path_extra = {0};
struct attr dummy_attr = {0}; struct attr dummy_attr = {0};
@ -2696,7 +2704,7 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
if (selected) { if (selected) {
if (subgroup_announce_check(dest, selected, subgrp, p, &attr, if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
false)) { NULL)) {
/* Route is selected, if the route is already installed /* Route is selected, if the route is already installed
* in FIB, then it is advertised * in FIB, then it is advertised
*/ */

View File

@ -785,7 +785,7 @@ extern bool subgroup_announce_check(struct bgp_dest *dest,
struct bgp_path_info *pi, struct bgp_path_info *pi,
struct update_subgroup *subgrp, struct update_subgroup *subgrp,
const struct prefix *p, struct attr *attr, const struct prefix *p, struct attr *attr,
bool skip_rmap_check); struct attr *post_attr);
extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer); extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer);
extern void bgp_process_queues_drain_immediate(void); extern void bgp_process_queues_drain_immediate(void);

View File

@ -691,7 +691,7 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
safi)) { safi)) {
if (subgroup_announce_check(dest, ri, subgrp, if (subgroup_announce_check(dest, ri, subgrp,
dest_p, &attr, dest_p, &attr,
false)) { NULL)) {
/* Check if route can be advertised */ /* Check if route can be advertised */
if (advertise) { if (advertise) {
if (!bgp_check_withdrawal(bgp, if (!bgp_check_withdrawal(bgp,
@ -910,7 +910,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
if (subgroup_announce_check( if (subgroup_announce_check(
dest, pi, subgrp, dest, pi, subgrp,
bgp_dest_get_prefix(dest), bgp_dest_get_prefix(dest),
&attr, false)) &attr, NULL))
bgp_adj_out_set_subgroup( bgp_adj_out_set_subgroup(
dest, subgrp, &attr, dest, subgrp, &attr,
pi); pi);

View File

@ -19,6 +19,7 @@ route-map ADV-MAP-1 permit 20
! !
route-map ADV-MAP-2 permit 10 route-map ADV-MAP-2 permit 10
match ip address prefix-list IP2 match ip address prefix-list IP2
set metric 911
! !
route-map EXIST-MAP permit 10 route-map EXIST-MAP permit 10
match community DEFAULT-ROUTE match community DEFAULT-ROUTE

View File

@ -334,7 +334,7 @@ def test_bgp_conditional_advertisement():
"192.0.2.1/32": None, "192.0.2.1/32": None,
"192.0.2.5/32": None, "192.0.2.5/32": None,
"10.139.224.0/20": None, "10.139.224.0/20": None,
"203.0.113.1/32": [{"protocol": "bgp"}], "203.0.113.1/32": [{"protocol": "bgp", "metric": 911}],
} }
return topotest.json_cmp(output, expected) return topotest.json_cmp(output, expected)