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 <francois.dumontet@6wind.com>
(cherry picked from commit
094dcc3cdac19d3da65b38effc45aa88d960909f)
/* Stream for SNMP. See aspath_snmp_pathseg */
static struct stream *snmp_stream;
+/* as-path orphan exclude list */
+static struct as_list_list_head as_exclude_list_orphan;
+
/* Callers are required to initialize the memory */
static as_t *assegment_data_new(int num)
{
/* Not reached */
}
+/* insert aspath exclude in head of orphan exclude list*/
+void as_exclude_set_orphan(struct aspath_exclude *ase)
+{
+ ase->exclude_aspath_acl = NULL;
+ as_list_list_add_head(&as_exclude_list_orphan, ase);
+}
+
+void as_exclude_remove_orphan(struct aspath_exclude *ase)
+{
+ if (as_list_list_count(&as_exclude_list_orphan))
+ as_list_list_del(&as_exclude_list_orphan, ase);
+}
+
+/* currently provide only one exclude, not a list */
+struct aspath_exclude *as_exclude_lookup_orphan(const char *acl_name)
+{
+ struct aspath_exclude *ase = NULL;
+ char *name = NULL;
+
+ frr_each (as_list_list, &as_exclude_list_orphan, ase) {
+ if (ase->exclude_aspath_acl_name) {
+ name = ase->exclude_aspath_acl_name;
+ if (!strcmp(name, acl_name))
+ break;
+ }
+ }
+ if (ase)
+ as_exclude_remove_orphan(ase);
+
+ return ase;
+}
+
/* Iterate over AS_PATH segments and wipe all occurrences of the
* listed AS numbers. Hence some segments may lose some or even
* all data on the way, the operation is implemented as a smarter
{
ashash = hash_create_size(32768, aspath_key_make, aspath_cmp,
"BGP AS Path");
+
+ as_list_list_init(&as_exclude_list_orphan);
}
void aspath_finish(void)
{
+ struct aspath_exclude *ase;
+
hash_clean_and_free(&ashash, (void (*)(void *))aspath_free);
if (snmp_stream)
stream_free(snmp_stream);
+
+ while ((ase = as_list_list_pop(&as_exclude_list_orphan))) {
+ aspath_free(ase->aspath);
+ if (ase->exclude_aspath_acl_name)
+ XFREE(MTYPE_TMP, ase->exclude_aspath_acl_name);
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, ase);
+ }
+ as_list_list_fini(&as_exclude_list_orphan);
}
/* return and as path value */
#include "lib/json.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_filter.h"
+#include <typesafe.h>
/* AS path segment type. */
#define AS_SET 1
/* `set as-path exclude ASn' */
struct aspath_exclude {
+ struct as_list_list_item exclude_list;
struct aspath *aspath;
bool exclude_all;
char *exclude_aspath_acl_name;
struct as_list *exclude_aspath_acl;
};
+DECLARE_DLIST(as_list_list, struct aspath_exclude, exclude_list);
+
/* Prototypes. */
extern void aspath_init(void);
extern struct aspath *aspath_dup(struct aspath *aspath);
extern struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2);
extern struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2);
+extern void as_exclude_set_orphan(struct aspath_exclude *ase);
+extern void as_exclude_remove_orphan(struct aspath_exclude *ase);
+extern struct aspath_exclude *as_exclude_lookup_orphan(const char *acl_name);
extern struct aspath *aspath_filter_exclude(struct aspath *source,
struct aspath *exclude_list);
extern struct aspath *aspath_filter_exclude_all(struct aspath *source);
#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_regex.h"
-/* List of AS filter list. */
+/* List of AS list. */
struct as_list_list {
struct as_list *head;
struct as_list *tail;
static void as_list_free(struct 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);
{
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;
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);
}
enum as_filter_type type;
struct as_filter *asfilter;
struct as_list *aslist;
+ struct aspath_exclude *ase;
regex_t *regex;
char *regstr;
int64_t seqnum = ASPATH_SEQ_NUMBER_AUTO;
else
as_list_filter_add(aslist, asfilter);
+ /* init the exclude rule list*/
+ as_list_list_init(&aslist->exclude_rule);
+
+ /* get aspath orphan exclude that are using this acl */
+ ase = as_exclude_lookup_orphan(alname);
+ if (ase) {
+ as_list_list_add_head(&aslist->exclude_rule, ase);
+ /* set reverse pointer */
+ ase->exclude_aspath_acl = aslist;
+ /* set list of aspath excludes using that acl */
+ while ((ase = as_exclude_lookup_orphan(alname))) {
+ as_list_list_add_head(&aslist->exclude_rule, ase);
+ ase->exclude_aspath_acl = aslist;
+ }
+ }
+
return CMD_SUCCESS;
}
enum as_filter_type type;
struct as_filter *asfilter;
struct as_list *aslist;
+ struct aspath_exclude *ase;
char *regstr;
regex_t *regex;
XFREE(MTYPE_TMP, regstr);
+ /* put aspath exclude list into orphan */
+ if (as_list_list_count(&aslist->exclude_rule))
+ while ((ase = as_list_list_pop(&aslist->exclude_rule)))
+ as_exclude_set_orphan(ase);
+
+ as_list_list_fini(&aslist->exclude_rule);
as_list_filter_delete(aslist, asfilter);
return CMD_SUCCESS;
#ifndef _QUAGGA_BGP_FILTER_H
#define _QUAGGA_BGP_FILTER_H
+#include <typesafe.h>
+
#define ASPATH_SEQ_NUMBER_AUTO -1
enum as_filter_type { AS_FILTER_DENY, AS_FILTER_PERMIT };
-
/* Element of AS path filter. */
struct as_filter {
struct as_filter *next;
int64_t seq;
};
-struct aspath_exclude_list {
- struct aspath_exclude_list *next;
- struct aspath_exclude *bp_as_excl;
-};
-
+PREDECL_DLIST(as_list_list);
/* AS path filter list. */
struct as_list {
char *name;
struct as_filter *head;
struct as_filter *tail;
- struct aspath_exclude_list *exclude_list;
+
+ /* Changes in AS path */
+ struct as_list_list_head exclude_rule;
};
static void *route_aspath_exclude_compile(const char *arg)
{
struct aspath_exclude *ase;
- struct aspath_exclude_list *ael;
+ struct as_list *aux_aslist;
const char *str = arg;
static const char asp_acl[] = "as-path-access-list";
while (*str == ' ')
str++;
ase->exclude_aspath_acl_name = XSTRDUP(MTYPE_TMP, str);
- ase->exclude_aspath_acl = as_list_lookup(str);
+ aux_aslist = as_list_lookup(str);
+ if (!aux_aslist)
+ /* new orphan filter */
+ as_exclude_set_orphan(ase);
+ else
+ as_list_list_add_head(&aux_aslist->exclude_rule, ase);
+
+ ase->exclude_aspath_acl = aux_aslist;
} 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;
+ struct as_list *acl;
+
+ /* manage references to that rule*/
+ if (ase->exclude_aspath_acl) {
+ acl = ase->exclude_aspath_acl;
+ as_list_list_del(&acl->exclude_rule, ase);
+ } else {
+ /* no ref to acl, this aspath exclude is orphan */
+ as_exclude_remove_orphan(ase);
+ }
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);
}
else if (ase->exclude_all)
path->attr->aspath = aspath_filter_exclude_all(new_path);
- else if (ase->exclude_aspath_acl_name) {
- if (!ase->exclude_aspath_acl)
- ase->exclude_aspath_acl =
- as_list_lookup(ase->exclude_aspath_acl_name);
- if (ase->exclude_aspath_acl)
- path->attr->aspath =
- aspath_filter_exclude_acl(new_path,
- ase->exclude_aspath_acl);
- }
-
+ else if (ase->exclude_aspath_acl)
+ path->attr->aspath =
+ aspath_filter_exclude_acl(new_path,
+ ase->exclude_aspath_acl);
return RMAP_OKAY;
}