diff options
| author | Francois Dumontet <francois.dumontet@6wind.com> | 2023-07-12 19:44:02 +0200 |
|---|---|---|
| committer | Francois Dumontet <francois.dumontet@6wind.com> | 2023-07-19 10:57:48 +0200 |
| commit | 4685db418e3a861205a28f975afeb9869f674337 (patch) | |
| tree | 88b1f16aa91218014d377b060449a611fca2e7a6 /bgpd/bgp_aspath.c | |
| parent | 3c7eec962545dbd53a0ada64c349fe2673671e37 (diff) | |
bgpd: add set as-path exclude acl-list command
A route-map applied on incoming BGP updates is not able
to exclude the unwanted as segments, based on an AS path
access-list.
The below configuration illustrates the case:
router bgp 65001
address-family ipv4 unicast
neighbor 192.168.1.2 route-map rule_2 in
exit-address-family
bgp as-path access-list RULE permit ^65
route-map rule_2 permit 10
set as-path exclude as-path-access-list RULE
```
BGP routing table entry for 10.10.10.10/32, version 13
Paths: (1 available, best #1, table default)
Advertised to non peer-group peers:
192.168.10.65
65000 1 2 3 123
192.168.10.65 from 192.168.10.65 (10.10.10.11)
Origin IGP, metric 0, valid, external, best (First path received)
```
After:
```
do show ip bgp 10.10.10.10/32
BGP routing table entry for 10.10.10.10/32, version 15
Paths: (1 available, best #1, table default)
Advertised to non peer-group peers:
192.168.10.65
2 3 123
192.168.10.65 from 192.168.10.65 (10.10.10.11)
Origin IGP, metric 0, valid, external, best (First path
received)
```
Signed-off-by: Francois Dumontet <francois.dumontet@6wind.com>
Diffstat (limited to 'bgpd/bgp_aspath.c')
| -rw-r--r-- | bgpd/bgp_aspath.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 22c9fe0e66..4ea81216bf 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -21,6 +21,7 @@ #include "bgpd/bgp_debug.h" #include "bgpd/bgp_attr.h" #include "bgpd/bgp_errors.h" +#include "bgpd/bgp_filter.h" /* Attr. Flags and Attr. Type Code. */ #define AS_HEADER_SIZE 2 @@ -1616,6 +1617,92 @@ struct aspath *aspath_filter_exclude_all(struct aspath *source) return newpath; } +struct aspath *aspath_filter_exclude_acl(struct aspath *source, + struct as_list *acl_list) +{ + struct assegment *cur_seg, *new_seg, *prev_seg, *next_seg; + struct as_list *cur_as_list; + struct as_filter *cur_as_filter; + char str_buf[ASPATH_STR_DEFAULT_LEN]; + uint32_t nb_as_del; + uint32_t i, j; + + cur_seg = source->segments; + prev_seg = NULL; + /* segments from source aspath */ + while (cur_seg) { + next_seg = cur_seg->next; + cur_as_list = acl_list; + nb_as_del = 0; + /* aspath filter list from acl_list */ + while (cur_as_list) { + cur_as_filter = cur_as_list->head; + while (cur_as_filter) { + for (i = 0; i < cur_seg->length; i++) { + if (cur_seg->as[i] == 0) + continue; + + snprintfrr(str_buf, + ASPATH_STR_DEFAULT_LEN, + ASN_FORMAT(source->asnotation), + &cur_seg->as[i]); + if (!regexec(cur_as_filter->reg, + str_buf, 0, NULL, 0)) { + cur_seg->as[i] = 0; + nb_as_del++; + } + } + + cur_as_filter = cur_as_filter->next; + } + + cur_as_list = cur_as_list->next; + } + /* full segment is excluded remove it */ + if (nb_as_del == cur_seg->length) { + if (cur_seg == source->segments) + /* first segment */ + source->segments = cur_seg->next; + else + prev_seg->next = cur_seg->next; + assegment_free(cur_seg); + } + /* change in segment size -> new allocation and replace segment*/ + else if (nb_as_del) { + new_seg = assegment_new(cur_seg->type, + cur_seg->length - nb_as_del); + j = 0; + for (i = 0; i < cur_seg->length; i++) { + if (cur_seg->as[i] == 0) + continue; + new_seg->as[j] = cur_seg->as[i]; + j++; + } + new_seg->next = next_seg; + if (cur_seg == source->segments) + /* first segment */ + source->segments = new_seg; + else if (prev_seg) + prev_seg->next = new_seg; + assegment_free(cur_seg); + } + prev_seg = cur_seg; + cur_seg = next_seg; + } + + + aspath_str_update(source, false); + /* We are happy returning even an empty AS_PATH, because the + * administrator + * might expect this very behaviour. There's a mean to avoid this, if + * necessary, + * by having a match rule against certain AS_PATH regexps in the + * route-map index. + */ + return source; +} + + /* Add specified AS to the leftmost of aspath. */ static struct aspath *aspath_add_asns(struct aspath *aspath, as_t asno, uint8_t type, unsigned num) |
