]> git.ipfire.org Git - thirdparty/bird.git/blobdiff - nest/a-path.c
Filter refactoring: dropped the recursion from the interpreter
[thirdparty/bird.git] / nest / a-path.c
index 6f1c40bfdf654ffa4ad3e825196c266924d6bc4a..d3a1d6364aa3f5cbdb77cac896255cee49a3e3da 100644 (file)
@@ -77,10 +77,10 @@ bad:
 }
 
 int
-as_path_16to32(byte *dst, byte *src, uint len)
+as_path_16to32(byte *dst, const byte *src, uint len)
 {
   byte *dst0 = dst;
-  byte *end = src + len;
+  const byte *end = src + len;
   uint i, n;
 
   while (src < end)
@@ -101,10 +101,10 @@ as_path_16to32(byte *dst, byte *src, uint len)
 }
 
 int
-as_path_32to16(byte *dst, byte *src, uint len)
+as_path_32to16(byte *dst, const byte *src, uint len)
 {
   byte *dst0 = dst;
-  byte *end = src + len;
+  const byte *end = src + len;
   uint i, n;
 
   while (src < end)
@@ -273,11 +273,11 @@ as_path_to_old(struct linpool *pool, const struct adata *path)
  * 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.
  */
-void
-as_path_cut(struct adata *path, uint num)
+struct adata *
+as_path_cut(struct linpool *pool, const struct adata *path, uint num)
 {
-  byte *pos = path->data;
-  byte *end = pos + path->length;
+  const byte *pos = path->data;
+  const byte *end = pos + path->length;
 
   while (pos < end)
   {
@@ -297,28 +297,39 @@ as_path_cut(struct adata *path, uint num)
     /* Cannot add whole segment, so try partial one and finish */
     if (num < n)
     {
+      const byte *nend = pos;
+      if (num)
+       nend += 2 + BS * num;
+
+      struct adata *res = lp_alloc_adata(pool, path->length);
+      res->length = nend - (const byte *) path->data;
+      memcpy(res->data, path->data, res->length);
+
       if (num)
       {
-       pos[1] = num;
-       pos += 2 + BS * num;
+       byte *dpos = ((byte *) res->data) + (pos - (const byte *) path->data);
+       dpos[1] = num;
       }
 
-      break;
+      return res;
     }
 
     num -= n;
     pos += 2 + BS * l;
   }
 
-  path->length = pos - path->data;
+  struct adata *res = lp_alloc_adata(pool, path->length);
+  res->length = path->length;
+  memcpy(res->data, path->data, res->length);
+  return res;
 }
 
 /*
  * Merge (concatenate) paths @p1 and @p2 and return the result.
  * In contrast to other as_path_* functions, @p1 and @p2 may be reused.
  */
-struct adata *
-as_path_merge(struct linpool *pool, struct adata *p1, struct adata *p2)
+const struct adata *
+as_path_merge(struct linpool *pool, const struct adata *p1, const struct adata *p2)
 {
   if (p1->length == 0)
     return p2;
@@ -561,7 +572,7 @@ as_path_contains(const struct adata *path, u32 as, int min)
 }
 
 int
-as_path_match_set(const struct adata *path, struct f_tree *set)
+as_path_match_set(const struct adata *path, const struct f_tree *set)
 {
   const u8 *p = path->data;
   const u8 *q = p+path->length;
@@ -574,7 +585,7 @@ as_path_match_set(const struct adata *path, struct f_tree *set)
       for (i=0; i<n; i++)
        {
          struct f_val v = {T_INT, .val.i = get_as(p)};
-         if (find_tree(set, v))
+         if (find_tree(set, &v))
            return 1;
          p += BS;
        }
@@ -583,8 +594,8 @@ as_path_match_set(const struct adata *path, struct f_tree *set)
   return 0;
 }
 
-struct adata *
-as_path_filter(struct linpool *pool, struct adata *path, struct f_tree *set, u32 key, int pos)
+const struct adata *
+as_path_filter(struct linpool *pool, const struct adata *path, const struct f_tree *set, u32 key, int pos)
 {
   if (!path)
     return NULL;
@@ -612,7 +623,10 @@ as_path_filter(struct linpool *pool, struct adata *path, struct f_tree *set, u32
          int match;
 
          if (set)
-           match = !!find_tree(set, (struct f_val){T_INT, .val.i = as});
+           {
+             struct f_val v = {T_INT, .val.i = as};
+             match = !!find_tree(set, &v);
+           }
          else
            match = (as == key);
 
@@ -771,7 +785,7 @@ pm_mark(struct pm_pos *pos, int i, int plen, int *nl, int *nh)
  * is marked.
  */
 int
-as_path_match(const struct adata *path, struct f_path_mask *mask)
+as_path_match(const struct adata *path, const struct f_path_mask *mask)
 {
   struct pm_pos pos[2048 + 1];
   int plen = parse_path(path, pos);
@@ -788,12 +802,12 @@ as_path_match(const struct adata *path, struct f_path_mask *mask)
   l = h = 0;
   pos[0].mark = 1;
 
-  while (mask)
+  for (uint m=0; m < mask->len; m++)
     {
       /* We remove this mark to not step after pos[plen] */
       pos[plen].mark = 0;
 
-      switch (mask->kind)
+      switch (mask->item[m].kind)
        {
        case PM_ASTERISK:
          for (i = l; i <= plen; i++)
@@ -802,13 +816,13 @@ as_path_match(const struct adata *path, struct f_path_mask *mask)
          break;
 
        case PM_ASN:    /* Define single ASN as ASN..ASN - very narrow interval */
-         val2 = val = mask->val;
+         val2 = val = mask->item[m].asn;
          goto step;
        case PM_ASN_EXPR:
          bug("Expressions should be evaluated on AS path mask construction.");
        case PM_ASN_RANGE:
-         val = mask->val;
-         val2 = mask->val2;
+         val = mask->item[m].from;
+         val2 = mask->item[m].to;
          goto step;
        case PM_QUESTION:
        step:
@@ -817,7 +831,7 @@ as_path_match(const struct adata *path, struct f_path_mask *mask)
            if (pos[i].mark)
              {
                pos[i].mark = 0;
-               if ((mask->kind == PM_QUESTION) || pm_match(pos + i, val, val2))
+               if ((mask->item[m].kind == PM_QUESTION) || pm_match(pos + i, val, val2))
                  pm_mark(pos, i, plen, &nl, &nh);
              }
 
@@ -828,8 +842,6 @@ as_path_match(const struct adata *path, struct f_path_mask *mask)
          l = nl;
          break;
        }
-
-      mask = mask->next;
     }
 
   return pos[plen].mark;