]>
Commit | Line | Data |
---|---|---|
58ef912c MM |
1 | /* |
2 | * BIRD Internet Routing Daemon -- Protocols | |
3 | * | |
7293c5dd | 4 | * (c) 1998--2000 Martin Mares <mj@ucw.cz> |
58ef912c MM |
5 | * |
6 | * Can be freely distributed and used under the terms of the GNU GPL. | |
7 | */ | |
8 | ||
9 | #ifndef _BIRD_PROTOCOL_H_ | |
10 | #define _BIRD_PROTOCOL_H_ | |
11 | ||
2326b001 | 12 | #include "lib/lists.h" |
1feea03e | 13 | #include "lib/resource.h" |
f4a60a9b | 14 | #include "lib/event.h" |
f4a60a9b | 15 | #include "nest/route.h" |
4cdd0784 | 16 | #include "conf/conf.h" |
58ef912c | 17 | |
2326b001 | 18 | struct iface; |
9a158361 | 19 | struct ifa; |
dca75fd7 | 20 | struct rtable; |
2326b001 MM |
21 | struct rte; |
22 | struct neighbor; | |
1b769b08 | 23 | struct rta; |
8c43696d | 24 | struct network; |
31b3e1bb | 25 | struct proto_config; |
f4a60a9b OZ |
26 | struct channel_limit; |
27 | struct channel_config; | |
31b3e1bb MM |
28 | struct config; |
29 | struct proto; | |
f4a60a9b | 30 | struct channel; |
bb027be1 | 31 | struct ea_list; |
3991d84e | 32 | struct eattr; |
ae97b946 | 33 | struct symbol; |
2326b001 | 34 | |
f4a60a9b | 35 | |
58ef912c MM |
36 | /* |
37 | * Routing Protocol | |
38 | */ | |
39 | ||
ee7e2ffd JMM |
40 | enum protocol_class { |
41 | PROTOCOL_NONE, | |
42 | PROTOCOL_BABEL, | |
43 | PROTOCOL_BFD, | |
44 | PROTOCOL_BGP, | |
45 | PROTOCOL_DEVICE, | |
46 | PROTOCOL_DIRECT, | |
47 | PROTOCOL_KERNEL, | |
48 | PROTOCOL_OSPF, | |
863ecfc7 | 49 | PROTOCOL_MRT, |
82b74253 | 50 | PROTOCOL_PERF, |
ee7e2ffd JMM |
51 | PROTOCOL_PIPE, |
52 | PROTOCOL_RADV, | |
53 | PROTOCOL_RIP, | |
54 | PROTOCOL_RPKI, | |
55 | PROTOCOL_STATIC, | |
56 | PROTOCOL__MAX | |
57 | }; | |
58 | ||
59 | extern struct protocol *class_to_protocol[PROTOCOL__MAX]; | |
60 | ||
58ef912c | 61 | struct protocol { |
a5f1a60e | 62 | node n; |
58ef912c | 63 | char *name; |
d272fe22 | 64 | char *template; /* Template for automatic generation of names */ |
4ba84ebc | 65 | int name_counter; /* Counter for automatic name generation */ |
ee7e2ffd | 66 | enum protocol_class class; /* Machine readable protocol class */ |
2bbc3083 | 67 | uint preference; /* Default protocol preference */ |
f4a60a9b OZ |
68 | uint channel_mask; /* Mask of accepted channel types (NB_*) */ |
69 | uint proto_size; /* Size of protocol data structure */ | |
70 | uint config_size; /* Size of protocol config data structure */ | |
58ef912c | 71 | |
31b3e1bb MM |
72 | void (*preconfig)(struct protocol *, struct config *); /* Just before configuring */ |
73 | void (*postconfig)(struct proto_config *); /* After configuring each instance */ | |
74 | struct proto * (*init)(struct proto_config *); /* Create new instance */ | |
50fe90ed | 75 | int (*reconfigure)(struct proto *, struct proto_config *); /* Try to reconfigure instance, returns success */ |
31b3e1bb MM |
76 | void (*dump)(struct proto *); /* Debugging dump */ |
77 | int (*start)(struct proto *); /* Start the instance */ | |
78 | int (*shutdown)(struct proto *); /* Stop the instance */ | |
cfe34a31 | 79 | void (*cleanup)(struct proto *); /* Called after shutdown when protocol became hungry/down */ |
9685deb9 | 80 | void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */ |
13c0be19 | 81 | void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */ |
258be565 | 82 | int (*get_attr)(const struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */ |
b8113a5e | 83 | void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */ |
a7f23f58 | 84 | void (*copy_config)(struct proto_config *, struct proto_config *); /* Copy config from given protocol instance */ |
58ef912c MM |
85 | }; |
86 | ||
4a23ede2 MM |
87 | void protos_build(void); /* Called from sysdep to initialize protocols */ |
88 | void proto_build(struct protocol *); /* Called from protocol to register itself */ | |
31b3e1bb | 89 | void protos_preconfig(struct config *); |
bf1aec97 | 90 | void protos_commit(struct config *new, struct config *old, int force_restart, int type); |
e0835db4 | 91 | struct proto * proto_spawn(struct proto_config *cf, uint disabled); |
87d2be86 | 92 | void protos_dump_all(void); |
a5f1a60e | 93 | |
3991d84e MM |
94 | #define GA_UNKNOWN 0 /* Attribute not recognized */ |
95 | #define GA_NAME 1 /* Result = name */ | |
96 | #define GA_FULL 2 /* Result = both name and value */ | |
58ef912c MM |
97 | |
98 | /* | |
99 | * Known protocols | |
100 | */ | |
101 | ||
2638249d | 102 | extern struct protocol |
863ecfc7 | 103 | proto_device, proto_radv, proto_rip, proto_static, proto_mrt, |
82b74253 MM |
104 | proto_ospf, proto_perf, |
105 | proto_pipe, proto_bgp, proto_bfd, proto_babel, proto_rpki; | |
58ef912c MM |
106 | |
107 | /* | |
108 | * Routing Protocol Instance | |
109 | */ | |
110 | ||
31b3e1bb MM |
111 | struct proto_config { |
112 | node n; | |
113 | struct config *global; /* Global configuration data */ | |
1d2664a4 MM |
114 | struct protocol *protocol; /* Protocol */ |
115 | struct proto *proto; /* Instance we've created */ | |
e0835db4 | 116 | struct proto_config *parent; /* Parent proto_config for dynamic protocols */ |
fd9f0c06 MM |
117 | const char *name; |
118 | const char *dsc; | |
a7f23f58 | 119 | int class; /* SYM_PROTO or SYM_TEMPLATE */ |
f4a60a9b OZ |
120 | u8 net_type; /* Protocol network type (NET_*), 0 for undefined */ |
121 | u8 disabled; /* Protocol enabled/disabled by default */ | |
18f70a62 | 122 | u8 vrf_set; /* Related VRF instance (below) is defined */ |
cf31112f | 123 | u32 debug, mrtdump; /* Debugging bitfields, both use D_* constants */ |
4cdd0784 | 124 | u32 router_id; /* Protocol specific router ID */ |
f4a60a9b OZ |
125 | |
126 | list channels; /* List of channel configs (struct channel_config) */ | |
943478b0 | 127 | struct iface *vrf; /* Related VRF instance, NULL if global */ |
31b3e1bb | 128 | |
a7f23f58 OZ |
129 | /* Check proto_reconfigure() and proto_copy_config() after changing struct proto_config */ |
130 | ||
31b3e1bb MM |
131 | /* Protocol-specific data follow... */ |
132 | }; | |
133 | ||
ebecb6f6 | 134 | /* Protocol statistics */ |
925fe2d3 OZ |
135 | struct proto_stats { |
136 | /* Import - from protocol to core */ | |
137 | u32 imp_routes; /* Number of routes successfully imported to the (adjacent) routing table */ | |
15550957 | 138 | u32 filt_routes; /* Number of routes rejected in import filter but kept in the routing table */ |
e1c275d8 | 139 | u32 pref_routes; /* Number of routes selected as best in the (adjacent) routing table */ |
925fe2d3 OZ |
140 | u32 imp_updates_received; /* Number of route updates received */ |
141 | u32 imp_updates_invalid; /* Number of route updates rejected as invalid */ | |
142 | u32 imp_updates_filtered; /* Number of route updates rejected by filters */ | |
143 | u32 imp_updates_ignored; /* Number of route updates rejected as already in route table */ | |
144 | u32 imp_updates_accepted; /* Number of route updates accepted and imported */ | |
145 | u32 imp_withdraws_received; /* Number of route withdraws received */ | |
146 | u32 imp_withdraws_invalid; /* Number of route withdraws rejected as invalid */ | |
147 | u32 imp_withdraws_ignored; /* Number of route withdraws rejected as already not in route table */ | |
148 | u32 imp_withdraws_accepted; /* Number of route withdraws accepted and processed */ | |
149 | ||
150 | /* Export - from core to protocol */ | |
151 | u32 exp_routes; /* Number of routes successfully exported to the protocol */ | |
152 | u32 exp_updates_received; /* Number of route updates received */ | |
153 | u32 exp_updates_rejected; /* Number of route updates rejected by protocol */ | |
154 | u32 exp_updates_filtered; /* Number of route updates rejected by filters */ | |
2bbc3083 | 155 | u32 exp_updates_accepted; /* Number of route updates accepted and exported */ |
925fe2d3 OZ |
156 | u32 exp_withdraws_received; /* Number of route withdraws received */ |
157 | u32 exp_withdraws_accepted; /* Number of route withdraws accepted and processed */ | |
158 | }; | |
159 | ||
58ef912c | 160 | struct proto { |
f4a60a9b | 161 | node n; /* Node in global proto_list */ |
58ef912c | 162 | struct protocol *proto; /* Protocol */ |
31b3e1bb | 163 | struct proto_config *cf; /* Configuration data */ |
50fe90ed | 164 | struct proto_config *cf_new; /* Configuration we want to switch to after shutdown (NULL=delete) */ |
31b3e1bb | 165 | pool *pool; /* Pool containing local objects */ |
f4a60a9b OZ |
166 | event *event; /* Protocol event */ |
167 | ||
168 | list channels; /* List of channels to rtables (struct channel) */ | |
169 | struct channel *main_channel; /* Primary channel */ | |
170 | struct rte_src *main_source; /* Primary route source */ | |
46434a3c | 171 | struct iface *vrf; /* Related VRF instance, NULL if global */ |
31b3e1bb | 172 | |
fd9f0c06 | 173 | const char *name; /* Name of this instance (== cf->name) */ |
cf31112f OZ |
174 | u32 debug; /* Debugging flags */ |
175 | u32 mrtdump; /* MRTDump flags */ | |
f4a60a9b OZ |
176 | uint active_channels; /* Number of active channels */ |
177 | byte net_type; /* Protocol network type (NET_*), 0 for undefined */ | |
ebecb6f6 | 178 | byte disabled; /* Manually disabled */ |
18f70a62 | 179 | byte vrf_set; /* Related VRF instance (above) is defined */ |
ebecb6f6 | 180 | byte proto_state; /* Protocol state machine (PS_*, see below) */ |
f4a60a9b OZ |
181 | byte active; /* From PS_START to cleanup after PS_STOP */ |
182 | byte do_start; /* Start actions are scheduled */ | |
183 | byte do_stop; /* Stop actions are scheduled */ | |
ebecb6f6 | 184 | byte reconfiguring; /* We're shutting down due to reconfiguration */ |
0c791f87 | 185 | byte gr_recovery; /* Protocol should participate in graceful restart recovery */ |
ebecb6f6 OZ |
186 | byte down_sched; /* Shutdown is scheduled for later (PDS_*) */ |
187 | byte down_code; /* Reason for shutdown (PDC_* codes) */ | |
7293c5dd | 188 | u32 hash_key; /* Random key used for hashing of neighbors */ |
f047271c | 189 | btime last_state_change; /* Time of last state transition */ |
df9f0fb3 | 190 | char *last_state_name_announced; /* Last state name we've announced to the user */ |
cd1d9961 | 191 | char *message; /* State-change message, allocated from proto_pool */ |
58ef912c | 192 | |
9e0e485e MM |
193 | /* |
194 | * General protocol hooks: | |
195 | * | |
196 | * if_notify Notify protocol about interface state changes. | |
9a158361 | 197 | * ifa_notify Notify protocol about interface address changes. |
9e0e485e MM |
198 | * rt_notify Notify protocol about routing table updates. |
199 | * neigh_notify Notify protocol about neighbor cache events. | |
d5a32563 MM |
200 | * preexport Called as the first step of the route exporting process. |
201 | * It can decide whether the route shall be exported: | |
202 | * -1 = reject, | |
203 | * 0 = continue to export filter | |
204 | * 1 = accept immediately | |
f4a60a9b | 205 | * reload_routes Request channel to reload all its routes to the core |
bf47fe4b OZ |
206 | * (using rte_update()). Returns: 0=reload cannot be done, |
207 | * 1= reload is scheduled and will happen (asynchronously). | |
f4a60a9b OZ |
208 | * feed_begin Notify channel about beginning of route feeding. |
209 | * feed_end Notify channel about finish of route feeding. | |
9e0e485e MM |
210 | */ |
211 | ||
9a158361 MM |
212 | void (*if_notify)(struct proto *, unsigned flags, struct iface *i); |
213 | void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a); | |
13c0be19 | 214 | void (*rt_notify)(struct proto *, struct channel *, struct network *net, struct rte *new, struct rte *old); |
4cc78c50 | 215 | void (*neigh_notify)(struct neighbor *neigh); |
d5a32563 | 216 | int (*preexport)(struct proto *, struct rte *rt); |
f4a60a9b OZ |
217 | void (*reload_routes)(struct channel *); |
218 | void (*feed_begin)(struct channel *, int initial); | |
219 | void (*feed_end)(struct channel *); | |
9e0e485e MM |
220 | |
221 | /* | |
094d2bdb | 222 | * Routing entry hooks (called only for routes belonging to this protocol): |
9e0e485e | 223 | * |
2bbc3083 | 224 | * rte_recalculate Called at the beginning of the best route selection |
9e0e485e | 225 | * rte_better Compare two rte's and decide which one is better (1=first, 0=second). |
67be5b23 | 226 | * rte_same Compare two rte's and decide whether they are identical (1=yes, 0=no). |
8d9eef17 | 227 | * rte_mergable Compare two rte's and decide whether they could be merged (1=yes, 0=no). |
9e0e485e MM |
228 | * rte_insert Called whenever a rte is inserted to a routing table. |
229 | * rte_remove Called whenever a rte is removed from the routing table. | |
230 | */ | |
58ef912c | 231 | |
be4cd99a | 232 | int (*rte_recalculate)(struct rtable *, struct network *, struct rte *, struct rte *, struct rte *); |
2326b001 | 233 | int (*rte_better)(struct rte *, struct rte *); |
8d9eef17 | 234 | int (*rte_mergable)(struct rte *, struct rte *); |
5bd73431 | 235 | struct rte * (*rte_modify)(struct rte *, struct linpool *); |
acc62f5e MM |
236 | void (*rte_insert)(struct network *, struct rte *); |
237 | void (*rte_remove)(struct network *, struct rte *); | |
d471d5fc | 238 | u32 (*rte_igp_metric)(struct rte *); |
2326b001 | 239 | |
58ef912c MM |
240 | /* Hic sunt protocol-specific data */ |
241 | }; | |
242 | ||
e304fd4b | 243 | struct proto_spec { |
fd9f0c06 | 244 | const void *ptr; |
e304fd4b OZ |
245 | int patt; |
246 | }; | |
247 | ||
248 | ||
ebecb6f6 OZ |
249 | #define PDS_DISABLE 1 /* Proto disable scheduled */ |
250 | #define PDS_RESTART 2 /* Proto restart scheduled */ | |
251 | ||
252 | #define PDC_CF_REMOVE 0x01 /* Removed in new config */ | |
253 | #define PDC_CF_DISABLE 0x02 /* Disabled in new config */ | |
254 | #define PDC_CF_RESTART 0x03 /* Restart due to reconfiguration */ | |
255 | #define PDC_CMD_DISABLE 0x11 /* Result of disable command */ | |
256 | #define PDC_CMD_RESTART 0x12 /* Result of restart command */ | |
5400c0e7 | 257 | #define PDC_CMD_SHUTDOWN 0x13 /* Result of global shutdown */ |
8a68316e | 258 | #define PDC_CMD_GR_DOWN 0x14 /* Result of global graceful restart */ |
b662290f OZ |
259 | #define PDC_RX_LIMIT_HIT 0x21 /* Route receive limit reached */ |
260 | #define PDC_IN_LIMIT_HIT 0x22 /* Route import limit reached */ | |
261 | #define PDC_OUT_LIMIT_HIT 0x23 /* Route export limit reached */ | |
ebecb6f6 OZ |
262 | |
263 | ||
f4a60a9b | 264 | void *proto_new(struct proto_config *); |
2bbc3083 | 265 | void *proto_config_new(struct protocol *, int class); |
a7f23f58 | 266 | void proto_copy_config(struct proto_config *dest, struct proto_config *src); |
e0835db4 | 267 | void proto_clone_config(struct symbol *sym, struct proto_config *parent); |
cd1d9961 | 268 | void proto_set_message(struct proto *p, char *msg, int len); |
a7f23f58 | 269 | |
0c791f87 OZ |
270 | void graceful_restart_recovery(void); |
271 | void graceful_restart_init(void); | |
272 | void graceful_restart_show_status(void); | |
f4a60a9b OZ |
273 | void channel_graceful_restart_lock(struct channel *c); |
274 | void channel_graceful_restart_unlock(struct channel *c); | |
0c791f87 OZ |
275 | |
276 | #define DEFAULT_GR_WAIT 240 | |
c0adf7e9 | 277 | |
f4a60a9b OZ |
278 | void channel_show_limit(struct channel_limit *l, const char *dsc); |
279 | void channel_show_info(struct channel *c); | |
61dae32b | 280 | void channel_cmd_debug(struct channel *c, uint mask); |
c0adf7e9 | 281 | |
cd1d9961 OZ |
282 | void proto_cmd_show(struct proto *, uintptr_t, int); |
283 | void proto_cmd_disable(struct proto *, uintptr_t, int); | |
284 | void proto_cmd_enable(struct proto *, uintptr_t, int); | |
285 | void proto_cmd_restart(struct proto *, uintptr_t, int); | |
286 | void proto_cmd_reload(struct proto *, uintptr_t, int); | |
287 | void proto_cmd_debug(struct proto *, uintptr_t, int); | |
288 | void proto_cmd_mrtdump(struct proto *, uintptr_t, int); | |
ae80a2de | 289 | |
cd1d9961 | 290 | void proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uintptr_t, int), int restricted, uintptr_t arg); |
02c1fbdd | 291 | struct proto *proto_get_named(struct symbol *, struct protocol *); |
c26c6bc2 OZ |
292 | struct proto *proto_iterate_named(struct symbol *sym, struct protocol *proto, struct proto *old); |
293 | ||
294 | #define PROTO_WALK_CMD(sym,pr,p) for(struct proto *p = NULL; p = proto_iterate_named(sym, pr, p); ) | |
295 | ||
e304fd4b OZ |
296 | |
297 | #define CMD_RELOAD 0 | |
298 | #define CMD_RELOAD_IN 1 | |
299 | #define CMD_RELOAD_OUT 2 | |
8a7fb885 | 300 | |
4cdd0784 OZ |
301 | static inline u32 |
302 | proto_get_router_id(struct proto_config *pc) | |
303 | { | |
304 | return pc->router_id ? pc->router_id : pc->global->router_id; | |
305 | } | |
306 | ||
f4a60a9b | 307 | |
d15b0b0a | 308 | extern pool *proto_pool; |
f4a60a9b | 309 | extern list proto_list; |
2326b001 | 310 | |
31b3e1bb MM |
311 | /* |
312 | * Each protocol instance runs two different state machines: | |
313 | * | |
314 | * [P] The protocol machine: (implemented inside protocol) | |
315 | * | |
316 | * DOWN ----> START | |
317 | * ^ | | |
318 | * | V | |
319 | * STOP <---- UP | |
320 | * | |
321 | * States: DOWN Protocol is down and it's waiting for the core | |
322 | * requesting protocol start. | |
323 | * START Protocol is waiting for connection with the rest | |
324 | * of the network and it's not willing to accept | |
325 | * packets. When it connects, it goes to UP state. | |
326 | * UP Protocol is up and running. When the network | |
327 | * connection breaks down or the core requests | |
328 | * protocol to be terminated, it goes to STOP state. | |
329 | * STOP Protocol is disconnecting from the network. | |
330 | * After it disconnects, it returns to DOWN state. | |
331 | * | |
332 | * In: start() Called in DOWN state to request protocol startup. | |
333 | * Returns new state: either UP or START (in this | |
334 | * case, the protocol will notify the core when it | |
335 | * finally comes UP). | |
336 | * stop() Called in START, UP or STOP state to request | |
337 | * protocol shutdown. Returns new state: either | |
338 | * DOWN or STOP (in this case, the protocol will | |
339 | * notify the core when it finally comes DOWN). | |
340 | * | |
341 | * Out: proto_notify_state() -- called by protocol instance when | |
342 | * it does any state transition not covered by | |
343 | * return values of start() and stop(). This includes | |
344 | * START->UP (delayed protocol startup), UP->STOP | |
345 | * (spontaneous shutdown) and STOP->DOWN (delayed | |
346 | * shutdown). | |
347 | */ | |
348 | ||
349 | #define PS_DOWN 0 | |
350 | #define PS_START 1 | |
351 | #define PS_UP 2 | |
352 | #define PS_STOP 3 | |
353 | ||
354 | void proto_notify_state(struct proto *p, unsigned state); | |
355 | ||
356 | /* | |
357 | * [F] The feeder machine: (implemented in core routines) | |
358 | * | |
359 | * HUNGRY ----> FEEDING | |
360 | * ^ | | |
a82f692e | 361 | * | V |
31b3e1bb MM |
362 | * FLUSHING <---- HAPPY |
363 | * | |
364 | * States: HUNGRY Protocol either administratively down (i.e., | |
365 | * disabled by the user) or temporarily down | |
366 | * (i.e., [P] is not UP) | |
367 | * FEEDING The protocol came up and we're feeding it | |
368 | * initial routes. [P] is UP. | |
369 | * HAPPY The protocol is up and it's receiving normal | |
370 | * routing updates. [P] is UP. | |
371 | * FLUSHING The protocol is down and we're removing its | |
372 | * routes from the table. [P] is STOP or DOWN. | |
373 | * | |
374 | * Normal lifecycle of a protocol looks like: | |
375 | * | |
376 | * HUNGRY/DOWN --> HUNGRY/START --> HUNGRY/UP --> | |
377 | * FEEDING/UP --> HAPPY/UP --> FLUSHING/STOP|DOWN --> | |
378 | * HUNGRY/STOP|DOWN --> HUNGRY/DOWN | |
bf47fe4b | 379 | * |
2bbc3083 | 380 | * Sometimes, protocol might switch from HAPPY/UP to FEEDING/UP |
bf47fe4b OZ |
381 | * if it wants to refeed the routes (for example BGP does so |
382 | * as a result of received ROUTE-REFRESH request). | |
31b3e1bb MM |
383 | */ |
384 | ||
0c791f87 | 385 | |
31b3e1bb | 386 | |
96d8e3bf MM |
387 | /* |
388 | * Debugging flags | |
389 | */ | |
390 | ||
391 | #define D_STATES 1 /* [core] State transitions */ | |
392 | #define D_ROUTES 2 /* [core] Routes passed by the filters */ | |
6a9f28b0 MM |
393 | #define D_FILTERS 4 /* [core] Routes rejected by the filters */ |
394 | #define D_IFACES 8 /* [core] Interface events */ | |
395 | #define D_EVENTS 16 /* Protocol events */ | |
396 | #define D_PACKETS 32 /* Packets sent/received */ | |
96d8e3bf | 397 | |
6a8d3f1c OZ |
398 | #ifndef PARSER |
399 | #define TRACE(flags, msg, args...) \ | |
400 | do { if (p->p.debug & flags) log(L_TRACE "%s: " msg, p->p.name , ## args ); } while(0) | |
401 | #endif | |
402 | ||
403 | ||
cf31112f OZ |
404 | /* |
405 | * MRTDump flags | |
406 | */ | |
407 | ||
408 | #define MD_STATES 1 /* Protocol state changes (BGP4MP_MESSAGE_AS4) */ | |
409 | #define MD_MESSAGES 2 /* Protocol packets (BGP4MP_MESSAGE_AS4) */ | |
410 | ||
50d8424a MM |
411 | /* |
412 | * Known unique protocol instances as referenced by config routines | |
413 | */ | |
414 | ||
31b3e1bb | 415 | extern struct proto_config *cf_dev_proto; |
50d8424a | 416 | |
ebecb6f6 OZ |
417 | |
418 | /* | |
419 | * Protocol limits | |
420 | */ | |
421 | ||
b662290f OZ |
422 | #define PLD_RX 0 /* Receive limit */ |
423 | #define PLD_IN 1 /* Import limit */ | |
424 | #define PLD_OUT 2 /* Export limit */ | |
425 | #define PLD_MAX 3 | |
426 | ||
f4a60a9b | 427 | #define PLA_NONE 0 /* No limit */ |
ebecb6f6 OZ |
428 | #define PLA_WARN 1 /* Issue log warning */ |
429 | #define PLA_BLOCK 2 /* Block new routes */ | |
430 | #define PLA_RESTART 4 /* Force protocol restart */ | |
431 | #define PLA_DISABLE 5 /* Shutdown and disable protocol */ | |
432 | ||
7d0a31de OZ |
433 | #define PLS_INITIAL 0 /* Initial limit state after protocol start */ |
434 | #define PLS_ACTIVE 1 /* Limit was hit */ | |
435 | #define PLS_BLOCKED 2 /* Limit is active and blocking new routes */ | |
436 | ||
f4a60a9b | 437 | struct channel_limit { |
ebecb6f6 | 438 | u32 limit; /* Maximum number of prefixes */ |
f4a60a9b OZ |
439 | u8 action; /* Action to take (PLA_*) */ |
440 | u8 state; /* State of limit (PLS_*) */ | |
ebecb6f6 OZ |
441 | }; |
442 | ||
f4a60a9b | 443 | void channel_notify_limit(struct channel *c, struct channel_limit *l, int dir, u32 rt_count); |
7d0a31de | 444 | |
2bbc3083 | 445 | |
0e02abfd | 446 | /* |
f4a60a9b | 447 | * Channels |
0e02abfd MM |
448 | */ |
449 | ||
f4a60a9b OZ |
450 | struct channel_class { |
451 | uint channel_size; /* Size of channel data structure */ | |
452 | uint config_size; /* Size of channel config data structure */ | |
453 | ||
d15b0b0a | 454 | void (*init)(struct channel *, struct channel_config *); /* Create new instance */ |
e2b530aa | 455 | int (*reconfigure)(struct channel *, struct channel_config *, int *import_changed, int *export_changed); /* Try to reconfigure instance, returns success */ |
f4a60a9b | 456 | int (*start)(struct channel *); /* Start the instance */ |
d15b0b0a OZ |
457 | void (*shutdown)(struct channel *); /* Stop the instance */ |
458 | void (*cleanup)(struct channel *); /* Channel finished flush */ | |
f4a60a9b OZ |
459 | |
460 | void (*copy_config)(struct channel_config *, struct channel_config *); /* Copy config from given channel instance */ | |
461 | #if 0 | |
d15b0b0a | 462 | XXXX; |
f4a60a9b OZ |
463 | void (*preconfig)(struct protocol *, struct config *); /* Just before configuring */ |
464 | void (*postconfig)(struct proto_config *); /* After configuring each instance */ | |
465 | ||
466 | ||
467 | void (*dump)(struct proto *); /* Debugging dump */ | |
d15b0b0a | 468 | |
f4a60a9b | 469 | void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */ |
13c0be19 | 470 | void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */ |
f4a60a9b OZ |
471 | int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */ |
472 | void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */ | |
473 | ||
474 | #endif | |
475 | }; | |
476 | ||
d15b0b0a OZ |
477 | extern struct channel_class channel_bgp; |
478 | ||
f4a60a9b | 479 | struct channel_config { |
0e02abfd | 480 | node n; |
f4a60a9b OZ |
481 | const char *name; |
482 | const struct channel_class *channel; | |
483 | ||
72163bd5 | 484 | struct proto_config *parent; /* Where channel is defined (proto or template) */ |
f4a60a9b | 485 | struct rtable_config *table; /* Table we're attached to */ |
0b39b1cb | 486 | const struct filter *in_filter, *out_filter; /* Attached filters */ |
f4a60a9b OZ |
487 | struct channel_limit rx_limit; /* Limit for receiving routes from protocol |
488 | (relevant when in_keep_filtered is active) */ | |
489 | struct channel_limit in_limit; /* Limit for importing routes from protocol */ | |
490 | struct channel_limit out_limit; /* Limit for exporting routes to protocol */ | |
491 | ||
492 | u8 net_type; /* Routing table network type (NET_*), 0 for undefined */ | |
493 | u8 ra_mode; /* Mode of received route advertisements (RA_*) */ | |
494 | u16 preference; /* Default route preference */ | |
61dae32b | 495 | u32 debug; /* Debugging flags (D_*) */ |
f4a60a9b OZ |
496 | u8 merge_limit; /* Maximal number of nexthops for RA_MERGED */ |
497 | u8 in_keep_filtered; /* Routes rejected in import filter are kept */ | |
d3782c72 | 498 | u8 rpki_reload; /* RPKI changes trigger channel reload */ |
f4a60a9b OZ |
499 | }; |
500 | ||
501 | struct channel { | |
502 | node n; /* Node in proto->channels */ | |
503 | node table_node; /* Node in table->channels */ | |
504 | ||
505 | const char *name; /* Channel name (may be NULL) */ | |
506 | const struct channel_class *channel; | |
0e02abfd | 507 | struct proto *proto; |
f4a60a9b OZ |
508 | |
509 | struct rtable *table; | |
0b39b1cb MM |
510 | const struct filter *in_filter; /* Input filter */ |
511 | const struct filter *out_filter; /* Output filter */ | |
5ea39eaa | 512 | struct bmap export_map; /* Keeps track which routes passed export filter */ |
f4a60a9b OZ |
513 | struct channel_limit rx_limit; /* Receive limit (for in_keep_filtered) */ |
514 | struct channel_limit in_limit; /* Input limit */ | |
515 | struct channel_limit out_limit; /* Output limit */ | |
516 | ||
517 | struct event *feed_event; /* Event responsible for feeding */ | |
518 | struct fib_iterator feed_fit; /* Routing table iterator used during feeding */ | |
519 | struct proto_stats stats; /* Per-channel protocol statistics */ | |
5ea39eaa | 520 | u32 refeed_count; /* Number of routes exported during refeed regardless of out_limit */ |
f4a60a9b OZ |
521 | |
522 | u8 net_type; /* Routing table network type (NET_*), 0 for undefined */ | |
523 | u8 ra_mode; /* Mode of received route advertisements (RA_*) */ | |
524 | u16 preference; /* Default route preference */ | |
61dae32b | 525 | u32 debug; /* Debugging flags (D_*) */ |
f4a60a9b OZ |
526 | u8 merge_limit; /* Maximal number of nexthops for RA_MERGED */ |
527 | u8 in_keep_filtered; /* Routes rejected in import filter are kept */ | |
528 | u8 disabled; | |
d15b0b0a | 529 | u8 stale; /* Used in reconfiguration */ |
f4a60a9b OZ |
530 | |
531 | u8 channel_state; | |
532 | u8 export_state; /* Route export state (ES_*, see below) */ | |
533 | u8 feed_active; | |
534 | u8 flush_active; | |
535 | u8 refeeding; /* We are refeeding (valid only if export_state == ES_FEEDING) */ | |
536 | u8 reloadable; /* Hook reload_routes() is allowed on the channel */ | |
537 | u8 gr_lock; /* Graceful restart mechanism should wait for this channel */ | |
538 | u8 gr_wait; /* Route export to channel is postponed until graceful restart */ | |
539 | ||
f047271c | 540 | btime last_state_change; /* Time of last state transition */ |
682d3f7d OZ |
541 | |
542 | struct rtable *in_table; /* Internal table for received routes */ | |
543 | struct event *reload_event; /* Event responsible for reloading from in_table */ | |
32a25405 MM |
544 | struct fib_iterator reload_fit; /* FIB iterator in in_table used during reloading */ |
545 | struct rte *reload_next_rte; /* Route iterator in in_table used during reloading */ | |
682d3f7d | 546 | u8 reload_active; /* Iterator reload_fit is linked */ |
b7d7599c | 547 | |
00b85905 OZ |
548 | u8 reload_pending; /* Reloading and another reload is scheduled */ |
549 | u8 refeed_pending; /* Refeeding and another refeed is scheduled */ | |
d3782c72 | 550 | u8 rpki_reload; /* RPKI changes trigger channel reload */ |
00b85905 | 551 | |
b7d7599c | 552 | struct rtable *out_table; /* Internal table for exported routes */ |
00b85905 OZ |
553 | |
554 | list roa_subscriptions; /* List of active ROA table subscriptions based on filters roa_check() */ | |
0e02abfd MM |
555 | }; |
556 | ||
f4a60a9b OZ |
557 | |
558 | /* | |
559 | * Channel states | |
560 | * | |
561 | * CS_DOWN - The initial and the final state of a channel. There is no route | |
562 | * exchange between the protocol and the table. Channel is not counted as | |
563 | * active. Channel keeps a ptr to the table, but do not lock the table and is | |
564 | * not linked in the table. Generally, new closed channels are created in | |
565 | * protocols' init() hooks. The protocol is expected to explicitly activate its | |
566 | * channels (by calling channel_init() or channel_open()). | |
567 | * | |
568 | * CS_START - The channel as a connection between the protocol and the table is | |
569 | * initialized (counted as active by the protocol, linked in the table and keeps | |
570 | * the table locked), but there is no current route exchange. There still may be | |
571 | * routes associated with the channel in the routing table if the channel falls | |
572 | * to CS_START from CS_UP. Generally, channels are initialized in protocols' | |
573 | * start() hooks when going to PS_START. | |
574 | * | |
575 | * CS_UP - The channel is initialized and the route exchange is allowed. Note | |
576 | * that even in CS_UP state, route export may still be down (ES_DOWN) by the | |
577 | * core decision (e.g. waiting for table convergence after graceful restart). | |
578 | * I.e., the protocol decides to open the channel but the core decides to start | |
579 | * route export. Route import (caused by rte_update() from the protocol) is not | |
580 | * restricted by that and is on volition of the protocol. Generally, channels | |
581 | * are opened in protocols' start() hooks when going to PS_UP. | |
582 | * | |
583 | * CS_FLUSHING - The transitional state between initialized channel and closed | |
584 | * channel. The channel is still initialized, but no route exchange is allowed. | |
585 | * Instead, the associated table is running flush loop to remove routes imported | |
586 | * through the channel. After that, the channel changes state to CS_DOWN and | |
587 | * is detached from the table (the table is unlocked and the channel is unlinked | |
588 | * from it). Unlike other states, the CS_FLUSHING state is not explicitly | |
589 | * entered or left by the protocol. A protocol may request to close a channel | |
590 | * (by calling channel_close()), which causes the channel to change state to | |
591 | * CS_FLUSHING and later to CS_DOWN. Also note that channels are closed | |
592 | * automatically by the core when the protocol is going down. | |
593 | * | |
594 | * Allowed transitions: | |
595 | * | |
596 | * CS_DOWN -> CS_START / CS_UP | |
597 | * CS_START -> CS_UP / CS_FLUSHING | |
598 | * CS_UP -> CS_START / CS_FLUSHING | |
599 | * CS_FLUSHING -> CS_DOWN (automatic) | |
600 | */ | |
601 | ||
602 | #define CS_DOWN 0 | |
603 | #define CS_START 1 | |
604 | #define CS_UP 2 | |
605 | #define CS_FLUSHING 3 | |
606 | ||
607 | #define ES_DOWN 0 | |
608 | #define ES_FEEDING 1 | |
609 | #define ES_READY 2 | |
610 | ||
611 | ||
612 | struct channel_config *proto_cf_find_channel(struct proto_config *p, uint net_type); | |
613 | static inline struct channel_config *proto_cf_main_channel(struct proto_config *pc) | |
47d92d8f | 614 | { return proto_cf_find_channel(pc, pc->net_type); } |
f4a60a9b OZ |
615 | |
616 | struct channel *proto_find_channel_by_table(struct proto *p, struct rtable *t); | |
b2949999 | 617 | struct channel *proto_find_channel_by_name(struct proto *p, const char *n); |
f4a60a9b OZ |
618 | struct channel *proto_add_channel(struct proto *p, struct channel_config *cf); |
619 | int proto_configure_channel(struct proto *p, struct channel **c, struct channel_config *cf); | |
620 | ||
621 | void channel_set_state(struct channel *c, uint state); | |
682d3f7d | 622 | void channel_setup_in_table(struct channel *c); |
b7d7599c | 623 | void channel_setup_out_table(struct channel *c); |
682d3f7d | 624 | void channel_schedule_reload(struct channel *c); |
f4a60a9b | 625 | |
f4a60a9b OZ |
626 | static inline void channel_init(struct channel *c) { channel_set_state(c, CS_START); } |
627 | static inline void channel_open(struct channel *c) { channel_set_state(c, CS_UP); } | |
628 | static inline void channel_close(struct channel *c) { channel_set_state(c, CS_FLUSHING); } | |
f4a60a9b OZ |
629 | |
630 | void channel_request_feeding(struct channel *c); | |
72163bd5 OZ |
631 | void *channel_config_new(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto); |
632 | void *channel_config_get(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto); | |
f4a60a9b OZ |
633 | int channel_reconfigure(struct channel *c, struct channel_config *cf); |
634 | ||
c8387626 | 635 | |
682d3f7d OZ |
636 | /* Moved from route.h to avoid dependency conflicts */ |
637 | static inline void rte_update(struct proto *p, const net_addr *n, rte *new) { rte_update2(p->main_channel, n, new, p->main_source); } | |
638 | ||
639 | static inline void | |
640 | rte_update3(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) | |
641 | { | |
642 | if (c->in_table && !rte_update_in(c, n, new, src)) | |
643 | return; | |
644 | ||
645 | rte_update2(c, n, new, src); | |
646 | } | |
647 | ||
648 | ||
58ef912c | 649 | #endif |