]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Functions for matching paths added, tested lightly.
authorPavel Machek <pavel@ucw.cz>
Mon, 10 Apr 2000 15:07:43 +0000 (15:07 +0000)
committerPavel Machek <pavel@ucw.cz>
Mon, 10 Apr 2000 15:07:43 +0000 (15:07 +0000)
Functions for working with community lists added, they compile.

This should not be definitive place for this stuff.

filter/config.Y
filter/filter.c

index 40034602f31f559503b3cf8e8ba4166e89c5b834..e17245dfc4b4163293b71c8e3171bca15ad88d0c 100644 (file)
@@ -11,6 +11,8 @@
        FIXME: IP addresses in ipv6
 
 
+        FIXME: check messages for \n at the end
+
 (1) Cesty
 
    AS paths budtez interne reprezentovany stejne jako v BGP (viz RFC 1771),
@@ -22,17 +24,22 @@ mnozina cisel ASu. Na cestach nadefinuji nasledujici operace:
 
 Filtry by mely podporovat:
 
-        - operator pridani AS k ceste
+        - operator pridani AS k ceste [bgp_path_prepend]
         - matchovani na pritomnost podposloupnosti v ceste (pricemz vyskytne-li
           se tam mnozina, tak si ji lze predstavit prerovnanou v libovolnem
           poradi)
+
         - operator zjisteni delky cesty (pro vypocet metrik)
 
 Byl bych rad, kdyby se samotne matchovaci funkce objevily v proto/bgp/attrs.c.
 
+Jsou v sitove endianite. [lib/unaligned.h]
+
 
 (2) Community-listy
 
+posloupnost 32bitovych cisel s delkou.
+
 Community list budiz interne reprezentovan jako posloupnost 32-bitovych cisel.
 
 Filtry by se mely na communities divat jako na usporadane dvojice 16-bitovych
@@ -40,33 +47,14 @@ cisel (prvni je cislo AS, ktery community definoval, druhe pak community ID
 v ramci AS) a melo by byt mozne definovat si konstanty typu community.
 K dispozici by mely byt nasledujici operace:
 
-        - zjisteni pritomnosti community v listu
-        - pridani community do listu
-        - odebrani community z listu
+        - zjisteni pritomnosti community v listu [linearni pruchod]
+        - pridani community do listu [s kopii]
+        - odebrani community z listu [s kopii]
         - zresetovani listu
 
 Pro operace na cestach i na community listech by se mela pouzivat `teckova'
 notace pouzita v mem puvodnim navrhu syntaxe.
 
-
-(3) Zmeny v semantice dynamickych atributu
-
-Aby se nemusely neustale kopirovat seznamy atributu, rad bych provedl jeste
-jednu zmenu v tom, jak filtry nakladaji s atributy (pevne doufam, ze posledni,
-ale uznavam, ze u te predchozi jsem to take tvrdil): Funkci f_run budiz
-pridan jeste jeden parametr, ktery prepina mezi dvema mody:
-
-        (a)  [incoming filter mode]  Jako nyni.
-
-        (b)  [outgoing filter mode]  Pokud se hleda atribut, hleda se nejdrive
-             v tmp_attrs a pokud to selze, tak v rta->attrs. Pokud se nastavuje,
-             dava se _vzdy_ do tmp_attrs.
-
-Diky tomu filtry pri exportu routes nebudou vubec muset modifikovat rta a
-protokoly, ktere v import_control potrebuji nastavovat i non-temporary
-atributy, je budou moci pridat do tmp_attrs, aniz by sahly na rta.
-
-
  */
 
 CF_HDR
@@ -83,6 +71,8 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
        FROM, GW, NET, MASK, SOURCE,
        LEN,
        DEFINED,
+       ADD, DELETE, CONTAINS, RESET,
+       APPEND, MATCH,
        FILTER, WHERE)
 
 %nonassoc THEN
@@ -400,6 +390,19 @@ term:
  | term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; }
  | term '.' LEN { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_INT; }
  | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; }
+
+/* Communities */
+
+ | term '.' ADD '(' term ')' { }
+ | term '.' DELETE '(' term ')' { }
+ | term '.' CONTAINS '(' term ')' { }
+ | term '.' RESET { }
+
+/* Paths */
+ | term '.' APPEND '(' term ')' { }
+/* | term '.' LEN { }  Hmm, this would colide with ip.len. What to do with that? */
+ | term '.' MATCH '(' term ')' { }
+
 /* function_call is inlined here */
  | SYM '(' var_list ')' {
      struct symbol *sym;
index af7ee53fa4fa80e541ecb1225fc3504a163b1b19..7549d6b7e608a4a82e15e904fb606cae91f04c6c 100644 (file)
@@ -16,6 +16,7 @@
 #include "lib/resource.h"
 #include "lib/socket.h"
 #include "lib/string.h"
+#include "lib/unaligned.h"
 #include "nest/route.h"
 #include "nest/protocol.h"
 #include "nest/iface.h"
@@ -133,6 +134,7 @@ val_print(struct f_val v)
   case T_SET: tree_print( v.val.t ); PRINTF( "\n" ); break;
   case T_ENUM: PRINTF( "(enum %x)%d", v.type, v.val.i ); break;
   default: PRINTF( "[unknown type %x]", v.type );
+#undef PRINTF
   }
   debug( buf );
 }
@@ -554,6 +556,7 @@ filters_postconfig(void)
       die( "Startup function resulted in error." );
     debug( "done\n" );
   }
+  self_test();
 } 
 
 int
@@ -566,3 +569,203 @@ filter_same(struct filter *new, struct filter *old)
     return 0;
   return i_same(new->root, old->root);
 }
+
+/* This should end up far away from here! */
+
+int
+path_getlen(u8 *p, int len)
+{
+  int res = 0;
+  u8 *q = p+len;
+  while (p<q) {
+    switch (*p++) {
+    case 1: len = *p++; res++;    p += 2*len; break;
+    case 2: len = *p++; res+=len; p += 2*len; break;
+    default: bug("This should not be in path");
+    }
+  }
+  return res;
+}
+
+
+#define PRINTF(a...) { int l; bsnprintf( buf, 8000, a ); s -= (l = strlen(buf)); if (s<bigbuf) return "Path was much too long"; memcpy(s, buf, l); }
+#define COMMA if (first) first = 0; else PRINTF( ", " );
+char *
+path_format(u8 *p, int len)
+{
+  char bigbuf[4096];   /* Keep it smaller than buf */
+  char *s = bigbuf+4095;
+  char buf[8000];
+  int first = 1;
+  int i;
+  u8 *q = p+len;
+  *s-- = 0;
+  while (p<q) {
+    switch (*p++) {
+    case 1:    /* This is a set */
+      len = *p++;
+      COMMA;
+      PRINTF( "}" );
+      {
+       int first = 1;
+       for (i=0; i<len; i++) {
+         COMMA;
+         PRINTF( "%d", get_u16(p));
+         p+=2;
+       }
+      }
+      PRINTF( "{" );
+      break;
+
+    case 2:    /* This is a sequence */
+      len = *p++;
+      for (i=0; i<len; i++) {
+       int l;
+       COMMA;
+       PRINTF( "%d", get_u16(p));
+       p+=2;
+      }
+      break;
+
+    default:
+      bug("This should not be in path");
+    }
+  }
+  return strdup(s);
+}
+#undef PRINTF
+#undef COMMA
+
+#define PM_END -1
+#define PM_ASTERIX -2
+
+#define MASK_PLUS do { if (*++mask == PM_END) return next == q; \
+                      asterix = (*mask == PM_ASTERIX); \
+                      printf( "Asterix now %d\n", asterix ); \
+                       if (asterix) { if (*++mask == PM_END) { printf( "Quick exit\n" ); return 1; } } \
+                      } while(0)
+
+
+int
+path_match(u8 *p, int len, s32 *mask)
+{
+  int i;
+  int asterix = 0;
+  u8 *q = p+len;
+  u8 *next;
+
+  while (p<q) {
+    switch (*p++) {
+    case 1:    /* This is a set */
+      len = *p++;
+      {
+       u8 *p_save = p;
+       next = p_save + 2*len;
+      retry:
+       p = p_save;
+       for (i=0; i<len; i++) {
+         if (asterix && (get_u16(p) == *mask)) {
+           MASK_PLUS;
+           goto retry;
+         }
+         if (!asterix && (get_u16(p) == *mask)) {
+           p = next;
+           MASK_PLUS;
+           goto okay;
+         }
+         p+=2;
+       }
+       if (!asterix)
+         return 0;
+      okay:
+      }
+      break;
+
+    case 2:    /* This is a sequence */
+      len = *p++;
+      for (i=0; i<len; i++) {
+       next = p+2;
+       if (asterix && (get_u16(p) == *mask))
+         MASK_PLUS;
+       else if (!asterix) {
+         if (get_u16(p) != *mask)
+           return 0;
+         MASK_PLUS;
+       }
+       p+=2;
+      }
+      break;
+
+    default:
+      bug("This should not be in path");
+    }
+  }
+  return 0;
+}
+
+struct adata *
+comlist_add(struct linpool *pool, struct adata *list, u32 val)
+{
+  struct adata *res = lp_alloc(pool, list->length + sizeof(struct adata) + 4);
+  res->length = list->length+4;
+  * (u32 *) res->data = val;
+  memcpy((char *) res->data + 4, list->data, list->length);
+  return res;
+}
+
+struct adata *
+comlist_contains(struct adata *list, u32 val)
+{
+  u32 *l = &(list->data);
+  int i;
+  for (i=0; i<list->length/4; i++)
+    if (*l++ == val)
+      return 1;
+  return 0;
+}
+
+struct adata *
+comlist_del(struct linpool *pool, struct adata *list, u32 val)
+{
+  struct adata *res;
+  u32 *l, *k;
+  int i;
+
+  if (!comlist_contains(list, val))
+    return list;
+
+  res = lp_alloc(pool, list->length + sizeof(struct adata) - 4);
+  res->length = list->length-4;
+
+  l = &(list->data);
+  k = &(res->data);
+  for (i=0; i<list->length/4; i++)
+    if (l[i] != val)
+      *k++ = l[i];
+
+  return res;
+}
+
+struct adata *
+comlist_empty(struct linpool *pool)
+{
+  struct adata *res = lp_alloc(pool, sizeof(struct adata));
+  res->length = 0;
+  return res;
+}
+
+void
+self_test(void)
+{
+  char path1[] = { 2, 5, 0, 5, 0, 4, 0, 3, 0, 2, 0, 1 };
+  char path2[] = { 2, 5, 0, 5, 0, 4, 0, 3, 0, 2, 0, 1, 1, 5, 0, 5, 0, 4, 0, 3, 0, 2, 0, 1 };
+  s32 match[] = { 5, PM_ASTERIX, 2, PM_ASTERIX, 1, 3, PM_END };
+
+  DBG( "Filters self-testing:\n" );
+  DBG( "%s\n", path_format(path1, sizeof(path1)) );
+  DBG( "%s\n", path_format(path2, sizeof(path2)) );
+  DBG( "5, 6 = %d, %d\n", path_getlen(path1, sizeof(path1)), path_getlen(path2, sizeof(path2)) );
+  DBG( "%d\n", path_match(path1, sizeof(path1), match));
+  DBG( "%d\n", path_match(path2, sizeof(path2), match));
+//  die( "okay" );
+}