]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit 'cc1099a0' into thread-next
authorMaria Matejka <mq@ucw.cz>
Sat, 28 Oct 2023 22:14:52 +0000 (00:14 +0200)
committerMaria Matejka <mq@ucw.cz>
Sat, 28 Oct 2023 22:14:52 +0000 (00:14 +0200)
Updated f_implicit_roa_check() to use type methods and moved to filter/f-util.c

1  2 
conf/cf-lex.l
filter/config.Y
filter/data.h
filter/decl.m4
filter/f-inst.c
filter/f-inst.h
filter/f-util.c

diff --cc conf/cf-lex.l
Simple merge
diff --cc filter/config.Y
index aaba2201f8d1d1b6db21bf104dd8fba331f93f1a,7cc6f88235a8d64c4a49ccd52e6fc61521fa727c..1922955ffff6b710f089570a931b9b2111def879
@@@ -244,21 -244,23 +244,6 @@@ f_new_lc_item(u32 f1, u32 t1, u32 f2, u
    return t;
  }
  
--static inline struct f_inst *
- f_implicit_roa_check(struct rtable_config *tab)
 -f_const_empty(enum f_type t)
--{
-   const struct ea_class *def = ea_class_find("bgp_path");
-   if (!def)
-     cf_error("Fatal: Couldn't find BGP path attribute definition.");
-   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),
-           f_new_inst(FI_AS_PATH_LAST, f_new_inst(FI_EA_GET, def)),
-           tab);
 -  switch (t) {
 -    case T_PATH:
 -    case T_CLIST:
 -    case T_ECLIST:
 -    case T_LCLIST:
 -      return f_new_inst(FI_CONSTANT, (struct f_val) {
 -      .type = t,
 -      .val.ad = &null_adata,
 -      });
 -    default:
 -      return f_new_inst(FI_CONSTANT, (struct f_val) {});
 -  }
--}
--
  /*
   * Remove all new lines and doubled whitespaces
   * and convert all tabulators to spaces
@@@ -894,14 -861,15 +879,13 @@@ static_attr
   | IFNAME  { $$ = f_new_static_attr(T_STRING,     SA_IFNAME,  0); }
   | IFINDEX { $$ = f_new_static_attr(T_INT,        SA_IFINDEX, 1); }
   | WEIGHT  { $$ = f_new_static_attr(T_INT,        SA_WEIGHT,  0); }
 - | PREFERENCE { $$ = f_new_static_attr(T_INT,   SA_PREF,      0); }
   | GW_MPLS { $$ = f_new_static_attr(T_INT,        SA_GW_MPLS, 0); }
 - | ONLINK  { $$ = f_new_static_attr(T_BOOL,       SA_ONLINK,  0); }
   ;
  
- term_dot_method: term '.' { f_method_call_start($1); } method_name_cont { $$ = $4; };
+ term_dot_method: term '.' { f_method_call_start($1); } method_name_cont { f_method_call_end(); $$ = $4; };
  method_name_cont:
     CF_SYM_METHOD_BARE {
-      $$ = $1->method->new_inst(FM.object, NULL);
-      f_method_call_end();
+      $$ = f_dispatch_method($1, FM.object, NULL);
     }
   | CF_SYM_METHOD_ARGS {
       f_method_call_args();
@@@ -938,20 -903,17 +921,15 @@@ term
  
   | static_attr { $$ = f_new_inst(FI_RTA_GET, $1); }
  
 - | dynamic_attr { $$ = f_new_inst(FI_EA_GET, $1); }
 -
   | term_dot_method
  
 - | '+' EMPTY '+' { $$ = f_const_empty(T_PATH); }
 - | '-' EMPTY '-' { $$ = f_const_empty(T_CLIST); }
 - | '-' '-' EMPTY '-' '-' { $$ = f_const_empty(T_ECLIST); }
 - | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_const_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); }
   | ADD '(' term ',' term ')' {
-      switch ($3->type) {
-        case T_CLIST: $$ = f_new_inst(FI_CLIST_ADD, $3, $5); break;
-        case T_ECLIST: $$ = f_new_inst(FI_ECLIST_ADD, $3, $5); break;
-        case T_LCLIST: $$ = f_new_inst(FI_LCLIST_ADD, $3, $5); break;
-        default: cf_error("Can't add to type %s", f_type_name($3->type));
-      }
+      $$ = 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 ')' {
diff --cc filter/data.h
index b668ead05b9e868a0b19b297516dce28f684dd3a,e136b65f3ebfd61225a48b7cf027265ff244c5ef..8fbbcef54ab561738a5ef4268ea8feb8b232f366
@@@ -16,7 -67,9 +16,9 @@@
  struct f_method {
    struct symbol *sym;
    struct f_inst *(*new_inst)(struct f_inst *obj, struct f_inst *args);
+   const struct f_method *next;
    uint arg_num;
 -  enum f_type args_type[];
++  enum btype args_type[];
  };
  
  /* Filter value; size of this affects filter memory consumption */
diff --cc filter/decl.m4
index 9d6b64ad0bcfa783a82e20a9fa8941cca46f32a6,217488eca3b2d1b2ddc97aabada3ec6c5170b13d..63670932d4712eda22352e49cd2bfceb0b81b8ea
@@@ -420,17 -422,13 +423,13 @@@ m4_undivert(112
    }
  
  FID_METHOD_SCOPE_INIT()m4_dnl
 -  [INST_METHOD_OBJECT_TYPE] = {},
 +  [INST_METHOD_OBJECT_TYPE] = { .active = 1, },
  FID_METHOD_REGISTER()m4_dnl
-   sym = cf_root_symbol(INST_METHOD_NAME, &f_type_method_scopes[INST_METHOD_OBJECT_TYPE]);
-   sym->class = SYM_METHOD;
-   sym->method = method = lp_allocz(global_root_scope_linpool, sizeof(struct f_method));
-   *method = (struct f_method) {
-     .sym = sym,
-     .new_inst = f_new_method_]]INST_NAME()[[,
-     .arg_num = INST_METHOD_NUM_ARGS,
-   };
 -  method = lp_allocz(global_root_scope_linpool, sizeof(struct f_method) + INST_METHOD_NUM_ARGS * sizeof(enum f_type));
++  method = lp_allocz(global_root_scope_linpool, sizeof(struct f_method) + INST_METHOD_NUM_ARGS * sizeof(enum btype));
+   method->new_inst = f_new_method_]]INST_NAME()[[;
+   method->arg_num = INST_METHOD_NUM_ARGS;
+ m4_undivert(113)
+   f_register_method(INST_METHOD_OBJECT_TYPE, INST_METHOD_NAME, method);
  
  ]])m4_dnl
  
@@@ -633,10 -631,27 +632,27 @@@ struct sym_scope *f_type_method_scope(e
    return (t < ARRAY_SIZE(f_type_method_scopes)) ? &f_type_method_scopes[t] : NULL;
  }
  
 -f_register_method(enum f_type t, const byte *name, struct f_method *dsc)
+ static void
 -    sym = cf_new_symbol(scope, global_root_scope_pool, global_root_scope_linpool, name);
++f_register_method(enum btype t, const byte *name, struct f_method *dsc)
+ {
+   struct sym_scope *scope = &f_type_method_scopes[t];
+   struct symbol *sym = cf_find_symbol_scope(scope, name);
+   if (!sym)
+   {
++    sym = cf_root_symbol(name, scope);
+     sym->class = SYM_METHOD;
+   }
+   dsc->sym = sym;
+   dsc->next = sym->method;
+   sym->method = dsc;
+ }
  void f_type_methods_register(void)
  {
-   struct symbol *sym;
    struct f_method *method;
  FID_WR_PUT(13)
  
    for (uint i = 0; i < ARRAY_SIZE(f_type_method_scopes); i++)
diff --cc filter/f-inst.c
index c66d64a1e06a5514e37ef2f7c8dab1b0082f9b01,a9de0960f2916b3c8e6218182607488d28f09dd5..94268220b4249081b464e088e6d105b9c8c26d58
        runtime("Can't delete non-pair");
    }
  
-   INST(FI_ECLIST_DEL, 2, 1) { /* (Extended) Community list add or delete */
+   INST(FI_ECLIST_DELETE_EC, 2, 1) {
      ARG(1, T_ECLIST);
-     ARG_ANY(2);
+     ARG(2, T_EC);
      METHOD_CONSTRUCTOR("delete");
-       /* v2.val is either EC or EC-set */
-       if ((v2.type == T_SET) && eclist_set_type(v2.val.t) || (v2.type == T_ECLIST))
-       RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 0) ]]);
-       else if (v2.type != T_EC)
-       runtime("Can't delete non-ec");
-       else
-       RESULT(T_ECLIST, ad, [[ ec_set_del(fpool, v1.val.ad, v2.val.ec) ]]);
+     RESULT(T_ECLIST, ad, [[ ec_set_del(fpool, v1.val.ad, v2.val.ec) ]]);
+   }
+   INST(FI_ECLIST_DELETE_ECLIST, 2, 1) {
+     ARG(1, T_ECLIST);
+     ARG(2, T_ECLIST);
+     METHOD_CONSTRUCTOR("delete");
+     RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 0) ]]);
    }
  
-   INST(FI_LCLIST_DEL, 2, 1) { /* (Extended) Community list add or delete */
+   INST(FI_ECLIST_DELETE_SET, 2, 1) {
+     ARG(1, T_ECLIST);
+     ARG(2, T_SET);
+     METHOD_CONSTRUCTOR("delete");
+     if (!eclist_set_type(v2.val.t))
+       runtime("Mismatched set type");
+     RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 0) ]]);
+   }
+   INST(FI_LCLIST_DELETE_LC, 2, 1) {
      ARG(1, T_LCLIST);
-     ARG_ANY(2);
+     ARG(2, T_LC);
      METHOD_CONSTRUCTOR("delete");
-       /* v2.val is either LC or LC-set */
-       if ((v2.type == T_SET) && lclist_set_type(v2.val.t) || (v2.type == T_LCLIST))
-       RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 0) ]]);
-       else if (v2.type != T_LC)
-       runtime("Can't delete non-lc");
-       else
-       RESULT(T_LCLIST, ad, [[ lc_set_del(fpool, v1.val.ad, v2.val.lc) ]]);
+     RESULT(T_LCLIST, ad, [[ lc_set_del(fpool, v1.val.ad, v2.val.lc) ]]);
+   }
+   INST(FI_LCLIST_DELETE_LCLIST, 2, 1) {
+     ARG(1, T_LCLIST);
+     ARG(2, T_LCLIST);
+     METHOD_CONSTRUCTOR("delete");
+     RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 0) ]]);
    }
  
-   INST(FI_PATH_FILTER, 2, 1) {        /* (Extended) Community list add or delete */
+   INST(FI_LCLIST_DELETE_SET, 2, 1) {
+     ARG(1, T_LCLIST);
+     ARG(2, T_SET);
+     METHOD_CONSTRUCTOR("delete");
+     if (!lclist_set_type(v2.val.t))
+       runtime("Mismatched set type");
+     RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 0) ]]);
+   }
+   INST(FI_PATH_FILTER_SET, 2, 1) {
      ARG(1, T_PATH);
-     ARG_ANY(2);
+     ARG(2, T_SET);
      METHOD_CONSTRUCTOR("filter");
  
-       if ((v2.type == T_SET) && path_set_type(v2.val.t))
-       RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 1) ]]);
-       else
-       runtime("Can't filter integer");
-     }
+     if (!path_set_type(v2.val.t))
+       runtime("Mismatched set type");
  
-   INST(FI_CLIST_FILTER, 2, 1) {
+     RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 1) ]]);
+   }
+   INST(FI_CLIST_FILTER_CLIST, 2, 1) {
      ARG(1, T_CLIST);
-     ARG_ANY(2);
+     ARG(2, T_CLIST);
      METHOD_CONSTRUCTOR("filter");
-       /* Community (or cluster) list */
-       struct f_val dummy;
+     RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 1) ]]);
+   }
  
-       if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy) || (v2.type == T_CLIST))
-       RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 1) ]]);
-       else
-       runtime("Can't filter pair");
+   INST(FI_CLIST_FILTER_SET, 2, 1) {
+     ARG(1, T_CLIST);
+     ARG(2, T_SET);
+     METHOD_CONSTRUCTOR("filter");
+     if (!clist_set_type(v2.val.t, &(struct f_val){}))
+       runtime("Mismatched set type");
+     RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 1) ]]);
    }
  
-   INST(FI_ECLIST_FILTER, 2, 1) {
+   INST(FI_ECLIST_FILTER_ECLIST, 2, 1) {
      ARG(1, T_ECLIST);
-     ARG_ANY(2);
+     ARG(2, T_ECLIST);
      METHOD_CONSTRUCTOR("filter");
-       /* v2.val is either EC or EC-set */
-       if ((v2.type == T_SET) && eclist_set_type(v2.val.t) || (v2.type == T_ECLIST))
-       RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 1) ]]);
-       else
-       runtime("Can't filter ec");
+     RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 1) ]]);
+   }
+   INST(FI_ECLIST_FILTER_SET, 2, 1) {
+     ARG(1, T_ECLIST);
+     ARG(2, T_SET);
+     METHOD_CONSTRUCTOR("filter");
+     if (!eclist_set_type(v2.val.t))
+       runtime("Mismatched set type");
+     RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 1) ]]);
    }
  
-   INST(FI_LCLIST_FILTER, 2, 1) {
+   INST(FI_LCLIST_FILTER_LCLIST, 2, 1) {
      ARG(1, T_LCLIST);
-     ARG_ANY(2);
+     ARG(2, T_LCLIST);
      METHOD_CONSTRUCTOR("filter");
-       /* v2.val is either LC or LC-set */
-       if ((v2.type == T_SET) && lclist_set_type(v2.val.t) || (v2.type == T_LCLIST))
-       RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 1) ]]);
-       else
-       runtime("Can't filter lc");
+     RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 1) ]]);
+   }
+   INST(FI_LCLIST_FILTER_SET, 2, 1) {
+     ARG(1, T_LCLIST);
+     ARG(2, T_SET);
+     METHOD_CONSTRUCTOR("filter");
+     if (!lclist_set_type(v2.val.t))
+       runtime("Mismatched set type");
+     RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 1) ]]);
    }
  
 -  INST(FI_ROA_CHECK_IMPLICIT, 0, 1) { /* ROA Check */
 -    NEVER_CONSTANT;
 -    RTC(1);
 -    struct rtable *table = rtc->table;
 -    ACCESS_RTE;
 -    ACCESS_EATTRS;
 -    const net_addr *net = (*fs->rte)->net->n.addr;
 -
 -    /* We ignore temporary attributes, probably not a problem here */
 -    /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
 -    eattr *e = ea_find(*fs->eattrs, EA_CODE(PROTOCOL_BGP, 0x02));
 -
 -    if (!e || ((e->type & EAF_TYPE_MASK) != EAF_TYPE_AS_PATH))
 -      runtime("Missing AS_PATH attribute");
 -
 -    u32 as = 0;
 -    as_path_get_last(e->u.ptr, &as);
 -
 -    if (!table)
 -      runtime("Missing ROA table");
 -
 -    if (table->addr_type != NET_ROA4 && table->addr_type != NET_ROA6)
 -      runtime("Table type must be either ROA4 or ROA6");
 -
 -    if (table->addr_type != (net->type == NET_IP4 ? NET_ROA4 : NET_ROA6))
 -      RESULT(T_ENUM_ROA, i, ROA_UNKNOWN); /* Prefix and table type mismatch */
 -    else
 -      RESULT(T_ENUM_ROA, i, [[ net_roa_check(table, net, as) ]]);
 -  }
 -
 -  INST(FI_ROA_CHECK_EXPLICIT, 2, 1) { /* ROA Check */
 +  INST(FI_ROA_CHECK, 2, 1) {  /* ROA Check */
      NEVER_CONSTANT;
      ARG(1, T_NET);
      ARG(2, T_INT);
diff --cc filter/f-inst.h
index c741265b292235490e0c2d7aa8b0bdcd04b23742,f5dfcd2021c983dded74c48d60e4a747ea1f2fa9..fa1fdbde6599bf002f0add52dcd05379154ba968
@@@ -96,12 -96,17 +96,15 @@@ void f_add_lines(const struct f_line_it
  
  
  struct filter *f_new_where(struct f_inst *);
 -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(struct symbol *sym, 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 0d998f3db949d1d9ec0e6364d64d273b9c402db7,7ce3f9c8c9422220827a72f5f8e85137958a6e09..7ae304d604a1f906f591616fb00d06cbd806a626
@@@ -41,6 -42,43 +42,43 @@@ f_new_where(struct f_inst *where
    return f;
  }
  
 -f_dispatch_method_x(const char *name, enum f_type t, struct f_inst *obj, struct f_inst *args)
+ static inline int
+ f_match_signature(const struct f_method *dsc, struct f_inst *args)
+ {
+   uint i;
+   for (i = 1; args && (i < dsc->arg_num); args = args->next, i++)
+     if (dsc->args_type[i] && (args->type != dsc->args_type[i]))
+       return 0;
+   return !args && !(i < dsc->arg_num);
+ }
+ struct f_inst *
+ f_dispatch_method(struct symbol *sym, struct f_inst *obj, struct f_inst *args)
+ {
+   /* Note! We should revert args */
+   for (const struct f_method *dsc = sym->method; dsc; dsc = dsc->next)
+     if (f_match_signature(dsc, args))
+       return dsc->new_inst(obj, args);
+   cf_error("Cannot dispatch method '%s'", sym->name);
+ }
+ struct f_inst *
++f_dispatch_method_x(const char *name, enum btype t, struct f_inst *obj, struct f_inst *args)
+ {
+   struct sym_scope *scope = f_type_method_scope(t);
+   struct symbol *sym = cf_find_symbol_scope(scope, name);
+   if (!sym)
+     cf_error("Cannot dispatch method '%s'", name);
+   return f_dispatch_method(sym, obj, args);
+ }
  struct f_inst *
  f_for_cycle(struct symbol *var, struct f_inst *term, struct f_inst *block)
  {
    return ms->method->new_inst(term, loop_start);
  }
  
++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),
++          f_dispatch_method(ms, path_getter, NULL),
++          tab);
++}
++
  struct f_inst *
  f_print(struct f_inst *vars, int flush, enum filter_return fret)
  {