Here is hopefully the last pieces to finish ASAP support. This adds filter support. It is similar to origin validation and called AVS (ASPA validation state). Only difference is that not-found is called unknown in AVS. The diff also adds `bgpctl show rib avs invalid` support.
~> bgpctl show rib avs invalid flags: * = Valid, > = Selected, I = via IBGP, A = Announced, S = Stale, E = Error origin validation state: N = not-found, V = valid, ! = invalid aspa validation state: ? = unknown, V = valid, ! = invalid origin: i = IGP, e = EGP, ? = Incomplete flags vs destination gateway lpref med aspath origin *> V-! 2606:b0c0:b00b::/48 2001:db8::252 100 0 8271 6939 61138 945 i *m V-! 2606:b0c0:b00b::/48 2001:db8::253 100 0 8271 6939 61138 945 i So with this I found the first two invalid ASPA paths, time to adjust the filters :) -- :wq Claudio Index: usr.sbin/bgpd/bgpd.conf.5 =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.conf.5,v retrieving revision 1.229 diff -u -p -r1.229 bgpd.conf.5 --- usr.sbin/bgpd/bgpd.conf.5 20 Jan 2023 15:41:33 -0000 1.229 +++ usr.sbin/bgpd/bgpd.conf.5 24 Jan 2023 13:10:37 -0000 @@ -1538,6 +1538,14 @@ deny from any { AS { 1, 2, 3 }, source-a .Ed .Pp .It Xo +.Ic avs +.Pq Ic valid | unknown | invalid +.Xc +This rule applies only to +.Em UPDATES +where the ASPA Validation State (AVS) matches. +.Pp +.It Xo .Ic community .Ar as-number Ns Li \&: Ns Ar local .Xc Index: usr.sbin/bgpd/bgpd.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v retrieving revision 1.459 diff -u -p -r1.459 bgpd.h --- usr.sbin/bgpd/bgpd.h 24 Jan 2023 11:28:41 -0000 1.459 +++ usr.sbin/bgpd/bgpd.h 24 Jan 2023 13:10:37 -0000 @@ -94,6 +94,9 @@ #define F_CTL_OVS_NOTFOUND 0x200000 #define F_CTL_NEIGHBORS 0x400000 /* only used by bgpctl */ #define F_CTL_HAS_PATHID 0x800000 /* only set on requests */ +#define F_CTL_AVS_VALID 0x1000000 +#define F_CTL_AVS_INVALID 0x2000000 +#define F_CTL_AVS_UNKNOWN 0x4000000 #define CTASSERT(x) extern char _ctassert[(x) ? 1 : -1 ] \ __attribute__((__unused__)) @@ -896,7 +899,7 @@ struct filter_originset { struct rde_prefixset *ps; }; -struct filter_ovs { +struct filter_vs { uint8_t validity; uint8_t is_set; }; @@ -1082,7 +1085,8 @@ struct filter_match { struct community community[MAX_COMM_MATCH]; struct filter_prefixset prefixset; struct filter_originset originset; - struct filter_ovs ovs; + struct filter_vs ovs; + struct filter_vs avs; int maxcomm; int maxextcomm; int maxlargecomm; Index: usr.sbin/bgpd/parse.y =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v retrieving revision 1.439 diff -u -p -r1.439 parse.y --- usr.sbin/bgpd/parse.y 20 Jan 2023 15:41:33 -0000 1.439 +++ usr.sbin/bgpd/parse.y 24 Jan 2023 13:10:37 -0000 @@ -231,7 +231,7 @@ typedef struct { %token COMMUNITY EXTCOMMUNITY LARGECOMMUNITY DELETE %token MAXCOMMUNITIES MAXEXTCOMMUNITIES MAXLARGECOMMUNITIES %token PREFIX PREFIXLEN PREFIXSET -%token ASPASET ROASET ORIGINSET OVS EXPIRES +%token ASPASET ROASET ORIGINSET OVS AVS EXPIRES %token ASSET SOURCEAS TRANSITAS PEERAS PROVIDERAS CUSTOMERAS MAXASLEN MAXASSEQ %token SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE NOMODIFY SELF %token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL ORIGIN PRIORITY @@ -244,7 +244,8 @@ typedef struct { %token <v.number> NUMBER %type <v.number> asnumber as4number as4number_any optnumber %type <v.number> espah family safi restart origincode nettype -%type <v.number> yesno inout restricted validity expires enforce +%type <v.number> yesno inout restricted expires enforce +%type <v.number> validity aspa_validity %type <v.number> addpathextra addpathmax %type <v.string> string %type <v.addr> address @@ -2622,6 +2623,14 @@ filter_elm : filter_prefix_h { fmopts.m.ovs.validity = $2; fmopts.m.ovs.is_set = 1; } + | AVS aspa_validity { + if (fmopts.m.avs.is_set) { + yyerror("avs filter already specified"); + YYERROR; + } + fmopts.m.avs.validity = $2; + fmopts.m.avs.is_set = 1; + } ; prefixlenop : /* empty */ { memset(&$$, 0, sizeof($$)); } @@ -3070,7 +3079,22 @@ validity : STRING { else if (!strcmp($1, "valid")) $$ = ROA_VALID; else { - yyerror("unknown validity \"%s\"", $1); + yyerror("unknown roa validity \"%s\"", $1); + free($1); + YYERROR; + } + free($1); + }; + +aspa_validity : STRING { + if (!strcmp($1, "unknown")) + $$ = ASPA_UNKNOWN; + else if (!strcmp($1, "invalid")) + $$ = ASPA_INVALID; + else if (!strcmp($1, "valid")) + $$ = ASPA_VALID; + else { + yyerror("unknown aspa validity \"%s\"", $1); free($1); YYERROR; } @@ -3149,6 +3173,7 @@ lookup(char *s) { "as-override", ASOVERRIDE}, { "as-set", ASSET }, { "aspa-set", ASPASET}, + { "avs", AVS}, { "blackhole", BLACKHOLE}, { "capabilities", CAPABILITIES}, { "community", COMMUNITY}, Index: usr.sbin/bgpd/printconf.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/printconf.c,v retrieving revision 1.162 diff -u -p -r1.162 printconf.c --- usr.sbin/bgpd/printconf.c 20 Jan 2023 15:41:33 -0000 1.162 +++ usr.sbin/bgpd/printconf.c 24 Jan 2023 13:10:37 -0000 @@ -944,6 +944,22 @@ print_rule(struct bgpd_config *conf, str } } + if (r->match.avs.is_set) { + switch (r->match.avs.validity) { + case ASPA_VALID: + printf("avs valid "); + break; + case ASPA_INVALID: + printf("avs invalid "); + break; + case ASPA_UNKNOWN: + printf("avs unknown "); + break; + default: + printf("avs ??? %d ??? ", r->match.avs.validity); + } + } + if (r->match.prefix.addr.aid != AID_UNSPEC) { printf("prefix "); print_prefix(&r->match.prefix); Index: usr.sbin/bgpd/rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.590 diff -u -p -r1.590 rde.c --- usr.sbin/bgpd/rde.c 24 Jan 2023 11:28:41 -0000 1.590 +++ usr.sbin/bgpd/rde.c 24 Jan 2023 13:10:37 -0000 @@ -103,7 +103,8 @@ static void network_dump_upcall(struct static void network_flush_upcall(struct rib_entry *, void *); void rde_shutdown(void); -int ovs_match(struct prefix *, uint32_t); +static int ovs_match(struct prefix *, uint32_t); +static int avs_match(struct prefix *, uint32_t); static struct imsgbuf *ibuf_se; static struct imsgbuf *ibuf_se_ctl; @@ -2776,6 +2777,8 @@ rde_dump_filter(struct prefix *p, struct } if (!ovs_match(p, req->flags)) return; + if (!avs_match(p, req->flags)) + return; rde_dump_rib_as(p, asp, req->pid, req->flags, adjout); } @@ -4528,7 +4531,7 @@ rde_roa_validity(struct rde_prefixset *p return (r & ROA_MASK); } -int +static int ovs_match(struct prefix *p, uint32_t flag) { if (flag & (F_CTL_OVS_VALID|F_CTL_OVS_INVALID|F_CTL_OVS_NOTFOUND)) { @@ -4543,6 +4546,31 @@ ovs_match(struct prefix *p, uint32_t fla break; case ROA_NOTFOUND: if (!(flag & F_CTL_OVS_NOTFOUND)) + return 0; + break; + default: + break; + } + } + + return 1; +} + +static int +avs_match(struct prefix *p, uint32_t flag) +{ + if (flag & (F_CTL_AVS_VALID|F_CTL_AVS_INVALID|F_CTL_AVS_UNKNOWN)) { + switch (prefix_aspa_vstate(p) & ASPA_MASK) { + case ASPA_VALID: + if (!(flag & F_CTL_AVS_VALID)) + return 0; + break; + case ASPA_INVALID: + if (!(flag & F_CTL_AVS_INVALID)) + return 0; + break; + case ASPA_UNKNOWN: + if (!(flag & F_CTL_AVS_UNKNOWN)) return 0; break; default: Index: usr.sbin/bgpd/rde_filter.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_filter.c,v retrieving revision 1.132 diff -u -p -r1.132 rde_filter.c --- usr.sbin/bgpd/rde_filter.c 24 Jan 2023 11:28:41 -0000 1.132 +++ usr.sbin/bgpd/rde_filter.c 24 Jan 2023 13:10:37 -0000 @@ -227,6 +227,11 @@ rde_filter_match(struct filter_rule *f, return (0); } + if (f->match.avs.is_set) { + if (((state->vstate >> 4) & ASPA_MASK) != f->match.avs.validity) + return (0); + } + if (asp != NULL && f->match.as.type != AS_UNDEF) { if (aspath_match(asp->aspath, &f->match.as, peer->conf.remote_as) == 0) Index: usr.sbin/bgpctl/bgpctl.8 =================================================================== RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.8,v retrieving revision 1.103 diff -u -p -r1.103 bgpctl.8 --- usr.sbin/bgpctl/bgpctl.8 22 Dec 2022 19:53:24 -0000 1.103 +++ usr.sbin/bgpctl/bgpctl.8 24 Jan 2023 13:10:37 -0000 @@ -375,6 +375,8 @@ Show all entries with anywhere but rightmost. .It Cm ovs Pq Ic valid | not-found | invalid Show all entries with matching Origin Validation State (OVS). +.It Cm avs Pq Ic valid | unknown | invalid +Show all entries with matching ASAP Validation State (AVS). .El .Pp Additionally, the following Index: usr.sbin/bgpctl/parser.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpctl/parser.c,v retrieving revision 1.118 diff -u -p -r1.118 parser.c --- usr.sbin/bgpctl/parser.c 10 Nov 2022 10:47:30 -0000 1.118 +++ usr.sbin/bgpctl/parser.c 24 Jan 2023 13:10:37 -0000 @@ -77,6 +77,7 @@ static const struct token t_show[]; static const struct token t_show_summary[]; static const struct token t_show_fib[]; static const struct token t_show_rib[]; +static const struct token t_show_avs[]; static const struct token t_show_ovs[]; static const struct token t_show_mrt[]; static const struct token t_show_mrt_file[]; @@ -181,6 +182,7 @@ static const struct token t_show_rib[] = { FLAG, "in", F_CTL_ADJ_IN, t_show_rib}, { FLAG, "out", F_CTL_ADJ_OUT, t_show_rib}, { KEYWORD, "neighbor", NONE, t_show_rib_neigh}, + { KEYWORD, "avs", NONE, t_show_avs}, { KEYWORD, "ovs", NONE, t_show_ovs}, { KEYWORD, "path-id", NONE, t_show_rib_path}, { KEYWORD, "table", NONE, t_show_rib_rib}, @@ -188,6 +190,13 @@ static const struct token t_show_rib[] = { KEYWORD, "memory", SHOW_RIB_MEM, NULL}, { FAMILY, "", NONE, t_show_rib}, { PREFIX, "", NONE, t_show_prefix}, + { ENDTOKEN, "", NONE, NULL} +}; + +static const struct token t_show_avs[] = { + { FLAG, "valid" , F_CTL_AVS_VALID, t_show_rib}, + { FLAG, "invalid", F_CTL_AVS_INVALID, t_show_rib}, + { FLAG, "unknonw", F_CTL_AVS_UNKNOWN, t_show_rib}, { ENDTOKEN, "", NONE, NULL} };