diff options
author | Eugene Bogomazov <eb@qrator.net> | 2022-06-17 12:14:46 +0200 |
---|---|---|
committer | Eugene Bogomazov <eb@qrator.net> | 2022-06-17 12:14:46 +0200 |
commit | d864dd9eb182eefaa4d08717bd2837f9182956a6 (patch) | |
tree | c60b9a1f8d0d4d8a9630d0a218b265cb743e8869 /bgpd/bgp_route.c | |
parent | Merge pull request #11422 from opensourcerouting/feature/autoclose_stale_issu... (diff) | |
download | frr-d864dd9eb182eefaa4d08717bd2837f9182956a6.tar.xz frr-d864dd9eb182eefaa4d08717bd2837f9182956a6.zip |
bgpd: Add RFC9234 implementation
RFC9234 is a way to establish correct connection roles (Customer/
Provider, Peer or with RS) between bgp speakers. This patch:
- Add a new configuration/terminal option to set the appropriate local
role;
- Add a mechanism for checking used roles, implemented by exchanging
the corresponding capabilities in OPEN messages;
- Add strict mode to force other party to use this feature;
- Add basic support for a new transitive optional bgp attribute - OTC
(Only to Customer);
- Add logic for default setting OTC attribute and filtering routes with
this attribute by the edge speakers, if the appropriate conditions are
met;
- Add two test stands to check role negotiation and route filtering
during role usage.
Signed-off-by: Eugene Bogomazov <eb@qrator.net>
Diffstat (limited to 'bgpd/bgp_route.c')
-rw-r--r-- | bgpd/bgp_route.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f9d01913a..90e3f8805 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1561,6 +1561,43 @@ static bool bgp_cluster_filter(struct peer *peer, struct attr *attr) return false; } +static bool bgp_otc_filter(struct peer *peer, struct attr *attr) +{ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) { + if (peer->local_role == ROLE_PROVIDER || + peer->local_role == ROLE_RS_SERVER) + return true; + if (peer->local_role == ROLE_PEER && attr->otc != peer->as) + return true; + return false; + } + if (peer->local_role == ROLE_CUSTOMER || + peer->local_role == ROLE_PEER || + peer->local_role == ROLE_RS_CLIENT) { + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC); + attr->otc = peer->as; + } + return false; +} + +static bool bgp_otc_egress(struct peer *peer, struct attr *attr) +{ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) { + if (peer->local_role == ROLE_CUSTOMER || + peer->local_role == ROLE_RS_CLIENT || + peer->local_role == ROLE_PEER) + return true; + return false; + } + if (peer->local_role == ROLE_PROVIDER || + peer->local_role == ROLE_PEER || + peer->local_role == ROLE_RS_SERVER) { + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC); + attr->otc = peer->bgp->as; + } + return false; +} + static int bgp_input_modifier(struct peer *peer, const struct prefix *p, struct attr *attr, afi_t afi, safi_t safi, const char *rmap_name, mpls_label_t *label, @@ -2165,6 +2202,9 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN); } + if (bgp_otc_egress(peer, attr)) + return false; + bgp_peer_remove_private_as(bgp, afi, safi, peer, attr); bgp_peer_as_override(bgp, afi, safi, peer, attr); @@ -3961,6 +4001,12 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, goto filtered; } + if (bgp_otc_filter(peer, &new_attr)) { + reason = "failing otc validation"; + bgp_attr_flush(&new_attr); + goto filtered; + } + /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following * condition : * Suppress fib is enabled @@ -10447,6 +10493,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, vty_out(vty, ", atomic-aggregate"); } + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) { + if (json_paths) + json_object_int_add(json_path, "otc", attr->otc); + else + vty_out(vty, ", otc %u", attr->otc); + } + if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH) || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED) && bgp_path_info_mpath_count(path))) { |