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 <vivek@cumulusnetworks.com>
Reviewed-by:   Don Slice <dslice@cumulusnetworks.com>
Reviewed-by:   Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
vivek 2020-03-18 15:40:04 -07:00
parent d69a76ac1a
commit e34291b86a
3 changed files with 61 additions and 19 deletions

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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,