Implement filter and control message matching for ASAP.
authorclaudio <claudio@openbsd.org>
Tue, 24 Jan 2023 14:13:11 +0000 (14:13 +0000)
committerclaudio <claudio@openbsd.org>
Tue, 24 Jan 2023 14:13:11 +0000 (14:13 +0000)
This adds avs (ASPA validation state) which can be 'unknown', 'valid'
or 'invalid'. It behaves similar to ovs but the ASPA validation state
of paths from iBGP sessions is 'unknown' and the role of the ebgp session
is important to get the right validation state.

OK tb@

usr.sbin/bgpd/bgpd.conf.5
usr.sbin/bgpd/bgpd.h
usr.sbin/bgpd/parse.y
usr.sbin/bgpd/printconf.c
usr.sbin/bgpd/rde.c
usr.sbin/bgpd/rde_filter.c

index dd0656b..e112bf8 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: bgpd.conf.5,v 1.229 2023/01/20 15:41:33 claudio Exp $
+.\" $OpenBSD: bgpd.conf.5,v 1.230 2023/01/24 14:13:11 claudio Exp $
 .\"
 .\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
 .\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -16,7 +16,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: January 20 2023 $
+.Dd $Mdocdate: January 24 2023 $
 .Dt BGPD.CONF 5
 .Os
 .Sh NAME
@@ -1538,6 +1538,14 @@ deny from any { AS { 1, 2, 3 }, source-as 4, transit-as 5 }
 .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 9cdad34..99ffdc1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: bgpd.h,v 1.459 2023/01/24 11:28:41 claudio Exp $ */
+/*     $OpenBSD: bgpd.h,v 1.460 2023/01/24 14:13:11 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -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 5c96dab..de3ee73 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parse.y,v 1.439 2023/01/20 15:41:33 claudio Exp $ */
+/*     $OpenBSD: parse.y,v 1.440 2023/01/24 14:13:11 claudio Exp $ */
 
 /*
  * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -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 cfa2bda..de6b4c3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: printconf.c,v 1.162 2023/01/20 15:41:33 claudio Exp $ */
+/*     $OpenBSD: printconf.c,v 1.163 2023/01/24 14:13:12 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -944,6 +944,22 @@ print_rule(struct bgpd_config *conf, struct filter_rule *r)
                }
        }
 
+       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 bca75af..62593bc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rde.c,v 1.590 2023/01/24 11:28:41 claudio Exp $ */
+/*     $OpenBSD: rde.c,v 1.591 2023/01/24 14:13:12 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -103,7 +103,8 @@ static void  network_dump_upcall(struct rib_entry *, void *);
 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 ctl_show_rib_request *req, int adjout)
        }
        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 *ps, struct bgpd_addr *prefix,
        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)) {
@@ -4552,3 +4555,28 @@ ovs_match(struct prefix *p, uint32_t flag)
 
        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:
+                       break;
+               }
+       }
+
+       return 1;
+}
index cbdba6c..be8fe97 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rde_filter.c,v 1.132 2023/01/24 11:28:41 claudio Exp $ */
+/*     $OpenBSD: rde_filter.c,v 1.133 2023/01/24 14:13:12 claudio Exp $ */
 
 /*
  * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -227,6 +227,11 @@ rde_filter_match(struct filter_rule *f, struct rde_peer *peer,
                        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)