Hello,
Here is a patch to expand RIB names in rules. When playing with multi-RIBs, it
allows to simplify ruleset.
Ex :
# cat /etc/bgpd.conf
[...]
peer_ribs = "{ m1, m2, m3 }"
deny rib m2 from any
allow rib $peer_ribs from any prefix { 2001:db8:1::/48, 2001:db8:2::/48 }
# bgpd -dnv
[...]
deny rib m2 from any
allow rib m3 from any prefix 2001:db8:2::/48
allow rib m3 from any prefix 2001:db8:1::/48
allow rib m2 from any prefix 2001:db8:2::/48
allow rib m2 from any prefix 2001:db8:1::/48
allow rib m1 from any prefix 2001:db8:2::/48
allow rib m1 from any prefix 2001:db8:1::/48
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
retrieving revision 1.295
diff -u -p -r1.295 parse.y
--- parse.y 18 Jan 2017 04:28:45 -0000 1.295
+++ parse.y 20 Jan 2017 20:15:20 -0000
@@ -91,6 +91,11 @@ static struct filter_rule *curpeer_filte
static struct filter_rule *curgroup_filter[2];
static u_int32_t id;
+struct filter_rib_l {
+ struct filter_rib_l *next;
+ char name[PEER_DESCR_LEN];
+};
+
struct filter_peers_l {
struct filter_peers_l *next;
struct filter_peers p;
@@ -128,8 +133,9 @@ struct rde_rib *find_rib(char *);
int get_id(struct peer *);
int merge_prefixspec(struct filter_prefix_l *,
struct filter_prefixlen *);
-int expand_rule(struct filter_rule *, struct filter_peers_l *,
- struct filter_match_l *, struct filter_set_head *);
+int expand_rule(struct filter_rule *, struct filter_rib_l *,
+ struct filter_peers_l *, struct filter_match_l *,
+ struct filter_set_head *);
int str2key(char *, char *, size_t);
int neighbor_consistent(struct peer *);
int merge_filterset(struct filter_set_head *, struct filter_set *);
@@ -153,6 +159,7 @@ typedef struct {
char *string;
struct bgpd_addr addr;
u_int8_t u8;
+ struct filter_rib_l *filter_rib;
struct filter_peers_l *filter_peers;
struct filter_match_l filter_match;
struct filter_prefix_l *filter_prefix;
@@ -203,10 +210,11 @@ typedef struct {
%type <v.number> asnumber as4number as4number_any optnumber
%type <v.number> espah family restart origincode nettype
%type <v.number> yesno inout restricted
-%type <v.string> string filter_rib
+%type <v.string> string
%type <v.addr> address
%type <v.prefix> prefix addrspec
%type <v.u8> action quick direction delete
+%type <v.filter_rib> filter_rib_h filter_rib_l filter_rib
%type <v.filter_peers> filter_peer filter_peer_l filter_peer_h
%type <v.filter_match> filter_match filter_elm filter_match_h
%type <v.filter_as> filter_as filter_as_l filter_as_h
@@ -1469,9 +1477,10 @@ encspec : /* nada */ {
}
;
-filterrule : action quick filter_rib direction filter_peer_h
filter_match_h filter_set
+filterrule : action quick filter_rib_h direction filter_peer_h
filter_match_h filter_set
{
struct filter_rule r;
+ struct filter_rib_l *rb, *rbnext;
bzero(&r, sizeof(r));
r.action = $1;
@@ -1481,25 +1490,15 @@ filterrule : action quick filter_rib dir
if (r.dir != DIR_IN) {
yyerror("rib only allowed on \"from\" "
"rules.");
- free($3);
- YYERROR;
- }
- if (!find_rib($3)) {
- yyerror("rib \"%s\" does not exist.",
- $3);
- free($3);
- YYERROR;
- }
- if (strlcpy(r.rib, $3, sizeof(r.rib)) >=
- sizeof(r.rib)) {
- yyerror("rib name \"%s\" too long: "
- "max %zu", $3, sizeof(r.rib) - 1);
- free($3);
+
+ for (rb = $3; rb != NULL; rb = rbnext) {
+ rbnext = rb->next;
+ free(rb);
+ }
YYERROR;
}
- free($3);
}
- if (expand_rule(&r, $5, &$6, $7) == -1)
+ if (expand_rule(&r, $3, $5, &$6, $7) == -1)
YYERROR;
}
;
@@ -1517,8 +1516,38 @@ direction : FROM { $$ = DIR_IN; }
| TO { $$ = DIR_OUT; }
;
-filter_rib : /* empty */ { $$ = NULL; }
- | RIB STRING { $$ = $2; }
+filter_rib_h : /* empty */ { $$ = NULL; }
+ | RIB filter_rib { $$ = $2; }
+ | RIB '{' filter_rib_l '}' { $$ = $3; }
+
+filter_rib_l : filter_rib { $$ = $1; }
+ | filter_rib_l comma filter_rib {
+ $3->next = $1;
+ $$ = $3;
+ }
+ ;
+
+filter_rib : STRING {
+ if (!find_rib($1)) {
+ yyerror("rib \"%s\" does not exist.", $1);
+ free($1);
+ YYERROR;
+ }
+ if (($$ = calloc(1, sizeof(struct filter_rib_l))) ==
+ NULL)
+ fatal(NULL);
+ $$->next = NULL;
+ if (strlcpy($$->name, $1, sizeof($$->name)) >=
+ sizeof($$->name)) {
+ yyerror("rib name \"%s\" too long: "
+ "max %zu", $1, sizeof($$->name) - 1);
+ free($1);
+ free($$);
+ YYERROR;
+ }
+ free($1);
+ }
+ ;
filter_peer_h : filter_peer
| '{' filter_peer_l '}' { $$ = $2; }
@@ -3450,58 +3479,76 @@ merge_prefixspec(struct filter_prefix_l
}
int
-expand_rule(struct filter_rule *rule, struct filter_peers_l *peer,
- struct filter_match_l *match, struct filter_set_head *set)
+expand_rule(struct filter_rule *rule, struct filter_rib_l *rib,
+ struct filter_peers_l *peer, struct filter_match_l *match,
+ struct filter_set_head *set)
{
struct filter_rule *r;
+ struct filter_rib_l *rb, *rbnext;
struct filter_peers_l *p, *pnext;
struct filter_prefix_l *prefix, *prefix_next;
struct filter_as_l *a, *anext;
struct filter_set *s;
- p = peer;
+ rb = rib;
do {
- a = match->as_l;
+ p = peer;
do {
- prefix = match->prefix_l;
+ a = match->as_l;
do {
- if ((r = calloc(1,
- sizeof(struct filter_rule))) == NULL) {
- log_warn("expand_rule");
- return (-1);
- }
-
- memcpy(r, rule, sizeof(struct filter_rule));
- memcpy(&r->match, match,
- sizeof(struct filter_match));
- TAILQ_INIT(&r->set);
- copy_filterset(set, &r->set);
-
- if (p != NULL)
- memcpy(&r->peer, &p->p,
- sizeof(struct filter_peers));
-
- if (prefix != NULL)
- memcpy(&r->match.prefix, &prefix->p,
- sizeof(r->match.prefix));
+ prefix = match->prefix_l;
+ do {
+ if ((r = calloc(1,
+ sizeof(struct filter_rule))) ==
+ NULL) {
+ log_warn("expand_rule");
+ return (-1);
+ }
+
+ memcpy(r, rule, sizeof(struct
filter_rule));
+ memcpy(&r->match, match,
+ sizeof(struct filter_match));
+ TAILQ_INIT(&r->set);
+ copy_filterset(set, &r->set);
+
+ if (rb != NULL)
+ strlcpy(r->rib, rb->name,
+ sizeof(r->rib));
+
+ if (p != NULL)
+ memcpy(&r->peer, &p->p,
+ sizeof(struct
filter_peers));
+
+ if (prefix != NULL)
+ memcpy(&r->match.prefix,
&prefix->p,
+ sizeof(r->match.prefix));
+
+ if (a != NULL)
+ memcpy(&r->match.as, &a->a,
+ sizeof(struct filter_as));
+
+ TAILQ_INSERT_TAIL(filter_l, r, entry);
+
+ if (prefix != NULL)
+ prefix = prefix->next;
+ } while (prefix != NULL);
if (a != NULL)
- memcpy(&r->match.as, &a->a,
- sizeof(struct filter_as));
-
- TAILQ_INSERT_TAIL(filter_l, r, entry);
+ a = a->next;
+ } while (a != NULL);
- if (prefix != NULL)
- prefix = prefix->next;
- } while (prefix != NULL);
-
- if (a != NULL)
- a = a->next;
- } while (a != NULL);
-
- if (p != NULL)
- p = p->next;
- } while (p != NULL);
+ if (p != NULL)
+ p = p->next;
+ } while (p != NULL);
+
+ if (rb != NULL)
+ rb = rb->next;
+ } while (rb != NULL);
+
+ for (rb = rib; rb != NULL; rb = rbnext) {
+ rbnext = rb->next;
+ free(rb);
+ }
for (p = peer; p != NULL; p = pnext) {
pnext = p->next;