bgpd: Reject routes having AS_SET or AS_CONFED_SET

This is the first step towards eliminating AS_SET and AS_CONFED_SET types
and obsolete them in the future.

More information:
https://datatracker.ietf.org/doc/html/draft-ietf-idr-deprecate-as-set-confed-set-02

Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
This commit is contained in:
Donatas Abraitis 2019-11-09 20:24:34 +02:00
parent 306c4dab55
commit fb29348a19
6 changed files with 133 additions and 7 deletions

View File

@ -414,6 +414,19 @@ unsigned int aspath_count_hops(const struct aspath *aspath)
return count;
}
/* Check if aspath has AS_SET or AS_CONFED_SET */
bool aspath_check_as_sets(struct aspath *aspath)
{
struct assegment *seg = aspath->segments;
while (seg) {
if (seg->type == AS_SET || seg->type == AS_CONFED_SET)
return true;
seg = seg->next;
}
return false;
}
/* Estimate size aspath /might/ take if encoded into an
* ASPATH attribute.
*

View File

@ -120,6 +120,7 @@ extern int aspath_confed_check(struct aspath *);
extern int aspath_left_confed_check(struct aspath *);
extern unsigned long aspath_count(void);
extern unsigned int aspath_count_hops(const struct aspath *);
extern bool aspath_check_as_sets(struct aspath *aspath);
extern unsigned int aspath_count_confeds(struct aspath *);
extern unsigned int aspath_size(struct aspath *);
extern as_t aspath_highest(struct aspath *);

View File

@ -1850,6 +1850,16 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
if (!bgp_outbound_policy_exists(peer, filter))
return 0;
/* draft-ietf-idr-deprecate-as-set-confed-set
* Filter routes having AS_SET or AS_CONFED_SET in the path.
* Eventually, This document (if approved) updates RFC 4271
* and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
* and obsoletes RFC 6472.
*/
if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
if (aspath_check_as_sets(attr->aspath))
return 0;
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
if (peer->sort == BGP_PEER_IBGP
|| peer->sort == BGP_PEER_CONFED) {
@ -3143,6 +3153,19 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
goto filtered;
}
/* draft-ietf-idr-deprecate-as-set-confed-set
* Filter routes having AS_SET or AS_CONFED_SET in the path.
* Eventually, This document (if approved) updates RFC 4271
* and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
* and obsoletes RFC 6472.
*/
if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
if (aspath_check_as_sets(attr->aspath)) {
reason =
"as-path contains AS_SET or AS_CONFED_SET type;";
goto filtered;
}
bgp_attr_dup(&new_attr, attr);
/* Apply incoming route-map.
@ -6363,6 +6386,7 @@ void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
/* Aggregate route attribute. */
#define AGGREGATE_SUMMARY_ONLY 1
#define AGGREGATE_AS_SET 1
#define AGGREGATE_AS_UNSET 0
static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
afi_t afi, safi_t safi)
@ -6465,6 +6489,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
struct prefix p;
struct bgp_node *rn;
struct bgp_aggregate *aggregate;
uint8_t as_set_new = as_set;
/* Convert string to prefix structure. */
ret = str2prefix(prefix_str, &p);
@ -6499,7 +6524,27 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
/* Make aggregate address structure. */
aggregate = bgp_aggregate_new();
aggregate->summary_only = summary_only;
aggregate->as_set = as_set;
/* Network operators MUST NOT locally generate any new
* announcements containing AS_SET or AS_CONFED_SET. If they have
* announced routes with AS_SET or AS_CONFED_SET in them, then they
* SHOULD withdraw those routes and re-announce routes for the
* aggregate or component prefixes (i.e., the more-specific routes
* subsumed by the previously aggregated route) without AS_SET
* or AS_CONFED_SET in the updates.
*/
if (bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED) {
if (as_set == AGGREGATE_AS_SET) {
as_set_new = AGGREGATE_AS_UNSET;
zlog_warn(
"%s: Ignoring as-set because `bgp reject-as-sets` is enabled.\n",
__func__);
vty_out(vty,
"Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
}
}
aggregate->as_set = as_set_new;
aggregate->safi = safi;
if (rmap) {
@ -6534,8 +6579,8 @@ DEFUN (aggregate_address,
argv_find(argv, argc, "A.B.C.D/M", &idx);
char *prefix = argv[idx]->arg;
char *rmap = NULL;
int as_set =
argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
: AGGREGATE_AS_UNSET;
idx = 0;
int summary_only = argv_find(argv, argc, "summary-only", &idx)
? AGGREGATE_SUMMARY_ONLY
@ -6569,8 +6614,8 @@ DEFUN (aggregate_address_mask,
char *mask = argv[idx + 1]->arg;
bool rmap_found;
char *rmap = NULL;
int as_set =
argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
: AGGREGATE_AS_UNSET;
idx = 0;
int summary_only = argv_find(argv, argc, "summary-only", &idx)
? AGGREGATE_SUMMARY_ONLY
@ -6658,8 +6703,8 @@ DEFUN (ipv6_aggregate_address,
char *prefix = argv[idx]->arg;
char *rmap = NULL;
bool rmap_found;
int as_set =
argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
: AGGREGATE_AS_UNSET;
idx = 0;
int sum_only = argv_find(argv, argc, "summary-only", &idx)

View File

@ -1921,6 +1921,56 @@ DEFUN(no_bgp_ebgp_requires_policy, no_bgp_ebgp_requires_policy_cmd,
return CMD_SUCCESS;
}
DEFUN(bgp_reject_as_sets, bgp_reject_as_sets_cmd,
"bgp reject-as-sets",
"BGP specific commands\n"
"Reject routes with AS_SET or AS_CONFED_SET flag\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
struct listnode *node, *nnode;
struct peer *peer;
bgp->reject_as_sets = BGP_REJECT_AS_SETS_ENABLED;
/* Reset existing BGP sessions to reject routes
* with aspath containing AS_SET or AS_CONFED_SET.
*/
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
peer->last_reset = PEER_DOWN_AS_SETS_REJECT;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
}
return CMD_SUCCESS;
}
DEFUN(no_bgp_reject_as_sets, no_bgp_reject_as_sets_cmd,
"no bgp reject-as-sets",
NO_STR
"BGP specific commands\n"
"Reject routes with AS_SET or AS_CONFED_SET flag\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
struct listnode *node, *nnode;
struct peer *peer;
bgp->reject_as_sets = BGP_REJECT_AS_SETS_DISABLED;
/* Reset existing BGP sessions to reject routes
* with aspath containing AS_SET or AS_CONFED_SET.
*/
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
peer->last_reset = PEER_DOWN_AS_SETS_REJECT;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
}
return CMD_SUCCESS;
}
/* "bgp deterministic-med" configuration. */
DEFUN (bgp_deterministic_med,
@ -13128,6 +13178,10 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &bgp_ebgp_requires_policy_cmd);
install_element(BGP_NODE, &no_bgp_ebgp_requires_policy_cmd);
/* bgp reject-as-sets */
install_element(BGP_NODE, &bgp_reject_as_sets_cmd);
install_element(BGP_NODE, &no_bgp_reject_as_sets_cmd);
/* "bgp deterministic-med" commands */
install_element(BGP_NODE, &bgp_deterministic_med_cmd);
install_element(BGP_NODE, &no_bgp_deterministic_med_cmd);

View File

@ -2966,6 +2966,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
bgp->dynamic_neighbors_count = 0;
bgp->ebgp_requires_policy = DEFAULT_EBGP_POLICY_DISABLED;
bgp->reject_as_sets = BGP_REJECT_AS_SETS_DISABLED;
#if DFLT_BGP_IMPORT_CHECK
bgp_flag_set(bgp, BGP_FLAG_IMPORT_CHECK);
#endif
@ -7588,6 +7589,10 @@ int bgp_config_write(struct vty *vty)
== DEFAULT_EBGP_POLICY_ENABLED)
vty_out(vty, " bgp ebgp-requires-policy\n");
/* draft-ietf-idr-deprecate-as-set-confed-set */
if (bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
vty_out(vty, " bgp reject-as-sets\n");
/* BGP default ipv4-unicast. */
if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4))
vty_out(vty, " no bgp default ipv4-unicast\n");

View File

@ -504,6 +504,13 @@ struct bgp {
#define DEFAULT_EBGP_POLICY_DISABLED 0
#define DEFAULT_EBGP_POLICY_ENABLED 1
/* draft-ietf-idr-deprecate-as-set-confed-set
* Reject aspaths with AS_SET and/or AS_CONFED_SET.
*/
bool reject_as_sets;
#define BGP_REJECT_AS_SETS_DISABLED 0
#define BGP_REJECT_AS_SETS_ENABLED 1
struct bgp_evpn_info *evpn_info;
/* EVPN - use RFC 8365 to auto-derive RT */
@ -1203,6 +1210,7 @@ struct peer {
#define PEER_DOWN_NBR_ADDR 28 /* Waiting for peer IPv6 IP Addr */
#define PEER_DOWN_VRF_UNINIT 29 /* Associated VRF is not init yet */
#define PEER_DOWN_NOAFI_ACTIVATED 30 /* No AFI/SAFI activated for peer */
#define PEER_DOWN_AS_SETS_REJECT 31 /* Reject routes with AS_SET */
size_t last_reset_cause_size;
uint8_t last_reset_cause[BGP_MAX_PACKET_SIZE];