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