1
0
mirror of https://gitlab.labs.nic.cz/labs/bird.git synced 2024-05-11 16:54:54 +00:00

Merge commit '17f91f9e6e70f7e3f29502e854823c0d48571eaa' into haugesund

This commit is contained in:
Maria Matejka
2022-05-30 16:59:24 +02:00
54 changed files with 1056 additions and 878 deletions

View File

@@ -22,6 +22,13 @@ static inline u32 pair_b(u32 p) { return p & 0xFFFF; }
#define f_generate_complex(fi_code, da, arg) \
f_new_inst(FI_EA_SET, f_new_inst(fi_code, f_new_inst(FI_EA_GET, da), arg), da)
#define f_generate_complex_sym(fi_code, sym, arg) ({ \
if (sym->class != SYM_ATTRIBUTE) \
cf_error("Can't empty %s: not an attribute", sym->name); \
f_generate_complex(fi_code, sym->attribute, arg); \
})
/*
* Sets and their items are during parsing handled as lists, linked
* through left ptr. The first item in a list also contains a pointer
@@ -161,27 +168,31 @@ f_new_lc_item(u32 f1, u32 t1, u32 f2, u32 t2, u32 f3, u32 t3)
}
static inline struct f_inst *
f_generate_empty(struct f_dynamic_attr dyn)
f_generate_empty(const struct symbol *sym)
{
const struct f_val *empty = f_get_empty(dyn.type);
if (sym->class != SYM_ATTRIBUTE)
cf_error("Can't empty %s: not an attribute", sym->name);
const struct ea_class *def = sym->attribute;
const struct f_val *empty = f_get_empty(def->type);
if (!empty)
cf_error("Can't empty that attribute");
cf_error("Can't empty attribute %s", def->name);
return f_new_inst(FI_EA_SET, f_new_inst(FI_CONSTANT, *empty), dyn);
return f_new_inst(FI_EA_SET, f_new_inst(FI_CONSTANT, *empty), def);
}
#define BA_AS_PATH 0x02
static inline struct f_inst *
f_implicit_roa_check(struct rtable_config *tab)
{
struct f_dynamic_attr fda = f_new_dynamic_attr(T_PATH, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
const struct ea_class *def = ea_class_find("bgp_path");
if (!def)
cf_error("Fatal: Couldn't find BGP path attribute definition.");
struct f_static_attr fsa = f_new_static_attr(T_NET, SA_NET, 1);
return f_new_inst(FI_ROA_CHECK,
f_new_inst(FI_RTA_GET, fsa),
f_new_inst(FI_AS_PATH_LAST, f_new_inst(FI_EA_GET, fda)),
f_new_inst(FI_AS_PATH_LAST, f_new_inst(FI_EA_GET, def)),
tab);
}
@@ -293,8 +304,8 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
%type <xp> cmds_int cmd_prep
%type <x> term block cmd cmds constant constructor print_list var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail
%type <fda> dynamic_attr attr_bit
%type <fsa> static_attr
%type <fab> attr_bit
%type <f> filter where_filter
%type <fl> filter_body function_body
%type <flv> lvalue
@@ -335,7 +346,14 @@ filter_eval:
conf: custom_attr ;
custom_attr: ATTRIBUTE type symbol ';' {
cf_define_symbol($3, SYM_ATTRIBUTE, attribute, ca_lookup(new_config->pool, $3->name, $2)->fda);
if (($3->class == SYM_ATTRIBUTE) && ($3->scope == new_config->root_scope))
cf_error("Duplicate attribute %s definition", $3->name);
cf_define_symbol($3, SYM_ATTRIBUTE, attribute,
ea_register_alloc(new_config->pool, (struct ea_class) {
.name = $3->name,
.type = $2,
})->class);
};
conf: bt_test_suite ;
@@ -736,7 +754,7 @@ symbol_value: CF_SYM_KNOWN
$$ = f_new_inst(FI_VAR_GET, $1);
break;
case SYM_ATTRIBUTE:
$$ = f_new_inst(FI_EA_GET, *$1->attribute);
$$ = f_new_inst(FI_EA_GET, $1->attribute);
break;
default:
cf_error("Can't get value of symbol %s", $1->name);
@@ -785,11 +803,9 @@ term:
| constructor { $$ = $1; }
| static_attr { $$ = f_new_inst(FI_RTA_GET, $1); }
| dynamic_attr { $$ = f_new_inst(FI_EA_GET, $1); }
| attr_bit {
struct f_inst *c = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = (1U << $1.bit)});
$$ = f_new_inst(FI_EQ, c, f_new_inst(FI_BITAND, f_new_inst(FI_EA_GET, $1), c));
$$ = f_new_inst(FI_EQ, c, f_new_inst(FI_BITAND, f_new_inst(FI_EA_GET, $1.class), c));
}
| term '.' IS_V4 { $$ = f_new_inst(FI_IS_V4, $1); }
@@ -833,8 +849,6 @@ term:
| FORMAT '(' term ')' { $$ = f_new_inst(FI_FORMAT, $3); }
/* | term '.' LEN { $$->code = P('P','l'); } */
| function_call
;
@@ -867,7 +881,9 @@ cmd:
$$ = f_new_inst(FI_VAR_SET, $3, $1);
break;
case SYM_ATTRIBUTE:
$$ = f_new_inst(FI_EA_SET, $3, *$1->attribute);
if ($1->attribute->readonly)
cf_error("Attribute %s is read-only", $1->attribute->name);
$$ = f_new_inst(FI_EA_SET, $3, $1->attribute);
break;
default:
cf_error("Can't assign to symbol %s", $1->name);
@@ -877,22 +893,23 @@ cmd:
DBG( "Ook, we'll return the value\n" );
$$ = f_new_inst(FI_RETURN, $2);
}
| dynamic_attr '=' term ';' {
$$ = f_new_inst(FI_EA_SET, $3, $1);
}
| static_attr '=' term ';' {
if ($1.readonly)
cf_error( "This static attribute is read-only.");
$$ = f_new_inst(FI_RTA_SET, $3, $1);
}
| UNSET '(' dynamic_attr ')' ';' {
$$ = f_new_inst(FI_EA_UNSET, $3);
| UNSET '(' CF_SYM_KNOWN ')' ';' {
if ($3->class != SYM_ATTRIBUTE)
cf_error("Can't unset %s", $3->name);
if ($3->attribute->readonly)
cf_error("Attribute %s is read-only", $3->attribute->name);
$$ = f_new_inst(FI_EA_UNSET, $3->attribute);
}
| attr_bit '=' term ';' {
$$ = f_new_inst(FI_CONDITION, $3,
f_generate_complex(FI_BITOR, $1,
f_generate_complex(FI_BITOR, $1.class,
f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = (1U << $1.bit)})),
f_generate_complex(FI_BITAND, $1,
f_generate_complex(FI_BITAND, $1.class,
f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = ~(1U << $1.bit)}))
);
}
@@ -919,11 +936,11 @@ cmd:
$$ = f_new_inst(FI_SWITCH, $2, build_tree($4));
}
| dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($1); }
| dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( FI_PATH_PREPEND, $1, $5 ); }
| dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD, $1, $5 ); }
| dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_DEL, $1, $5 ); }
| dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_FILTER, $1, $5 ); }
| CF_SYM_KNOWN '.' EMPTY ';' { $$ = f_generate_empty($1); }
| CF_SYM_KNOWN '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex_sym( FI_PATH_PREPEND, $1, $5 ); }
| CF_SYM_KNOWN '.' ADD '(' term ')' ';' { $$ = f_generate_complex_sym( FI_CLIST_ADD, $1, $5 ); }
| CF_SYM_KNOWN '.' DELETE '(' term ')' ';' { $$ = f_generate_complex_sym( FI_CLIST_DEL, $1, $5 ); }
| CF_SYM_KNOWN '.' FILTER '(' term ')' ';' { $$ = f_generate_complex_sym( FI_CLIST_FILTER, $1, $5 ); }
| BT_ASSERT '(' get_cf_position term get_cf_position ')' ';' { $$ = assert_done($4, $3 + 1, $5 - 1); }
| BT_CHECK_ASSIGN '(' get_cf_position lvalue get_cf_position ',' term ')' ';' { $$ = assert_assign(&$4, $7, $3 + 1, $5 - 1); }
;
@@ -934,8 +951,17 @@ get_cf_position:
};
lvalue:
CF_SYM_KNOWN { cf_assert_symbol($1, SYM_VARIABLE); $$ = (struct f_lval) { .type = F_LVAL_VARIABLE, .sym = $1 }; }
CF_SYM_KNOWN {
switch ($1->class) {
case SYM_VARIABLE_RANGE:
$$ = (struct f_lval) { .type = F_LVAL_VARIABLE, .sym = $1 };
break;
case SYM_ATTRIBUTE:
$$ = (struct f_lval) { .type = F_LVAL_EA, .da = $1->attribute };
break;
}
}
| static_attr { $$ = (struct f_lval) { .type = F_LVAL_SA, .sa = $1 }; }
| dynamic_attr { $$ = (struct f_lval) { .type = F_LVAL_EA, .da = $1 }; };
;
CF_END

View File

@@ -21,13 +21,6 @@ struct f_val {
#define fputip(a) ({ ip_addr *ax = falloc(sizeof(*ax)); *ax = (a); ax; })
/* Dynamic attribute definition (eattrs) */
struct f_dynamic_attr {
btype type; /* EA type (EAF_*) */
u8 bit; /* For bitfield accessors */
uint ea_code; /* EA code */
};
enum f_sa_code {
SA_FROM = 1,
SA_GW,
@@ -53,7 +46,6 @@ struct f_static_attr {
/* Filter l-value type */
enum f_lval_type {
F_LVAL_VARIABLE,
F_LVAL_PREFERENCE,
F_LVAL_SA,
F_LVAL_EA,
};
@@ -63,7 +55,7 @@ struct f_lval {
enum f_lval_type type;
union {
struct symbol *sym;
struct f_dynamic_attr da;
const struct ea_class *da;
struct f_static_attr sa;
};
};

View File

@@ -94,7 +94,7 @@ FID_DUMP_BODY()m4_dnl
debug("%s" $4 "\n", INDENT, $5);
]])
FID_INTERPRET_EXEC()m4_dnl
const $1 $2 = whati->$2
$1 $2 = whati->$2
FID_INTERPRET_BODY')
# Instruction arguments are needed only until linearization is done.
@@ -256,7 +256,7 @@ FID_INTERPRET_BODY()')
m4_define(SYMBOL, `FID_MEMBER(struct symbol *, sym, [[strcmp(f1->sym->name, f2->sym->name) || (f1->sym->class != f2->sym->class)]], "symbol %s", item->sym->name)')
m4_define(RTC, `FID_MEMBER(struct rtable_config *, rtc, [[strcmp(f1->rtc->name, f2->rtc->name)]], "route table %s", item->rtc->name)')
m4_define(STATIC_ATTR, `FID_MEMBER(struct f_static_attr, sa, f1->sa.sa_code != f2->sa.sa_code,,)')
m4_define(DYNAMIC_ATTR, `FID_MEMBER(struct f_dynamic_attr, da, f1->da.ea_code != f2->da.ea_code,,)')
m4_define(DYNAMIC_ATTR, `FID_MEMBER(const struct ea_class *, da, f1->da != f2->da,,)')
m4_define(ACCESS_RTE, `FID_HIC(,[[do { if (!fs->rte) runtime("No route to access"); } while (0)]],NEVER_CONSTANT())')
# 2) Code wrapping

View File

@@ -662,14 +662,14 @@
DYNAMIC_ATTR;
ACCESS_RTE;
ACCESS_EATTRS;
RESULT_TYPE(da.type);
RESULT_TYPE(da->type);
{
const struct f_val *empty;
eattr *e = ea_find(*fs->eattrs, da.ea_code);
const eattr *e = ea_find(*fs->eattrs, da->id);
if (e)
{
ASSERT_DIE(e->type == da.type);
ASSERT_DIE(e->type == da->type);
switch (e->type) {
case T_IP:
@@ -682,7 +682,7 @@
}]]);
}
}
else if (empty = f_get_empty(da.type))
else if (empty = f_get_empty(da->type))
RESULT_VAL(*empty);
else
RESULT_VOID;
@@ -694,16 +694,16 @@
ACCESS_EATTRS;
ARG_ANY(1);
DYNAMIC_ATTR;
ARG_TYPE(1, da.type);
ARG_TYPE(1, da->type);
{
struct eattr *a;
if (da.type >= EAF_TYPE__MAX)
if (da->type >= EAF_TYPE__MAX)
bug("Unsupported attribute type");
f_rta_cow(fs);
switch (da.type) {
switch (da->type) {
case T_OPAQUE:
case T_IFACE:
runtime( "Setting opaque attribute is not allowed" );
@@ -711,12 +711,12 @@
case T_IP:
a = ea_set_attr(fs->eattrs,
EA_LITERAL_STORE_ADATA(da.ea_code, da.type, 0, &v1.val.ip, sizeof(ip_addr)));
EA_LITERAL_STORE_ADATA(da, 0, &v1.val.ip, sizeof(ip_addr)));
break;
default:
a = ea_set_attr(fs->eattrs,
EA_LITERAL_GENERIC(da.ea_code, da.type, 0, .u = v1.val.bval));
EA_LITERAL_GENERIC(da->id, da->type, 0, .u = v1.val.bval));
break;
}
@@ -731,7 +731,7 @@
ACCESS_EATTRS;
f_rta_cow(fs);
ea_unset_attr(fs->eattrs, 1, da.ea_code);
ea_unset_attr(fs->eattrs, 1, da);
}
INST(FI_LENGTH, 1, 1) { /* Get length of */

View File

@@ -87,15 +87,17 @@ void f_add_lines(const struct f_line_item *what, struct filter_iterator *fit);
struct filter *f_new_where(struct f_inst *);
static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, uint code)
{ return (struct f_dynamic_attr) { .type = type, .ea_code = code }; }
static inline struct f_dynamic_attr f_new_dynamic_attr_bit(u8 bit, uint code)
{ return (struct f_dynamic_attr) { .type = T_INT, .bit = bit, .ea_code = code }; }
static inline struct f_static_attr f_new_static_attr(btype type, int code, int readonly)
{ return (struct f_static_attr) { .type = type, .sa_code = code, .readonly = readonly }; }
struct f_inst *f_generate_complex(enum f_instruction_code fi_code, struct f_dynamic_attr da, struct f_inst *argument);
struct f_inst *f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn);
struct f_attr_bit {
const struct ea_class *class;
uint bit;
};
#define f_new_dynamic_attr_bit(_bit, _name) ((struct f_attr_bit) { .bit = _bit, .class = ea_class_find(_name) })
/* Hook for call bt_assert() function in configuration */
extern void (*bt_assert_hook)(int result, const struct f_line_item *assert);

View File

@@ -2,7 +2,7 @@
* Filters: utility functions
*
* Copyright 1998 Pavel Machek <pavel@ucw.cz>
* 2017 Jan Maria Matejka <mq@ucw.cz>
* 2017 Maria Matejka <mq@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@@ -40,129 +40,3 @@ struct filter *f_new_where(struct f_inst *where)
f->root = f_linearize(cond);
return f;
}
#define CA_KEY(n) n->name, n->fda.type
#define CA_NEXT(n) n->next
#define CA_EQ(na,ta,nb,tb) (!strcmp(na,nb) && (ta == tb))
#define CA_FN(n,t) (mem_hash(n, strlen(n)) ^ (t*0xaae99453U))
#define CA_ORDER 8 /* Fixed */
struct ca_storage {
struct ca_storage *next;
struct f_dynamic_attr fda;
u32 uc;
char name[0];
};
HASH(struct ca_storage) ca_hash;
static struct idm ca_idm;
static struct ca_storage **ca_storage;
static uint ca_storage_max;
static void
ca_free(resource *r)
{
struct custom_attribute *ca = (void *) r;
struct ca_storage *cas = HASH_FIND(ca_hash, CA, ca->name, ca->fda->type);
ASSERT(cas);
ca->name = NULL;
ca->fda = NULL;
if (!--cas->uc) {
uint id = EA_CUSTOM_ID(cas->fda.ea_code);
idm_free(&ca_idm, id);
HASH_REMOVE(ca_hash, CA, cas);
ca_storage[id] = NULL;
mb_free(cas);
}
}
static void
ca_dump(resource *r)
{
struct custom_attribute *ca = (void *) r;
debug("name \"%s\" id 0x%04x ea_type 0x%02x\n",
ca->name, ca->fda->ea_code, ca->fda->type);
}
static struct resclass ca_class = {
.name = "Custom attribute",
.size = sizeof(struct custom_attribute),
.free = ca_free,
.dump = ca_dump,
.lookup = NULL,
.memsize = NULL,
};
struct custom_attribute *
ca_lookup(pool *p, const char *name, btype type)
{
switch (type) {
case T_INT:
case T_IP:
case T_QUAD:
case T_PATH:
case T_CLIST:
case T_ECLIST:
case T_LCLIST:
break;
default:
cf_error("Custom route attribute of unsupported type");
}
static int inited = 0;
if (!inited) {
idm_init(&ca_idm, &root_pool, 8);
HASH_INIT(ca_hash, &root_pool, CA_ORDER);
ca_storage_max = 256;
ca_storage = mb_allocz(&root_pool, sizeof(struct ca_storage *) * ca_storage_max);
inited++;
}
struct ca_storage *cas = HASH_FIND(ca_hash, CA, name, type);
if (cas) {
cas->uc++;
} else {
uint id = idm_alloc(&ca_idm);
if (id >= EA_CUSTOM_BIT)
cf_error("Too many custom attributes.");
if (id >= ca_storage_max) {
ca_storage_max *= 2;
ca_storage = mb_realloc(ca_storage, sizeof(struct ca_storage *) * ca_storage_max * 2);
}
cas = mb_allocz(&root_pool, sizeof(struct ca_storage) + strlen(name) + 1);
cas->fda = f_new_dynamic_attr(type, EA_CUSTOM(id));
cas->uc = 1;
strcpy(cas->name, name);
ca_storage[id] = cas;
HASH_INSERT(ca_hash, CA, cas);
}
struct custom_attribute *ca = ralloc(p, &ca_class);
ca->fda = &(cas->fda);
ca->name = cas->name;
return ca;
}
const char *
ea_custom_name(uint ea)
{
uint id = EA_CUSTOM_ID(ea);
if (id >= ca_storage_max)
return NULL;
if (!ca_storage[id])
return NULL;
return ca_storage[id]->name;
}

View File

@@ -70,13 +70,4 @@ void filters_dump_all(void);
#define FF_SILENT 2 /* Silent filter execution */
/* Custom route attributes */
struct custom_attribute {
resource r;
struct f_dynamic_attr *fda;
const char *name;
};
struct custom_attribute *ca_lookup(pool *p, const char *name, btype type);
#endif

View File

@@ -9,7 +9,109 @@ router id 62.168.0.1;
/* We have to setup any protocol */
protocol device { }
/* Setting some custom attributes, enough to force BIRD to reallocate the attribute idmap */
attribute int test_ca_int1;
attribute int test_ca_int2;
attribute int test_ca_int3;
attribute int test_ca_int4;
attribute int test_ca_int5;
attribute int test_ca_int6;
attribute int test_ca_int7;
attribute int test_ca_int8;
attribute int test_ca_int9;
attribute int test_ca_int10;
attribute ip test_ca_ip1;
attribute ip test_ca_ip2;
attribute ip test_ca_ip3;
attribute ip test_ca_ip4;
attribute ip test_ca_ip5;
attribute ip test_ca_ip6;
attribute ip test_ca_ip7;
attribute ip test_ca_ip8;
attribute ip test_ca_ip9;
attribute ip test_ca_ip10;
attribute quad test_ca_quad1;
attribute quad test_ca_quad2;
attribute quad test_ca_quad3;
attribute quad test_ca_quad4;
attribute quad test_ca_quad5;
attribute quad test_ca_quad6;
attribute quad test_ca_quad7;
attribute quad test_ca_quad8;
attribute quad test_ca_quad9;
attribute quad test_ca_quad10;
attribute bgppath test_ca_bgppath1;
attribute bgppath test_ca_bgppath2;
attribute bgppath test_ca_bgppath3;
attribute bgppath test_ca_bgppath4;
attribute bgppath test_ca_bgppath5;
attribute bgppath test_ca_bgppath6;
attribute bgppath test_ca_bgppath7;
attribute bgppath test_ca_bgppath8;
attribute bgppath test_ca_bgppath9;
attribute bgppath test_ca_bgppath10;
attribute clist test_ca_clist1;
attribute clist test_ca_clist2;
attribute clist test_ca_clist3;
attribute clist test_ca_clist4;
attribute clist test_ca_clist5;
attribute clist test_ca_clist6;
attribute clist test_ca_clist7;
attribute clist test_ca_clist8;
attribute clist test_ca_clist9;
attribute clist test_ca_clist10;
attribute eclist test_ca_eclist1;
attribute eclist test_ca_eclist2;
attribute eclist test_ca_eclist3;
attribute eclist test_ca_eclist4;
attribute eclist test_ca_eclist5;
attribute eclist test_ca_eclist6;
attribute eclist test_ca_eclist7;
attribute eclist test_ca_eclist8;
attribute eclist test_ca_eclist9;
attribute eclist test_ca_eclist10;
attribute lclist test_ca_lclist1;
attribute lclist test_ca_lclist2;
attribute lclist test_ca_lclist3;
attribute lclist test_ca_lclist4;
attribute lclist test_ca_lclist5;
attribute lclist test_ca_lclist6;
attribute lclist test_ca_lclist7;
attribute lclist test_ca_lclist8;
attribute lclist test_ca_lclist9;
attribute lclist test_ca_lclist10;
attribute lclist test_ca_lclist_max1;
attribute lclist test_ca_lclist_max2;
attribute lclist test_ca_lclist_max3;
attribute lclist test_ca_lclist_max4;
attribute lclist test_ca_lclist_max5;
attribute lclist test_ca_lclist_max6;
attribute lclist test_ca_lclist_max7;
attribute lclist test_ca_lclist_max8;
attribute lclist test_ca_lclist_max9;
attribute lclist test_ca_lclist_max10;
attribute lclist test_ca_lclist_max11;
attribute lclist test_ca_lclist_max12;
attribute lclist test_ca_lclist_max13;
attribute lclist test_ca_lclist_max14;
attribute lclist test_ca_lclist_max15;
attribute lclist test_ca_lclist_max16;
attribute lclist test_ca_lclist_max17;
attribute lclist test_ca_lclist_max18;
attribute lclist test_ca_lclist_max19;
attribute lclist test_ca_lclist_max20;
attribute lclist test_ca_lclist_max21;
/* Uncomment this to get an error */
#attribute int bgp_path;
/*
* Common definitions and functions
@@ -1331,6 +1433,7 @@ function __test2()
filter testf
int j;
bool t;
{
print "Heya, filtering route to ", net.ip, " prefixlen ", net.len, " source ", source;
print "This route was from ", from;
@@ -1342,6 +1445,52 @@ int j;
rip_metric = 14;
unset(rip_metric);
test_ca_int1 = 42;
test_ca_ip2 = 1.3.5.7;
test_ca_quad3 = 2.4.6.8;
test_ca_bgppath4 = +empty+;
test_ca_clist5 = -empty-;
test_ca_eclist6 = --empty--;
test_ca_lclist7 = ---empty---;
igp_metric = 53;
babel_metric = 64;
t = defined(babel_router_id);
j = babel_seqno;
bgp_origin = ORIGIN_IGP;
bgp_path = +empty+;
bgp_next_hop = 3456:789a:bcde:f012::3456:789a;
bgp_med = 71;
bgp_local_pref = 942;
t = defined(bgp_atomic_aggr);
t = defined(bgp_aggregator);
bgp_community = -empty-;
bgp_originator_id = 9.7.5.3;
bgp_cluster_list = -empty-;
t = defined(bgp_mp_reach_nlri);
t = defined(bgp_mp_unreach_nlri);
bgp_ext_community = --empty--;
bgp_as4_path = +empty+;
t = defined(bgp_as4_aggregator);
t = defined(bgp_aigp);
bgp_large_community = ---empty---;
t = defined(bgp_mpls_label_stack);
ospf_metric1 = 64;
ospf_metric2 = 111;
ospf_tag = 654432;
radv_preference = RA_PREF_LOW;
radv_lifetime = 28;
rip_metric = 2;
rip_tag = 4;
t = defined(rip_from);
krt_source = 17;
krt_metric = 19;
# krt_lock_mtu = false;
# krt_lock_window = true;
# krt_lock_rtt = krt_lock_rttvar && krt_lock_sstresh || krt_lock_cwnd;