From e34291b86a7de4f0a8911bb8d9a01cc454e6a76e Mon Sep 17 00:00:00 2001 From: vivek Date: Wed, 18 Mar 2020 15:40:04 -0700 Subject: [PATCH] bgpd: Allow EVPN advertise route-map to modify attributes Ensure that the EVPN advertise route-map is applied on a copy of the original path_info and associated attribute, so that if the route-map has SET clauses, they can operate properly. This closely follows the model already in use in other route-map application code. Signed-off-by: Vivek Venkatraman Reviewed-by: Don Slice Reviewed-by: Donald Sharp --- bgpd/bgp_evpn.c | 28 +++++++++++++++++++++++----- bgpd/bgp_route.c | 35 +++++++++++++++++++++-------------- bgpd/bgp_route.h | 17 +++++++++++++++++ 3 files changed, 61 insertions(+), 19 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 664d62fd11..c3a9527b66 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -4576,16 +4576,34 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi, /* apply the route-map */ if (bgp_vrf->adv_cmd_rmap[afi][safi].map) { route_map_result_t ret; + struct bgp_path_info tmp_pi; + struct bgp_path_info_extra tmp_pie; + struct attr tmp_attr; + + tmp_attr = *pi->attr; + + /* Fill temp path_info */ + prep_for_rmap_apply( + &tmp_pi, &tmp_pie, rn, pi, + pi->peer, &tmp_attr); + + RESET_FLAG(tmp_attr.rmap_change_flags); ret = route_map_apply( bgp_vrf->adv_cmd_rmap[afi][safi] .map, - &rn->p, RMAP_BGP, pi); - if (ret == RMAP_DENYMATCH) + &rn->p, RMAP_BGP, &tmp_pi); + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(&tmp_attr); continue; - } - bgp_evpn_advertise_type5_route( - bgp_vrf, &rn->p, pi->attr, afi, safi); + } + bgp_evpn_advertise_type5_route( + bgp_vrf, &rn->p, &tmp_attr, + afi, safi); + } else + bgp_evpn_advertise_type5_route( + bgp_vrf, &rn->p, pi->attr, + afi, safi); break; } } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 18da60dfb4..1a4e47cfaa 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1875,16 +1875,9 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, struct bgp_path_info_extra dummy_rmap_path_extra = {0}; struct attr dummy_attr = {0}; - memset(&rmap_path, 0, sizeof(struct bgp_path_info)); - rmap_path.peer = peer; - rmap_path.attr = attr; - rmap_path.net = rn; - - if (pi->extra) { - memcpy(&dummy_rmap_path_extra, pi->extra, - sizeof(struct bgp_path_info_extra)); - rmap_path.extra = &dummy_rmap_path_extra; - } + /* Fill temp path_info */ + prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, + rn, pi, peer, attr); /* don't confuse inbound and outbound setting */ RESET_FLAG(attr->rmap_change_flags); @@ -2693,16 +2686,30 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, /* apply the route-map */ if (bgp->adv_cmd_rmap[afi][safi].map) { route_map_result_t ret; + struct bgp_path_info rmap_path; + struct bgp_path_info_extra rmap_path_extra; + struct attr dummy_attr; + + dummy_attr = *new_select->attr; + + /* Fill temp path_info */ + prep_for_rmap_apply( + &rmap_path, &rmap_path_extra, + rn, new_select, new_select->peer, + &dummy_attr); + + RESET_FLAG(dummy_attr.rmap_change_flags); ret = route_map_apply( bgp->adv_cmd_rmap[afi][safi].map, - &rn->p, RMAP_BGP, new_select); - if (ret == RMAP_DENYMATCH) + &rn->p, RMAP_BGP, &rmap_path); + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(&dummy_attr); bgp_evpn_withdraw_type5_route( bgp, &rn->p, afi, safi); - else + } else bgp_evpn_advertise_type5_route( - bgp, &rn->p, new_select->attr, + bgp, &rn->p, &dummy_attr, afi, safi); } else { bgp_evpn_advertise_type5_route(bgp, diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 0ad656d133..2fd9921934 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -467,6 +467,23 @@ static inline bool is_pi_family_matching(struct bgp_path_info *pi, return false; } +static inline void prep_for_rmap_apply(struct bgp_path_info *dst_pi, + struct bgp_path_info_extra *dst_pie, + struct bgp_node *rn, + struct bgp_path_info *src_pi, + struct peer *peer, struct attr *attr) +{ + memset(dst_pi, 0, sizeof(struct bgp_path_info)); + dst_pi->peer = peer; + dst_pi->attr = attr; + dst_pi->net = rn; + if (src_pi->extra) { + memcpy(dst_pie, src_pi->extra, + sizeof(struct bgp_path_info_extra)); + dst_pi->extra = dst_pie; + } +} + /* called before bgp_process() */ DECLARE_HOOK(bgp_process, (struct bgp *bgp, afi_t afi, safi_t safi, -- 2.39.5