mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-17 08:38:42 +00:00
Filter: merged filter instruction constructors, counting line size on instruction construct
This commit is contained in:
parent
0a793ebc60
commit
4f082dfa89
@ -18,6 +18,12 @@ AC_ARG_ENABLE([debug],
|
||||
[enable_debug=no]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([debug-generated],
|
||||
[AS_HELP_STRING([--enable-debug-generated], [enable this to abstain from generating #line @<:@no@:>@])],
|
||||
[],
|
||||
[enable_debug_generated=no]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([memcheck],
|
||||
[AS_HELP_STRING([--enable-memcheck], [check memory allocations when debugging @<:@yes@:>@])],
|
||||
[],
|
||||
@ -156,7 +162,7 @@ test -z "$M4" && AC_MSG_ERROR([M4 is missing.])
|
||||
AC_MSG_CHECKING([bison version])
|
||||
BIRD_CHECK_BISON_VERSION(BISON_VERSION)
|
||||
AC_MSG_RESULT([$BISON_VERSION])
|
||||
if test "$bird_bison_synclines" = yes; then
|
||||
if test "$bird_bison_synclines" = yes && test "$enable_debug_generated" = no; then
|
||||
M4FLAGS="$M4FLAGS -s"
|
||||
fi
|
||||
|
||||
|
@ -1,13 +1,10 @@
|
||||
src := filter.c f-util.c tree.c trie.c f-inst-new.c
|
||||
src := filter.c f-util.c tree.c trie.c
|
||||
obj := $(src-o-files)
|
||||
$(all-daemon)
|
||||
$(cf-local)
|
||||
|
||||
M4FLAGS_FILTERS=$(filter-out -s,$(M4FLAGS))
|
||||
|
||||
$(o)f-inst-line-size.c: $(s)line-size.m4 $(s)f-inst.c $(objdir)/.dir-stamp
|
||||
$(M4) $(M4FLAGS_FILTERS) -P $^ >$@
|
||||
|
||||
$(o)f-inst-postfixify.c: $(s)postfixify.m4 $(s)f-inst.c $(objdir)/.dir-stamp
|
||||
$(M4) $(M4FLAGS_FILTERS) -P $^ >$@
|
||||
|
||||
@ -17,16 +14,13 @@ $(o)f-inst-interpret.c: $(s)interpret.m4 $(s)f-inst.c $(objdir)/.dir-stamp
|
||||
$(o)f-inst-same.c: $(s)same.m4 $(s)f-inst.c $(objdir)/.dir-stamp
|
||||
$(M4) $(M4FLAGS_FILTERS) -P $^ >$@
|
||||
|
||||
$(o)f-inst-struct.h: $(s)struct.m4 $(s)f-inst.c $(objdir)/.dir-stamp
|
||||
$(M4) $(M4FLAGS_FILTERS) -P $^ >$@
|
||||
|
||||
$(o)f-inst-new.c: $(s)new.m4 $(s)f-inst.c $(objdir)/.dir-stamp
|
||||
$(o)f-inst-decl.h: $(s)decl.m4 $(s)f-inst.c $(objdir)/.dir-stamp
|
||||
$(M4) $(M4FLAGS_FILTERS) -P $^ >$@
|
||||
|
||||
$(o)f-inst-dump.c: $(s)dump.m4 $(s)f-inst.c $(objdir)/.dir-stamp
|
||||
$(M4) $(M4FLAGS_FILTERS) -P $^ >$@
|
||||
|
||||
$(o)filter.o: $(o)f-inst-interpret.c $(o)f-inst-line-size.c $(o)f-inst-postfixify.c $(o)f-inst-same.c $(o)f-inst-dump.c $(o)f-inst-struct.h
|
||||
$(o)filter.o: $(o)f-inst-interpret.c $(o)f-inst-postfixify.c $(o)f-inst-same.c $(o)f-inst-dump.c $(o)f-inst-decl.h
|
||||
|
||||
tests_src := tree_test.c filter_test.c trie_test.c
|
||||
tests_targets := $(tests_targets) $(tests-target-files)
|
||||
|
@ -11,7 +11,7 @@
|
||||
CF_HDR
|
||||
|
||||
#include "filter/f-inst.h"
|
||||
#include "filter/f-util.h"
|
||||
#include "filter/data.h"
|
||||
|
||||
CF_DEFINES
|
||||
|
||||
@ -418,7 +418,7 @@ assert_assign(struct f_lval *lval, struct f_inst *expr, const char *start, const
|
||||
}
|
||||
|
||||
checker = f_new_inst(FI_EQ, expr, getter);
|
||||
f_inst_next(setter, checker);
|
||||
setter->next = checker;
|
||||
|
||||
return assert_done(setter, start, end);
|
||||
}
|
||||
@ -550,7 +550,7 @@ one_decl:
|
||||
decls: /* EMPTY */ { $$ = NULL; }
|
||||
| one_decl ';' decls {
|
||||
$$ = $1;
|
||||
f_inst_next($$, $3);
|
||||
$$->next = $3;
|
||||
}
|
||||
;
|
||||
|
||||
@ -559,7 +559,7 @@ declsn: one_decl { $$.inst = $1; $$.count = 1; }
|
||||
| one_decl ';' declsn {
|
||||
$$ = $3;
|
||||
$$.count++;
|
||||
f_inst_next($$.inst, $1);
|
||||
$$.inst->next = $1;
|
||||
}
|
||||
;
|
||||
|
||||
@ -640,7 +640,7 @@ cmds: /* EMPTY */ { $$ = NULL; }
|
||||
;
|
||||
|
||||
cmds_int: cmd { $$[0] = $$[1] = $1; }
|
||||
| cmds_int cmd { $$[1] = $2; f_inst_next($1[1], $2); $$[0] = $1[0]; }
|
||||
| cmds_int cmd { $$[1] = $2; $1[1]->next = $2; $$[0] = $1[0]; }
|
||||
;
|
||||
|
||||
block:
|
||||
@ -803,11 +803,11 @@ bgp_path:
|
||||
;
|
||||
|
||||
bgp_path_tail:
|
||||
NUM bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .asn = $1, .kind = PM_ASN, }, }); f_inst_next($$, $2); }
|
||||
| NUM DDOT NUM bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .from = $1, .to = $3, .kind = PM_ASN_RANGE }, }); f_inst_next($$, $4); }
|
||||
| '*' bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_ASTERISK }, }); f_inst_next($$, $2); }
|
||||
| '?' bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_QUESTION }, }); f_inst_next($$, $2); }
|
||||
| bgp_path_expr bgp_path_tail { $$ = $1; f_inst_next($$, $2); }
|
||||
NUM bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .asn = $1, .kind = PM_ASN, }, }); $$->next = $2; }
|
||||
| NUM DDOT NUM bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .from = $1, .to = $3, .kind = PM_ASN_RANGE }, }); $$->next = $4; }
|
||||
| '*' bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_ASTERISK }, }); $$->next = $2; }
|
||||
| '?' bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_QUESTION }, }); $$->next = $2; }
|
||||
| bgp_path_expr bgp_path_tail { $$ = $1; $$->next = $2; }
|
||||
| { $$ = NULL; }
|
||||
;
|
||||
|
||||
@ -946,7 +946,7 @@ print_list: /* EMPTY */ { $$ = NULL; }
|
||||
| print_one { $$ = $1; }
|
||||
| print_one ',' print_list {
|
||||
if ($1) {
|
||||
f_inst_next($1, $3);
|
||||
$1->next = $3;
|
||||
$$ = $1;
|
||||
} else $$ = $3;
|
||||
}
|
||||
@ -957,7 +957,7 @@ var_listn: term {
|
||||
}
|
||||
| term ',' var_listn {
|
||||
$$ = $1;
|
||||
f_inst_next($$, $3);
|
||||
$$->next = $3;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* BIRD Internet Routing Daemon -- Filter utils
|
||||
* BIRD Internet Routing Daemon -- Dynamic data structures
|
||||
*
|
||||
* (c) 1999 Pavel Machek <pavel@ucw.cz>
|
||||
* (c) 2018--2019 Maria Matejka <mq@jmq.cz>
|
||||
@ -7,14 +7,10 @@
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
#ifndef _BIRD_F_UTIL_H_
|
||||
#define _BIRD_F_UTIL_H_
|
||||
#ifndef _BIRD_FILTER_DATA_H_
|
||||
#define _BIRD_FILTER_DATA_H_
|
||||
|
||||
/* IP prefix range structure */
|
||||
struct f_prefix {
|
||||
net_addr net; /* The matching prefix must match this net */
|
||||
u8 lo, hi; /* And its length must fit between lo and hi */
|
||||
};
|
||||
#include "nest/bird.h"
|
||||
|
||||
/* Type numbers must be in 0..0xff range */
|
||||
#define T_MASK 0xff
|
||||
@ -84,8 +80,6 @@ struct f_val {
|
||||
} val;
|
||||
};
|
||||
|
||||
#define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val));
|
||||
|
||||
/* Dynamic attribute definition (eattrs) */
|
||||
struct f_dynamic_attr {
|
||||
u8 type; /* EA type (EAF_*) */
|
||||
@ -113,6 +107,30 @@ struct f_static_attr {
|
||||
int readonly:1; /* Don't allow writing */
|
||||
};
|
||||
|
||||
/* Filter l-value type */
|
||||
enum f_lval_type {
|
||||
F_LVAL_VARIABLE,
|
||||
F_LVAL_PREFERENCE,
|
||||
F_LVAL_SA,
|
||||
F_LVAL_EA,
|
||||
};
|
||||
|
||||
/* Filter l-value */
|
||||
struct f_lval {
|
||||
enum f_lval_type type;
|
||||
union {
|
||||
const struct symbol *sym;
|
||||
struct f_dynamic_attr da;
|
||||
struct f_static_attr sa;
|
||||
};
|
||||
};
|
||||
|
||||
/* IP prefix range structure */
|
||||
struct f_prefix {
|
||||
net_addr net; /* The matching prefix must match this net */
|
||||
u8 lo, hi; /* And its length must fit between lo and hi */
|
||||
};
|
||||
|
||||
struct f_tree {
|
||||
struct f_tree *left, *right;
|
||||
struct f_val from, to;
|
128
filter/decl.m4
Normal file
128
filter/decl.m4
Normal file
@ -0,0 +1,128 @@
|
||||
m4_divert(-1)m4_dnl
|
||||
#
|
||||
# BIRD -- Construction of per-instruction structures
|
||||
#
|
||||
# (c) 2018 Maria Matejka <mq@jmq.cz>
|
||||
#
|
||||
# Can be freely distributed and used under the terms of the GNU GPL.
|
||||
#
|
||||
#
|
||||
# Global Diversions:
|
||||
# 4 enum fi_code
|
||||
# 1 struct f_inst_FI_...
|
||||
# 2 union in struct f_inst
|
||||
# 3 constructors
|
||||
#
|
||||
# Per-inst Diversions:
|
||||
# 11 content of struct f_inst_FI_...
|
||||
# 12 constructor arguments
|
||||
# 13 constructor body
|
||||
|
||||
# Flush the completed instruction
|
||||
|
||||
m4_define(FID_END, `m4_divert(-1)')
|
||||
|
||||
m4_define(FID_ZONE, `m4_divert($1) /* $2 for INST_NAME() */')
|
||||
m4_define(FID_STRUCT, `FID_ZONE(1, Per-instruction structure)')
|
||||
m4_define(FID_UNION, `FID_ZONE(2, Union member)')
|
||||
m4_define(FID_NEW, `FID_ZONE(3, Constructor)')
|
||||
m4_define(FID_ENUM, `FID_ZONE(4, Code enum)')
|
||||
|
||||
m4_define(FID_STRUCT_IN, `m4_divert(101)')
|
||||
m4_define(FID_NEW_ARGS, `m4_divert(102)')
|
||||
m4_define(FID_NEW_BODY, `m4_divert(103)')
|
||||
|
||||
m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[
|
||||
FID_ENUM
|
||||
INST_NAME(),
|
||||
FID_STRUCT
|
||||
struct f_inst_[[]]INST_NAME() {
|
||||
m4_undivert(101)
|
||||
};
|
||||
FID_UNION
|
||||
struct f_inst_[[]]INST_NAME() i_[[]]INST_NAME();
|
||||
FID_NEW
|
||||
static inline struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
|
||||
m4_undivert(102)
|
||||
) {
|
||||
struct f_inst *what_ = cfg_allocz(sizeof(struct f_inst));
|
||||
what_->fi_code = fi_code;
|
||||
what_->lineno = ifs->lino;
|
||||
what_->size = 1;
|
||||
struct f_inst_[[]]INST_NAME() *what UNUSED = &(what_->i_[[]]INST_NAME());
|
||||
m4_undivert(103)
|
||||
return what_;
|
||||
}
|
||||
FID_END
|
||||
]])')
|
||||
|
||||
m4_define(INST, `INST_FLUSH()m4_define([[INST_NAME]], [[$1]])')
|
||||
|
||||
m4_define(FID_MEMBER, `m4_dnl
|
||||
FID_STRUCT_IN
|
||||
$1 $2;
|
||||
FID_NEW_ARGS
|
||||
, $1 $2
|
||||
FID_NEW_BODY
|
||||
what->$2 = $2;
|
||||
FID_END')
|
||||
|
||||
m4_define(ARG, `FID_MEMBER(const struct f_inst *, f$1)
|
||||
FID_NEW_BODY
|
||||
for (const struct f_inst *child = f$1; child; child = child->next) what_->size += child->size;
|
||||
FID_END')
|
||||
m4_define(ARG_ANY, `FID_MEMBER(const struct f_inst *, f$1)
|
||||
FID_NEW_BODY
|
||||
for (const struct f_inst *child = f$1; child; child = child->next) what_->size += child->size;
|
||||
FID_END')
|
||||
m4_define(LINE, `FID_MEMBER(const struct f_inst *, f$1)')
|
||||
m4_define(LINEP, `FID_STRUCT_IN
|
||||
const struct f_line *fl$1;
|
||||
FID_END')
|
||||
m4_define(SYMBOL, `FID_MEMBER(const struct symbol *, sym)')
|
||||
m4_define(VALI, `FID_MEMBER(struct f_val, vali)')
|
||||
m4_define(VALP, `FID_MEMBER(const struct f_val *, valp)')
|
||||
m4_define(VAR, `m4_dnl
|
||||
FID_STRUCT_IN
|
||||
const struct f_val *valp;
|
||||
const struct symbol *sym;
|
||||
FID_NEW_ARGS
|
||||
, const struct symbol *sym
|
||||
FID_NEW_BODY
|
||||
what->valp = (what->sym = sym)->def;
|
||||
FID_END')
|
||||
m4_define(FRET, `FID_MEMBER(enum filter_return, fret)')
|
||||
m4_define(ECS, `FID_MEMBER(enum ec_subtype, ecs)')
|
||||
m4_define(RTC, `FID_MEMBER(const struct rtable_config *, rtc)')
|
||||
m4_define(STATIC_ATTR, `FID_MEMBER(struct f_static_attr, sa)')
|
||||
m4_define(DYNAMIC_ATTR, `FID_MEMBER(struct f_dynamic_attr, da)')
|
||||
m4_define(COUNT, `FID_MEMBER(uint, count)')
|
||||
m4_define(TREE, `FID_MEMBER(const struct f_tree *, tree)')
|
||||
m4_define(STRING, `FID_MEMBER(const char *, s)')
|
||||
|
||||
m4_m4wrap(`
|
||||
INST_FLUSH()
|
||||
m4_divert(0)
|
||||
/* Filter instruction codes */
|
||||
enum f_instruction_code {
|
||||
m4_undivert(4)
|
||||
};
|
||||
|
||||
/* Per-instruction structures */
|
||||
m4_undivert(1)
|
||||
|
||||
struct f_inst {
|
||||
const struct f_inst *next; /* Next instruction */
|
||||
enum f_instruction_code fi_code; /* Instruction code */
|
||||
int size; /* How many instructions are underneath */
|
||||
int lineno; /* Line number */
|
||||
union {
|
||||
m4_undivert(2)
|
||||
};
|
||||
};
|
||||
|
||||
/* Instruction constructors */
|
||||
m4_undivert(3)
|
||||
')
|
||||
|
||||
m4_changequote([[,]])
|
@ -109,15 +109,15 @@
|
||||
ARG_ANY(1);
|
||||
COUNT(2);
|
||||
|
||||
NEW(, [[
|
||||
uint len = 0;
|
||||
uint dyn = 0;
|
||||
for (const struct f_inst *tt = f1; tt; tt = tt->next, len++)
|
||||
if (tt->fi_code != FI_CONSTANT)
|
||||
dyn++;
|
||||
FID_NEW_BODY
|
||||
uint len = 0;
|
||||
uint dyn = 0;
|
||||
for (const struct f_inst *tt = f1; tt; tt = tt->next, len++)
|
||||
if (tt->fi_code != FI_CONSTANT)
|
||||
dyn++;
|
||||
|
||||
WHAT().count = len;
|
||||
]]);
|
||||
what->count = len;
|
||||
FID_END
|
||||
|
||||
if (vstk.cnt < what->count) /* TODO: make this check systematic */
|
||||
runtime("Construction of BGP path mask from %u elements must have at least that number of elements", what->count);
|
||||
@ -719,17 +719,17 @@
|
||||
/* Then push the arguments */
|
||||
LINE(1,1);
|
||||
|
||||
NEW(, [[
|
||||
if (sym->class != SYM_FUNCTION)
|
||||
cf_error("You can't call something which is not a function. Really.");
|
||||
FID_NEW_BODY
|
||||
if (sym->class != SYM_FUNCTION)
|
||||
cf_error("You can't call something which is not a function. Really.");
|
||||
|
||||
uint count = 0;
|
||||
for (const struct f_inst *inst = f1; inst; inst = inst->next)
|
||||
count++;
|
||||
|
||||
if (count != sym->aux2)
|
||||
cf_error("Function %s takes %u arguments, got %u.", sym->name, sym->aux2, count);
|
||||
]]);
|
||||
uint count = 0;
|
||||
for (const struct f_inst *inst = f1; inst; inst = inst->next)
|
||||
count++;
|
||||
|
||||
if (count != sym->aux2)
|
||||
cf_error("Function %s takes %u arguments, got %u.", sym->name, sym->aux2, count);
|
||||
FID_END
|
||||
}
|
||||
|
||||
INST(FI_DROP_RESULT, 1, 0) {
|
||||
|
131
filter/f-inst.h
131
filter/f-inst.h
@ -10,137 +10,21 @@
|
||||
#ifndef _BIRD_F_INST_H_
|
||||
#define _BIRD_F_INST_H_
|
||||
|
||||
#include "nest/bird.h"
|
||||
#include "conf/conf.h"
|
||||
#include "filter/filter.h"
|
||||
#include "filter/f-util.h"
|
||||
#include "filter/data.h"
|
||||
|
||||
/* Filter l-value type */
|
||||
enum f_lval_type {
|
||||
F_LVAL_VARIABLE,
|
||||
F_LVAL_PREFERENCE,
|
||||
F_LVAL_SA,
|
||||
F_LVAL_EA,
|
||||
};
|
||||
/* Include generated filter instruction declarations */
|
||||
#include "filter/f-inst-decl.h"
|
||||
|
||||
/* Filter l-value */
|
||||
struct f_lval {
|
||||
enum f_lval_type type;
|
||||
union {
|
||||
const struct symbol *sym;
|
||||
struct f_dynamic_attr da;
|
||||
struct f_static_attr sa;
|
||||
};
|
||||
};
|
||||
|
||||
/* Filter instruction declarations */
|
||||
#define FI__LIST \
|
||||
F(FI_NOP) \
|
||||
F(FI_ADD, ARG, ARG) \
|
||||
F(FI_SUBTRACT, ARG, ARG) \
|
||||
F(FI_MULTIPLY, ARG, ARG) \
|
||||
F(FI_DIVIDE, ARG, ARG) \
|
||||
F(FI_AND, ARG, LINE) \
|
||||
F(FI_OR, ARG, LINE) \
|
||||
F(FI_PAIR_CONSTRUCT, ARG, ARG) \
|
||||
F(FI_EC_CONSTRUCT, ARG, ARG, ECS) \
|
||||
F(FI_LC_CONSTRUCT, ARG, ARG, ARG) \
|
||||
F(FI_PATHMASK_CONSTRUCT, ARG, COUNT) \
|
||||
F(FI_NEQ, ARG, ARG) \
|
||||
F(FI_EQ, ARG, ARG) \
|
||||
F(FI_LT, ARG, ARG) \
|
||||
F(FI_LTE, ARG, ARG) \
|
||||
F(FI_NOT, ARG) \
|
||||
F(FI_MATCH, ARG, ARG) \
|
||||
F(FI_NOT_MATCH, ARG, ARG) \
|
||||
F(FI_DEFINED, ARG) \
|
||||
F(FI_TYPE, ARG) \
|
||||
F(FI_IS_V4, ARG) \
|
||||
F(FI_SET, ARG, SYMBOL) \
|
||||
F(FI_CONSTANT, VALI) \
|
||||
F(FI_VARIABLE, SYMBOL) \
|
||||
F(FI_CONSTANT_INDIRECT, VALP) \
|
||||
F(FI_PRINT, ARG) \
|
||||
F(FI_CONDITION, ARG, LINE, LINE) \
|
||||
F(FI_PRINT_AND_DIE, ARG, FRET) \
|
||||
F(FI_RTA_GET, SA) \
|
||||
F(FI_RTA_SET, ARG, SA) \
|
||||
F(FI_EA_GET, EA) \
|
||||
F(FI_EA_SET, ARG, EA) \
|
||||
F(FI_EA_UNSET, EA) \
|
||||
F(FI_PREF_GET) \
|
||||
F(FI_PREF_SET, ARG) \
|
||||
F(FI_LENGTH, ARG) \
|
||||
F(FI_ROA_MAXLEN, ARG) \
|
||||
F(FI_ROA_ASN, ARG) \
|
||||
F(FI_SADR_SRC, ARG) \
|
||||
F(FI_IP, ARG) \
|
||||
F(FI_ROUTE_DISTINGUISHER, ARG) \
|
||||
F(FI_AS_PATH_FIRST, ARG) \
|
||||
F(FI_AS_PATH_LAST, ARG) \
|
||||
F(FI_AS_PATH_LAST_NAG, ARG) \
|
||||
F(FI_RETURN, ARG) \
|
||||
F(FI_CALL, SYMBOL, LINE) \
|
||||
F(FI_DROP_RESULT, ARG) \
|
||||
F(FI_SWITCH, ARG, TREE) \
|
||||
F(FI_IP_MASK, ARG, ARG) \
|
||||
F(FI_PATH_PREPEND, ARG, ARG) \
|
||||
F(FI_CLIST_ADD, ARG, ARG) \
|
||||
F(FI_CLIST_DEL, ARG, ARG) \
|
||||
F(FI_CLIST_FILTER, ARG, ARG) \
|
||||
F(FI_ROA_CHECK_IMPLICIT, RTC) \
|
||||
F(FI_ROA_CHECK_EXPLICIT, ARG, ARG, RTC) \
|
||||
F(FI_FORMAT, ARG) \
|
||||
F(FI_ASSERT, ARG, STRING)
|
||||
|
||||
/* The enum itself */
|
||||
enum f_instruction_code {
|
||||
#define F(c, ...) c,
|
||||
FI__LIST
|
||||
#undef F
|
||||
FI__MAX,
|
||||
} PACKED;
|
||||
#define f_new_inst(...) MACRO_CONCAT_AFTER(f_new_inst_, MACRO_FIRST(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
/* Convert the instruction back to the enum name */
|
||||
const char *f_instruction_name(enum f_instruction_code fi);
|
||||
|
||||
struct f_inst;
|
||||
void f_inst_next(struct f_inst *first, const struct f_inst *append);
|
||||
struct f_inst *f_clear_local_vars(struct f_inst *decls);
|
||||
|
||||
#define FIA(x) , FIA_##x
|
||||
#define FIA_ARG const struct f_inst *
|
||||
#define FIA_LINE const struct f_inst *
|
||||
#define FIA_COUNT uint
|
||||
#define FIA_SYMBOL const struct symbol *
|
||||
#define FIA_VALI struct f_val
|
||||
#define FIA_VALP const struct f_val *
|
||||
#define FIA_FRET enum filter_return
|
||||
#define FIA_ECS enum ec_subtype
|
||||
#define FIA_SA struct f_static_attr
|
||||
#define FIA_EA struct f_dynamic_attr
|
||||
#define FIA_RTC const struct rtable_config *
|
||||
#define FIA_TREE const struct f_tree *
|
||||
#define FIA_STRING const char *
|
||||
#define F(c, ...) \
|
||||
struct f_inst *f_new_inst_##c(enum f_instruction_code MACRO_IFELSE(MACRO_ISLAST(__VA_ARGS__))()(MACRO_FOREACH(FIA, __VA_ARGS__)));
|
||||
FI__LIST
|
||||
#undef F
|
||||
#undef FIA_ARG
|
||||
#undef FIA_LINE
|
||||
#undef FIA_LINEP
|
||||
#undef FIA_COUNT
|
||||
#undef FIA_SYMBOL
|
||||
#undef FIA_VALI
|
||||
#undef FIA_VALP
|
||||
#undef FIA_FRET
|
||||
#undef FIA_ECS
|
||||
#undef FIA_SA
|
||||
#undef FIA_EA
|
||||
#undef FIA_RTC
|
||||
#undef FIA_STRING
|
||||
#undef FIA
|
||||
|
||||
#define f_new_inst(...) MACRO_CONCAT_AFTER(f_new_inst_, MACRO_FIRST(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
/* Flags for instructions */
|
||||
enum f_instruction_flags {
|
||||
FIF_PRINTED = 1, /* FI_PRINT_AND_DIE: message put in buffer */
|
||||
@ -202,7 +86,4 @@ struct f_bt_test_suite {
|
||||
const char *dsc; /* Description */
|
||||
};
|
||||
|
||||
/* Include the auto-generated structures */
|
||||
#include "filter/f-inst-struct.h"
|
||||
|
||||
#endif
|
||||
|
@ -17,22 +17,6 @@
|
||||
|
||||
#define P(a,b) ((a<<8) | b)
|
||||
|
||||
static const char * const f_instruction_name_str[] = {
|
||||
#define F(c,...) \
|
||||
[c] = #c,
|
||||
FI__LIST
|
||||
#undef F
|
||||
};
|
||||
|
||||
const char *
|
||||
f_instruction_name(enum f_instruction_code fi)
|
||||
{
|
||||
if (fi < FI__MAX)
|
||||
return f_instruction_name_str[fi];
|
||||
else
|
||||
bug("Got unknown instruction code: %d", fi);
|
||||
}
|
||||
|
||||
char *
|
||||
filter_name(struct filter *filter)
|
||||
{
|
||||
@ -56,18 +40,21 @@ struct filter *f_new_where(const struct f_inst *where)
|
||||
struct f_inst acc = {
|
||||
.fi_code = FI_PRINT_AND_DIE,
|
||||
.lineno = ifs->lino,
|
||||
.size = 1,
|
||||
.i_FI_PRINT_AND_DIE = { .fret = F_ACCEPT, },
|
||||
};
|
||||
|
||||
struct f_inst rej = {
|
||||
.fi_code = FI_PRINT_AND_DIE,
|
||||
.lineno = ifs->lino,
|
||||
.size = 1,
|
||||
.i_FI_PRINT_AND_DIE = { .fret = F_REJECT, },
|
||||
};
|
||||
|
||||
struct f_inst i = {
|
||||
.fi_code = FI_CONDITION,
|
||||
.lineno = ifs->lino,
|
||||
.size = 3,
|
||||
.i_FI_CONDITION = {
|
||||
.f1 = where,
|
||||
.f2 = &acc,
|
||||
|
@ -48,7 +48,7 @@
|
||||
#include "conf/conf.h"
|
||||
#include "filter/filter.h"
|
||||
#include "filter/f-inst.h"
|
||||
#include "filter/f-util.h"
|
||||
#include "filter/data.h"
|
||||
|
||||
#define CMP_ERROR 999
|
||||
|
||||
@ -64,6 +64,75 @@ struct filter_state {
|
||||
|
||||
void (*bt_assert_hook)(int result, const struct f_line_item *assert);
|
||||
|
||||
static const char * const f_instruction_name_str[] = {
|
||||
/* TODO: Make this better */
|
||||
[FI_ADD] = "FI_ADD",
|
||||
[FI_SUBTRACT] = "FI_SUBTRACT",
|
||||
[FI_MULTIPLY] = "FI_MULTIPLY",
|
||||
[FI_DIVIDE] = "FI_DIVIDE",
|
||||
[FI_AND] = "FI_AND",
|
||||
[FI_OR] = "FI_OR",
|
||||
[FI_PAIR_CONSTRUCT] = "FI_PAIR_CONSTRUCT",
|
||||
[FI_EC_CONSTRUCT] = "FI_EC_CONSTRUCT",
|
||||
[FI_LC_CONSTRUCT] = "FI_LC_CONSTRUCT",
|
||||
[FI_PATHMASK_CONSTRUCT] = "FI_PATHMASK_CONSTRUCT",
|
||||
[FI_NEQ] = "FI_NEQ",
|
||||
[FI_EQ] = "FI_EQ",
|
||||
[FI_LT] = "FI_LT",
|
||||
[FI_LTE] = "FI_LTE",
|
||||
[FI_NOT] = "FI_NOT",
|
||||
[FI_MATCH] = "FI_MATCH",
|
||||
[FI_NOT_MATCH] = "FI_NOT_MATCH",
|
||||
[FI_DEFINED] = "FI_DEFINED",
|
||||
[FI_TYPE] = "FI_TYPE",
|
||||
[FI_IS_V4] = "FI_IS_V4",
|
||||
[FI_SET] = "FI_SET",
|
||||
[FI_CONSTANT] = "FI_CONSTANT",
|
||||
[FI_VARIABLE] = "FI_VARIABLE",
|
||||
[FI_CONSTANT_INDIRECT] = "FI_CONSTANT_INDIRECT",
|
||||
[FI_PRINT] = "FI_PRINT",
|
||||
[FI_CONDITION] = "FI_CONDITION",
|
||||
[FI_PRINT_AND_DIE] = "FI_PRINT_AND_DIE",
|
||||
[FI_RTA_GET] = "FI_RTA_GET",
|
||||
[FI_RTA_SET] = "FI_RTA_SET",
|
||||
[FI_EA_GET] = "FI_EA_GET",
|
||||
[FI_EA_SET] = "FI_EA_SET",
|
||||
[FI_EA_UNSET] = "FI_EA_UNSET",
|
||||
[FI_PREF_GET] = "FI_PREF_GET",
|
||||
[FI_PREF_SET] = "FI_PREF_SET",
|
||||
[FI_LENGTH] = "FI_LENGTH",
|
||||
[FI_SADR_SRC] = "FI_SADR_SRC",
|
||||
[FI_ROA_MAXLEN] = "FI_ROA_MAXLEN",
|
||||
[FI_ROA_ASN] = "FI_ROA_ASN",
|
||||
[FI_IP] = "FI_IP",
|
||||
[FI_ROUTE_DISTINGUISHER] = "FI_ROUTE_DISTINGUISHER",
|
||||
[FI_AS_PATH_FIRST] = "FI_AS_PATH_FIRST",
|
||||
[FI_AS_PATH_LAST] = "FI_AS_PATH_LAST",
|
||||
[FI_AS_PATH_LAST_NAG] = "FI_AS_PATH_LAST_NAG",
|
||||
[FI_RETURN] = "FI_RETURN",
|
||||
[FI_CALL] = "FI_CALL",
|
||||
[FI_DROP_RESULT] = "FI_DROP_RESULT",
|
||||
[FI_SWITCH] = "FI_SWITCH",
|
||||
[FI_IP_MASK] = "FI_IP_MASK",
|
||||
[FI_PATH_PREPEND] = "FI_PATH_PREPEND",
|
||||
[FI_CLIST_ADD] = "FI_CLIST_ADD",
|
||||
[FI_CLIST_DEL] = "FI_CLIST_DEL",
|
||||
[FI_CLIST_FILTER] = "FI_CLIST_FILTER",
|
||||
[FI_ROA_CHECK_IMPLICIT] = "FI_ROA_CHECK_IMPLICIT",
|
||||
[FI_ROA_CHECK_EXPLICIT] = "FI_ROA_CHECK_EXPLICIT",
|
||||
[FI_FORMAT] = "FI_FORMAT",
|
||||
[FI_ASSERT] = "FI_ASSERT",
|
||||
};
|
||||
|
||||
const char *
|
||||
f_instruction_name(enum f_instruction_code fi)
|
||||
{
|
||||
if (fi < (sizeof(f_instruction_name_str) / sizeof(f_instruction_name_str[0])))
|
||||
return f_instruction_name_str[fi];
|
||||
else
|
||||
bug("Got unknown instruction code: %d", fi);
|
||||
}
|
||||
|
||||
/* Special undef value for paths and clists */
|
||||
static inline int
|
||||
undef_value(struct f_val v)
|
||||
@ -615,18 +684,6 @@ val_format_str(struct filter_state *fs, struct f_val *v) {
|
||||
|
||||
static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;
|
||||
|
||||
static uint
|
||||
inst_line_size(const struct f_inst *what_)
|
||||
{
|
||||
uint cnt = 0;
|
||||
for ( ; what_; what_ = what_->next) {
|
||||
switch (what_->fi_code) {
|
||||
#include "filter/f-inst-line-size.c"
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
#define INDENT (((const char *) f_dump_line_indent_str) + sizeof(f_dump_line_indent_str) - (indent) - 1)
|
||||
static const char f_dump_line_indent_str[] = " ";
|
||||
|
||||
@ -685,7 +742,8 @@ f_postfixify_concat(const struct f_inst * const inst[], uint count)
|
||||
{
|
||||
uint len = 0;
|
||||
for (uint i=0; i<count; i++)
|
||||
len += inst_line_size(inst[i]);
|
||||
for (const struct f_inst *what = inst[i]; what; what = what->next)
|
||||
len += what->size;
|
||||
|
||||
struct f_line *out = cfg_allocz(sizeof(struct f_line) + sizeof(struct f_line_item)*len);
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "test/bt-utils.h"
|
||||
|
||||
#include "filter/filter.h"
|
||||
#include "filter/f-util.h"
|
||||
#include "filter/data.h"
|
||||
#include "filter/f-inst.h"
|
||||
#include "conf/conf.h"
|
||||
|
||||
|
@ -63,10 +63,11 @@ m4_define(TREE, `')
|
||||
m4_define(STRING, `')
|
||||
m4_define(COUNT, `')
|
||||
m4_define(POSTFIXIFY, `')
|
||||
m4_define(LINE_SIZE, `')
|
||||
m4_define(SAME, `')
|
||||
m4_define(STRUCT, `')
|
||||
m4_define(NEW, `')
|
||||
m4_define(FID_STRUCT_IN, `m4_divert(-1)')
|
||||
m4_define(FID_NEW_ARGS, `m4_divert(-1)')
|
||||
m4_define(FID_NEW_BODY, `m4_divert(-1)')
|
||||
m4_define(FID_END, `m4_divert(2)')
|
||||
|
||||
m4_m4wrap(`
|
||||
INST_FLUSH()
|
||||
|
@ -1,41 +0,0 @@
|
||||
m4_divert(-1)m4_dnl
|
||||
#
|
||||
# BIRD -- Line size counting
|
||||
#
|
||||
# (c) 2018 Maria Matejka <mq@jmq.cz>
|
||||
#
|
||||
# Can be freely distributed and used under the terms of the GNU GPL.
|
||||
#
|
||||
|
||||
# Common aliases
|
||||
m4_define(DNL, `m4_dnl')
|
||||
|
||||
m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[
|
||||
m4_divert(1)
|
||||
case INST_NAME():
|
||||
cnt += 1;
|
||||
#define what ((const struct f_inst_]]INST_NAME()[[ *) &(what_->i_]]INST_NAME()[[))
|
||||
m4_undivert(2)
|
||||
#undef what
|
||||
break;
|
||||
m4_divert(-1)
|
||||
]])')
|
||||
m4_define(INST, `INST_FLUSH()m4_define([[INST_NAME]], [[$1]])')
|
||||
|
||||
m4_define(ARG, `m4_divert(2)cnt += inst_line_size(what->f$1);
|
||||
m4_divert(-1)')
|
||||
m4_define(ARG_T, `m4_divert(2)cnt += inst_line_size(what->f$1);
|
||||
m4_divert(-1)')
|
||||
m4_define(ARG_ANY, `m4_divert(2)cnt += inst_line_size(what->f$1);
|
||||
m4_divert(-1)')
|
||||
m4_define(LINE_SIZE, `m4_divert(2)$1m4_divert(-1)')
|
||||
|
||||
m4_m4wrap(`
|
||||
INST_FLUSH()
|
||||
m4_divert(0)DNL
|
||||
m4_undivert(1)
|
||||
|
||||
default: bug( "Unknown instruction %d (%c)", what_->fi_code, what_->fi_code & 0xff);
|
||||
')
|
||||
|
||||
m4_changequote([[,]])
|
@ -1,78 +0,0 @@
|
||||
m4_divert(-1)m4_dnl
|
||||
#
|
||||
# BIRD -- Construction of per-instruction structures
|
||||
#
|
||||
# (c) 2018 Maria Matejka <mq@jmq.cz>
|
||||
#
|
||||
# Can be freely distributed and used under the terms of the GNU GPL.
|
||||
#
|
||||
#
|
||||
# Diversions:
|
||||
# 1 for prepared output
|
||||
# 2 for function arguments
|
||||
# 3 for function body
|
||||
|
||||
# Common aliases
|
||||
m4_define(DNL, `m4_dnl')
|
||||
|
||||
m4_define(FNSTOP, `m4_divert(-1)')
|
||||
m4_define(FNOUT, `m4_divert(1)')
|
||||
m4_define(FNARG, `m4_divert(2)')
|
||||
m4_define(FNBODY, `m4_divert(3)')
|
||||
|
||||
m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[
|
||||
FNOUT()DNL
|
||||
struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
|
||||
m4_undivert(2)
|
||||
) {
|
||||
struct f_inst *what = cfg_allocz(sizeof(struct f_inst));
|
||||
what->fi_code = fi_code;
|
||||
what->lineno = ifs->lino;
|
||||
m4_undivert(3)
|
||||
return what;
|
||||
}
|
||||
FNSTOP()
|
||||
]]DNL
|
||||
)')
|
||||
|
||||
m4_define(INST, `INST_FLUSH()m4_define([[INST_NAME]], [[$1]])')
|
||||
|
||||
m4_define(WHAT, `what->i_[[]]INST_NAME()')
|
||||
|
||||
m4_define(FNMETAARG, `FNARG(), $1 $2
|
||||
FNBODY() WHAT().$2 = $2;
|
||||
FNSTOP()')
|
||||
m4_define(ARG, `FNMETAARG(const struct f_inst *, f$1)')
|
||||
m4_define(ARG_ANY, `FNMETAARG(const struct f_inst *, f$1)')
|
||||
m4_define(LINE, `FNMETAARG(const struct f_inst *, f$1)')
|
||||
m4_define(SYMBOL, `FNMETAARG(const struct symbol *, sym)')
|
||||
m4_define(VALI, `FNMETAARG(struct f_val, vali)')
|
||||
m4_define(VALP, `FNMETAARG(const struct f_val *, valp)')
|
||||
m4_define(VAR, `FNARG(), const struct symbol * sym
|
||||
FNBODY() WHAT().valp = (WHAT().sym = sym)->def;
|
||||
FNSTOP()')
|
||||
m4_define(FRET, `FNMETAARG(enum filter_return, fret)')
|
||||
m4_define(ECS, `FNMETAARG(enum ec_subtype, ecs)')
|
||||
m4_define(RTC, `FNMETAARG(const struct rtable_config *, rtc)')
|
||||
m4_define(STATIC_ATTR, `FNMETAARG(struct f_static_attr, sa)')
|
||||
m4_define(DYNAMIC_ATTR, `FNMETAARG(struct f_dynamic_attr, da)')
|
||||
m4_define(COUNT, `FNMETAARG(uint, count)')
|
||||
m4_define(TREE, `FNMETAARG(const struct f_tree *, tree)')
|
||||
m4_define(STRING, `FNMETAARG(const char *, s)')
|
||||
m4_define(NEW, `FNARG()$1
|
||||
FNBODY()$2
|
||||
FNSTOP()')
|
||||
|
||||
m4_m4wrap(`
|
||||
INST_FLUSH()
|
||||
m4_divert(0)
|
||||
#include "nest/bird.h"
|
||||
#include "conf/conf.h"
|
||||
#include "filter/filter.h"
|
||||
#include "filter/f-inst.h"
|
||||
|
||||
m4_undivert(1)
|
||||
|
||||
')
|
||||
|
||||
m4_changequote([[,]])
|
@ -1,73 +0,0 @@
|
||||
m4_divert(-1)m4_dnl
|
||||
#
|
||||
# BIRD -- Definition of per-instruction structures
|
||||
#
|
||||
# (c) 2018 Maria Matejka <mq@jmq.cz>
|
||||
#
|
||||
# Can be freely distributed and used under the terms of the GNU GPL.
|
||||
#
|
||||
|
||||
# Common aliases
|
||||
m4_define(DNL, `m4_dnl')
|
||||
|
||||
m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[
|
||||
m4_divert(1)
|
||||
struct f_inst_[[]]INST_NAME() {
|
||||
m4_undivert(2)
|
||||
};
|
||||
m4_divert(3)
|
||||
struct f_inst_[[]]INST_NAME() i_[[]]INST_NAME();
|
||||
m4_divert(-1)
|
||||
]])')
|
||||
m4_define(INST, `INST_FLUSH()m4_define([[INST_NAME]], [[$1]])')
|
||||
|
||||
m4_define(ARG, `m4_divert(2)const struct f_inst *f$1;
|
||||
m4_divert(-1)')
|
||||
m4_define(ARG_ANY, `m4_divert(2)const struct f_inst *f$1;
|
||||
m4_divert(-1)')
|
||||
m4_define(LINE, `m4_divert(2)const struct f_inst *f$1;
|
||||
m4_divert(-1)')
|
||||
m4_define(LINEP, `m4_divert(2)const struct f_line *fl$1;
|
||||
m4_divert(-1)')
|
||||
m4_define(SYMBOL, `m4_divert(2)const struct symbol *sym;
|
||||
m4_divert(-1)')
|
||||
m4_define(VALI, `m4_divert(2)struct f_val vali;
|
||||
m4_divert(-1)')
|
||||
m4_define(VALP, `m4_divert(2)const struct f_val *valp;
|
||||
m4_divert(-1)')
|
||||
m4_define(VAR, `VALP()SYMBOL()')
|
||||
m4_define(FRET, `m4_divert(2)enum filter_return fret;
|
||||
m4_divert(-1)')
|
||||
m4_define(ECS, `m4_divert(2)enum ec_subtype ecs;
|
||||
m4_divert(-1)')
|
||||
m4_define(RTC, `m4_divert(2)const struct rtable_config *rtc;
|
||||
m4_divert(-1)')
|
||||
m4_define(STATIC_ATTR, `m4_divert(2)struct f_static_attr sa;
|
||||
m4_divert(-1)')
|
||||
m4_define(DYNAMIC_ATTR, `m4_divert(2)struct f_dynamic_attr da;
|
||||
m4_divert(-1)')
|
||||
m4_define(COUNT, `m4_divert(2)uint count;
|
||||
m4_divert(-1)')
|
||||
m4_define(TREE, `m4_divert(2)const struct f_tree *tree;
|
||||
m4_divert(-1)')
|
||||
m4_define(STRING, `m4_divert(2)const char *s;
|
||||
m4_divert(-1)')
|
||||
m4_define(STRUCT, `m4_divert(2)$1
|
||||
m4_divert(-1)')
|
||||
|
||||
m4_m4wrap(`
|
||||
INST_FLUSH()
|
||||
m4_divert(0)DNL
|
||||
m4_undivert(1)
|
||||
|
||||
struct f_inst {
|
||||
const struct f_inst *next; /* Next instruction */
|
||||
enum f_instruction_code fi_code; /* Instruction code */
|
||||
int lineno; /* Line number */
|
||||
union {
|
||||
m4_undivert(3)
|
||||
};
|
||||
};
|
||||
')
|
||||
|
||||
m4_changequote([[,]])
|
@ -10,7 +10,7 @@
|
||||
#include "nest/bird.h"
|
||||
#include "conf/conf.h"
|
||||
#include "filter/filter.h"
|
||||
#include "filter/f-util.h"
|
||||
#include "filter/data.h"
|
||||
|
||||
/**
|
||||
* find_tree
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "test/bt-utils.h"
|
||||
|
||||
#include "filter/filter.h"
|
||||
#include "filter/f-util.h"
|
||||
#include "filter/data.h"
|
||||
#include "conf/conf.h"
|
||||
|
||||
#define MAX_TREE_HEIGHT 13
|
||||
|
@ -73,7 +73,7 @@
|
||||
#include "lib/string.h"
|
||||
#include "conf/conf.h"
|
||||
#include "filter/filter.h"
|
||||
#include "filter/f-util.h"
|
||||
#include "filter/data.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "test/bt-utils.h"
|
||||
|
||||
#include "filter/filter.h"
|
||||
#include "filter/f-util.h"
|
||||
#include "filter/data.h"
|
||||
#include "conf/conf.h"
|
||||
|
||||
#define TESTS_NUM 10
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "lib/resource.h"
|
||||
#include "lib/unaligned.h"
|
||||
#include "lib/string.h"
|
||||
#include "filter/f-util.h"
|
||||
#include "filter/data.h"
|
||||
|
||||
// static inline void put_as(byte *data, u32 as) { put_u32(data, as); }
|
||||
// static inline u32 get_as(byte *data) { return get_u32(data); }
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "lib/string.h"
|
||||
#include "lib/resource.h"
|
||||
#include "filter/filter.h"
|
||||
#include "filter/f-util.h"
|
||||
#include "filter/data.h"
|
||||
|
||||
extern int shutting_down;
|
||||
extern int configuring;
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include "lib/string.h"
|
||||
#include "conf/conf.h"
|
||||
#include "filter/filter.h"
|
||||
#include "filter/f-util.h"
|
||||
#include "filter/data.h"
|
||||
#include "lib/hash.h"
|
||||
#include "lib/string.h"
|
||||
#include "lib/alloca.h"
|
||||
|
@ -139,7 +139,7 @@ stat_route:
|
||||
stat_route_item:
|
||||
cmd {
|
||||
if (this_srt_last_cmd)
|
||||
f_inst_next(this_srt_last_cmd, $1);
|
||||
this_srt_last_cmd->next = $1;
|
||||
else
|
||||
this_srt_cmds = $1;
|
||||
this_srt_last_cmd = $1;
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "nest/locks.h"
|
||||
#include "conf/conf.h"
|
||||
#include "filter/filter.h"
|
||||
#include "filter/f-util.h"
|
||||
#include "filter/data.h"
|
||||
|
||||
#include "unix.h"
|
||||
#include "krt.h"
|
||||
|
Loading…
Reference in New Issue
Block a user