From 0a06a9b8b3dbd59c850303c49eea97c12e1ac0ff Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 29 Mar 2000 09:02:00 +0000 Subject: [PATCH] f_run gets one more parameter to distinguish between in and out modes. --- filter/config.Y | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ filter/filter.c | 13 ++++++++--- filter/filter.h | 4 +++- nest/rt-table.c | 8 +++---- 4 files changed, 75 insertions(+), 8 deletions(-) diff --git a/filter/config.Y b/filter/config.Y index 00aeefc1..413e88cb 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -9,6 +9,64 @@ FIXME (for BGP): whole system of paths, path ~ string, path.prepend(), path.originate FIXME: create community lists FIXME: IP addresses in ipv6 + + +(1) Cesty + + AS paths budtez interne reprezentovany stejne jako v BGP (viz RFC 1771), +to znamena jako posloupnost segmentu, z nichz kazdy je budto posloupnost nebo +mnozina cisel ASu. Na cestach nadefinuji nasledujici operace: + + - zformatovani do stringu + - append dalsiho AS k ceste + +Filtry by mely podporovat: + + - operator pridani AS k ceste + - 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. + + +(2) Community-listy + +Community list budiz interne reprezentovan jako posloupnost 32-bitovych cisel. + +Filtry by se mely na communities divat jako na usporadane dvojice 16-bitovych +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 + - 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 diff --git a/filter/filter.c b/filter/filter.c index 5faabfef..6a590725 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -145,6 +145,7 @@ val_print(struct f_val v) static struct rte **f_rte, *f_rte_old; static struct linpool *f_pool; static struct ea_list **f_tmp_attrs; +static int f_flags; #define runtime(x) do { \ log( L_ERR x ); \ @@ -329,9 +330,14 @@ interpret(struct f_inst *what) break; case P('e','a'): /* Access to extended attributes */ { - eattr *e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i ); + eattr *e = NULL; + if (!(f_flags & FF_OUTGOING)) + e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i ); if (!e) e = ea_find( (*f_tmp_attrs), what->a2.i ); + if ((!e) && (f_flags & FF_OUTGOING)) + e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i ); + if (!e) { res.type = T_VOID; break; @@ -371,7 +377,7 @@ interpret(struct f_inst *what) break; } - if (!(what->aux & EAF_TEMP)) { + if (!(what->aux & EAF_TEMP) && (!(f_flags & FF_OUTGOING))) { *f_rte = rte_do_cow(*f_rte); l->next = (*f_rte)->attrs->eattrs; (*f_rte)->attrs->eattrs = l; @@ -523,12 +529,13 @@ i_same(struct f_inst *f1, struct f_inst *f2) } int -f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool) +f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags) { struct f_inst *inst; struct f_val res; DBG( "Running filter `%s'...", filter->name ); + f_flags = flags; f_tmp_attrs = tmp_attrs; f_rte = rte; f_rte_old = *rte; diff --git a/filter/filter.h b/filter/filter.h index 3f05f6a3..b05e6a7a 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -67,7 +67,7 @@ int same_tree(struct f_tree *t1, struct f_tree *t2); struct ea_list; struct rte; -int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool); +int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags); char *filter_name(struct filter *filter); int filter_same(struct filter *new, struct filter *old); @@ -122,4 +122,6 @@ struct f_tree { #define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val)); +#define FF_OUTGOING 1 + #endif diff --git a/nest/rt-table.c b/nest/rt-table.c index d3fcf64a..687e9402 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -141,7 +141,7 @@ do_rte_announce(struct announce_hook *a, net *net, rte *new, rte *old, ea_list * else if (ok) rte_trace_out(D_FILTERS, p, new, "forced accept by protocol"); else if (p->out_filter == FILTER_REJECT || - p->out_filter && f_run(p->out_filter, &new, &tmpa, rte_update_pool) > F_ACCEPT) + p->out_filter && f_run(p->out_filter, &new, &tmpa, rte_update_pool, 0) > F_ACCEPT) { rte_trace_out(D_FILTERS, p, new, "filtered out"); new = NULL; @@ -155,7 +155,7 @@ do_rte_announce(struct announce_hook *a, net *net, rte *new, rte *old, ea_list * else { ea_list *tmpb = p->make_tmp_attrs ? p->make_tmp_attrs(old, rte_update_pool) : NULL; - if (f_run(p->out_filter, &old, &tmpb, rte_update_pool) > F_ACCEPT) + if (f_run(p->out_filter, &old, &tmpb, rte_update_pool, 0) > F_ACCEPT) old = NULL; } } @@ -387,7 +387,7 @@ rte_update(rtable *table, net *net, struct proto *p, rte *new) if (p->in_filter) { ea_list *old_tmpa = tmpa; - int fr = f_run(p->in_filter, &new, &tmpa, rte_update_pool); + int fr = f_run(p->in_filter, &new, &tmpa, rte_update_pool, 0); if (fr > F_ACCEPT) { rte_trace_in(D_FILTERS, p, new, "filtered out"); @@ -695,7 +695,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) struct ea_list *tmpa = NULL; ee = e; rte_update_lock(); /* We use the update buffer for filtering */ - if (d->filter == FILTER_ACCEPT || f_run(d->filter, &ee, &tmpa, rte_update_pool) <= F_ACCEPT) + if (d->filter == FILTER_ACCEPT || f_run(d->filter, &ee, &tmpa, rte_update_pool, 0) <= F_ACCEPT) { rt_show_rte(c, ia, e, d); ia[0] = 0;