-.\" $OpenBSD: bgpd.conf.5,v 1.219 2022/03/31 17:27:29 naddy Exp $
+.\" $OpenBSD: bgpd.conf.5,v 1.220 2022/05/31 09:45:33 claudio Exp $
.\"
.\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
.\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: March 31 2022 $
+.Dd $Mdocdate: May 31 2022 $
.Dt BGPD.CONF 5
.Os
.Sh NAME
.Ar len
times.
.Pp
+.It Ic max-communities Ns | Ns Ic max-large-communities Ns | \
+Ns Ic max-ext-communities Ar num
+This rule applies only to
+.Em UPDATES
+where the
+.Em Basic,
+.Em Large ,
+or
+.Em Extended Community
+attribute has more than
+.Ar num
+elements.
+.Pp
.It Ic nexthop Ar address
This rule applies only to
.Em UPDATES
-/* $OpenBSD: bgpd.h,v 1.424 2022/05/25 16:03:34 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.425 2022/05/31 09:45:33 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
struct filter_prefixset prefixset;
struct filter_originset originset;
struct filter_ovs ovs;
+ int maxcomm;
+ int maxextcomm;
+ int maxlargecomm;
};
struct filter_rule {
-/* $OpenBSD: parse.y,v 1.424 2022/05/23 13:40:12 deraadt Exp $ */
+/* $OpenBSD: parse.y,v 1.425 2022/05/31 09:45:33 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
%token FROM TO ANY
%token CONNECTED STATIC
%token COMMUNITY EXTCOMMUNITY LARGECOMMUNITY DELETE
+%token MAXCOMMUNITIES MAXEXTCOMMUNITIES MAXLARGECOMMUNITIES
%token PREFIX PREFIXLEN PREFIXSET
%token ROASET ORIGINSET OVS EXPIRES
%token ASSET SOURCEAS TRANSITAS PEERAS MAXASLEN MAXASSEQ
}
free($3);
}
+ | MAXCOMMUNITIES NUMBER {
+ if ($2 < 0 || $2 > INT16_MAX) {
+ yyerror("bad max-comunities %lld", $2);
+ YYERROR;
+ }
+ if (fmopts.m.maxcomm != 0) {
+ yyerror("%s already specified",
+ "max-communities");
+ YYERROR;
+ }
+ /*
+ * Offset by 1 since 0 means not used.
+ * The match function then uses >= to compensate.
+ */
+ fmopts.m.maxcomm = $2 + 1;
+ }
+ | MAXEXTCOMMUNITIES NUMBER {
+ if ($2 < 0 || $2 > INT16_MAX) {
+ yyerror("bad max-ext-communities %lld", $2);
+ YYERROR;
+ }
+ if (fmopts.m.maxextcomm != 0) {
+ yyerror("%s already specified",
+ "max-ext-communities");
+ YYERROR;
+ }
+ fmopts.m.maxextcomm = $2 + 1;
+ }
+ | MAXLARGECOMMUNITIES NUMBER {
+ if ($2 < 0 || $2 > INT16_MAX) {
+ yyerror("bad max-large-communities %lld", $2);
+ YYERROR;
+ }
+ if (fmopts.m.maxlargecomm != 0) {
+ yyerror("%s already specified",
+ "max-large-communities");
+ YYERROR;
+ }
+ fmopts.m.maxlargecomm = $2 + 1;
+ }
| NEXTHOP address {
if (fmopts.m.nexthop.flags) {
yyerror("nexthop already specified");
{ "match", MATCH},
{ "max-as-len", MAXASLEN},
{ "max-as-seq", MAXASSEQ},
+ { "max-communities", MAXCOMMUNITIES},
+ { "max-ext-communities", MAXEXTCOMMUNITIES},
+ { "max-large-communities", MAXLARGECOMMUNITIES},
{ "max-prefix", MAXPREFIX},
{ "maxlen", MAXLEN},
{ "md5sig", MD5SIG},
-/* $OpenBSD: printconf.c,v 1.151 2022/05/25 16:03:34 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.152 2022/05/31 09:45:33 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
}
}
+ if (r->match.maxcomm != 0)
+ printf("max-communities %d ", r->match.maxcomm - 1);
+ if (r->match.maxextcomm != 0)
+ printf("max-ext-communities %d ", r->match.maxextcomm - 1);
+ if (r->match.maxlargecomm != 0)
+ printf("max-large-communities %d ", r->match.maxlargecomm - 1);
+
print_set(&r->set);
printf("\n");
-/* $OpenBSD: rde.h,v 1.252 2022/05/25 16:03:34 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.253 2022/05/31 09:45:33 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
/* rde_community.c */
int community_match(struct rde_community *, struct community *,
struct rde_peer *);
+int community_count(struct rde_community *, uint8_t type);
int community_set(struct rde_community *, struct community *,
struct rde_peer *);
void community_delete(struct rde_community *, struct community *,
-/* $OpenBSD: rde_community.c,v 1.5 2022/05/25 16:03:34 claudio Exp $ */
+/* $OpenBSD: rde_community.c,v 1.6 2022/05/31 09:45:33 claudio Exp $ */
/*
* Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org>
}
}
+/*
+ * Count the number of communities of type type.
+ */
+int
+community_count(struct rde_community *comm, uint8_t type)
+{
+ size_t l;
+ int count = 0;
+
+ /* use the fact that the array is ordered by type */
+ switch (type) {
+ case COMMUNITY_TYPE_BASIC:
+ for (l = 0; l < comm->nentries; l++) {
+ if ((uint8_t)comm->communities[l].flags == type)
+ count++;
+ else
+ break;
+ }
+ break;
+ case COMMUNITY_TYPE_EXT:
+ for (l = 0; l < comm->nentries; l++) {
+ if ((uint8_t)comm->communities[l].flags == type)
+ count++;
+ else if ((uint8_t)comm->communities[l].flags > type)
+ break;
+ }
+ break;
+ case COMMUNITY_TYPE_LARGE:
+ for (l = comm->nentries; l > 0; l--) {
+ if ((uint8_t)comm->communities[l - 1].flags == type)
+ count++;
+ else
+ break;
+ }
+ break;
+ }
+ return count;
+}
+
/*
* Insert a community, expanding local-as and neighbor-as if needed.
*/
-/* $OpenBSD: rde_filter.c,v 1.127 2022/02/06 09:51:19 claudio Exp $ */
+/* $OpenBSD: rde_filter.c,v 1.128 2022/05/31 09:45:33 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
return (0);
}
+ if (f->match.maxcomm != 0) {
+ if (f->match.maxcomm >
+ community_count(&state->communities, COMMUNITY_TYPE_BASIC))
+ return (0);
+ }
+ if (f->match.maxextcomm != 0) {
+ if (f->match.maxextcomm >
+ community_count(&state->communities, COMMUNITY_TYPE_EXT))
+ return (0);
+ }
+ if (f->match.maxlargecomm != 0) {
+ if (f->match.maxlargecomm >
+ community_count(&state->communities, COMMUNITY_TYPE_LARGE))
+ return (0);
+ }
+
if (f->match.nexthop.flags != 0) {
struct bgpd_addr *nexthop, *cmpaddr;
if (state->nexthop == NULL)