]>
Commit | Line | Data |
---|---|---|
9b46748d MM |
1 | /* |
2 | * BIRD Internet Routing Daemon -- Filter instructions | |
3 | * | |
8bdb05ed | 4 | * (c) 1999 Pavel Machek <pavel@ucw.cz> |
9b46748d MM |
5 | * (c) 2018--2019 Maria Matejka <mq@jmq.cz> |
6 | * | |
7 | * Can be freely distributed and used under the terms of the GNU GPL. | |
e1ac6f1e MM |
8 | * |
9 | * Filter interpreter data structures and internal API. | |
0da06b71 | 10 | * See filter/f-inst.c for documentation. |
9b46748d MM |
11 | */ |
12 | ||
8bdb05ed MM |
13 | #ifndef _BIRD_F_INST_H_ |
14 | #define _BIRD_F_INST_H_ | |
15 | ||
4f082dfa MM |
16 | #include "nest/bird.h" |
17 | #include "conf/conf.h" | |
8bdb05ed | 18 | #include "filter/filter.h" |
4f082dfa | 19 | #include "filter/data.h" |
d06a875b | 20 | #include "lib/buffer.h" |
ff2ca10c | 21 | #include "lib/flowspec.h" |
fc354788 | 22 | #include "lib/string.h" |
8bdb05ed | 23 | |
ea4f55e3 MM |
24 | /* Flags for instructions */ |
25 | enum f_instruction_flags { | |
26bc4f99 | 26 | FIF_RECURSIVE = 1, /* FI_CALL: function is directly recursive */ |
ea4f55e3 MM |
27 | } PACKED; |
28 | ||
4f082dfa | 29 | /* Include generated filter instruction declarations */ |
87bd7cd7 | 30 | #include "filter/inst-gen.h" |
8bdb05ed | 31 | |
4f082dfa | 32 | #define f_new_inst(...) MACRO_CONCAT_AFTER(f_new_inst_, MACRO_FIRST(__VA_ARGS__))(__VA_ARGS__) |
9b46748d MM |
33 | |
34 | /* Convert the instruction back to the enum name */ | |
87512e97 OZ |
35 | const char *f_instruction_name_(enum f_instruction_code fi); |
36 | static inline const char *f_instruction_name(enum f_instruction_code fi) | |
37 | { return f_instruction_name_(fi) + 3; } | |
9b46748d | 38 | |
f0d13960 OZ |
39 | |
40 | int f_const_promotion_(struct f_inst *arg, enum f_type want, int update); | |
41 | ||
42 | static inline int f_const_promotion(struct f_inst *arg, enum f_type want) | |
43 | { return f_const_promotion_(arg, want, 1); } | |
44 | ||
45 | static inline int f_try_const_promotion(struct f_inst *arg, enum f_type want) | |
46 | { return f_const_promotion_(arg, want, 0); } | |
47 | ||
48 | ||
93d6096c OZ |
49 | struct f_arg { |
50 | struct symbol *arg; | |
51 | struct f_arg *next; | |
52 | }; | |
53 | ||
8bdb05ed | 54 | /* Filter structures for execution */ |
8bdb05ed MM |
55 | /* Line of instructions to be unconditionally executed one after another */ |
56 | struct f_line { | |
57 | uint len; /* Line length */ | |
f249d0b8 | 58 | u8 args; /* Function: Args required */ |
96d757c1 | 59 | u8 vars; |
a2527ee5 | 60 | u8 results; /* Results left on stack: cmd -> 0, term -> 1 */ |
062ff656 | 61 | u8 return_type; /* Type which the function returns */ |
93d6096c | 62 | struct f_arg *arg_list; |
8bdb05ed MM |
63 | struct f_line_item items[0]; /* The items themselves */ |
64 | }; | |
9b46748d | 65 | |
8bdb05ed | 66 | /* Convert the f_inst infix tree to the f_line structures */ |
a2527ee5 OZ |
67 | struct f_line *f_linearize_concat(const struct f_inst * const inst[], uint count, uint results); |
68 | static inline struct f_line *f_linearize(const struct f_inst *root, uint results) | |
69 | { return f_linearize_concat(&root, 1, results); } | |
8bdb05ed | 70 | |
ea4f55e3 MM |
71 | void f_dump_line(const struct f_line *, uint indent); |
72 | ||
d06a875b OZ |
73 | |
74 | /* Recursive iteration over filter instructions */ | |
75 | ||
76 | struct filter_iterator { | |
77 | BUFFER_(const struct f_line *) lines; | |
78 | }; | |
79 | ||
80 | void f_add_lines(const struct f_line_item *what, struct filter_iterator *fit); | |
81 | ||
82 | #define FILTER_ITERATE_INIT(fit, filter, pool) \ | |
83 | ({ \ | |
84 | BUFFER_INIT((fit)->lines, (pool), 32); \ | |
85 | BUFFER_PUSH((fit)->lines) = (filter)->root; \ | |
86 | }) | |
87 | ||
88 | #define FILTER_ITERATE(fit, fi) ({ \ | |
89 | const struct f_line *fl_; \ | |
90 | while (!BUFFER_EMPTY((fit)->lines)) \ | |
91 | { \ | |
92 | BUFFER_POP((fit)->lines); \ | |
93 | fl_ = (fit)->lines.data[(fit)->lines.used]; \ | |
94 | for (uint i_ = 0; i_ < fl_->len; i_++) \ | |
95 | { \ | |
96 | const struct f_line_item *fi = &fl_->items[i_]; \ | |
97 | f_add_lines(fi, (fit)); | |
98 | ||
99 | #define FILTER_ITERATE_END } } }) | |
100 | ||
101 | #define FILTER_ITERATE_CLEANUP(fit) \ | |
102 | ({ \ | |
103 | mb_free((fit)->lines.data); \ | |
104 | memset((fit), 0, sizeof(struct filter_iterator)); \ | |
105 | }) | |
106 | ||
107 | ||
63f49457 | 108 | struct filter *f_new_where(struct f_inst *); |
7395b97d | 109 | struct f_inst *f_dispatch_method(struct symbol *sym, struct f_inst *obj, struct f_inst *args, int skip); |
cc1099a0 | 110 | struct f_inst *f_dispatch_method_x(const char *name, enum f_type t, struct f_inst *obj, struct f_inst *args); |
21faa54e | 111 | struct f_inst *f_for_cycle(struct symbol *var, struct f_inst *term, struct f_inst *block); |
fdd39c81 | 112 | struct f_inst *f_print(struct f_inst *vars, int flush, enum filter_return fret); |
21faa54e | 113 | |
78976974 MM |
114 | static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, enum f_type f_type, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */ |
115 | { return (struct f_dynamic_attr) { .type = type, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */ | |
116 | static inline struct f_dynamic_attr f_new_dynamic_attr_bit(u8 bit, enum f_type f_type, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */ | |
117 | { return (struct f_dynamic_attr) { .type = EAF_TYPE_BITFIELD, .bit = bit, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */ | |
8bdb05ed MM |
118 | static inline struct f_static_attr f_new_static_attr(int f_type, int code, int readonly) |
119 | { return (struct f_static_attr) { .f_type = f_type, .sa_code = code, .readonly = readonly }; } | |
8bdb05ed | 120 | |
a0fb0eaa | 121 | static inline int f_type_attr(int f_type) { |
122 | switch (f_type) { | |
123 | case T_INT: return EAF_TYPE_INT; | |
124 | case T_IP: return EAF_TYPE_IP_ADDRESS; | |
125 | case T_QUAD: return EAF_TYPE_ROUTER_ID; | |
126 | case T_PATH: return EAF_TYPE_AS_PATH; | |
127 | case T_CLIST: return EAF_TYPE_INT_SET; | |
128 | case T_ECLIST: return EAF_TYPE_EC_SET; | |
129 | case T_LCLIST: return EAF_TYPE_LC_SET; | |
130 | case T_BYTESTRING: return EAF_TYPE_OPAQUE; | |
131 | default: | |
132 | cf_error("Custom route attribute of unsupported type"); | |
133 | } | |
134 | } | |
135 | ||
8bdb05ed MM |
136 | /* Hook for call bt_assert() function in configuration */ |
137 | extern void (*bt_assert_hook)(int result, const struct f_line_item *assert); | |
138 | ||
139 | /* Bird Tests */ | |
140 | struct f_bt_test_suite { | |
141 | node n; /* Node in config->tests */ | |
0b39b1cb MM |
142 | const struct f_line *fn; /* Root of function */ |
143 | const struct f_line *cmp; /* Compare to this function */ | |
8bdb05ed MM |
144 | const char *fn_name; /* Name of test */ |
145 | const char *dsc; /* Description */ | |
132529ce | 146 | int result; /* Desired result */ |
9b46748d MM |
147 | }; |
148 | ||
8bdb05ed | 149 | #endif |