]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge branch 'mq-filter-stack' of gitlab.labs.nic.cz:labs/bird into mq-filter-stack
authorMaria Matejka <mq@ucw.cz>
Wed, 3 Jul 2019 06:44:42 +0000 (08:44 +0200)
committerMaria Matejka <mq@ucw.cz>
Wed, 3 Jul 2019 06:44:42 +0000 (08:44 +0200)
17 files changed:
conf/confbase.Y
filter/config.Y
filter/decl.m4
filter/f-inst.c
filter/f-inst.h
filter/f-util.c
filter/filter.c
filter/filter.h
nest/a-path.c
nest/config.Y
proto/babel/config.Y
proto/bgp/config.Y
proto/ospf/config.Y
proto/radv/config.Y
proto/rip/config.Y
sysdep/linux/netlink.Y
sysdep/unix/krt.Y

index bcfd3f1a4a79b45bd0e5365446f68e77430132f9..775af22d7cdb5602b3054e32de2fa17f93ce0854 100644 (file)
@@ -64,7 +64,9 @@ CF_DECLS
   struct rtable_config *r;
   struct channel_config *cc;
   struct f_inst *x;
-  struct f_inst *xp[2];
+  struct {
+    struct f_inst *begin, *end;
+  } xp;
   enum filter_return fret;
   enum ec_subtype ecs;
   struct f_dynamic_attr fda;
index ff2b966e53a96b9c6601d9ee2d8db59447300605..c40f28d4292bc981d5ab4fd5bd232f9a1775554b 100644 (file)
@@ -447,7 +447,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
 %nonassoc ELSE
 
 %type <xp> cmds_int
-%type <x> term block cmd cmds constant constructor print_one print_list var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail
+%type <x> term block cmd cmds constant constructor print_list var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail
 %type <fda> dynamic_attr
 %type <fsa> static_attr
 %type <f> filter where_filter
@@ -621,11 +621,21 @@ function_def:
 /* Programs */
 
 cmds: /* EMPTY */ { $$ = NULL; }
- | cmds_int { $$ = $1[0]; }
+ | cmds_int { $$ = $1.begin; }
  ;
 
-cmds_int: cmd { $$[0] = $$[1] = $1; }
- | cmds_int cmd { $$[1] = $2; $1[1]->next = $2; $$[0] = $1[0]; }
+cmds_int: cmd {
+  $$.begin = $$.end = $1;
+  while ($$.end->next)
+    $$.end = $$.end->next;
+  }
+ | cmds_int cmd {
+  $$.begin = $1.begin;
+  $1.end->next = $2;
+  $$.end = $2;
+  while ($$.end->next)
+    $$.end = $$.end->next;
+ }
  ;
 
 block:
@@ -960,17 +970,13 @@ break_command:
  | PRINTN { $$ = F_NONL; }
  ;
 
-print_one:
-   term { $$ = f_new_inst(FI_PRINT, $1); }
- ;
-
 print_list: /* EMPTY */ { $$ = NULL; }
- | print_one { $$ = $1; }
- | print_one ',' print_list {
-     if ($1) {
-       $1->next = $3;
-       $$ = $1;
-     } else $$ = $3;
+ | term { $$ = $1; }
+ | term ',' print_list {
+     ASSERT($1);
+     ASSERT($1->next == NULL);
+     $1->next = $3;
+     $$ = $1;
    }
  ;
 
@@ -1011,7 +1017,22 @@ cmd:
  | UNSET '(' dynamic_attr ')' ';' {
      $$ = f_new_inst(FI_EA_UNSET, $3);
    }
- | break_command print_list ';' { $$ = f_new_inst(FI_PRINT_AND_DIE, $2, $1); }
+ | break_command print_list ';' {
+    struct f_inst *breaker = NULL;
+    struct f_inst *printer = NULL;
+    if ($2)
+      printer = f_new_inst(FI_PRINT, $2);
+    if ($1 != F_NONL)
+      breaker = f_new_inst(FI_DIE, $1);
+
+    if (printer && breaker)
+      printer->next = breaker;
+
+    if (printer)
+      $$ = printer;
+    else
+      $$ = breaker;
+   }
  | function_call ';' { $$ = f_new_inst(FI_DROP_RESULT, $1); } 
  | CASE term '{' switch_body '}' {
       $$ = f_new_inst(FI_SWITCH, $2, build_tree($4));
index d1c514409c9a327f8a594ae7c32bc6ab59afd49d..aa4ab5768f47708c507dade598615ab7b88fd774 100644 (file)
@@ -6,177 +6,123 @@ m4_divert(-1)m4_dnl
 #
 #      Can be freely distributed and used under the terms of the GNU GPL.
 #
+#      THIS IS A M4 MACRO FILE GENERATING 3 FILES ALTOGETHER.
+#      KEEP YOUR HANDS OFF UNLESS YOU KNOW WHAT YOU'RE DOING.
+#      EDITING AND DEBUGGING THIS FILE MAY DAMAGE YOUR BRAIN SERIOUSLY.
+#
+#      But you're welcome to read and edit and debug if you aren't scared.
+#
+#      Uncomment the following line to get exhaustive debug output.
+#      m4_debugmode(aceflqtx)
+#
+#      How it works:
+#      1) Instruction to code conversion (uses diversions 100..199)
+#      2) Code wrapping (uses diversions 1..99)
+#      3) Final preparation (uses diversions 200..299)
+#      4) Shipout
+#
+#      See below for detailed description.
 #
-#      Global Diversions:
-#      4       enum fi_code
-#      5       enum fi_code to string
-#      6       dump line item
-#      7       dump line item callers
-#      8       linearize
-#      9       same (filter comparator)
-#      1       union in struct f_inst
-#      3       constructors + interpreter
 #
-#      Per-inst Diversions:
+#      1) Instruction to code conversion
+#      The code provided in f-inst.c between consecutive INST() calls
+#      is interleaved for many different places. It is here processed
+#      and split into separate instances where split-by-instruction
+#      happens. These parts are stored in temporary diversions listed:
+#
 #      101     content of per-inst struct
 #      102     constructor arguments
 #      103     constructor body
 #      104     dump line item content
+#              (there may be nothing in dump-line content and
+#               it must be handled specially in phase 2)
 #      105     linearize body
 #      106     comparator body
 #      107     struct f_line_item content
 #      108     interpreter body
 #
-#      Final diversions
-#      200+    completed text before it is flushed to output
-
-m4_dnl m4_debugmode(aceflqtx)
-
-m4_define(FID_ZONE, `m4_divert($1) /* $2 for INST_NAME() */')
-m4_define(FID_INST, `FID_ZONE(1, Instruction structure for config)')
-m4_define(FID_LINE, `FID_ZONE(2, Instruction structure for interpreter)')
-m4_define(FID_NEW, `FID_ZONE(3, Constructor)')
-m4_define(FID_ENUM, `FID_ZONE(4, Code enum)')
-m4_define(FID_ENUM_STR, `FID_ZONE(5, Code enum to string)')
-m4_define(FID_DUMP, `FID_ZONE(6, Dump line)')
-m4_define(FID_DUMP_CALLER, `FID_ZONE(7, Dump line caller)')
-m4_define(FID_LINEARIZE, `FID_ZONE(8, Linearize)')
-m4_define(FID_SAME, `FID_ZONE(9, Comparison)')
-
+#      Here are macros to allow you to _divert to the right directions.
 m4_define(FID_STRUCT_IN, `m4_divert(101)')
 m4_define(FID_NEW_ARGS, `m4_divert(102)')
 m4_define(FID_NEW_BODY, `m4_divert(103)')
 m4_define(FID_DUMP_BODY, `m4_divert(104)m4_define([[FID_DUMP_BODY_EXISTS]])')
-m4_define(FID_LINEARIZE_BODY, `m4_divert(105)m4_define([[FID_LINEARIZE_BODY_EXISTS]])')
+m4_define(FID_LINEARIZE_BODY, `m4_divert(105)')
 m4_define(FID_SAME_BODY, `m4_divert(106)')
 m4_define(FID_LINE_IN, `m4_divert(107)')
 m4_define(FID_INTERPRET_BODY, `m4_divert(108)')
 
-m4_define(FID_ALL, `FID_INTERPRET_BODY');
+#      Sometimes you want slightly different code versions in different
+#      outputs.
+#      Use FID_HIC(code for inst-gen.h, code for inst-gen.c, code for inst-interpret.c)
+#      and put it into [[ ]] quotes if it shall contain commas.
 m4_define(FID_HIC, `m4_ifelse(TARGET, [[H]], [[$1]], TARGET, [[I]], [[$2]], TARGET, [[C]], [[$3]])')
 
+#      In interpreter code, this is quite common.
 m4_define(FID_INTERPRET_EXEC, `FID_HIC(,[[FID_INTERPRET_BODY()]],[[m4_divert(-1)]])')
 m4_define(FID_INTERPRET_NEW,  `FID_HIC(,[[m4_divert(-1)]],[[FID_INTERPRET_BODY()]])')
+
+#      If the instruction is never converted to constant, the interpret
+#      code is not produced at all for constructor
 m4_define(NEVER_CONSTANT, `m4_define([[INST_NEVER_CONSTANT]])')
 m4_define(FID_IFCONST, `m4_ifdef([[INST_NEVER_CONSTANT]],[[$2]],[[$1]])')
 
-m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[
-FID_ENUM
-INST_NAME(),
-FID_ENUM_STR
-[INST_NAME()] = "INST_NAME()",
-FID_INST
-struct {
-m4_undivert(101)
-} i_[[]]INST_NAME();
-FID_LINE
-struct {
-m4_undivert(107)
-} i_[[]]INST_NAME();
-FID_NEW
-FID_HIC(
-[[
-struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
-m4_undivert(102)
-);]],
-[[
-  case INST_NAME():
-  #define whati (&(what->i_]]INST_NAME()[[))
-  m4_ifelse(m4_eval(INST_INVAL() > 0), 1, [[if (fstk->vcnt < INST_INVAL()) runtime("Stack underflow"); fstk->vcnt -= INST_INVAL(); ]])
-  m4_undivert(108)
-  #undef whati
-  break;
-]],
-[[
-struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
-m4_undivert(102)
-)
-  {
-    struct f_inst *what = fi_new(fi_code);
-    FID_IFCONST([[uint constargs = 1;]])
-  #define whati (&(what->i_]]INST_NAME()[[))
-  m4_undivert(103)
-    FID_IFCONST([[if (!constargs)]])
-      return what;
-    FID_IFCONST([[m4_undivert(108)]])
-  #undef whati
-  }
-]])
-
-FID_DUMP_CALLER
-case INST_NAME(): f_dump_line_item_]]INST_NAME()[[(item, indent + 1); break;
-
-FID_DUMP
-m4_ifdef([[FID_DUMP_BODY_EXISTS]],
-[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item_, const int indent)]],
-[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item UNUSED, const int indent UNUSED)]])
-m4_undefine([[FID_DUMP_BODY_EXISTS]])
-{
-#define item (&(item_->i_]]INST_NAME()[[))
-m4_undivert(104)
-#undef item
-}
-
-FID_LINEARIZE
-case INST_NAME(): {
-#define whati (&(what->i_]]INST_NAME()[[))
-#define item (&(dest->items[pos].i_]]INST_NAME()[[))
-  m4_undivert(105)
-#undef whati
-#undef item
-  dest->items[pos].fi_code = what->fi_code;
-  dest->items[pos].lineno = what->lineno;
-  break;
-}
-m4_undefine([[FID_LINEARIZE_BODY_EXISTS]])
-
-FID_SAME
-case INST_NAME():
-#define f1 (&(f1_->i_]]INST_NAME()[[))
-#define f2 (&(f2_->i_]]INST_NAME()[[))
-m4_undivert(106)
-#undef f1
-#undef f2
-break;
-m4_divert(-1)FID_FLUSH(101,200)
-]])')
-
-m4_define(INST, `m4_dnl
-INST_FLUSH()m4_dnl
-m4_define([[INST_NAME]], [[$1]])m4_dnl
-m4_define([[INST_INVAL]], [[$2]])m4_dnl
-m4_undefine([[INST_NEVER_CONSTANT]])m4_dnl
-FID_ALL() m4_dnl
-')
-
+#      If the instruction has some attributes (here called members),
+#      these are typically carried with the instruction from constructor
+#      to interpreter. This yields a line of code everywhere on the path.
+#      FID_MEMBER is a macro to help with this task.
 m4_define(FID_MEMBER, `m4_dnl
-FID_LINE_IN
-$1 $2;
-FID_STRUCT_IN
-$1 $2;
-FID_NEW_ARGS
-, $1 $2
-FID_NEW_BODY
+FID_LINE_IN()m4_dnl
+      $1 $2;
+FID_STRUCT_IN()m4_dnl
+      $1 $2;
+FID_NEW_ARGS()m4_dnl
+  , $1 $2
+FID_NEW_BODY()m4_dnl
 whati->$2 = $2;
-FID_LINEARIZE_BODY
+FID_LINEARIZE_BODY()m4_dnl
 item->$2 = whati->$2;
 m4_ifelse($3,,,[[
-FID_SAME_BODY
+FID_SAME_BODY()m4_dnl
 if ($3) return 0;
 ]])
 m4_ifelse($4,,,[[
-FID_DUMP_BODY
+FID_DUMP_BODY()m4_dnl
 debug("%s$4\n", INDENT, $5);
 ]])
-FID_INTERPRET_EXEC
+FID_INTERPRET_EXEC()m4_dnl
 const $1 $2 = whati->$2
-FID_ALL')
+FID_INTERPRET_BODY')
+
+m4_define(FID_MEMBER_IN, `m4_dnl
+FID_LINE_IN()m4_dnl
+      $1 $2;
+FID_STRUCT_IN()m4_dnl
+      $1 $2;
+FID_LINEARIZE_BODY()m4_dnl
+item->$2 = whati->$2;
+m4_ifelse($3,,,[[
+FID_SAME_BODY()m4_dnl
+if ($3) return 0;
+]])
+m4_ifelse($4,,,[[
+FID_DUMP_BODY()m4_dnl
+debug("%s$4\n", INDENT, $5);
+]])
+FID_INTERPRET_EXEC()m4_dnl
+const $1 $2 = whati->$2
+FID_INTERPRET_BODY')
 
+#      Instruction arguments are needed only until linearization is done.
+#      This puts the arguments into the filter line to be executed before
+#      the instruction itself.
+#
+#      To achieve this, ARG_ANY must be called before anything writes into
+#      the instruction line as it moves the instruction pointer forward.
 m4_define(ARG_ANY, `
-FID_STRUCT_IN
-struct f_inst * f$1;
-FID_NEW_ARGS
-, struct f_inst * f$1
+FID_STRUCT_IN()m4_dnl
+      struct f_inst * f$1;
+FID_NEW_ARGS()m4_dnl
+  , struct f_inst * f$1
 FID_NEW_BODY
 whati->f$1 = f$1;
 for (const struct f_inst *child = f$1; child; child = child->next) {
@@ -188,14 +134,17 @@ FID_IFCONST([[
 }
 FID_LINEARIZE_BODY
 pos = linearize(dest, whati->f$1, pos);
-FID_ALL()')
+FID_INTERPRET_BODY()')
 
+#      Some arguments need to check their type. After that, ARG_ANY is called.
 m4_define(ARG, `ARG_ANY($1)
-FID_INTERPRET_EXEC()
+FID_INTERPRET_EXEC()m4_dnl
 if (v$1.type != $2) runtime("Argument $1 of instruction %s must be of type $2, got 0x%02x", f_instruction_name(what->fi_code), v$1.type)m4_dnl
-FID_ALL()')
+FID_INTERPRET_BODY()')
 
-m4_define(LINEX, `FID_INTERPRET_EXEC()LINEX_($1)FID_INTERPRET_NEW()return $1 FID_ALL()')
+#      Executing another filter line. This replaces the recursion
+#      that was needed in the former implementation.
+m4_define(LINEX, `FID_INTERPRET_EXEC()LINEX_($1)FID_INTERPRET_NEW()return $1 FID_INTERPRET_BODY()')
 m4_define(LINEX_, `do {
   fstk->estk[fstk->ecnt].pos = 0;
   fstk->estk[fstk->ecnt].line = $1;
@@ -206,47 +155,212 @@ m4_define(LINEX_, `do {
 } while (0)')
 
 m4_define(LINE, `
-FID_LINE_IN
-const struct f_line * fl$1;
-FID_STRUCT_IN
-struct f_inst * f$1;
-FID_NEW_ARGS
-, struct f_inst * f$1
-FID_NEW_BODY
+FID_LINE_IN()m4_dnl
+      const struct f_line * fl$1;
+FID_STRUCT_IN()m4_dnl
+      struct f_inst * f$1;
+FID_NEW_ARGS()m4_dnl
+  , struct f_inst * f$1
+FID_NEW_BODY()m4_dnl
 whati->f$1 = f$1;
-FID_DUMP_BODY
+FID_DUMP_BODY()m4_dnl
 f_dump_line(item->fl$1, indent + 1);
-FID_LINEARIZE_BODY
+FID_LINEARIZE_BODY()m4_dnl
 item->fl$1 = f_linearize(whati->f$1);
-FID_SAME_BODY
+FID_SAME_BODY()m4_dnl
 if (!f_same(f1->fl$1, f2->fl$1)) return 0;
-FID_INTERPRET_EXEC
+FID_INTERPRET_EXEC()m4_dnl
 do { if (whati->fl$1) {
   LINEX_(whati->fl$1);
 } } while(0)
-FID_INTERPRET_NEW
+FID_INTERPRET_NEW()m4_dnl
 return whati->f$1
-FID_ALL()')
+FID_INTERPRET_BODY()')
 
+#      Some of the instructions have a result. These constructions
+#      state the result and put it to the right place.
 m4_define(RESULT, `RESULT_VAL([[ (struct f_val) { .type = $1, .val.$2 = $3 } ]])')
 m4_define(RESULT_VAL, `FID_HIC(, [[do { res = $1; fstk->vcnt++; } while (0)]],
 [[return fi_constant(what, $1)]])')
 m4_define(RESULT_VOID, `RESULT_VAL([[ (struct f_val) { .type = T_VOID } ]])')
 
-m4_define(SYMBOL, `FID_MEMBER(struct symbol *, sym, 
-[[strcmp(f1->sym->name, f2->sym->name) || (f1->sym->class != f2->sym->class)]], symbol %s, item->sym->name)')
+#      Some common filter instruction members
+m4_define(SYMBOL, `FID_MEMBER(struct symbol *, sym, [[strcmp(f1->sym->name, f2->sym->name) || (f1->sym->class != f2->sym->class)]], symbol %s, item->sym->name)')
 m4_define(RTC, `FID_MEMBER(struct rtable_config *, rtc, [[strcmp(f1->rtc->name, f2->rtc->name)]], route table %s, item->rtc->name)')
 m4_define(STATIC_ATTR, `FID_MEMBER(struct f_static_attr, sa, f1->sa.sa_code != f2->sa.sa_code,,)')
 m4_define(DYNAMIC_ATTR, `FID_MEMBER(struct f_dynamic_attr, da, f1->da.ea_code != f2->da.ea_code,,)')
 m4_define(ACCESS_RTE, `NEVER_CONSTANT()')
 
+#      2) Code wrapping
+#      The code produced in 1xx temporary diversions is a raw code without
+#      any auxiliary commands and syntactical structures around. When the
+#      instruction is done, INST_FLUSH is called. More precisely, it is called
+#      at the beginning of INST() call and at the end of file.
+#
+#      INST_FLUSH picks all the temporary diversions, wraps their content
+#      into appropriate headers and structures and saves them into global
+#      diversions listed:
+#
+#      4       enum fi_code
+#      5       enum fi_code to string
+#      6       dump line item
+#      7       dump line item callers
+#      8       linearize
+#      9       same (filter comparator)
+#      1       union in struct f_inst
+#      3       constructors + interpreter
+#
+#      These global diversions contain blocks of code that can be directly
+#      put into the final file, yet it still can't be written out now as
+#      every instruction writes to all of these diversions.
+
+#      Code wrapping diversion names. Here we want an explicit newline
+#      after the C comment.
+m4_define(FID_ZONE, `m4_divert($1) /* $2 for INST_NAME() */
+')
+m4_define(FID_INST, `FID_ZONE(1, Instruction structure for config)')
+m4_define(FID_LINE, `FID_ZONE(2, Instruction structure for interpreter)')
+m4_define(FID_NEW, `FID_ZONE(3, Constructor)')
+m4_define(FID_ENUM, `FID_ZONE(4, Code enum)')
+m4_define(FID_ENUM_STR, `FID_ZONE(5, Code enum to string)')
+m4_define(FID_DUMP, `FID_ZONE(6, Dump line)')
+m4_define(FID_DUMP_CALLER, `FID_ZONE(7, Dump line caller)')
+m4_define(FID_LINEARIZE, `FID_ZONE(8, Linearize)')
+m4_define(FID_SAME, `FID_ZONE(9, Comparison)')
+
+#      This macro does all the code wrapping. See inline comments.
+m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[
+FID_ENUM()m4_dnl                        Contents of enum fi_code { ... }
+  INST_NAME(),
+FID_ENUM_STR()m4_dnl                    Contents of const char * indexed by enum fi_code
+  [INST_NAME()] = "INST_NAME()",
+FID_INST()m4_dnl                        Anonymous structure inside struct f_inst
+    struct {
+m4_undivert(101)m4_dnl
+    } i_[[]]INST_NAME();
+FID_LINE()m4_dnl                        Anonymous structure inside struct f_line_item
+    struct {
+m4_undivert(107)m4_dnl
+    } i_[[]]INST_NAME();
+FID_NEW()m4_dnl                                 Constructor and interpreter code together
+FID_HIC(
+[[m4_dnl                                Public declaration of constructor in H file
+struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
+m4_undivert(102)m4_dnl
+);]],
+[[m4_dnl                                The one case in The Big Switch inside interpreter
+  case INST_NAME():
+  #define whati (&(what->i_]]INST_NAME()[[))
+  m4_ifelse(m4_eval(INST_INVAL() > 0), 1, [[if (fstk->vcnt < INST_INVAL()) runtime("Stack underflow"); fstk->vcnt -= INST_INVAL(); ]])
+  m4_undivert(108)m4_dnl
+  #undef whati
+  break;
+]],
+[[m4_dnl                                Constructor itself
+struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
+m4_undivert(102)m4_dnl
+)
+  {
+    /* Allocate the structure */
+    struct f_inst *what = fi_new(fi_code);
+    FID_IFCONST([[uint constargs = 1;]])
+
+    /* Initialize all the members */
+  #define whati (&(what->i_]]INST_NAME()[[))
+  m4_undivert(103)m4_dnl
+
+    /* If not constant, return the instruction itself */
+    FID_IFCONST([[if (!constargs)]])
+      return what;
+
+    /* Try to pre-calculate the result */
+    FID_IFCONST([[m4_undivert(108)]])m4_dnl
+  #undef whati
+  }
+]])
+
+FID_DUMP_CALLER()m4_dnl                         Case in another big switch used in instruction dumping (debug)
+case INST_NAME(): f_dump_line_item_]]INST_NAME()[[(item, indent + 1); break;
+
+FID_DUMP()m4_dnl                        The dumper itself
+m4_ifdef([[FID_DUMP_BODY_EXISTS]],
+[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item_, const int indent)]],
+[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item UNUSED, const int indent UNUSED)]])
+m4_undefine([[FID_DUMP_BODY_EXISTS]])
+{
+#define item (&(item_->i_]]INST_NAME()[[))
+m4_undivert(104)m4_dnl
+#undef item
+}
+
+FID_LINEARIZE()m4_dnl                   The linearizer
+case INST_NAME(): {
+#define whati (&(what->i_]]INST_NAME()[[))
+#define item (&(dest->items[pos].i_]]INST_NAME()[[))
+  m4_undivert(105)m4_dnl
+#undef whati
+#undef item
+  dest->items[pos].fi_code = what->fi_code;
+  dest->items[pos].lineno = what->lineno;
+  break;
+}
+
+FID_SAME()m4_dnl                        This code compares two f_line"s while reconfiguring
+case INST_NAME():
+#define f1 (&(f1_->i_]]INST_NAME()[[))
+#define f2 (&(f2_->i_]]INST_NAME()[[))
+m4_undivert(106)m4_dnl
+#undef f1
+#undef f2
+break;
+
+m4_divert(-1)FID_FLUSH(101,200)m4_dnl  And finally this flushes all the unused diversions
+]])')
+
+m4_define(INST, `m4_dnl                                This macro is called on beginning of each instruction.
+INST_FLUSH()m4_dnl                             First, old data is flushed
+m4_define([[INST_NAME]], [[$1]])m4_dnl         Then we store instruction name,
+m4_define([[INST_INVAL]], [[$2]])m4_dnl                instruction input value count
+m4_undefine([[INST_NEVER_CONSTANT]])m4_dnl     and reset NEVER_CONSTANT trigger.
+FID_INTERPRET_BODY()m4_dnl                     By default, every code is interpreter code.
+')
+
+#      3) Final preparation
+#
+#      Now we prepare all the code around the global diversions.
+#      It must be here, not in m4wrap, as we want M4 to mark the code
+#      by #line directives correctly, not to claim that every single line
+#      is at the beginning of the m4wrap directive.
+#
+#      This part is split by the final file.
+#      H for inst-gen.h
+#      I for inst-interpret.c
+#      C for inst-gen.c
+#
+#      So we in cycle:
+#        A. open a diversion
+#        B. send there some code
+#        C. close that diversion
+#        D. flush a global diversion
+#        E. open another diversion and goto B.
+#
+#      Final diversions
+#      200+    completed text before it is flushed to output
+
+#      This is a list of output diversions
 m4_define(FID_WR_PUT_LIST)
+
+#      This macro does the steps C to E, see before.
 m4_define(FID_WR_PUT_ALSO, `m4_define([[FID_WR_PUT_LIST]],FID_WR_PUT_LIST()[[FID_WR_DPUT(]]FID_WR_DIDX[[)FID_WR_DPUT(]]$1[[)]])m4_define([[FID_WR_DIDX]],m4_eval(FID_WR_DIDX+1))m4_divert(FID_WR_DIDX)')
 
+#      These macros do the splitting between H/I/C
 m4_define(FID_WR_DIRECT, `m4_ifelse(TARGET,[[$1]],[[FID_WR_INIT()]],[[FID_WR_STOP()]])')
 m4_define(FID_WR_INIT, `m4_define([[FID_WR_DIDX]],200)m4_define([[FID_WR_PUT]],[[FID_WR_PUT_ALSO($]][[@)]])m4_divert(200)')
 m4_define(FID_WR_STOP, `m4_define([[FID_WR_PUT]])m4_divert(-1)')
 
+#      Here is the direct code to be put into the output files
+#      together with the undiversions, being hidden under FID_WR_PUT()
+
 m4_changequote([[,]])
 FID_WR_DIRECT(I)
 FID_WR_PUT(3)
@@ -395,7 +509,7 @@ FID_WR_PUT(9)
 FID_WR_DIRECT(H)
 /* Filter instruction codes */
 enum f_instruction_code {
-FID_WR_PUT(4)
+FID_WR_PUT(4)m4_dnl
 } PACKED;
 
 /* Filter instruction structure for config */
@@ -405,7 +519,7 @@ struct f_inst {
   int size;                            /* How many instructions are underneath */
   int lineno;                          /* Line number */
   union {
-    FID_WR_PUT(1)
+FID_WR_PUT(1)m4_dnl
   };
 };
 
@@ -415,19 +529,30 @@ struct f_line_item {
   enum f_instruction_flags flags;      /* Flags, instruction-specific */
   uint lineno;                         /* Where */
   union {
-    FID_WR_PUT(2)
+FID_WR_PUT(2)m4_dnl
   };
 };
 
 /* Instruction constructors */
 FID_WR_PUT(3)
-
 m4_divert(-1)
+
+#      4) Shipout
+#
+#      Everything is prepared in FID_WR_PUT_LIST now. Let's go!
+
 m4_changequote(`,')
 
+#      Flusher auxiliary macro
 m4_define(FID_FLUSH, `m4_ifelse($1,$2,,[[m4_undivert($1)FID_FLUSH(m4_eval($1+1),$2)]])')
+
+#      Defining the macro used in FID_WR_PUT_LIST
 m4_define(FID_WR_DPUT, `m4_undivert($1)')
 
+#      After the code is read and parsed, we:
 m4_m4wrap(`INST_FLUSH()m4_divert(0)FID_WR_PUT_LIST()m4_divert(-1)FID_FLUSH(1,200)')
 
 m4_changequote([[,]])
+#      And now M4 is going to parse f-inst.c, fill the diversions
+#      and after the file is done, the content of m4_m4wrap (see before)
+#      is executed.
index edc9779408d90f049a6d4075b704aafbde60d006..8d5c6656f37cad1eee033e29bd21c7ef33c7305e 100644 (file)
        }
        whati->f1 = NULL;
       }
-    FID_ALL
+    FID_INTERPRET_BODY
 
     FID_INTERPRET_EXEC
     if (fstk->vcnt < whati->count) /* TODO: make this check systematic */
       runtime("Construction of BGP path mask from %u elements must have at least that number of elements", whati->count);
 
-#define pv fstk->vstk[fstk->vcnt - count + i]
+#define pv fstk->vstk[fstk->vcnt - whati->count + i]
 
     FID_INTERPRET_NEW
 #define pv items[i]->i_FI_CONSTANT.val
 
     FID_INTERPRET_EXEC
       fstk->vcnt -= whati->count;
-    FID_ALL
+    FID_INTERPRET_BODY
 
     pm->len = whati->count;
     RESULT(T_PATH_MASK, path_mask, pm);
 
     RESULT_VAL(val);
   }
-  INST(FI_PRINT, 1, 0) {
-    NEVER_CONSTANT;
-    ARG_ANY(1);
-    val_format(&(v1), &fs->buf);
-  }
   INST(FI_CONDITION, 1, 0) {
     ARG(1, T_BOOL);
     if (v1.val.i)
     else
       LINE(3,1);
   }
-  INST(FI_PRINT_AND_DIE, 0, 0) {
-    NEVER_CONSTANT;
-    FID_LINEARIZE_BODY
-    {
-      uint opos = pos;
-      FID_ALL
 
+  INST(FI_PRINT, 0, 0) {
+    NEVER_CONSTANT;
     ARG_ANY(1);
+    FID_MEMBER_IN(uint, count, f1->count != f2->count, number of items %u, item->count);
 
-      FID_LINEARIZE_BODY
-      if (opos < pos)
-       dest->items[pos].flags |= FIF_PRINTED;
-    }
-    FID_ALL
+    FID_NEW_BODY
+      uint len = 0;
+      for (const struct f_inst *tt = f1; tt; tt = tt->next, len++)
+       ;
+      whati->count = len;
+
+    FID_INTERPRET_BODY
+
+#define pv fstk->vstk[fstk->vcnt - whati->count + i]
+    if (whati->count)
+      for (uint i=0; i<whati->count; i++)
+       val_format(&(pv), &fs->buf);
+#undef pv
 
+    fstk->vcnt -= whati->count;
+  }
+
+  INST(FI_DIE, 0, 0) {
+    NEVER_CONSTANT;
     FID_MEMBER(enum filter_return, fret, f1->fret != f2->fret, %s, filter_return_str(item->fret));
 
-    if ((fret == F_NOP || (fret != F_NONL && (what->flags & FIF_PRINTED))) &&
-       !(fs->flags & FF_SILENT))
+    if (fs->buf.start < fs->buf.pos)
       log_commit(*L_INFO, &fs->buf);
 
-    switch (fret) {
+    switch (whati->fret) {
     case F_QUITBIRD:
       die( "Filter asked me to die" );
     case F_ACCEPT:
     case F_ERROR:
     case F_REJECT:     /* FIXME (noncritical) Should print complete route along with reason to reject route */
       return fret;     /* We have to return now, no more processing. */
-    case F_NONL:
     case F_NOP:
       break;
     default:
   INST(FI_ASSERT, 1, 0) {      /* Birdtest Assert */
     NEVER_CONSTANT;
     ARG(1, T_BOOL);
-    FID_MEMBER(char *, s, [[strcmp(f1->s, f2->s)]], string \"%s\", item->s);
+
+    FID_MEMBER(char *, s, [[strcmp(f1->s, f2->s)]], string %s, item->s);
 
     ASSERT(s);
 
index 2a2d050e8c6fdaf475861d9379813dfb6dd2d095..58a60f0fc699189dccbbf0fdfbd65c3b76bb59e9 100644 (file)
@@ -80,8 +80,10 @@ static inline struct f_line *f_linearize(const struct f_inst *root)
 void f_dump_line(const struct f_line *, uint indent);
 
 struct filter *f_new_where(struct f_inst *);
-static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, u8 bit, enum f_type f_type, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
-{ return (struct f_dynamic_attr) { .type = type, .bit = bit, .f_type = f_type, .ea_code = code }; }   /* f_type currently unused; will be handy for static type checking */
+static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, enum f_type f_type, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
+{ return (struct f_dynamic_attr) { .type = type, .f_type = f_type, .ea_code = code }; }   /* f_type currently unused; will be handy for static type checking */
+static inline struct f_dynamic_attr f_new_dynamic_attr_bit(u8 bit, enum f_type f_type, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
+{ return (struct f_dynamic_attr) { .type = EAF_TYPE_BITFIELD, .bit = bit, .f_type = f_type, .ea_code = code }; }   /* f_type currently unused; will be handy for static type checking */
 static inline struct f_static_attr f_new_static_attr(int f_type, int code, int readonly)
 { return (struct f_static_attr) { .f_type = f_type, .sa_code = code, .readonly = readonly }; }
 struct f_inst *f_generate_complex(enum f_instruction_code fi_code, struct f_dynamic_attr da, struct f_inst *argument);
index 4b580fb9853d0a9eda0d4be9d790fb76cca472aa..e61949f241cf058fb75446f1c2db7f8952bc1b1b 100644 (file)
@@ -33,17 +33,17 @@ filter_name(const struct filter *filter)
 struct filter *f_new_where(struct f_inst *where)
 {
   struct f_inst acc = {
-    .fi_code = FI_PRINT_AND_DIE,
+    .fi_code = FI_DIE,
     .lineno = ifs->lino,
     .size = 1,
-    .i_FI_PRINT_AND_DIE = { .fret = F_ACCEPT, },
+    .i_FI_DIE = { .fret = F_ACCEPT, },
   };
 
   struct f_inst rej = {
-    .fi_code = FI_PRINT_AND_DIE,
+    .fi_code = FI_DIE,
     .lineno = ifs->lino,
     .size = 1,
-    .i_FI_PRINT_AND_DIE = { .fret = F_REJECT, },
+    .i_FI_DIE = { .fret = F_REJECT, },
   };
 
   struct f_inst i = {
@@ -174,7 +174,7 @@ ca_lookup(pool *p, const char *name, int f_type)
     }
 
     cas = mb_allocz(&root_pool, sizeof(struct ca_storage) + strlen(name) + 1);
-    cas->fda = f_new_dynamic_attr(ea_type, 0, f_type, EA_CUSTOM(id));
+    cas->fda = f_new_dynamic_attr(ea_type, f_type, EA_CUSTOM(id));
     cas->uc = 1;
 
     strcpy(cas->name, name);
index ed0b21bc26e51ae4525eea5561855711767aed36..d9c98872ac6d27cf88d5a8b3add641cec8a32943 100644 (file)
@@ -482,3 +482,41 @@ filter_commit(struct config *new, struct config *old)
        break;
     }
 }
+
+void filters_dump_all(void)
+{
+  struct symbol *sym;
+  WALK_LIST(sym, config->symbols) {
+    switch (sym->class) {
+      case SYM_FILTER:
+       debug("Named filter %s:\n", sym->name);
+       f_dump_line(sym->filter->root, 1);
+       break;
+      case SYM_FUNCTION:
+       debug("Function %s:\n", sym->name);
+       f_dump_line(sym->function, 1);
+       break;
+      case SYM_PROTO:
+       {
+         debug("Protocol %s:\n", sym->name);
+         struct channel *c;
+         WALK_LIST(c, sym->proto->proto->channels) {
+           debug(" Channel %s (%s) IMPORT", c->name, net_label[c->net_type]);
+           if (c->in_filter == FILTER_ACCEPT)
+             debug(" ALL\n");
+           else if (c->in_filter == FILTER_REJECT)
+             debug(" NONE\n");
+           else if (c->in_filter == FILTER_UNDEF)
+             debug(" UNDEF\n");
+           else if (c->in_filter->sym) {
+             ASSERT(c->in_filter->sym->filter == c->in_filter);
+             debug(" named filter %s\n", c->in_filter->sym->name);
+           } else {
+             debug("\n");
+             f_dump_line(c->in_filter->root, 2);
+           }
+         }
+       }
+    }
+  }
+}
index 36b63e7c8d37105598292c1019fa873802f88525..9d997efbf9b9c755256d11b2a024dbe4dc39527d 100644 (file)
@@ -64,9 +64,11 @@ int f_same(const struct f_line *f1, const struct f_line *f2);
 
 void filter_commit(struct config *new, struct config *old);
 
+void filters_dump_all(void);
+
 #define FILTER_ACCEPT NULL
-#define FILTER_REJECT ((void *) 1)
-#define FILTER_UNDEF  ((void *) 2)     /* Used in BGP */
+#define FILTER_REJECT ((struct filter *) 1)
+#define FILTER_UNDEF  ((struct filter *) 2)    /* Used in BGP */
 
 #define FF_SILENT 2                    /* Silent filter execution */
 
index 62369af3a1ae21d10056d411ca672bd7fec31bc2..a1b7c42f8cd5333865c27d652b670e3644bf937f 100644 (file)
@@ -271,7 +271,6 @@ as_path_to_old(struct linpool *pool, const struct adata *path)
 /*
  * Cut the path to the length @num, measured to the usual path metric. Note that
  * AS_CONFED_* segments have zero length and must be added if they are on edge.
- * In contrast to other as_path_* functions, @path is modified in place.
  */
 struct adata *
 as_path_cut(struct linpool *pool, const struct adata *path, uint num)
index e4dedc66fa1c78e94622bddcd26c5df05c9547c6..e97b8fb37d61ed4ba4d759eb2156c0a5a70a0805 100644 (file)
@@ -731,6 +731,8 @@ CF_CLI(DUMP ROUTES,,, [[Dump routing table]])
 { rt_dump_all(); cli_msg(0, ""); } ;
 CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]])
 { protos_dump_all(); cli_msg(0, ""); } ;
+CF_CLI(DUMP FILTER ALL,,, [[Dump all filters in linearized form]])
+{ filters_dump_all(); cli_msg(0, ""); } ;
 
 CF_CLI(EVAL, term, <expr>, [[Evaluate an expression]])
 { cmd_eval(f_linearize($2)); } ;
@@ -791,7 +793,7 @@ proto_patt2:
  | TEXT { $$.ptr = $1; $$.patt = 1; }
  ;
 
-dynamic_attr: IGP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_GEN_IGP_METRIC); } ;
+dynamic_attr: IGP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_GEN_IGP_METRIC); } ;
 
 
 CF_CODE
index 7817532322c70c111b866a44f4b967bcb04232a4..b6bc70fa89e39d65a2a982ceec82b3105d2e7b51 100644 (file)
@@ -125,7 +125,7 @@ babel_iface_opt_list:
 babel_iface:
   babel_iface_start iface_patt_list_nopx babel_iface_opt_list babel_iface_finish;
 
-dynamic_attr: BABEL_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_BABEL_METRIC); } ;
+dynamic_attr: BABEL_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_BABEL_METRIC); } ;
 
 CF_CLI_HELP(SHOW BABEL, ..., [[Show information about Babel protocol]]);
 
index f9e5efaf67b87b79075a25757bdeeab8836ab6fa..ac8d024aaa2d182d7e501ad6c1b86bb626d681aa 100644 (file)
@@ -272,29 +272,29 @@ bgp_proto_channel: bgp_channel_start bgp_channel_opt_list bgp_channel_end;
 
 
 dynamic_attr: BGP_ORIGIN
-       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_ENUM_BGP_ORIGIN, EA_CODE(PROTOCOL_BGP, BA_ORIGIN)); } ;
+       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_ENUM_BGP_ORIGIN, EA_CODE(PROTOCOL_BGP, BA_ORIGIN)); } ;
 dynamic_attr: BGP_PATH
-       { $$ = f_new_dynamic_attr(EAF_TYPE_AS_PATH, 0, T_PATH, EA_CODE(PROTOCOL_BGP, BA_AS_PATH)); } ;
+       { $$ = f_new_dynamic_attr(EAF_TYPE_AS_PATH, T_PATH, EA_CODE(PROTOCOL_BGP, BA_AS_PATH)); } ;
 dynamic_attr: BGP_NEXT_HOP
-       { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, 0, T_IP, EA_CODE(PROTOCOL_BGP, BA_NEXT_HOP)); } ;
+       { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_CODE(PROTOCOL_BGP, BA_NEXT_HOP)); } ;
 dynamic_attr: BGP_MED
-       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC)); } ;
+       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC)); } ;
 dynamic_attr: BGP_LOCAL_PREF
-       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF)); } ;
+       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF)); } ;
 dynamic_attr: BGP_ATOMIC_AGGR
-       { $$ = f_new_dynamic_attr(EAF_TYPE_OPAQUE, 0, T_ENUM_EMPTY, EA_CODE(PROTOCOL_BGP, BA_ATOMIC_AGGR)); } ;
+       { $$ = f_new_dynamic_attr(EAF_TYPE_OPAQUE, T_ENUM_EMPTY, EA_CODE(PROTOCOL_BGP, BA_ATOMIC_AGGR)); } ;
 dynamic_attr: BGP_AGGREGATOR
-       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_CODE(PROTOCOL_BGP, BA_AGGREGATOR)); } ;
+       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_AGGREGATOR)); } ;
 dynamic_attr: BGP_COMMUNITY
-       { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, 0, T_CLIST, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY)); } ;
+       { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY)); } ;
 dynamic_attr: BGP_ORIGINATOR_ID
-       { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, 0, T_QUAD, EA_CODE(PROTOCOL_BGP, BA_ORIGINATOR_ID)); } ;
+       { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, T_QUAD, EA_CODE(PROTOCOL_BGP, BA_ORIGINATOR_ID)); } ;
 dynamic_attr: BGP_CLUSTER_LIST
-       { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, 0, T_CLIST, EA_CODE(PROTOCOL_BGP, BA_CLUSTER_LIST)); } ;
+       { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(PROTOCOL_BGP, BA_CLUSTER_LIST)); } ;
 dynamic_attr: BGP_EXT_COMMUNITY
-       { $$ = f_new_dynamic_attr(EAF_TYPE_EC_SET, 0, T_ECLIST, EA_CODE(PROTOCOL_BGP, BA_EXT_COMMUNITY)); } ;
+       { $$ = f_new_dynamic_attr(EAF_TYPE_EC_SET, T_ECLIST, EA_CODE(PROTOCOL_BGP, BA_EXT_COMMUNITY)); } ;
 dynamic_attr: BGP_LARGE_COMMUNITY
-       { $$ = f_new_dynamic_attr(EAF_TYPE_LC_SET, 0, T_LCLIST, EA_CODE(PROTOCOL_BGP, BA_LARGE_COMMUNITY)); } ;
+       { $$ = f_new_dynamic_attr(EAF_TYPE_LC_SET, T_LCLIST, EA_CODE(PROTOCOL_BGP, BA_LARGE_COMMUNITY)); } ;
 
 
 
index 66cf60c1b4ab7ed916a574b4c0ffd165745a4b11..2e9ed0ac0d8a59c98a3cd0f8768b01602a7cf7eb 100644 (file)
@@ -498,10 +498,10 @@ ospf_iface:
   ospf_iface_start ospf_iface_patt_list ospf_iface_opt_list { ospf_iface_finish(); }
  ;
 
-dynamic_attr: OSPF_METRIC1 { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_OSPF_METRIC1); } ;
-dynamic_attr: OSPF_METRIC2 { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_OSPF_METRIC2); } ;
-dynamic_attr: OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_OSPF_TAG); } ;
-dynamic_attr: OSPF_ROUTER_ID { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, 0, T_QUAD, EA_OSPF_ROUTER_ID); } ;
+dynamic_attr: OSPF_METRIC1 { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_OSPF_METRIC1); } ;
+dynamic_attr: OSPF_METRIC2 { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_OSPF_METRIC2); } ;
+dynamic_attr: OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_OSPF_TAG); } ;
+dynamic_attr: OSPF_ROUTER_ID { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, T_QUAD, EA_OSPF_ROUTER_ID); } ;
 
 CF_CLI_HELP(SHOW OSPF, ..., [[Show information about OSPF protocol]]);
 CF_CLI(SHOW OSPF, optproto, [<name>], [[Show information about OSPF protocol]])
index b8eeb4394a8494cb9f35e1b62d9dc034f932bf7e..53715f776c31df1ec3f62e7d6a25c3363c081551 100644 (file)
@@ -332,8 +332,8 @@ radv_sensitive:
  | SENSITIVE bool { $$ = $2; }
  ;
 
-dynamic_attr: RA_PREFERENCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_ENUM_RA_PREFERENCE, EA_RA_PREFERENCE); } ;
-dynamic_attr: RA_LIFETIME { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_RA_LIFETIME); } ;
+dynamic_attr: RA_PREFERENCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_ENUM_RA_PREFERENCE, EA_RA_PREFERENCE); } ;
+dynamic_attr: RA_LIFETIME { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_RA_LIFETIME); } ;
 
 CF_CODE
 
index 4ab793d19c74542a1b87e64d7c3b46fbe98ffd2b..5b5f94a0b1943785ef2fb63cddaca8fcb379bf6a 100644 (file)
@@ -186,8 +186,8 @@ rip_iface:
   rip_iface_start iface_patt_list_nopx rip_iface_opt_list rip_iface_finish;
 
 
-dynamic_attr: RIP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_RIP_METRIC); } ;
-dynamic_attr: RIP_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_RIP_TAG); } ;
+dynamic_attr: RIP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_RIP_METRIC); } ;
+dynamic_attr: RIP_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_RIP_TAG); } ;
 
 CF_CLI_HELP(SHOW RIP, ..., [[Show information about RIP protocol]]);
 
index 8f0a91c135ff9867ceb9c45bae90bd3d11e929bb..7097f577df1d4d1c4fd7ae52db140629ecb95597 100644 (file)
@@ -26,39 +26,39 @@ kern_sys_item:
  | METRIC expr { THIS_KRT->sys.metric = $2; }
  ;
 
-dynamic_attr: KRT_PREFSRC      { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, 0, T_IP, EA_KRT_PREFSRC); } ;
-dynamic_attr: KRT_REALM        { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_REALM); } ;
-dynamic_attr: KRT_SCOPE        { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_SCOPE); } ;
+dynamic_attr: KRT_PREFSRC      { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_KRT_PREFSRC); } ;
+dynamic_attr: KRT_REALM        { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_REALM); } ;
+dynamic_attr: KRT_SCOPE        { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SCOPE); } ;
 
-dynamic_attr: KRT_MTU          { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_MTU); } ;
-dynamic_attr: KRT_WINDOW       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_WINDOW); } ;
-dynamic_attr: KRT_RTT          { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_RTT); } ;
-dynamic_attr: KRT_RTTVAR       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_RTTVAR); } ;
-dynamic_attr: KRT_SSTRESH      { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_SSTRESH); } ;
-dynamic_attr: KRT_CWND         { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_CWND); } ;
-dynamic_attr: KRT_ADVMSS       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_ADVMSS); } ;
-dynamic_attr: KRT_REORDERING   { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_REORDERING); } ;
-dynamic_attr: KRT_HOPLIMIT     { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_HOPLIMIT); } ;
-dynamic_attr: KRT_INITCWND     { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_INITCWND); } ;
-dynamic_attr: KRT_RTO_MIN      { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_RTO_MIN); } ;
-dynamic_attr: KRT_INITRWND     { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_INITRWND); } ;
-dynamic_attr: KRT_QUICKACK     { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_QUICKACK); } ;
+dynamic_attr: KRT_MTU          { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_MTU); } ;
+dynamic_attr: KRT_WINDOW       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_WINDOW); } ;
+dynamic_attr: KRT_RTT          { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_RTT); } ;
+dynamic_attr: KRT_RTTVAR       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_RTTVAR); } ;
+dynamic_attr: KRT_SSTRESH      { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SSTRESH); } ;
+dynamic_attr: KRT_CWND         { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_CWND); } ;
+dynamic_attr: KRT_ADVMSS       { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_ADVMSS); } ;
+dynamic_attr: KRT_REORDERING   { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_REORDERING); } ;
+dynamic_attr: KRT_HOPLIMIT     { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_HOPLIMIT); } ;
+dynamic_attr: KRT_INITCWND     { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_INITCWND); } ;
+dynamic_attr: KRT_RTO_MIN      { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_RTO_MIN); } ;
+dynamic_attr: KRT_INITRWND     { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_INITRWND); } ;
+dynamic_attr: KRT_QUICKACK     { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_QUICKACK); } ;
 
 /* Bits of EA_KRT_LOCK, based on RTAX_* constants */
 
-dynamic_attr: KRT_LOCK_MTU     { $$ = f_new_dynamic_attr(EAF_TYPE_BITFIELD, 2, T_BOOL, EA_KRT_LOCK); } ;
-dynamic_attr: KRT_LOCK_WINDOW  { $$ = f_new_dynamic_attr(EAF_TYPE_BITFIELD, 3, T_BOOL, EA_KRT_LOCK); } ;
-dynamic_attr: KRT_LOCK_RTT     { $$ = f_new_dynamic_attr(EAF_TYPE_BITFIELD, 4, T_BOOL, EA_KRT_LOCK); } ;
-dynamic_attr: KRT_LOCK_RTTVAR  { $$ = f_new_dynamic_attr(EAF_TYPE_BITFIELD, 5, T_BOOL, EA_KRT_LOCK); } ;
-dynamic_attr: KRT_LOCK_SSTRESH { $$ = f_new_dynamic_attr(EAF_TYPE_BITFIELD, 6, T_BOOL, EA_KRT_LOCK); } ;
-dynamic_attr: KRT_LOCK_CWND    { $$ = f_new_dynamic_attr(EAF_TYPE_BITFIELD, 7, T_BOOL, EA_KRT_LOCK); } ;
-dynamic_attr: KRT_LOCK_ADVMSS  { $$ = f_new_dynamic_attr(EAF_TYPE_BITFIELD, 8, T_BOOL, EA_KRT_LOCK); } ;
-dynamic_attr: KRT_LOCK_REORDERING { $$ = f_new_dynamic_attr(EAF_TYPE_BITFIELD, 9, T_BOOL, EA_KRT_LOCK); } ;
-dynamic_attr: KRT_LOCK_HOPLIMIT { $$ = f_new_dynamic_attr(EAF_TYPE_BITFIELD, 10, T_BOOL, EA_KRT_LOCK); } ;
-dynamic_attr: KRT_LOCK_RTO_MIN { $$ = f_new_dynamic_attr(EAF_TYPE_BITFIELD, 13, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_MTU     { $$ = f_new_dynamic_attr_bit(2, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_WINDOW  { $$ = f_new_dynamic_attr_bit(3, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_RTT     { $$ = f_new_dynamic_attr_bit(4, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_RTTVAR  { $$ = f_new_dynamic_attr_bit(5, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_SSTRESH { $$ = f_new_dynamic_attr_bit(6, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_CWND    { $$ = f_new_dynamic_attr_bit(7, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_ADVMSS  { $$ = f_new_dynamic_attr_bit(8, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_REORDERING { $$ = f_new_dynamic_attr_bit(9, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_HOPLIMIT { $$ = f_new_dynamic_attr_bit(10, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_RTO_MIN { $$ = f_new_dynamic_attr_bit(13, T_BOOL, EA_KRT_LOCK); } ;
 
-dynamic_attr: KRT_FEATURE_ECN  { $$ = f_new_dynamic_attr(EAF_TYPE_BITFIELD, 0, T_BOOL, EA_KRT_FEATURES); } ;
-dynamic_attr: KRT_FEATURE_ALLFRAG { $$ = f_new_dynamic_attr(EAF_TYPE_BITFIELD, 3, T_BOOL, EA_KRT_FEATURES); } ;
+dynamic_attr: KRT_FEATURE_ECN  { $$ = f_new_dynamic_attr_bit(0, T_BOOL, EA_KRT_FEATURES); } ;
+dynamic_attr: KRT_FEATURE_ALLFRAG { $$ = f_new_dynamic_attr(3, T_BOOL, EA_KRT_FEATURES); } ;
 
 
 CF_CODE
index e3f6271c4da552ae4fad4671262f3cdf44ab04ab..95b54d65dae1454bc09fcbbdd7d4bfff3677cd43 100644 (file)
@@ -122,8 +122,8 @@ kif_iface:
   kif_iface_start iface_patt_list_nopx kif_iface_opt_list;
 
 
-dynamic_attr: KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_SOURCE); } ;
-dynamic_attr: KRT_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_KRT_METRIC); } ;
+dynamic_attr: KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SOURCE); } ;
+dynamic_attr: KRT_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_METRIC); } ;
 
 CF_CODE