Skip to content

Commit 094dcc3

Browse files
bgpd: fix "bgp as-pah access-list" with "set aspath exclude" set/unset issues
whith the following config router bgp 65001 no bgp ebgp-requires-policy neighbor 192.168.1.2 remote-as external neighbor 192.168.1.2 timers 3 10 ! address-family ipv4 unicast neighbor 192.168.1.2 route-map r2 in exit-address-family exit ! bgp as-path access-list FIRST seq 5 permit ^65 bgp as-path access-list SECOND seq 5 permit 2$ ! route-map r2 permit 6 match ip address prefix-list p2 set as-path exclude as-path-access-list SECOND exit ! route-map r2 permit 10 match ip address prefix-list p1 set as-path exclude 65003 exit ! route-map r2 permit 20 match ip address prefix-list p3 set as-path exclude all exit making some no bgp as-path access-list SECOND permit 2$ bgp as-path access-list SECOND permit 3$ clear bgp * no bgp as-path access-list SECOND permit 3$ bgp as-path access-list SECOND permit 2$ clear bgp * will induce some crashes thus we rework the links between aslists and aspath_exclude Signed-off-by: Francois Dumontet <[email protected]>
1 parent db1e2a0 commit 094dcc3

File tree

5 files changed

+108
-59
lines changed

5 files changed

+108
-59
lines changed

bgpd/bgp_aspath.c

+47
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ static struct hash *ashash;
7777
/* Stream for SNMP. See aspath_snmp_pathseg */
7878
static struct stream *snmp_stream;
7979

80+
/* as-path orphan exclude list */
81+
static struct as_list_list_head as_exclude_list_orphan;
82+
8083
/* Callers are required to initialize the memory */
8184
static as_t *assegment_data_new(int num)
8285
{
@@ -1558,6 +1561,38 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
15581561
/* Not reached */
15591562
}
15601563

1564+
/* insert aspath exclude in head of orphan exclude list*/
1565+
void as_exclude_set_orphan(struct aspath_exclude *ase)
1566+
{
1567+
ase->exclude_aspath_acl = NULL;
1568+
as_list_list_add_head(&as_exclude_list_orphan, ase);
1569+
}
1570+
1571+
void as_exclude_remove_orphan(struct aspath_exclude *ase)
1572+
{
1573+
if (as_list_list_count(&as_exclude_list_orphan))
1574+
as_list_list_del(&as_exclude_list_orphan, ase);
1575+
}
1576+
1577+
/* currently provide only one exclude, not a list */
1578+
struct aspath_exclude *as_exclude_lookup_orphan(const char *acl_name)
1579+
{
1580+
struct aspath_exclude *ase = NULL;
1581+
char *name = NULL;
1582+
1583+
frr_each (as_list_list, &as_exclude_list_orphan, ase) {
1584+
if (ase->exclude_aspath_acl_name) {
1585+
name = ase->exclude_aspath_acl_name;
1586+
if (!strcmp(name, acl_name))
1587+
break;
1588+
}
1589+
}
1590+
if (ase)
1591+
as_exclude_remove_orphan(ase);
1592+
1593+
return ase;
1594+
}
1595+
15611596
/* Iterate over AS_PATH segments and wipe all occurrences of the
15621597
* listed AS numbers. Hence some segments may lose some or even
15631598
* all data on the way, the operation is implemented as a smarter
@@ -2236,14 +2271,26 @@ void aspath_init(void)
22362271
{
22372272
ashash = hash_create_size(32768, aspath_key_make, aspath_cmp,
22382273
"BGP AS Path");
2274+
2275+
as_list_list_init(&as_exclude_list_orphan);
22392276
}
22402277

22412278
void aspath_finish(void)
22422279
{
2280+
struct aspath_exclude *ase;
2281+
22432282
hash_clean_and_free(&ashash, (void (*)(void *))aspath_free);
22442283

22452284
if (snmp_stream)
22462285
stream_free(snmp_stream);
2286+
2287+
while ((ase = as_list_list_pop(&as_exclude_list_orphan))) {
2288+
aspath_free(ase->aspath);
2289+
if (ase->exclude_aspath_acl_name)
2290+
XFREE(MTYPE_TMP, ase->exclude_aspath_acl_name);
2291+
XFREE(MTYPE_ROUTE_MAP_COMPILED, ase);
2292+
}
2293+
as_list_list_fini(&as_exclude_list_orphan);
22472294
}
22482295

22492296
/* return and as path value */

bgpd/bgp_aspath.h

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "lib/json.h"
1010
#include "bgpd/bgp_route.h"
1111
#include "bgpd/bgp_filter.h"
12+
#include <typesafe.h>
1213

1314
/* AS path segment type. */
1415
#define AS_SET 1
@@ -67,11 +68,14 @@ struct aspath {
6768

6869
/* `set as-path exclude ASn' */
6970
struct aspath_exclude {
71+
struct as_list_list_item exclude_list;
7072
struct aspath *aspath;
7173
bool exclude_all;
7274
char *exclude_aspath_acl_name;
7375
struct as_list *exclude_aspath_acl;
7476
};
77+
DECLARE_DLIST(as_list_list, struct aspath_exclude, exclude_list);
78+
7579

7680
/* Prototypes. */
7781
extern void aspath_init(void);
@@ -83,6 +87,9 @@ extern struct aspath *aspath_parse(struct stream *s, size_t length,
8387
extern struct aspath *aspath_dup(struct aspath *aspath);
8488
extern struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2);
8589
extern struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2);
90+
extern void as_exclude_set_orphan(struct aspath_exclude *ase);
91+
extern void as_exclude_remove_orphan(struct aspath_exclude *ase);
92+
extern struct aspath_exclude *as_exclude_lookup_orphan(const char *acl_name);
8693
extern struct aspath *aspath_filter_exclude(struct aspath *source,
8794
struct aspath *exclude_list);
8895
extern struct aspath *aspath_filter_exclude_all(struct aspath *source);

bgpd/bgp_filter.c

+25-16
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include "bgpd/bgp_aspath.h"
1717
#include "bgpd/bgp_regex.h"
1818

19-
/* List of AS filter list. */
19+
/* List of AS list. */
2020
struct as_list_list {
2121
struct as_list *head;
2222
struct as_list *tail;
@@ -205,14 +205,6 @@ static struct as_list *as_list_new(void)
205205

206206
static void as_list_free(struct as_list *aslist)
207207
{
208-
struct aspath_exclude_list *cur_bp = aslist->exclude_list;
209-
struct aspath_exclude_list *next_bp = NULL;
210-
211-
while (cur_bp) {
212-
next_bp = cur_bp->next;
213-
XFREE(MTYPE_ROUTE_MAP_COMPILED, cur_bp);
214-
cur_bp = next_bp;
215-
}
216208

217209
XFREE (MTYPE_AS_STR, aslist->name);
218210
XFREE (MTYPE_AS_LIST, aslist);
@@ -299,7 +291,6 @@ static void as_list_delete(struct as_list *aslist)
299291
{
300292
struct as_list_list *list;
301293
struct as_filter *filter, *next;
302-
struct aspath_exclude_list *cur_bp;
303294

304295
for (filter = aslist->head; filter; filter = next) {
305296
next = filter->next;
@@ -318,12 +309,6 @@ static void as_list_delete(struct as_list *aslist)
318309
else
319310
list->head = aslist->next;
320311

321-
cur_bp = aslist->exclude_list;
322-
while (cur_bp) {
323-
cur_bp->bp_as_excl->exclude_aspath_acl = NULL;
324-
cur_bp = cur_bp->next;
325-
}
326-
327312
as_list_free(aslist);
328313
}
329314

@@ -431,6 +416,7 @@ DEFUN(as_path, bgp_as_path_cmd,
431416
enum as_filter_type type;
432417
struct as_filter *asfilter;
433418
struct as_list *aslist;
419+
struct aspath_exclude *ase;
434420
regex_t *regex;
435421
char *regstr;
436422
int64_t seqnum = ASPATH_SEQ_NUMBER_AUTO;
@@ -482,6 +468,22 @@ DEFUN(as_path, bgp_as_path_cmd,
482468
else
483469
as_list_filter_add(aslist, asfilter);
484470

471+
/* init the exclude rule list*/
472+
as_list_list_init(&aslist->exclude_rule);
473+
474+
/* get aspath orphan exclude that are using this acl */
475+
ase = as_exclude_lookup_orphan(alname);
476+
if (ase) {
477+
as_list_list_add_head(&aslist->exclude_rule, ase);
478+
/* set reverse pointer */
479+
ase->exclude_aspath_acl = aslist;
480+
/* set list of aspath excludes using that acl */
481+
while ((ase = as_exclude_lookup_orphan(alname))) {
482+
as_list_list_add_head(&aslist->exclude_rule, ase);
483+
ase->exclude_aspath_acl = aslist;
484+
}
485+
}
486+
485487
return CMD_SUCCESS;
486488
}
487489

@@ -502,6 +504,7 @@ DEFUN(no_as_path, no_bgp_as_path_cmd,
502504
enum as_filter_type type;
503505
struct as_filter *asfilter;
504506
struct as_list *aslist;
507+
struct aspath_exclude *ase;
505508
char *regstr;
506509
regex_t *regex;
507510

@@ -556,6 +559,12 @@ DEFUN(no_as_path, no_bgp_as_path_cmd,
556559

557560
XFREE(MTYPE_TMP, regstr);
558561

562+
/* put aspath exclude list into orphan */
563+
if (as_list_list_count(&aslist->exclude_rule))
564+
while ((ase = as_list_list_pop(&aslist->exclude_rule)))
565+
as_exclude_set_orphan(ase);
566+
567+
as_list_list_fini(&aslist->exclude_rule);
559568
as_list_filter_delete(aslist, asfilter);
560569

561570
return CMD_SUCCESS;

bgpd/bgp_filter.h

+6-7
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
#ifndef _QUAGGA_BGP_FILTER_H
77
#define _QUAGGA_BGP_FILTER_H
88

9+
#include <typesafe.h>
10+
911
#define ASPATH_SEQ_NUMBER_AUTO -1
1012

1113
enum as_filter_type { AS_FILTER_DENY, AS_FILTER_PERMIT };
1214

13-
1415
/* Element of AS path filter. */
1516
struct as_filter {
1617
struct as_filter *next;
@@ -25,11 +26,7 @@ struct as_filter {
2526
int64_t seq;
2627
};
2728

28-
struct aspath_exclude_list {
29-
struct aspath_exclude_list *next;
30-
struct aspath_exclude *bp_as_excl;
31-
};
32-
29+
PREDECL_DLIST(as_list_list);
3330
/* AS path filter list. */
3431
struct as_list {
3532
char *name;
@@ -39,7 +36,9 @@ struct as_list {
3936

4037
struct as_filter *head;
4138
struct as_filter *tail;
42-
struct aspath_exclude_list *exclude_list;
39+
40+
/* Changes in AS path */
41+
struct as_list_list_head exclude_rule;
4342
};
4443

4544

bgpd/bgp_routemap.c

+23-36
Original file line numberDiff line numberDiff line change
@@ -2325,7 +2325,7 @@ static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
23252325
static void *route_aspath_exclude_compile(const char *arg)
23262326
{
23272327
struct aspath_exclude *ase;
2328-
struct aspath_exclude_list *ael;
2328+
struct as_list *aux_aslist;
23292329
const char *str = arg;
23302330
static const char asp_acl[] = "as-path-access-list";
23312331

@@ -2337,44 +2337,37 @@ static void *route_aspath_exclude_compile(const char *arg)
23372337
while (*str == ' ')
23382338
str++;
23392339
ase->exclude_aspath_acl_name = XSTRDUP(MTYPE_TMP, str);
2340-
ase->exclude_aspath_acl = as_list_lookup(str);
2340+
aux_aslist = as_list_lookup(str);
2341+
if (!aux_aslist)
2342+
/* new orphan filter */
2343+
as_exclude_set_orphan(ase);
2344+
else
2345+
as_list_list_add_head(&aux_aslist->exclude_rule, ase);
2346+
2347+
ase->exclude_aspath_acl = aux_aslist;
23412348
} else
23422349
ase->aspath = aspath_str2aspath(str, bgp_get_asnotation(NULL));
23432350

2344-
if (ase->exclude_aspath_acl) {
2345-
ael = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
2346-
sizeof(struct aspath_exclude_list));
2347-
ael->bp_as_excl = ase;
2348-
ael->next = ase->exclude_aspath_acl->exclude_list;
2349-
ase->exclude_aspath_acl->exclude_list = ael;
2350-
}
2351-
23522351
return ase;
23532352
}
23542353

23552354
static void route_aspath_exclude_free(void *rule)
23562355
{
23572356
struct aspath_exclude *ase = rule;
2358-
struct aspath_exclude_list *cur_ael = NULL;
2359-
struct aspath_exclude_list *prev_ael = NULL;
2357+
struct as_list *acl;
2358+
2359+
/* manage references to that rule*/
2360+
if (ase->exclude_aspath_acl) {
2361+
acl = ase->exclude_aspath_acl;
2362+
as_list_list_del(&acl->exclude_rule, ase);
2363+
} else {
2364+
/* no ref to acl, this aspath exclude is orphan */
2365+
as_exclude_remove_orphan(ase);
2366+
}
23602367

23612368
aspath_free(ase->aspath);
23622369
if (ase->exclude_aspath_acl_name)
23632370
XFREE(MTYPE_TMP, ase->exclude_aspath_acl_name);
2364-
if (ase->exclude_aspath_acl)
2365-
cur_ael = ase->exclude_aspath_acl->exclude_list;
2366-
while (cur_ael) {
2367-
if (cur_ael->bp_as_excl == ase) {
2368-
if (prev_ael)
2369-
prev_ael->next = cur_ael->next;
2370-
else
2371-
ase->exclude_aspath_acl->exclude_list = NULL;
2372-
XFREE(MTYPE_ROUTE_MAP_COMPILED, cur_ael);
2373-
break;
2374-
}
2375-
prev_ael = cur_ael;
2376-
cur_ael = cur_ael->next;
2377-
}
23782371
XFREE(MTYPE_ROUTE_MAP_COMPILED, ase);
23792372
}
23802373

@@ -2409,16 +2402,10 @@ route_set_aspath_exclude(void *rule, const struct prefix *dummy, void *object)
24092402
else if (ase->exclude_all)
24102403
path->attr->aspath = aspath_filter_exclude_all(new_path);
24112404

2412-
else if (ase->exclude_aspath_acl_name) {
2413-
if (!ase->exclude_aspath_acl)
2414-
ase->exclude_aspath_acl =
2415-
as_list_lookup(ase->exclude_aspath_acl_name);
2416-
if (ase->exclude_aspath_acl)
2417-
path->attr->aspath =
2418-
aspath_filter_exclude_acl(new_path,
2419-
ase->exclude_aspath_acl);
2420-
}
2421-
2405+
else if (ase->exclude_aspath_acl)
2406+
path->attr->aspath =
2407+
aspath_filter_exclude_acl(new_path,
2408+
ase->exclude_aspath_acl);
24222409
return RMAP_OKAY;
24232410
}
24242411

0 commit comments

Comments
 (0)