]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit 'f0187d713c36e841fe8bab350e84f5257a74981a' into thread-next
authorMaria Matejka <mq@ucw.cz>
Tue, 31 Oct 2023 09:20:22 +0000 (10:20 +0100)
committerMaria Matejka <mq@ucw.cz>
Tue, 31 Oct 2023 09:20:22 +0000 (10:20 +0100)
1  2 
filter/data.c
filter/f-inst.c
lib/type.h

diff --cc filter/data.c
index c55cc7b0c44c552731f7f73d6fe86cacd854d8ff,de745654a729a64efd7a1f30ec2c563da3f6ab78..ee10c5ac1895fb9c60db79a197f0dae8dd69fb9d
@@@ -61,21 -58,23 +61,22 @@@ static const char * const f_type_str[] 
    [T_RD]      = "rd",
  
    [T_ROUTE]   = "route",
+   [T_ROUTES_BLOCK] = "block of routes",
 +
 +  [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)
  {
 -  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;
@@@ -295,6 -304,15 +298,13 @@@ val_same(const struct f_val *v1, const 
      return trie_same(v1->val.ti, v2->val.ti);
    case T_ROUTE:
      return rte_same(v1->val.rte, v2->val.rte);
 -    for (
 -      rte *r1 = v1->val.rte, *r2 = v2->val.rte;
 -      r1 || r2;
 -      r1 = r1->next, r2 = r2->next
 -      )
 -      if (!r1 || !r2 || !rte_same(r1, r2))
+   case T_ROUTES_BLOCK:
++    if (v1->val.rte_block.len != v2->val.rte_block.len)
++      return 0;
++    for (uint i=0; i < v1->val.rte_block.len; i++)
++      if (!rte_same(v1->val.rte_block.rte[i], v2->val.rte_block.rte[i]))
+       return 0;
+     return 1;
    default:
      bug("Invalid type in val_same(): %x", v1->type);
    }
@@@ -583,6 -601,19 +593,19 @@@ rte_format(const struct rte *rte, buffe
      buffer_puts(buf, "[No route]");
  }
  
 -rte_block_format(const struct rte *rte, buffer *buf)
+ static void
 -  for (int i = 0; rte; rte = rte->next, i++)
++rte_block_format(const struct rte_block *block, buffer *buf)
+ {
+   buffer_print(buf, "Block of routes:");
 -    rte_format(rte, buf);
++  for (uint i = 0; i < block->len; i++)
+   {
+     buffer_print(buf, "%s%d: ", i ? "; " : " ", i);
++    rte_format(block->rte[i], buf);
+   }
+ }
  /*
   * val_format - format filter value
   */
@@@ -613,6 -644,7 +636,7 @@@ val_format(const struct f_val *v, buffe
    case T_LCLIST: lc_set_format(v->val.ad, -1, buf2, 1000); buffer_print(buf, "(lclist %s)", buf2); return;
    case T_PATH_MASK: pm_format(v->val.path_mask, buf); return;
    case T_ROUTE: rte_format(v->val.rte, buf); return;
 -  case T_ROUTES_BLOCK: rte_block_format(v->val.rte, buf); return;
++  case T_ROUTES_BLOCK: rte_block_format(&v->val.rte_block, buf); return;
    default:    buffer_print(buf, "[unknown type %x]", v->type); return;
    }
  }
diff --cc filter/f-inst.c
index b2b449cbe622586053f4ed9af8f11030d5461195,42e38a4bf273d5e2d6145033ad9b404ad5a9e67a..4aa4c489d58164d830fb12d20bd8ad19e8754266
      METHOD_CONSTRUCTOR("!for_next");
    }
  
 -    /* Loop auxiliary variable is initialized to T_VOID.
 -     * In the first run, we initialize the auxiliary variable
 -     * to the routes block supplied. It changes its type
 -     * to T_ROUTES_BLOCK and therefore won't be run again. */
 -    if (v2.type == T_VOID)
 -      v2 = v1;
 -
 -    if (v2.val.rte)
+   INST(FI_ROUTES_BLOCK_FOR_NEXT, 3, 0) {
+     NEVER_CONSTANT;
+     ARG(1, T_ROUTES_BLOCK);
 -      /* There is some route to process, set it into the iterator variable.
 -       * Its type has been already initialized by f_for_cycle(). */
 -      v3.val.rte = v2.val.rte;
 -      v3.val.eattrs = v3.val.rte->attrs->eattrs;
 -
 -      /* Prepare next route in the loop auxiliary variable */
 -      v2.val.rte = v2.val.rte->next;
 -
 -      /* And execute the line */
++    if (v2.val.i < v1.val.rte_block.len)
+     {
++      v3.val.rte = v1.val.rte_block.rte[v2.val.i++];
+       LINE(2,0);
+     }
+     METHOD_CONSTRUCTOR("!for_next");
+   }
    INST(FI_CONDITION, 1, 0) {
      ARG(1, T_BOOL);
      if (v1.val.i)
diff --cc lib/type.h
index 7260340ff2d19a6499089f6885e79e63bf55f891,0000000000000000000000000000000000000000..32f16382b91a728346cb286bb97727d01936e16f
mode 100644,000000..100644
--- /dev/null
@@@ -1,117 -1,0 +1,122 @@@
 +/*
 + *     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 adata *bs;
 +  const struct f_tree *t;
 +  const struct f_trie *ti;
 +  const struct f_path_mask *path_mask;
 +  struct f_path_mask_item pmi;
 +  struct rte *rte;
++  struct rte_block {
++    struct rte **rte;
++    uint len;
++  } rte_block;
 +};
 +
 +
 +/* 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_ROUTES_BLOCK = 0x68,      /* Block of route pointers */
 +  T_ROUTE = 0x6a,             /* One route pointer */
 +  T_NEXTHOP_LIST = 0x6c,      /* The whole nexthop block */
 +  T_HOSTENTRY = 0x6e,         /* 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