diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index ebfc7d087d66..2a831c3a5510 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -65,6 +65,14 @@ struct aspath { #define ASPATH_STR_DEFAULT_LEN 32 +/* `set as-path exclude ASn' */ +struct aspath_exclude { + struct aspath *aspath; + bool exclude_all; + char *exclude_aspath_acl_name; + struct as_list *exclude_aspath_acl; +}; + /* Prototypes. */ extern void aspath_init(void); extern void aspath_finish(void); diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c index ad541b67ad44..a85117965aaa 100644 --- a/bgpd/bgp_filter.c +++ b/bgpd/bgp_filter.c @@ -205,8 +205,17 @@ static struct as_list *as_list_new(void) static void as_list_free(struct as_list *aslist) { - XFREE(MTYPE_AS_STR, aslist->name); - XFREE(MTYPE_AS_LIST, aslist); + struct aspath_exclude_list *cur_bp = aslist->exclude_list; + struct aspath_exclude_list *next_bp = NULL; + + while (cur_bp) { + next_bp = cur_bp->next; + XFREE(MTYPE_ROUTE_MAP_COMPILED, cur_bp); + cur_bp = next_bp; + } + + XFREE (MTYPE_AS_STR, aslist->name); + XFREE (MTYPE_AS_LIST, aslist); } /* Insert new AS list to list of as_list. Each as_list is sorted by @@ -290,6 +299,7 @@ static void as_list_delete(struct as_list *aslist) { struct as_list_list *list; struct as_filter *filter, *next; + struct aspath_exclude_list *cur_bp; for (filter = aslist->head; filter; filter = next) { next = filter->next; @@ -308,6 +318,12 @@ static void as_list_delete(struct as_list *aslist) else list->head = aslist->next; + cur_bp = aslist->exclude_list; + while (cur_bp) { + cur_bp->bp_as_excl->exclude_aspath_acl = NULL; + cur_bp = cur_bp->next; + } + as_list_free(aslist); } diff --git a/bgpd/bgp_filter.h b/bgpd/bgp_filter.h index 1890fd3d9664..2d9f07ce84a3 100644 --- a/bgpd/bgp_filter.h +++ b/bgpd/bgp_filter.h @@ -25,6 +25,11 @@ struct as_filter { int64_t seq; }; +struct aspath_exclude_list { + struct aspath_exclude_list *next; + struct aspath_exclude *bp_as_excl; +}; + /* AS path filter list. */ struct as_list { char *name; @@ -34,6 +39,7 @@ struct as_list { struct as_filter *head; struct as_filter *tail; + struct aspath_exclude_list *exclude_list; }; diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 36e04c5e681e..f4ebd4aa9b5a 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -2323,17 +2323,10 @@ static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = { route_set_aspath_prepend_free, }; -/* `set as-path exclude ASn' */ -struct aspath_exclude { - struct aspath *aspath; - bool exclude_all; - char *exclude_aspath_acl_name; - struct as_list *exclude_aspath_acl; -}; - static void *route_aspath_exclude_compile(const char *arg) { struct aspath_exclude *ase; + struct aspath_exclude_list *ael; const char *str = arg; static const char asp_acl[] = "as-path-access-list"; @@ -2348,16 +2341,41 @@ static void *route_aspath_exclude_compile(const char *arg) ase->exclude_aspath_acl = as_list_lookup(str); } else ase->aspath = aspath_str2aspath(str, bgp_get_asnotation(NULL)); + + if (ase->exclude_aspath_acl) { + ael = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, + sizeof(struct aspath_exclude_list)); + ael->bp_as_excl = ase; + ael->next = ase->exclude_aspath_acl->exclude_list; + ase->exclude_aspath_acl->exclude_list = ael; + } + return ase; } static void route_aspath_exclude_free(void *rule) { struct aspath_exclude *ase = rule; + struct aspath_exclude_list *cur_ael = NULL; + struct aspath_exclude_list *prev_ael = NULL; aspath_free(ase->aspath); if (ase->exclude_aspath_acl_name) XFREE(MTYPE_TMP, ase->exclude_aspath_acl_name); + if (ase->exclude_aspath_acl) + cur_ael = ase->exclude_aspath_acl->exclude_list; + while (cur_ael) { + if (cur_ael->bp_as_excl == ase) { + if (prev_ael) + prev_ael->next = cur_ael->next; + else + ase->exclude_aspath_acl->exclude_list = NULL; + XFREE(MTYPE_ROUTE_MAP_COMPILED, cur_ael); + break; + } + prev_ael = cur_ael; + cur_ael = cur_ael->next; + } XFREE(MTYPE_ROUTE_MAP_COMPILED, ase); }