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.

Reply via email to