Also looks good to me, OK
On 2017 Jan 20 (Fri) at 21:19:22 +0100 (+0100), Denis Fondras wrote:
: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;
:
--
Those who can, do. Those who can't, simulate.