Functions for matching paths added, tested lightly.
Functions for working with community lists added, they compile. This should not be definitive place for this stuff.
This commit is contained in:
parent
73e03bce66
commit
7f77e25002
2 changed files with 229 additions and 23 deletions
|
@ -11,6 +11,8 @@
|
||||||
FIXME: IP addresses in ipv6
|
FIXME: IP addresses in ipv6
|
||||||
|
|
||||||
|
|
||||||
|
FIXME: check messages for \n at the end
|
||||||
|
|
||||||
(1) Cesty
|
(1) Cesty
|
||||||
|
|
||||||
AS paths budtez interne reprezentovany stejne jako v BGP (viz RFC 1771),
|
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:
|
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
|
- matchovani na pritomnost podposloupnosti v ceste (pricemz vyskytne-li
|
||||||
se tam mnozina, tak si ji lze predstavit prerovnanou v libovolnem
|
se tam mnozina, tak si ji lze predstavit prerovnanou v libovolnem
|
||||||
poradi)
|
poradi)
|
||||||
|
|
||||||
- operator zjisteni delky cesty (pro vypocet metrik)
|
- operator zjisteni delky cesty (pro vypocet metrik)
|
||||||
|
|
||||||
Byl bych rad, kdyby se samotne matchovaci funkce objevily v proto/bgp/attrs.c.
|
Byl bych rad, kdyby se samotne matchovaci funkce objevily v proto/bgp/attrs.c.
|
||||||
|
|
||||||
|
Jsou v sitove endianite. [lib/unaligned.h]
|
||||||
|
|
||||||
|
|
||||||
(2) Community-listy
|
(2) Community-listy
|
||||||
|
|
||||||
|
posloupnost 32bitovych cisel s delkou.
|
||||||
|
|
||||||
Community list budiz interne reprezentovan jako posloupnost 32-bitovych cisel.
|
Community list budiz interne reprezentovan jako posloupnost 32-bitovych cisel.
|
||||||
|
|
||||||
Filtry by se mely na communities divat jako na usporadane dvojice 16-bitovych
|
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.
|
v ramci AS) a melo by byt mozne definovat si konstanty typu community.
|
||||||
K dispozici by mely byt nasledujici operace:
|
K dispozici by mely byt nasledujici operace:
|
||||||
|
|
||||||
- zjisteni pritomnosti community v listu
|
- zjisteni pritomnosti community v listu [linearni pruchod]
|
||||||
- pridani community do listu
|
- pridani community do listu [s kopii]
|
||||||
- odebrani community z listu
|
- odebrani community z listu [s kopii]
|
||||||
- zresetovani listu
|
- zresetovani listu
|
||||||
|
|
||||||
Pro operace na cestach i na community listech by se mela pouzivat `teckova'
|
Pro operace na cestach i na community listech by se mela pouzivat `teckova'
|
||||||
notace pouzita v mem puvodnim navrhu syntaxe.
|
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
|
CF_HDR
|
||||||
|
@ -83,6 +71,8 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
||||||
FROM, GW, NET, MASK, SOURCE,
|
FROM, GW, NET, MASK, SOURCE,
|
||||||
LEN,
|
LEN,
|
||||||
DEFINED,
|
DEFINED,
|
||||||
|
ADD, DELETE, CONTAINS, RESET,
|
||||||
|
APPEND, MATCH,
|
||||||
FILTER, WHERE)
|
FILTER, WHERE)
|
||||||
|
|
||||||
%nonassoc THEN
|
%nonassoc THEN
|
||||||
|
@ -400,6 +390,19 @@ term:
|
||||||
| term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; }
|
| 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 '.' 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; }
|
| 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 */
|
/* function_call is inlined here */
|
||||||
| SYM '(' var_list ')' {
|
| SYM '(' var_list ')' {
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
|
|
203
filter/filter.c
203
filter/filter.c
|
@ -16,6 +16,7 @@
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
#include "lib/socket.h"
|
#include "lib/socket.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
|
#include "lib/unaligned.h"
|
||||||
#include "nest/route.h"
|
#include "nest/route.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
#include "nest/iface.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_SET: tree_print( v.val.t ); PRINTF( "\n" ); break;
|
||||||
case T_ENUM: PRINTF( "(enum %x)%d", v.type, v.val.i ); break;
|
case T_ENUM: PRINTF( "(enum %x)%d", v.type, v.val.i ); break;
|
||||||
default: PRINTF( "[unknown type %x]", v.type );
|
default: PRINTF( "[unknown type %x]", v.type );
|
||||||
|
#undef PRINTF
|
||||||
}
|
}
|
||||||
debug( buf );
|
debug( buf );
|
||||||
}
|
}
|
||||||
|
@ -554,6 +556,7 @@ filters_postconfig(void)
|
||||||
die( "Startup function resulted in error." );
|
die( "Startup function resulted in error." );
|
||||||
debug( "done\n" );
|
debug( "done\n" );
|
||||||
}
|
}
|
||||||
|
self_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -566,3 +569,203 @@ filter_same(struct filter *new, struct filter *old)
|
||||||
return 0;
|
return 0;
|
||||||
return i_same(new->root, old->root);
|
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" );
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue