]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit 'a3dc2645' into thread-next
authorMaria Matejka <mq@ucw.cz>
Sat, 28 Oct 2023 22:50:38 +0000 (00:50 +0200)
committerMaria Matejka <mq@ucw.cz>
Sat, 28 Oct 2023 22:50:38 +0000 (00:50 +0200)
12 files changed:
1  2 
conf/cf-lex.l
conf/confbase.Y
doc/bird.sgml
filter/config.Y
filter/data.c
filter/data.h
filter/decl.m4
filter/f-inst.c
filter/f-inst.h
filter/f-util.c
filter/test.conf
lib/type.h

diff --cc conf/cf-lex.l
Simple merge
diff --cc conf/confbase.Y
index d86c2ef5734222b76fb0988586d25fafcf7fa112,7b368fc6d82cb20fd7aefd708a9642455c2265d6..f841c9742d4661ceed612769029d51301cc0d734
@@@ -128,8 -125,7 +128,8 @@@ CF_DECL
  
  %nonassoc PREFIX_DUMMY
  %left AND OR
- %nonassoc '=' '<' '>' '~' GEQ LEQ NEQ NMA PO PC
+ %nonassoc '=' '<' '>' '~' GEQ LEQ NEQ NMA IMP PO PC
 +%left '|' '&'
  %left '+' '-'
  %left '*' '/' '%'
  %left '!'
diff --cc doc/bird.sgml
Simple merge
diff --cc filter/config.Y
index 1922955ffff6b710f089570a931b9b2111def879,a87fb0e5ff93dfb02cf478102380071872ee6f43..76e804361e50944e927f5298886c84e9a88072f3
@@@ -374,7 -357,8 +374,7 @@@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UN
  %nonassoc ELSE
  
  %type <xp> cmds_int cmd_prep
- %type <x> term term_bs cmd cmd_var cmds cmds_scoped constant constructor var var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail term_dot_method method_name_cont
+ %type <x> term term_bs cmd cmd_var cmds cmds_scoped constant constructor var var_list var_list_r function_call symbol_value bgp_path_expr bgp_path bgp_path_tail term_dot_method method_name_cont
 -%type <fda> dynamic_attr
  %type <fsa> static_attr
  %type <f> filter where_filter
  %type <fl> filter_body function_body
@@@ -566,19 -535,13 +571,14 @@@ function_body
   ;
  
  conf: function_def ;
- maybe_type:
-    /* EMPTY */ { $$ = T_VOID; }
-  | type { $$ = $1; }
-  ;
  
  function_def:
-    FUNCTION maybe_type symbol {
-      DBG( "Beginning of function %s\n", $3->name );
-      this_function = cf_define_symbol(new_config, $3, SYM_FUNCTION, function, NULL);
- /*   if ($2 == T_VOID) cf_warn("Support for functions without explicit return type will be removed soon" ); */
+    FUNCTION symbol {
+      DBG( "Beginning of function %s\n", $2->name );
+      this_function = cf_define_symbol(new_config, $2, SYM_FUNCTION, function, NULL);
 +     cf_enter_filters();
       cf_push_scope(new_config, this_function);
-    } function_args {
+    } function_args function_type {
       /* Make dummy f_line for storing function prototype */
       struct f_line *dummy = cfg_allocz(sizeof(struct f_line));
       this_function->function = dummy;
       $7->args = this_function->function->args;
       $7->arg_list = this_function->function->arg_list;
       $7->return_type = this_function->function->return_type;
-      $3->function = $7;
+      $2->function = $7;
       cf_pop_scope(new_config);
 +     cf_exit_filters();
     }
   ;
  
@@@ -828,13 -790,30 +828,30 @@@ constructor
   ;
  
  
- /* This generates the function_call variable list backwards. */
- var_list: /* EMPTY */ { $$ = NULL; }
+ /* This generates the function_call variable list backwards */
+ var_list_r:
+    /* EMPTY */ { $$ = NULL; }
   | term { $$ = $1; }
-  | var_list ',' term { $$ = $3; $$->next = $1; }
+  | var_list_r ',' term { $$ = $3; $$->next = $1; }
+  ;
+ var_list: var_list_r
+    {
+      $$ = NULL;
+      /* Revert the var_list_r */
+      while ($1) {
+        struct f_inst *tmp = $1;
+        $1 = $1->next;
+        tmp->next = $$;
+        $$ = tmp;
+      }
+    }
+  ;
  
  function_call:
 -   symbol_known '(' var_list ')'
 +   CF_SYM_KNOWN '(' var_list ')'
     {
       if ($1->class != SYM_FUNCTION)
         cf_error("You can't call something which is not a function. Really.");
@@@ -921,28 -893,22 +928,32 @@@ term
  
   | static_attr { $$ = f_new_inst(FI_RTA_GET, $1); }
  
 - | dynamic_attr { $$ = f_new_inst(FI_EA_GET, $1); }
 -
   | term_dot_method
  
 - | '+' EMPTY '+' { $$ = f_new_inst(FI_CONSTANT, val_empty(T_PATH)); }
 - | '-' EMPTY '-' { $$ = f_new_inst(FI_CONSTANT, val_empty(T_CLIST)); }
 - | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_CONSTANT, val_empty(T_ECLIST)); }
 - | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_CONSTANT, val_empty(T_LCLIST)); }
 + | '+' EMPTY '+' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_PATH)); }
 + | '-' EMPTY '-' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_CLIST)); }
 + | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_ECLIST)); }
 + | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_LCLIST)); }
-  | PREPEND '(' term ',' term ')' { $$ = f_new_inst(FI_PATH_PREPEND, $3, $5); }
 -| PREPEND '(' term ',' term ')' { $$ = f_dispatch_method_x("prepend", $3->type, $3, $5); }
 - | ADD '(' term ',' term ')' { $$ = f_dispatch_method_x("add", $3->type, $3, $5); }
 - | DELETE '(' term ',' term ')' { $$ = f_dispatch_method_x("delete", $3->type, $3, $5); }
 - | FILTER '(' term ',' term ')' { $$ = f_dispatch_method_x("filter", $3->type, $3, $5); }
++ | PREPEND '(' term ',' term ')' {
++     $$ = f_dispatch_method_x("prepend", $3->type, $3, $5);
++     cf_warn("prepend(x,y) function is deprecated, please use x.prepend(y)");
++   }
 + | ADD '(' term ',' term ')' {
 +     $$ = f_dispatch_method_x("add", $3->type, $3, $5);
 +     cf_warn("add(x,y) function is deprecated, please use x.add(y)");
 +   }
 + | DELETE '(' term ',' term ')' {
 +     $$ = f_dispatch_method_x("delete", $3->type, $3, $5);
 +     cf_warn("delete(x,y) function is deprecated, please use x.delete(y)");
 +   }
 + | FILTER '(' term ',' term ')' {
 +     $$ = f_dispatch_method_x("filter", $3->type, $3, $5);
 +     cf_warn("filter(x,y) function is deprecated, please use x.filter(y)");
 +   }
  
 - | ROA_CHECK '(' rtable ')' { $$ = f_new_inst(FI_ROA_CHECK_IMPLICIT, $3); }
 - | ROA_CHECK '(' rtable ',' term ',' term ')' { $$ = f_new_inst(FI_ROA_CHECK_EXPLICIT, $5, $7, $3); }
 + | ROA_CHECK '(' rtable ')' { $$ = f_implicit_roa_check($3); }
 + | ROA_CHECK '(' rtable ',' term ',' term ')' { $$ = f_new_inst(FI_ROA_CHECK, $5, $7, $3); }
  
   | FORMAT '(' term ')' {  $$ = f_new_inst(FI_FORMAT, $3); }
  
         cf_error( "This static attribute is read-only.");
       $$ = f_new_inst(FI_RTA_SET, $3, $1);
     }
 - | UNSET '(' dynamic_attr ')' ';' {
 -     $$ = f_new_inst(FI_EA_UNSET, $3);
 + | UNSET '(' CF_SYM_KNOWN ')' ';' {
 +     if ($3->class != SYM_ATTRIBUTE)
 +       cf_error("Can't unset %s", $3->name);
 +     if ($3->attribute->readonly)
 +       cf_error("Attribute %s is read-only", $3->attribute->name);
 +     $$ = f_new_inst(FI_EA_UNSET, $3->attribute);
     }
-  | break_command var_list ';' {
+  | break_command var_list_r ';' {
      $$ = f_print($2, !!$2, $1);
     }
-  | PRINT var_list ';' {
+  | PRINT var_list_r ';' {
      $$ = f_print($2, 1, F_NOP);
     }
-  | PRINTN var_list ';' {
+  | PRINTN var_list_r ';' {
      $$ = f_print($2, 0, F_NOP);
     }
   | function_call ';' { $$ = f_new_inst(FI_DROP_RESULT, $1); }
diff --cc filter/data.c
index d700f7d2b4321a7b34c7890dd9a192e542bf7ce5,deca00e0a3b9032c6e20dd4803994539fd932e1d..610af8a21977c733efbc572f30d43d525c355711
  
  static const char * const f_type_str[] = {
    [T_VOID]    = "void",
+   [T_NONE]    = "none",
 +  [T_OPAQUE]  = "opaque byte string",
 +  [T_IFACE]   = "interface",
 +
    [T_INT]     = "int",
    [T_BOOL]    = "bool",
    [T_PAIR]    = "pair",
    [T_LC]      = "lc",
    [T_LCLIST]  = "lclist",
    [T_RD]      = "rd",
 +
 +  [T_SET]     = "set",
 +  [T_PREFIX_SET] = "prefix set",
  };
  
++STATIC_ASSERT((1 << (8 * sizeof(btype))) == ARRAY_SIZE(f_type_str));
++
  const char *
 -f_type_name(enum f_type t)
 +f_type_name(btype t)
  {
-   return (t < ARRAY_SIZE(f_type_str)) ? (f_type_str[t] ?: "?") : "?";
 -  if (t < ARRAY_SIZE(f_type_str))
 -    return f_type_str[t] ?: "?";
 -
 -  if ((t == T_SET) || (t == T_PREFIX_SET))
 -    return "set";
 -
 -  return "?";
++  return f_type_str[t] ?: "?";
  }
  
 -enum f_type
 -f_type_element_type(enum f_type t)
 +btype
 +f_type_element_type(btype t)
  {
    switch(t) {
      case T_PATH:   return T_INT;
diff --cc filter/data.h
Simple merge
diff --cc filter/decl.m4
index 63670932d4712eda22352e49cd2bfceb0b81b8ea,57bf94546bd6ebf32d69538c2061197db8ecc45b..2cb09f28c9f2e7dabb9a1af1d646398f3c08d7f7
@@@ -573,8 -573,8 +574,8 @@@ fi_constant(struct f_inst *what, struc
    return what;
  }
  
- static int
- f_const_promotion(struct f_inst *arg, btype want)
+ int
 -f_const_promotion_(struct f_inst *arg, enum f_type want, int update)
++f_const_promotion_(struct f_inst *arg, btype want, int update)
  {
    if (arg->fi_code != FI_CONSTANT)
      return 0;
diff --cc filter/f-inst.c
Simple merge
diff --cc filter/f-inst.h
index fa1fdbde6599bf002f0add52dcd05379154ba968,2bde6378c30043c587e779a475cbe1f5e7aad569..a476c998e834911634e83ff94787613a67aa57b6
@@@ -36,6 -36,16 +36,16 @@@ const char *f_instruction_name_(enum f_
  static inline const char *f_instruction_name(enum f_instruction_code fi)
  { return f_instruction_name_(fi) + 3; }
  
 -int f_const_promotion_(struct f_inst *arg, enum f_type want, int update);
 -static inline int f_const_promotion(struct f_inst *arg, enum f_type want)
++int f_const_promotion_(struct f_inst *arg, enum btype want, int update);
 -static inline int f_try_const_promotion(struct f_inst *arg, enum f_type want)
++static inline int f_const_promotion(struct f_inst *arg, enum btype want)
+ { return f_const_promotion_(arg, want, 1); }
++static inline int f_try_const_promotion(struct f_inst *arg, enum btype want)
+ { return f_const_promotion_(arg, want, 0); }
  struct f_arg {
    struct symbol *arg;
    struct f_arg *next;
@@@ -96,15 -106,17 +106,15 @@@ void f_add_lines(const struct f_line_it
  
  
  struct filter *f_new_where(struct f_inst *);
- struct f_inst *f_dispatch_method(struct symbol *sym, struct f_inst *obj, struct f_inst *args);
+ struct f_inst *f_dispatch_method(struct symbol *sym, struct f_inst *obj, struct f_inst *args, int skip);
 -struct f_inst *f_dispatch_method_x(const char *name, enum f_type t, struct f_inst *obj, struct f_inst *args);
 +struct f_inst *f_dispatch_method_x(const char *name, enum btype t, struct f_inst *obj, struct f_inst *args);
  struct f_inst *f_for_cycle(struct symbol *var, struct f_inst *term, struct f_inst *block);
 +struct f_inst *f_implicit_roa_check(struct rtable_config *tab);
  struct f_inst *f_print(struct f_inst *vars, int flush, enum filter_return fret);
  
 -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 }; }
 +static inline struct f_static_attr f_new_static_attr(btype type, int code, int readonly)
 +{ return (struct f_static_attr) { .type = type, .sa_code = code, .readonly = readonly }; }
 +struct f_inst *f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn);
  
  /* Hook for call bt_assert() function in configuration */
  extern void (*bt_assert_hook)(int result, const struct f_line_item *assert);
diff --cc filter/f-util.c
index 7ae304d604a1f906f591616fb00d06cbd806a626,d589927a191553e4af577722ac9c3777db34e678..e014b22482337d6e72380526c3f9955a16c666ce
@@@ -87,9 -162,9 +162,9 @@@ f_for_cycle(struct symbol *var, struct 
  
    /* Static type check */
    if (term->type == T_VOID)
-     cf_error("Couldn't infer the type of FOR expression, please assign it to a variable.");
+     cf_error("Cannot infer type of FOR expression, please assign it to a variable");
  
 -  enum f_type el_type = f_type_element_type(term->type);
 +  enum btype el_type = f_type_element_type(term->type);
    struct sym_scope *scope = el_type ? f_type_method_scope(term->type) : NULL;
    struct symbol *ms = scope ? cf_find_symbol_scope(scope, "!for_next") : NULL;
  
    return ms->method->new_inst(term, loop_start);
  }
  
-           f_dispatch_method(ms, path_getter, NULL),
 +struct f_inst *
 +f_implicit_roa_check(struct rtable_config *tab)
 +{
 +  const struct ea_class *def = ea_class_find("bgp_path");
 +  if (!def)
 +    bug("Couldn't find BGP AS Path attribute definition.");
 +
 +  struct f_inst *path_getter = f_new_inst(FI_EA_GET, def);
 +  struct sym_scope *scope = f_type_method_scope(path_getter->type);
 +  struct symbol *ms = scope ? cf_find_symbol_scope(scope, "last") : NULL;
 +
 +  if (!ms)
 +    bug("Couldn't find the \"last\" method for AS Path.");
 +
 +  struct f_static_attr fsa = f_new_static_attr(T_NET, SA_NET, 1);
 +
 +  return f_new_inst(FI_ROA_CHECK,
 +          f_new_inst(FI_RTA_GET, fsa),
++          ms->method->new_inst(path_getter, NULL),
 +          tab);
 +}
 +
  struct f_inst *
  f_print(struct f_inst *vars, int flush, enum filter_return fret)
  {
Simple merge
diff --cc lib/type.h
index 232e7aef27130a49c584bfe24a5530ac61d52c3b,0000000000000000000000000000000000000000..0195308782d3cc9ba849ea5ea54579b8b29674a1
mode 100644,000000..100644
--- /dev/null
@@@ -1,114 -1,0 +1,115 @@@
 +/*
 + *     BIRD Internet Routing Daemon -- Internal Data Types
 + *
 + *     (c) 2022 Maria Matejka <mq@jmq.cz>
 + *
 + *     Can be freely distributed and used under the terms of the GNU GPL.
 + */
 +
 +#ifndef _BIRD_TYPE_H_
 +#define _BIRD_TYPE_H_
 +
 +#include "lib/birdlib.h"
 +#include "lib/attrs.h"
 +
 +union bval {
 +#define BVAL_ITEMS                                                                    \
 +  struct {                                                                            \
 +    u32 data;                 /* Integer type inherited from eattrs */                \
 +    PADDING(data, 0, 4);      /* Must be padded on 64-bits */                         \
 +  };                                                                                  \
 +  struct {                                                                            \
 +    u32 i;                    /* Integer type inherited from filters */               \
 +    PADDING(i, 0, 4);         /* Must be padded on 64-bits */                         \
 +  };                                                                                  \
 +  const struct adata *ptr;    /* Generic attribute data inherited from eattrs */      \
 +  const struct adata *ad;             /* Generic attribute data inherited from filters */     \
 +
 +  BVAL_ITEMS;
 +};
 +
 +union bval_long {
 +  union bval bval;            /* For direct assignments */
 +  BVAL_ITEMS;                 /* For item-wise access */
 +
 +  u64 ec;
 +  lcomm lc;
 +  ip_addr ip;
 +  const net_addr *net;
 +  const char *s;
 +  const struct bytestring *bs;
 +  const struct f_tree *t;
 +  const struct f_trie *ti;
 +  const struct f_path_mask *path_mask;
 +  struct f_path_mask_item pmi;
 +};
 +
 +
 +/* Internal types */
 +enum btype {
 +/* Nothing. Simply nothing. */
 +  T_VOID = 0,
++  T_NONE = 0xff,
 +
 +/* Something but inaccessible. */
 +  T_OPAQUE = 0x02,            /* Opaque byte string (not filterable) */
 +  T_IFACE = 0x0c,             /* Pointer to an interface (inside adata) */
 +  T_NEXTHOP_LIST = 0x2c,      /* The whole nexthop block */
 +  T_HOSTENTRY = 0x2e,         /* Hostentry with possible MPLS labels */
 +
 +/* Types shared with eattrs */
 +  T_INT = 0x01,                       /* 32-bit unsigned integer number */
 +  T_IP = 0x04,                        /* IP address */
 +  T_QUAD = 0x05,              /* Router ID (IPv4 address) */
 +  T_PATH = 0x06,              /* BGP AS path (encoding per RFC 1771:4.3) */
 +  T_CLIST = 0x0a,             /* Set of u32's (e.g., a community list) */
 +  T_ECLIST = 0x0e,            /* Set of pairs of u32's - ext. community list */
 +  T_LCLIST = 0x08,            /* Set of triplets of u32's - large community list */
 +
 +  T_ENUM_BGP_ORIGIN = 0x11,   /* BGP Origin enum */
 +  T_ENUM_RA_PREFERENCE = 0x13,        /* RA Preference enum */
 +  T_ENUM_FLOWSPEC_VALID = 0x15,       /* Flowspec validation result */
 +
 +#define EAF_TYPE__MAX 0x1f
 +#define EAF_EMBEDDED 0x01             /* Data stored in eattr.u.data (part of type spec) */
 +                                      /* Otherwise, attribute data is adata */
 +
 +/* Other user visible types which fit in int */
 +  T_BOOL = 0xa0,
 +  T_PAIR = 0xa4,  /*  Notice that pair is stored as integer: first << 16 | second */
 +
 +/* Put enumerational types in 0x20..0x3f range */
 +  T_ENUM_LO = 0x10,
 +  T_ENUM_HI = 0x3f,
 +
 +  T_ENUM_RTS = 0x31,
 +  T_ENUM_SCOPE = 0x33,
 +  T_ENUM_RTD = 0x37,
 +  T_ENUM_ROA = 0x39,
 +  T_ENUM_NETTYPE = 0x3b,
 +  T_ENUM_AF = 0x3d,
 +
 +/* new enums go here */
 +
 +#define T_ENUM T_ENUM_LO ... T_ENUM_HI
 +
 +/* Bigger ones */
 +  T_NET = 0xb0,
 +  T_STRING = 0xb4,
 +  T_PATH_MASK = 0xb8, /* mask for BGP path */
 +  T_EC = 0xbc,                /* Extended community value, u64 */
 +  T_LC = 0xc0,                /* Large community value, lcomm */
 +  T_RD = 0xc4,                /* Route distinguisher for VPN addresses */
 +  T_PATH_MASK_ITEM = 0xc8,    /* Path mask item for path mask constructors */
 +  T_BYTESTRING = 0xcc,
 +
 +  T_SET = 0x80,
 +  T_PREFIX_SET = 0x84,
 +} PACKED;
 +
 +typedef enum btype btype;
 +
 +STATIC_ASSERT(sizeof(btype) == sizeof(byte));
 +
 +
 +#endif