On Tue, Mar 28, 2017 at 02:12:42PM -0500, Job Snijders wrote:
> Dear all,
> 
> BGP Origin Validation State communities are non-transitive opaque
> extended communities to carry the origination Autonomous System
> validation state inside an autonomous system. IBGP speakers that
> receive this validation state can configure local policies that allow it
> to influence their decision process. https://tools.ietf.org/html/rfc8097
> 
> This patch allows to configurations such as the below. This
> configuration was generated based on an external validation source (in
> this case RPKI) and allows manipulation through well-known identifiers.
> 
>     match from any \
>         set { ext-community bovs not-found \
>               ext-community delete bovs invalid \
>               ext-community delete bovs valid }
>     match from any \
>         prefix 2a02:898::/32 or-longer \
>         set { ext-community bovs invalid }
>     match from any \
>         prefix 2a02:898::/32 source-as 8283 \
>         set { ext-community bovs valid }
>     match from any ext-community bovs valid \
>         set { ext-community delete bovs invalid \
>               ext-community delete bovs not-found }
>     match from any ext-community bovs invalid \
>         set { ext-community delete bovs not-found }
> 
> The following new mapping exists between keywords and Extended BGP
> Communities:
> 
>       keywords        | ext type | subtype | value
>       ----------------+----------+---------+-------
>       bovs valid      |   0x2b   |   0x0   |  0x0
>       bovs not-found  |   0x2b   |   0x0   |  0x1
>       bovs invalid    |   0x2b   |   0x0   |  0x2
> 
> [job@kiera ~]$ bgpctl show rib detail 2a02:898::/32 longer-prefixes
> 
> BGP routing table entry for 2a02:898::/32
>     2914 8283
>     Nexthop 2001:728:0:1000::2 (via ???) from AS15562_scarlett_IPv6 
> (165.254.255.1)
>     Origin IGP, metric 0, localpref 100, weight 0, internal
>     Last update: 00:00:49 ago
>     Communities: 2914:420 2914:1206 2914:2203 2914:3200 65504:8283
>     Ext. communities: bovs valid
> 
> [job@kiera ~]$
> 
> Index: bgpctl/bgpctl.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
> retrieving revision 1.193
> diff -u -p -r1.193 bgpctl.c
> --- bgpctl/bgpctl.c   23 Jan 2017 23:38:51 -0000      1.193
> +++ bgpctl/bgpctl.c   28 Mar 2017 19:01:33 -0000
> @@ -1585,7 +1585,7 @@ show_ext_community(u_char *data, u_int16
>       struct in_addr  ip;
>       u_int32_t       as4, u32;
>       u_int16_t       i, as2, u16;
> -     u_int8_t        type, subtype;
> +     u_int8_t        type, subtype, state;
>  
>       if (len & 0x7)
>               return;
> @@ -1618,6 +1618,13 @@ show_ext_community(u_char *data, u_int16
>                       ext = betoh64(ext) & 0xffffffffffffLL;
>                       printf("%s 0x%llx", log_ext_subtype(subtype), ext);
>                       break;
> +             case EXT_COMMUNITY_NON_TRANS_OPAQUE:
> +                     if (subtype == EXT_COMMUNITY_VALIDATION_STATE) {
> +                             state = data[i + 7];
> +                             printf("%s %s", log_ext_subtype(subtype),
> +                                 log_ext_bovs_value(state));
> +                             break;
> +                     }
>               default:
>                       memcpy(&ext, data + i, sizeof(ext));
>                       printf("0x%llx", betoh64(ext));
> Index: bgpd/bgpd.8
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/bgpd.8,v
> retrieving revision 1.52
> diff -u -p -r1.52 bgpd.8
> --- bgpd/bgpd.8       19 Feb 2017 11:38:24 -0000      1.52
> +++ bgpd/bgpd.8       28 Mar 2017 19:01:33 -0000
> @@ -390,6 +390,17 @@ control socket
>  .%R draft-ietf-idr-shutdown
>  .%T BGP Administrative Shutdown Communication
>  .Re
> +.Pp
> +.Rs
> +.%A P. Mohapatra
> +.%A K. Patel
> +.%A J. Scudder
> +.%A D. Ward
> +.%A R. Bush
> +.%D March 2017
> +.%R RFC 8097
> +.%T BGP Prefix Origin Validation State Extended Community
> +.Re
>  .Sh HISTORY
>  The
>  .Nm
> Index: bgpd/bgpd.conf.5
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/bgpd.conf.5,v
> retrieving revision 1.152
> diff -u -p -r1.152 bgpd.conf.5
> --- bgpd/bgpd.conf.5  13 Jan 2017 18:59:12 -0000      1.152
> +++ bgpd/bgpd.conf.5  28 Mar 2017 19:01:33 -0000
> @@ -1195,6 +1195,11 @@ which is expanded to the current neighbo
>  .Ic ext-community
>  .Ar subtype Ar numvalue
>  .Xc
> +.It Xo
> +.Ic ext-community
> +.Ar bovs
> +.Pq Ic valid | not-found | invalid
> +.Xc
>  This rule applies only to
>  .Em UPDATES
>  where the
> @@ -1456,6 +1461,11 @@ to do wildcard matching.
>  .Ic ext-community Op Ar delete
>  .Ar subtype Ar numvalue
>  .Xc
> +.It Xo
> +.Ic ext-community Op Ar delete
> +.Ar bovs
> +.Pq Ic valid | not-found | invalid
> +.Xc
>  Set or delete the
>  .Em Extended Community
>  AS path attribute.
> @@ -1481,6 +1491,7 @@ odi      OSPF Domain Identifier
>  ort      OSPF Route Type
>  ori      OSPF Router ID
>  bdc      BGP Data Collection
> +bovs     BGP Origin Validation State
>  .Ed
>  .Pp
>  Not all type and subtype value pairs are allowed by IANA and the parser
> Index: bgpd/bgpd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
> retrieving revision 1.300
> diff -u -p -r1.300 bgpd.h
> --- bgpd/bgpd.h       25 Jan 2017 00:11:07 -0000      1.300
> +++ bgpd/bgpd.h       28 Mar 2017 19:01:33 -0000
> @@ -755,7 +755,8 @@ struct filter_peers {
>  #define EXT_COMMUNITY_TWO_AS         0       /* 2 octet AS specific */
>  #define EXT_COMMUNITY_IPV4           1       /* IPv4 specific */
>  #define EXT_COMMUNITY_FOUR_AS                2       /* 4 octet AS specific 
> */
> -#define EXT_COMMUNITY_OPAQUE         3       /* opaque ext community */
> +#define EXT_COMMUNITY_OPAQUE         3       /* transitive opaque ext */
> +#define EXT_COMMUNITY_NON_TRANS_OPAQUE 43    /* non-transitive opaque ext */
>  /* sub types */
>  #define EXT_COMMUNITY_ROUTE_TGT              2       /* RFC 4360 & RFC4364 */
>  #define EXT_COMMUNITY_ROUTE_ORIG     3       /* RFC 4360 & RFC4364 */
> @@ -763,6 +764,11 @@ struct filter_peers {
>  #define EXT_COMMUNITY_OSPF_RTR_TYPE  6       /* RFC 4577 */
>  #define EXT_COMMUNITY_OSPF_RTR_ID    7       /* RFC 4577 */
>  #define EXT_COMMUNITY_BGP_COLLECT    8       /* RFC 4384 */
> +#define EXT_COMMUNITY_VALIDATION_STATE       0       /* RFC 8097 */
> +/* RFC 8097 validation states */
> +#define EXT_COMMUNITY_VALIDATION_STATE_VALID 0
> +#define EXT_COMMUNITY_VALIDATION_STATE_NOTFOUND      1
> +#define EXT_COMMUNITY_VALIDATION_STATE_INVALID       2
>  /* other handy defines */
>  #define EXT_COMMUNITY_OPAQUE_MAX     0xffffffffffffULL
>  #define EXT_COMMUNITY_FLAG_VALID     0x01
> @@ -783,7 +789,8 @@ struct ext_comm_pairs {
>       { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_ROUTE_TGT, 0 },             \
>       { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_ROUTE_ORIG, 0 },            \
>       { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_OSPF_RTR_ID, 0 },           \
> -     { EXT_COMMUNITY_OPAQUE, EXT_COMMUNITY_OSPF_RTR_TYPE, 0 }        \
> +     { EXT_COMMUNITY_OPAQUE, EXT_COMMUNITY_OSPF_RTR_TYPE, 0 },       \
> +     { EXT_COMMUNITY_NON_TRANS_OPAQUE, EXT_COMMUNITY_VALIDATION_STATE, 0 }   
> \
>  }
>  
>  
> @@ -1067,6 +1074,7 @@ const char      *log_sockaddr(struct sockaddr
>  const char   *log_as(u_int32_t);
>  const char   *log_rd(u_int64_t);
>  const char   *log_ext_subtype(u_int8_t);
> +const char   *log_ext_bovs_value(u_int8_t);
>  const char   *log_shutcomm(const char *);
>  int           aspath_snprint(char *, size_t, void *, u_int16_t);
>  int           aspath_asprint(char **, void *, u_int16_t);
> Index: bgpd/parse.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
> retrieving revision 1.298
> diff -u -p -r1.298 parse.y
> --- bgpd/parse.y      22 Feb 2017 13:55:14 -0000      1.298
> +++ bgpd/parse.y      28 Mar 2017 19:01:33 -0000
> @@ -145,6 +145,7 @@ int                parsecommunity(struct filter_commu
>  int64_t       getlargecommunity(char *);
>  int           parselargecommunity(struct filter_largecommunity *, char *);
>  int           parsesubtype(char *);
> +int           parse_bgp_validation_state(char *);
>  int           parseextvalue(char *, u_int32_t *);
>  int           parseextcommunity(struct filter_extcommunity *, char *,
>                   char *);
> @@ -3022,11 +3023,31 @@ parselargecommunity(struct filter_largec
>  }
>  
>  int
> +parse_bgp_validation_state(char *state)
> +{
> +     /* this has to be sorted always */
> +     static const struct keywords keywords[] = {
> +             { "invalid",    EXT_COMMUNITY_VALIDATION_STATE_INVALID },
> +             { "not-found",  EXT_COMMUNITY_VALIDATION_STATE_NOTFOUND },
> +             { "valid",      EXT_COMMUNITY_VALIDATION_STATE_VALID }
> +     };

Is there an expectation that this list will grow? I find it a bit overkill
to use bsearch for 3 values. I understand we use similar constructs for
other tables. Doing 3 strcmp in a row would have been easier I think.

Apart from that I'm with benno@, the name bovs is not great but kind of
fits in line with bdc, odi, ori, etc... Anyway this is for after unlock.

> +     const struct keywords   *p;
> +     p = bsearch(state, keywords, sizeof(keywords)/sizeof(keywords[0]),
> +             sizeof(keywords[0]), kw_cmp);
> +
> +     if (p)
> +             return (p->k_val);
> +     else
> +             return (-1);
> +}
> +
> +int
>  parsesubtype(char *type)
>  {
>       /* this has to be sorted always */
>       static const struct keywords keywords[] = {
>               { "bdc",        EXT_COMMUNITY_BGP_COLLECT },
> +             { "bovs",       EXT_COMMUNITY_VALIDATION_STATE },
>               { "odi",        EXT_COMMUNITY_OSPF_DOM_ID },
>               { "ori",        EXT_COMMUNITY_OSPF_RTR_ID },
>               { "ort",        EXT_COMMUNITY_OSPF_RTR_TYPE },
> @@ -3100,15 +3121,22 @@ parseextcommunity(struct filter_extcommu
>       u_int32_t        uval;
>       char            *p, *ep;
>       unsigned int     i;
> -     int              type, subtype;
> +     int              type, state, subtype;
>  
>       if ((subtype = parsesubtype(t)) == -1) {
>               yyerror("Bad ext-community unknown type");
>               return (-1);
>       }
>  
> -     if ((p = strchr(s, ':')) == NULL) {
> -             type = EXT_COMMUNITY_OPAQUE,
> +     if (subtype == EXT_COMMUNITY_VALIDATION_STATE) {
> +             if ((state = parse_bgp_validation_state(s)) == -1) {
> +                     yyerror("Invalid BGP Origin Validation State 
> Community");
> +                     return(-1);
> +             }
> +             type = EXT_COMMUNITY_NON_TRANS_OPAQUE;
> +             c->data.ext_opaq = state;
> +     } else if ((p = strchr(s, ':')) == NULL) {
> +             type = EXT_COMMUNITY_OPAQUE;
>               errno = 0;
>               ullval = strtoull(s, &ep, 0);
>               if (s[0] == '\0' || *ep != '\0') {
> Index: bgpd/printconf.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/printconf.c,v
> retrieving revision 1.100
> diff -u -p -r1.100 printconf.c
> --- bgpd/printconf.c  24 Jan 2017 04:22:42 -0000      1.100
> +++ bgpd/printconf.c  28 Mar 2017 19:01:34 -0000
> @@ -149,6 +149,7 @@ print_extcommunity(struct filter_extcomm
>                   log_as(c->data.ext_as4.as4), c->data.ext_as.val);
>               break;
>       case EXT_COMMUNITY_OPAQUE:
> +     case EXT_COMMUNITY_NON_TRANS_OPAQUE:
>               printf("%s 0x%llx ", log_ext_subtype(c->subtype),
>                   c->data.ext_opaq);
>               break;
> Index: bgpd/util.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/util.c,v
> retrieving revision 1.24
> diff -u -p -r1.24 util.c
> --- bgpd/util.c       24 Jan 2017 04:22:42 -0000      1.24
> +++ bgpd/util.c       28 Mar 2017 19:01:34 -0000
> @@ -154,11 +154,32 @@ log_ext_subtype(u_int8_t subtype)
>               return ("ori"); /* ospf router id */
>       case EXT_COMMUNITY_BGP_COLLECT:
>               return ("bdc"); /* bgp data collection */
> +     case EXT_COMMUNITY_VALIDATION_STATE:
> +             return ("bovs"); /* RFC 8097 */
>       default:
>               snprintf(etype, sizeof(etype), "[%u]", subtype);
>               return (etype);
>       }
>  }
> +
> +const char *
> +log_ext_bovs_value(u_int8_t value)
> +{
> +     static char s[6];
> +
> +     switch (value) {
> +     case EXT_COMMUNITY_VALIDATION_STATE_VALID:
> +             return ("valid");
> +     case EXT_COMMUNITY_VALIDATION_STATE_NOTFOUND:
> +             return ("not-found");
> +     case EXT_COMMUNITY_VALIDATION_STATE_INVALID:
> +             return ("invalid");
> +     default:
> +             snprintf(s, sizeof(s), "[%u?]", value);
> +             return (s);
> +     }
> +}
> +
>  
>  const char *
>  log_shutcomm(const char *communication) {
> 

-- 
:wq Claudio

Reply via email to