iof-bird-daemon / proto / bgp / bgp.c @ ef5081af
History | View | Annotate | Download (71.6 KB)
1 |
/*
|
---|---|
2 |
* BIRD -- The Border Gateway Protocol
|
3 |
*
|
4 |
* (c) 2000 Martin Mares <mj@ucw.cz>
|
5 |
* (c) 2008--2016 Ondrej Zajicek <santiago@crfreenet.org>
|
6 |
* (c) 2008--2016 CZ.NIC z.s.p.o.
|
7 |
*
|
8 |
* Can be freely distributed and used under the terms of the GNU GPL.
|
9 |
*/
|
10 |
|
11 |
/**
|
12 |
* DOC: Border Gateway Protocol
|
13 |
*
|
14 |
* The BGP protocol is implemented in three parts: |bgp.c| which takes care of
|
15 |
* the connection and most of the interface with BIRD core, |packets.c| handling
|
16 |
* both incoming and outgoing BGP packets and |attrs.c| containing functions for
|
17 |
* manipulation with BGP attribute lists.
|
18 |
*
|
19 |
* As opposed to the other existing routing daemons, BIRD has a sophisticated
|
20 |
* core architecture which is able to keep all the information needed by BGP in
|
21 |
* the primary routing table, therefore no complex data structures like a
|
22 |
* central BGP table are needed. This increases memory footprint of a BGP router
|
23 |
* with many connections, but not too much and, which is more important, it
|
24 |
* makes BGP much easier to implement.
|
25 |
*
|
26 |
* Each instance of BGP (corresponding to a single BGP peer) is described by a
|
27 |
* &bgp_proto structure to which are attached individual connections represented
|
28 |
* by &bgp_connection (usually, there exists only one connection, but during BGP
|
29 |
* session setup, there can be more of them). The connections are handled
|
30 |
* according to the BGP state machine defined in the RFC with all the timers and
|
31 |
* all the parameters configurable.
|
32 |
*
|
33 |
* In incoming direction, we listen on the connection's socket and each time we
|
34 |
* receive some input, we pass it to bgp_rx(). It decodes packet headers and the
|
35 |
* markers and passes complete packets to bgp_rx_packet() which distributes the
|
36 |
* packet according to its type.
|
37 |
*
|
38 |
* In outgoing direction, we gather all the routing updates and sort them to
|
39 |
* buckets (&bgp_bucket) according to their attributes (we keep a hash table for
|
40 |
* fast comparison of &rta's and a &fib which helps us to find if we already
|
41 |
* have another route for the same destination queued for sending, so that we
|
42 |
* can replace it with the new one immediately instead of sending both
|
43 |
* updates). There also exists a special bucket holding all the route
|
44 |
* withdrawals which cannot be queued anywhere else as they don't have any
|
45 |
* attributes. If we have any packet to send (due to either new routes or the
|
46 |
* connection tracking code wanting to send a Open, Keepalive or Notification
|
47 |
* message), we call bgp_schedule_packet() which sets the corresponding bit in a
|
48 |
* @packet_to_send bit field in &bgp_conn and as soon as the transmit socket
|
49 |
* buffer becomes empty, we call bgp_fire_tx(). It inspects state of all the
|
50 |
* packet type bits and calls the corresponding bgp_create_xx() functions,
|
51 |
* eventually rescheduling the same packet type if we have more data of the same
|
52 |
* type to send.
|
53 |
*
|
54 |
* The processing of attributes consists of two functions: bgp_decode_attrs()
|
55 |
* for checking of the attribute blocks and translating them to the language of
|
56 |
* BIRD's extended attributes and bgp_encode_attrs() which does the
|
57 |
* converse. Both functions are built around a @bgp_attr_table array describing
|
58 |
* all important characteristics of all known attributes. Unknown transitive
|
59 |
* attributes are attached to the route as %EAF_TYPE_OPAQUE byte streams.
|
60 |
*
|
61 |
* BGP protocol implements graceful restart in both restarting (local restart)
|
62 |
* and receiving (neighbor restart) roles. The first is handled mostly by the
|
63 |
* graceful restart code in the nest, BGP protocol just handles capabilities,
|
64 |
* sets @gr_wait and locks graceful restart until end-of-RIB mark is received.
|
65 |
* The second is implemented by internal restart of the BGP state to %BS_IDLE
|
66 |
* and protocol state to %PS_START, but keeping the protocol up from the core
|
67 |
* point of view and therefore maintaining received routes. Routing table
|
68 |
* refresh cycle (rt_refresh_begin(), rt_refresh_end()) is used for removing
|
69 |
* stale routes after reestablishment of BGP session during graceful restart.
|
70 |
*
|
71 |
* Supported standards:
|
72 |
* <itemize>
|
73 |
* <item> <rfc id="4271"> - Border Gateway Protocol 4 (BGP)
|
74 |
* <item> <rfc id="1997"> - BGP Communities Attribute
|
75 |
* <item> <rfc id="2385"> - Protection of BGP Sessions via TCP MD5 Signature
|
76 |
* <item> <rfc id="2545"> - Use of BGP Multiprotocol Extensions for IPv6
|
77 |
* <item> <rfc id="2918"> - Route Refresh Capability
|
78 |
* <item> <rfc id="3107"> - Carrying Label Information in BGP
|
79 |
* <item> <rfc id="4360"> - BGP Extended Communities Attribute
|
80 |
* <item> <rfc id="4364"> - BGP/MPLS IPv4 Virtual Private Networks
|
81 |
* <item> <rfc id="4456"> - BGP Route Reflection
|
82 |
* <item> <rfc id="4486"> - Subcodes for BGP Cease Notification Message
|
83 |
* <item> <rfc id="4659"> - BGP/MPLS IPv6 Virtual Private Networks
|
84 |
* <item> <rfc id="4724"> - Graceful Restart Mechanism for BGP
|
85 |
* <item> <rfc id="4760"> - Multiprotocol extensions for BGP
|
86 |
* <item> <rfc id="4798"> - Connecting IPv6 Islands over IPv4 MPLS
|
87 |
* <item> <rfc id="5065"> - AS confederations for BGP
|
88 |
* <item> <rfc id="5082"> - Generalized TTL Security Mechanism
|
89 |
* <item> <rfc id="5492"> - Capabilities Advertisement with BGP
|
90 |
* <item> <rfc id="5549"> - Advertising IPv4 NLRI with an IPv6 Next Hop
|
91 |
* <item> <rfc id="5575"> - Dissemination of Flow Specification Rules
|
92 |
* <item> <rfc id="5668"> - 4-Octet AS Specific BGP Extended Community
|
93 |
* <item> <rfc id="6286"> - AS-Wide Unique BGP Identifier
|
94 |
* <item> <rfc id="6608"> - Subcodes for BGP Finite State Machine Error
|
95 |
* <item> <rfc id="6793"> - BGP Support for 4-Octet AS Numbers
|
96 |
* <item> <rfc id="7313"> - Enhanced Route Refresh Capability for BGP
|
97 |
* <item> <rfc id="7606"> - Revised Error Handling for BGP UPDATE Messages
|
98 |
* <item> <rfc id="7911"> - Advertisement of Multiple Paths in BGP
|
99 |
* <item> <rfc id="7947"> - Internet Exchange BGP Route Server
|
100 |
* <item> <rfc id="8092"> - BGP Large Communities Attribute
|
101 |
* <item> <rfc id="8203"> - BGP Administrative Shutdown Communication
|
102 |
* <item> <rfc id="8212"> - Default EBGP Route Propagation Behavior without Policies
|
103 |
* </itemize>
|
104 |
*/
|
105 |
|
106 |
#undef LOCAL_DEBUG
|
107 |
|
108 |
#include <stdlib.h> |
109 |
#include <time.h> |
110 |
|
111 |
#include "nest/bird.h" |
112 |
#include "nest/iface.h" |
113 |
#include "nest/protocol.h" |
114 |
#include "nest/route.h" |
115 |
#include "nest/cli.h" |
116 |
#include "nest/locks.h" |
117 |
#include "conf/conf.h" |
118 |
#include "filter/filter.h" |
119 |
#include "lib/socket.h" |
120 |
#include "lib/resource.h" |
121 |
#include "lib/string.h" |
122 |
|
123 |
#include "bgp.h" |
124 |
|
125 |
struct linpool *bgp_linpool; /* Global temporary pool */ |
126 |
struct linpool *bgp_linpool2; /* Global temporary pool for bgp_rt_notify() */ |
127 |
static list bgp_sockets; /* Global list of listening sockets */ |
128 |
|
129 |
|
130 |
static void bgp_connect(struct bgp_proto *p); |
131 |
static void bgp_active(struct bgp_proto *p); |
132 |
static void bgp_update_bfd(struct bgp_proto *p, int use_bfd); |
133 |
|
134 |
static int bgp_incoming_connection(sock *sk, uint dummy UNUSED); |
135 |
static void bgp_listen_sock_err(sock *sk UNUSED, int err); |
136 |
|
137 |
/**
|
138 |
* bgp_open - open a BGP instance
|
139 |
* @p: BGP instance
|
140 |
*
|
141 |
* This function allocates and configures shared BGP resources, mainly listening
|
142 |
* sockets. Should be called as the last step during initialization (when lock
|
143 |
* is acquired and neighbor is ready). When error, caller should change state to
|
144 |
* PS_DOWN and return immediately.
|
145 |
*/
|
146 |
static int |
147 |
bgp_open(struct bgp_proto *p)
|
148 |
{ |
149 |
struct bgp_socket *bs = NULL; |
150 |
struct iface *ifa = p->cf->strict_bind ? p->cf->iface : NULL; |
151 |
ip_addr addr = p->cf->strict_bind ? p->cf->local_ip : |
152 |
(ipa_is_ip4(p->cf->remote_ip) ? IPA_NONE4 : IPA_NONE6); |
153 |
uint port = p->cf->local_port; |
154 |
|
155 |
/* FIXME: Add some global init? */
|
156 |
if (!bgp_linpool)
|
157 |
init_list(&bgp_sockets); |
158 |
|
159 |
/* We assume that cf->iface is defined iff cf->local_ip is link-local */
|
160 |
|
161 |
WALK_LIST(bs, bgp_sockets) |
162 |
if (ipa_equal(bs->sk->saddr, addr) && (bs->sk->iface == ifa) && (bs->sk->sport == port))
|
163 |
{ |
164 |
bs->uc++; |
165 |
p->sock = bs; |
166 |
return 0; |
167 |
} |
168 |
|
169 |
sock *sk = sk_new(proto_pool); |
170 |
sk->type = SK_TCP_PASSIVE; |
171 |
sk->ttl = 255;
|
172 |
sk->saddr = addr; |
173 |
sk->sport = port; |
174 |
sk->flags = 0;
|
175 |
sk->tos = IP_PREC_INTERNET_CONTROL; |
176 |
sk->rbsize = BGP_RX_BUFFER_SIZE; |
177 |
sk->tbsize = BGP_TX_BUFFER_SIZE; |
178 |
sk->rx_hook = bgp_incoming_connection; |
179 |
sk->err_hook = bgp_listen_sock_err; |
180 |
|
181 |
if (sk_open(sk) < 0) |
182 |
goto err;
|
183 |
|
184 |
bs = mb_allocz(proto_pool, sizeof(struct bgp_socket)); |
185 |
bs->sk = sk; |
186 |
bs->uc = 1;
|
187 |
p->sock = bs; |
188 |
|
189 |
add_tail(&bgp_sockets, &bs->n); |
190 |
|
191 |
if (!bgp_linpool)
|
192 |
{ |
193 |
bgp_linpool = lp_new_default(proto_pool); |
194 |
bgp_linpool2 = lp_new_default(proto_pool); |
195 |
} |
196 |
|
197 |
return 0; |
198 |
|
199 |
err:
|
200 |
sk_log_error(sk, p->p.name); |
201 |
log(L_ERR "%s: Cannot open listening socket", p->p.name);
|
202 |
rfree(sk); |
203 |
return -1; |
204 |
} |
205 |
|
206 |
/**
|
207 |
* bgp_close - close a BGP instance
|
208 |
* @p: BGP instance
|
209 |
*
|
210 |
* This function frees and deconfigures shared BGP resources.
|
211 |
*/
|
212 |
static void |
213 |
bgp_close(struct bgp_proto *p)
|
214 |
{ |
215 |
struct bgp_socket *bs = p->sock;
|
216 |
|
217 |
ASSERT(bs && bs->uc); |
218 |
|
219 |
if (--bs->uc)
|
220 |
return;
|
221 |
|
222 |
rfree(bs->sk); |
223 |
rem_node(&bs->n); |
224 |
mb_free(bs); |
225 |
|
226 |
if (!EMPTY_LIST(bgp_sockets))
|
227 |
return;
|
228 |
|
229 |
rfree(bgp_linpool); |
230 |
bgp_linpool = NULL;
|
231 |
|
232 |
rfree(bgp_linpool2); |
233 |
bgp_linpool2 = NULL;
|
234 |
} |
235 |
|
236 |
static inline int |
237 |
bgp_setup_auth(struct bgp_proto *p, int enable) |
238 |
{ |
239 |
if (p->cf->password)
|
240 |
{ |
241 |
int rv = sk_set_md5_auth(p->sock->sk,
|
242 |
p->cf->local_ip, p->cf->remote_ip, p->cf->iface, |
243 |
enable ? p->cf->password : NULL, p->cf->setkey);
|
244 |
|
245 |
if (rv < 0) |
246 |
sk_log_error(p->sock->sk, p->p.name); |
247 |
|
248 |
return rv;
|
249 |
} |
250 |
else
|
251 |
return 0; |
252 |
} |
253 |
|
254 |
static inline struct bgp_channel * |
255 |
bgp_find_channel(struct bgp_proto *p, u32 afi)
|
256 |
{ |
257 |
struct bgp_channel *c;
|
258 |
WALK_LIST(c, p->p.channels) |
259 |
if (c->afi == afi)
|
260 |
return c;
|
261 |
|
262 |
return NULL; |
263 |
} |
264 |
|
265 |
static void |
266 |
bgp_startup(struct bgp_proto *p)
|
267 |
{ |
268 |
//sameMetricUpdater = 3;
|
269 |
BGP_TRACE(D_EVENTS, "Started");
|
270 |
p->start_state = BSS_CONNECT; |
271 |
|
272 |
if (!p->cf->passive)
|
273 |
bgp_active(p); |
274 |
|
275 |
initRTmap(); |
276 |
loadComplessivo = 0;
|
277 |
} |
278 |
|
279 |
static void |
280 |
bgp_startup_timeout(timer *t) |
281 |
{ |
282 |
bgp_startup(t->data); |
283 |
} |
284 |
|
285 |
static inline struct bgp_channel * |
286 |
bgp_get_channel_to_send(struct bgp_proto *p, struct bgp_conn *conn) |
287 |
{ |
288 |
uint i = conn->last_channel; |
289 |
|
290 |
/* Try the last channel, but at most several times */
|
291 |
if ((conn->channels_to_send & (1 << i)) && |
292 |
(conn->last_channel_count < 16))
|
293 |
goto found;
|
294 |
|
295 |
/* Find channel with non-zero channels_to_send */
|
296 |
do
|
297 |
{ |
298 |
i++; |
299 |
if (i >= p->channel_count)
|
300 |
i = 0;
|
301 |
} |
302 |
while (! (conn->channels_to_send & (1 << i))); |
303 |
|
304 |
/* Use that channel */
|
305 |
conn->last_channel = i; |
306 |
conn->last_channel_count = 0;
|
307 |
|
308 |
found:
|
309 |
conn->last_channel_count++; |
310 |
return p->channel_map[i];
|
311 |
} |
312 |
|
313 |
static void |
314 |
bgp_mrai_timeout(timer *t) |
315 |
{ |
316 |
//How to extract data from the timer
|
317 |
struct bgp_conn *conn = t->data;
|
318 |
struct bgp_channel *c;
|
319 |
|
320 |
//Simple message for the user
|
321 |
log(L_INFO "CIAO, MRAI timer scaduto, posso schedulare i pacchetti");
|
322 |
} |
323 |
|
324 |
static void |
325 |
bgp_initiate(struct bgp_proto *p)
|
326 |
{ |
327 |
int err_val;
|
328 |
|
329 |
if (bgp_open(p) < 0) |
330 |
{ err_val = BEM_NO_SOCKET; goto err1; }
|
331 |
|
332 |
if (bgp_setup_auth(p, 1) < 0) |
333 |
{ err_val = BEM_INVALID_MD5; goto err2; }
|
334 |
|
335 |
if (p->cf->bfd)
|
336 |
bgp_update_bfd(p, p->cf->bfd); |
337 |
|
338 |
|
339 |
|
340 |
if (p->startup_delay)
|
341 |
{ |
342 |
p->start_state = BSS_DELAY; |
343 |
BGP_TRACE(D_EVENTS, "Startup delayed by %d seconds due to errors", p->startup_delay);
|
344 |
bgp_start_timer(p->startup_timer, p->startup_delay); |
345 |
} |
346 |
else
|
347 |
bgp_startup(p); |
348 |
|
349 |
return;
|
350 |
|
351 |
err2:
|
352 |
bgp_close(p); |
353 |
err1:
|
354 |
p->p.disabled = 1;
|
355 |
bgp_store_error(p, NULL, BE_MISC, err_val);
|
356 |
proto_notify_state(&p->p, PS_DOWN); |
357 |
|
358 |
return;
|
359 |
} |
360 |
|
361 |
/**
|
362 |
* bgp_start_timer - start a BGP timer
|
363 |
* @t: timer
|
364 |
* @value: time (in seconds) to fire (0 to disable the timer)
|
365 |
*
|
366 |
* This functions calls tm_start() on @t with time @value and the amount of
|
367 |
* randomization suggested by the BGP standard. Please use it for all BGP
|
368 |
* timers.
|
369 |
*/
|
370 |
void
|
371 |
bgp_start_timer(timer *t, uint value) |
372 |
{ |
373 |
if (value)
|
374 |
{ |
375 |
/* The randomization procedure is specified in RFC 4271 section 10 */
|
376 |
btime time = value S; |
377 |
btime randomize = random() % ((time / 4) + 1); |
378 |
tm_start(t, time - randomize); |
379 |
} |
380 |
else
|
381 |
tm_stop(t); |
382 |
} |
383 |
|
384 |
/**
|
385 |
* bgp_close_conn - close a BGP connection
|
386 |
* @conn: connection to close
|
387 |
*
|
388 |
* This function takes a connection described by the &bgp_conn structure, closes
|
389 |
* its socket and frees all resources associated with it.
|
390 |
*/
|
391 |
void
|
392 |
bgp_close_conn(struct bgp_conn *conn)
|
393 |
{ |
394 |
DBG("BGP: Closing connection\n");
|
395 |
|
396 |
//log(L_INFO "AS del vicino con cui si vuole chiudere la connessione: %d",conn->bgp->remote_as);
|
397 |
const char *keyRTmap; |
398 |
map_iter_t iterRTmap; |
399 |
const char *keyNHmap_RTmap; |
400 |
map_iter_t iterNHmap_RTmap; |
401 |
|
402 |
//NH removing from the data structure
|
403 |
iterRTmap = map_iter(&RTmap); |
404 |
while ((keyRTmap = map_next(&RTmap, &iterRTmap))) {
|
405 |
RTable *RTmap_element = map_get(&RTmap, keyRTmap); |
406 |
iterNHmap_RTmap = map_iter(&RTmap_element->NH); |
407 |
while ((keyNHmap_RTmap = map_next(&RTmap_element->NH, &iterNHmap_RTmap))) {
|
408 |
int *NH_AS_value = map_get(&RTmap_element->NH, keyNHmap_RTmap);
|
409 |
if(NH_AS_value != NULL) { |
410 |
if (*NH_AS_value == conn->bgp->remote_as)
|
411 |
map_remove(&RTmap, keyRTmap); |
412 |
} |
413 |
} |
414 |
|
415 |
//Load removing from the data structure
|
416 |
const char *keyLoadInmap_RTmap; |
417 |
map_iter_t iterLoadInmap_RTmap = map_iter(&RTmap_element->loadin); |
418 |
while ((keyLoadInmap_RTmap = map_next(&RTmap_element->loadin, &iterLoadInmap_RTmap))) {
|
419 |
int keyValue = (int) strtol(keyLoadInmap_RTmap, (char **)NULL, 16); |
420 |
|
421 |
if(keyValue == conn->bgp->remote_as)
|
422 |
map_remove(&RTmap_element->loadin, keyLoadInmap_RTmap); |
423 |
} |
424 |
} |
425 |
|
426 |
conn->packets_to_send = 0;
|
427 |
conn->channels_to_send = 0;
|
428 |
rfree(conn->connect_timer); |
429 |
conn->connect_timer = NULL;
|
430 |
rfree(conn->keepalive_timer); |
431 |
conn->keepalive_timer = NULL;
|
432 |
rfree(conn->hold_timer); |
433 |
conn->hold_timer = NULL;
|
434 |
|
435 |
/* My MRAI timer */
|
436 |
rfree(conn->mrai_timer); |
437 |
conn->mrai_timer = NULL;
|
438 |
|
439 |
rfree(conn->tx_ev); |
440 |
conn->tx_ev = NULL;
|
441 |
rfree(conn->sk); |
442 |
conn->sk = NULL;
|
443 |
|
444 |
mb_free(conn->local_caps); |
445 |
conn->local_caps = NULL;
|
446 |
mb_free(conn->remote_caps); |
447 |
conn->remote_caps = NULL;
|
448 |
} |
449 |
|
450 |
/**
|
451 |
* bgp_update_startup_delay - update a startup delay
|
452 |
* @p: BGP instance
|
453 |
*
|
454 |
* This function updates a startup delay that is used to postpone next BGP
|
455 |
* connect. It also handles disable_after_error and might stop BGP instance
|
456 |
* when error happened and disable_after_error is on.
|
457 |
*
|
458 |
* It should be called when BGP protocol error happened.
|
459 |
*/
|
460 |
void
|
461 |
bgp_update_startup_delay(struct bgp_proto *p)
|
462 |
{ |
463 |
struct bgp_config *cf = p->cf;
|
464 |
|
465 |
DBG("BGP: Updating startup delay\n");
|
466 |
|
467 |
if (p->last_proto_error && ((current_time() - p->last_proto_error) >= cf->error_amnesia_time S))
|
468 |
p->startup_delay = 0;
|
469 |
|
470 |
p->last_proto_error = current_time(); |
471 |
|
472 |
if (cf->disable_after_error)
|
473 |
{ |
474 |
p->startup_delay = 0;
|
475 |
p->p.disabled = 1;
|
476 |
return;
|
477 |
} |
478 |
|
479 |
if (!p->startup_delay)
|
480 |
p->startup_delay = cf->error_delay_time_min; |
481 |
else
|
482 |
p->startup_delay = MIN(2 * p->startup_delay, cf->error_delay_time_max);
|
483 |
} |
484 |
|
485 |
static void |
486 |
bgp_graceful_close_conn(struct bgp_conn *conn, uint subcode, byte *data, uint len)
|
487 |
{ |
488 |
switch (conn->state)
|
489 |
{ |
490 |
case BS_IDLE:
|
491 |
case BS_CLOSE:
|
492 |
return;
|
493 |
|
494 |
case BS_CONNECT:
|
495 |
case BS_ACTIVE:
|
496 |
bgp_conn_enter_idle_state(conn); |
497 |
return;
|
498 |
|
499 |
case BS_OPENSENT:
|
500 |
case BS_OPENCONFIRM:
|
501 |
case BS_ESTABLISHED:
|
502 |
bgp_error(conn, 6, subcode, data, len);
|
503 |
return;
|
504 |
|
505 |
default:
|
506 |
bug("bgp_graceful_close_conn: Unknown state %d", conn->state);
|
507 |
} |
508 |
} |
509 |
|
510 |
static void |
511 |
bgp_down(struct bgp_proto *p)
|
512 |
{ |
513 |
if (p->start_state > BSS_PREPARE)
|
514 |
{ |
515 |
bgp_setup_auth(p, 0);
|
516 |
bgp_close(p); |
517 |
} |
518 |
|
519 |
BGP_TRACE(D_EVENTS, "Down");
|
520 |
proto_notify_state(&p->p, PS_DOWN); |
521 |
} |
522 |
|
523 |
static void |
524 |
bgp_decision(void *vp)
|
525 |
{ |
526 |
struct bgp_proto *p = vp;
|
527 |
|
528 |
DBG("BGP: Decision start\n");
|
529 |
if ((p->p.proto_state == PS_START) &&
|
530 |
(p->outgoing_conn.state == BS_IDLE) && |
531 |
(p->incoming_conn.state != BS_OPENCONFIRM) && |
532 |
!p->cf->passive) |
533 |
bgp_active(p); |
534 |
|
535 |
if ((p->p.proto_state == PS_STOP) &&
|
536 |
(p->outgoing_conn.state == BS_IDLE) && |
537 |
(p->incoming_conn.state == BS_IDLE)) |
538 |
bgp_down(p); |
539 |
} |
540 |
|
541 |
void
|
542 |
bgp_stop(struct bgp_proto *p, uint subcode, byte *data, uint len)
|
543 |
{ |
544 |
proto_notify_state(&p->p, PS_STOP); |
545 |
bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len); |
546 |
bgp_graceful_close_conn(&p->incoming_conn, subcode, data, len); |
547 |
ev_schedule(p->event); |
548 |
} |
549 |
|
550 |
static inline void |
551 |
bgp_conn_set_state(struct bgp_conn *conn, uint new_state)
|
552 |
{ |
553 |
if (conn->bgp->p.mrtdump & MD_STATES)
|
554 |
mrt_dump_bgp_state_change(conn, conn->state, new_state); |
555 |
|
556 |
conn->state = new_state; |
557 |
} |
558 |
|
559 |
void
|
560 |
bgp_conn_enter_openconfirm_state(struct bgp_conn *conn)
|
561 |
{ |
562 |
/* Really, most of the work is done in bgp_rx_open(). */
|
563 |
bgp_conn_set_state(conn, BS_OPENCONFIRM); |
564 |
} |
565 |
|
566 |
static const struct bgp_af_caps dummy_af_caps = { }; |
567 |
|
568 |
void
|
569 |
bgp_conn_enter_established_state(struct bgp_conn *conn)
|
570 |
{ |
571 |
struct bgp_proto *p = conn->bgp;
|
572 |
struct bgp_caps *local = conn->local_caps;
|
573 |
struct bgp_caps *peer = conn->remote_caps;
|
574 |
struct bgp_channel *c;
|
575 |
|
576 |
BGP_TRACE(D_EVENTS, "BGP session established");
|
577 |
|
578 |
/* For multi-hop BGP sessions */
|
579 |
if (ipa_zero(p->source_addr))
|
580 |
p->source_addr = conn->sk->saddr; |
581 |
|
582 |
conn->sk->fast_rx = 0;
|
583 |
|
584 |
p->conn = conn; |
585 |
p->last_error_class = 0;
|
586 |
p->last_error_code = 0;
|
587 |
|
588 |
p->as4_session = conn->as4_session; |
589 |
|
590 |
p->route_refresh = peer->route_refresh; |
591 |
p->enhanced_refresh = local->enhanced_refresh && peer->enhanced_refresh; |
592 |
|
593 |
/* Whether we may handle possible GR of peer (it has some AF GR-able) */
|
594 |
p->gr_ready = 0; /* Updated later */ |
595 |
|
596 |
/* Whether peer is ready to handle our GR recovery */
|
597 |
int peer_gr_ready = peer->gr_aware && !(peer->gr_flags & BGP_GRF_RESTART);
|
598 |
|
599 |
if (p->gr_active_num)
|
600 |
tm_stop(p->gr_timer); |
601 |
|
602 |
/* Number of active channels */
|
603 |
int num = 0; |
604 |
|
605 |
WALK_LIST(c, p->p.channels) |
606 |
{ |
607 |
const struct bgp_af_caps *loc = bgp_find_af_caps(local, c->afi); |
608 |
const struct bgp_af_caps *rem = bgp_find_af_caps(peer, c->afi); |
609 |
|
610 |
/* Ignore AFIs that were not announced in multiprotocol capability */
|
611 |
if (!loc || !loc->ready)
|
612 |
loc = &dummy_af_caps; |
613 |
|
614 |
if (!rem || !rem->ready)
|
615 |
rem = &dummy_af_caps; |
616 |
|
617 |
int active = loc->ready && rem->ready;
|
618 |
c->c.disabled = !active; |
619 |
c->c.reloadable = p->route_refresh; |
620 |
|
621 |
c->index = active ? num++ : 0;
|
622 |
|
623 |
c->feed_state = BFS_NONE; |
624 |
c->load_state = BFS_NONE; |
625 |
|
626 |
/* Channels where peer may do GR */
|
627 |
c->gr_ready = active && local->gr_aware && rem->gr_able; |
628 |
p->gr_ready = p->gr_ready || c->gr_ready; |
629 |
|
630 |
/* Channels not able to recover gracefully */
|
631 |
if (p->p.gr_recovery && (!active || !peer_gr_ready))
|
632 |
channel_graceful_restart_unlock(&c->c); |
633 |
|
634 |
/* Channels waiting for local convergence */
|
635 |
if (p->p.gr_recovery && loc->gr_able && peer_gr_ready)
|
636 |
c->c.gr_wait = 1;
|
637 |
|
638 |
/* Channels where peer is not able to recover gracefully */
|
639 |
if (c->gr_active && ! (c->gr_ready && (rem->gr_af_flags & BGP_GRF_FORWARDING)))
|
640 |
bgp_graceful_restart_done(c); |
641 |
|
642 |
/* GR capability implies that neighbor will send End-of-RIB */
|
643 |
if (peer->gr_aware)
|
644 |
c->load_state = BFS_LOADING; |
645 |
|
646 |
c->ext_next_hop = c->cf->ext_next_hop && (bgp_channel_is_ipv6(c) || rem->ext_next_hop); |
647 |
c->add_path_rx = (loc->add_path & BGP_ADD_PATH_RX) && (rem->add_path & BGP_ADD_PATH_TX); |
648 |
c->add_path_tx = (loc->add_path & BGP_ADD_PATH_TX) && (rem->add_path & BGP_ADD_PATH_RX); |
649 |
|
650 |
/* Update RA mode */
|
651 |
if (c->add_path_tx)
|
652 |
c->c.ra_mode = RA_ANY; |
653 |
else if (c->cf->secondary) |
654 |
c->c.ra_mode = RA_ACCEPTED; |
655 |
else
|
656 |
c->c.ra_mode = RA_OPTIMAL; |
657 |
} |
658 |
|
659 |
p->afi_map = mb_alloc(p->p.pool, num * sizeof(u32));
|
660 |
p->channel_map = mb_alloc(p->p.pool, num * sizeof(void *)); |
661 |
p->channel_count = num; |
662 |
|
663 |
WALK_LIST(c, p->p.channels) |
664 |
{ |
665 |
if (c->c.disabled)
|
666 |
continue;
|
667 |
|
668 |
p->afi_map[c->index] = c->afi; |
669 |
p->channel_map[c->index] = c; |
670 |
} |
671 |
|
672 |
/* proto_notify_state() will likely call bgp_feed_begin(), setting c->feed_state */
|
673 |
|
674 |
bgp_conn_set_state(conn, BS_ESTABLISHED); |
675 |
proto_notify_state(&p->p, PS_UP); |
676 |
|
677 |
//Start del timer mrai
|
678 |
//bgp_start_timer(conn->mrai_timer, 5);
|
679 |
} |
680 |
|
681 |
static void |
682 |
bgp_conn_leave_established_state(struct bgp_proto *p)
|
683 |
{ |
684 |
BGP_TRACE(D_EVENTS, "BGP session closed");
|
685 |
p->conn = NULL;
|
686 |
|
687 |
if (p->p.proto_state == PS_UP)
|
688 |
bgp_stop(p, 0, NULL, 0); |
689 |
} |
690 |
|
691 |
void
|
692 |
bgp_conn_enter_close_state(struct bgp_conn *conn)
|
693 |
{ |
694 |
struct bgp_proto *p = conn->bgp;
|
695 |
int os = conn->state;
|
696 |
|
697 |
bgp_conn_set_state(conn, BS_CLOSE); |
698 |
tm_stop(conn->keepalive_timer); |
699 |
conn->sk->rx_hook = NULL;
|
700 |
|
701 |
/* Timeout for CLOSE state, if we cannot send notification soon then we just hangup */
|
702 |
bgp_start_timer(conn->hold_timer, 10);
|
703 |
|
704 |
if (os == BS_ESTABLISHED)
|
705 |
bgp_conn_leave_established_state(p); |
706 |
} |
707 |
|
708 |
void
|
709 |
bgp_conn_enter_idle_state(struct bgp_conn *conn)
|
710 |
{ |
711 |
struct bgp_proto *p = conn->bgp;
|
712 |
int os = conn->state;
|
713 |
|
714 |
bgp_close_conn(conn); |
715 |
bgp_conn_set_state(conn, BS_IDLE); |
716 |
ev_schedule(p->event); |
717 |
|
718 |
if (os == BS_ESTABLISHED)
|
719 |
bgp_conn_leave_established_state(p); |
720 |
} |
721 |
|
722 |
/**
|
723 |
* bgp_handle_graceful_restart - handle detected BGP graceful restart
|
724 |
* @p: BGP instance
|
725 |
*
|
726 |
* This function is called when a BGP graceful restart of the neighbor is
|
727 |
* detected (when the TCP connection fails or when a new TCP connection
|
728 |
* appears). The function activates processing of the restart - starts routing
|
729 |
* table refresh cycle and activates BGP restart timer. The protocol state goes
|
730 |
* back to %PS_START, but changing BGP state back to %BS_IDLE is left for the
|
731 |
* caller.
|
732 |
*/
|
733 |
void
|
734 |
bgp_handle_graceful_restart(struct bgp_proto *p)
|
735 |
{ |
736 |
ASSERT(p->conn && (p->conn->state == BS_ESTABLISHED) && p->gr_ready); |
737 |
|
738 |
BGP_TRACE(D_EVENTS, "Neighbor graceful restart detected%s",
|
739 |
p->gr_active_num ? " - already pending" : ""); |
740 |
|
741 |
p->gr_active_num = 0;
|
742 |
|
743 |
struct bgp_channel *c;
|
744 |
WALK_LIST(c, p->p.channels) |
745 |
{ |
746 |
/* FIXME: perhaps check for channel state instead of disabled flag? */
|
747 |
if (c->c.disabled)
|
748 |
continue;
|
749 |
|
750 |
if (c->gr_ready)
|
751 |
{ |
752 |
if (c->gr_active)
|
753 |
rt_refresh_end(c->c.table, &c->c); |
754 |
|
755 |
c->gr_active = 1;
|
756 |
p->gr_active_num++; |
757 |
rt_refresh_begin(c->c.table, &c->c); |
758 |
} |
759 |
else
|
760 |
{ |
761 |
/* Just flush the routes */
|
762 |
rt_refresh_begin(c->c.table, &c->c); |
763 |
rt_refresh_end(c->c.table, &c->c); |
764 |
} |
765 |
|
766 |
/* Reset bucket and prefix tables */
|
767 |
bgp_free_bucket_table(c); |
768 |
bgp_free_prefix_table(c); |
769 |
bgp_init_bucket_table(c); |
770 |
bgp_init_prefix_table(c); |
771 |
c->packets_to_send = 0;
|
772 |
} |
773 |
|
774 |
/* p->gr_ready -> at least one active channel is c->gr_ready */
|
775 |
ASSERT(p->gr_active_num > 0);
|
776 |
|
777 |
proto_notify_state(&p->p, PS_START); |
778 |
bgp_start_timer(p->gr_timer, p->conn->remote_caps->gr_time); |
779 |
} |
780 |
|
781 |
/**
|
782 |
* bgp_graceful_restart_done - finish active BGP graceful restart
|
783 |
* @c: BGP channel
|
784 |
*
|
785 |
* This function is called when the active BGP graceful restart of the neighbor
|
786 |
* should be finished for channel @c - either successfully (the neighbor sends
|
787 |
* all paths and reports end-of-RIB for given AFI/SAFI on the new session) or
|
788 |
* unsuccessfully (the neighbor does not support BGP graceful restart on the new
|
789 |
* session). The function ends the routing table refresh cycle.
|
790 |
*/
|
791 |
void
|
792 |
bgp_graceful_restart_done(struct bgp_channel *c)
|
793 |
{ |
794 |
struct bgp_proto *p = (void *) c->c.proto; |
795 |
|
796 |
ASSERT(c->gr_active); |
797 |
c->gr_active = 0;
|
798 |
p->gr_active_num--; |
799 |
|
800 |
if (!p->gr_active_num)
|
801 |
BGP_TRACE(D_EVENTS, "Neighbor graceful restart done");
|
802 |
|
803 |
rt_refresh_end(c->c.table, &c->c); |
804 |
} |
805 |
|
806 |
/**
|
807 |
* bgp_graceful_restart_timeout - timeout of graceful restart 'restart timer'
|
808 |
* @t: timer
|
809 |
*
|
810 |
* This function is a timeout hook for @gr_timer, implementing BGP restart time
|
811 |
* limit for reestablisment of the BGP session after the graceful restart. When
|
812 |
* fired, we just proceed with the usual protocol restart.
|
813 |
*/
|
814 |
|
815 |
static void |
816 |
bgp_graceful_restart_timeout(timer *t) |
817 |
{ |
818 |
struct bgp_proto *p = t->data;
|
819 |
|
820 |
BGP_TRACE(D_EVENTS, "Neighbor graceful restart timeout");
|
821 |
bgp_stop(p, 0, NULL, 0); |
822 |
} |
823 |
|
824 |
|
825 |
/**
|
826 |
* bgp_refresh_begin - start incoming enhanced route refresh sequence
|
827 |
* @c: BGP channel
|
828 |
*
|
829 |
* This function is called when an incoming enhanced route refresh sequence is
|
830 |
* started by the neighbor, demarcated by the BoRR packet. The function updates
|
831 |
* the load state and starts the routing table refresh cycle. Note that graceful
|
832 |
* restart also uses routing table refresh cycle, but RFC 7313 and load states
|
833 |
* ensure that these two sequences do not overlap.
|
834 |
*/
|
835 |
void
|
836 |
bgp_refresh_begin(struct bgp_channel *c)
|
837 |
{ |
838 |
struct bgp_proto *p = (void *) c->c.proto; |
839 |
|
840 |
if (c->load_state == BFS_LOADING)
|
841 |
{ log(L_WARN "%s: BEGIN-OF-RR received before END-OF-RIB, ignoring", p->p.name); return; } |
842 |
|
843 |
c->load_state = BFS_REFRESHING; |
844 |
rt_refresh_begin(c->c.table, &c->c); |
845 |
} |
846 |
|
847 |
/**
|
848 |
* bgp_refresh_end - finish incoming enhanced route refresh sequence
|
849 |
* @c: BGP channel
|
850 |
*
|
851 |
* This function is called when an incoming enhanced route refresh sequence is
|
852 |
* finished by the neighbor, demarcated by the EoRR packet. The function updates
|
853 |
* the load state and ends the routing table refresh cycle. Routes not received
|
854 |
* during the sequence are removed by the nest.
|
855 |
*/
|
856 |
void
|
857 |
bgp_refresh_end(struct bgp_channel *c)
|
858 |
{ |
859 |
struct bgp_proto *p = (void *) c->c.proto; |
860 |
|
861 |
if (c->load_state != BFS_REFRESHING)
|
862 |
{ log(L_WARN "%s: END-OF-RR received without prior BEGIN-OF-RR, ignoring", p->p.name); return; } |
863 |
|
864 |
c->load_state = BFS_NONE; |
865 |
rt_refresh_end(c->c.table, &c->c); |
866 |
} |
867 |
|
868 |
|
869 |
static void |
870 |
bgp_send_open(struct bgp_conn *conn)
|
871 |
{ |
872 |
DBG("BGP: Sending open\n");
|
873 |
conn->sk->rx_hook = bgp_rx; |
874 |
conn->sk->tx_hook = bgp_tx; |
875 |
tm_stop(conn->connect_timer); |
876 |
bgp_schedule_packet(conn, NULL, PKT_OPEN);
|
877 |
bgp_conn_set_state(conn, BS_OPENSENT); |
878 |
bgp_start_timer(conn->hold_timer, conn->bgp->cf->initial_hold_time); |
879 |
|
880 |
/* My timer startup */
|
881 |
//bgp_start_timer(conn->mrai_timer, 10);
|
882 |
} |
883 |
|
884 |
static void |
885 |
bgp_connected(sock *sk) |
886 |
{ |
887 |
struct bgp_conn *conn = sk->data;
|
888 |
struct bgp_proto *p = conn->bgp;
|
889 |
|
890 |
BGP_TRACE(D_EVENTS, "Connected");
|
891 |
bgp_send_open(conn); |
892 |
} |
893 |
|
894 |
static void |
895 |
bgp_connect_timeout(timer *t) |
896 |
{ |
897 |
struct bgp_conn *conn = t->data;
|
898 |
struct bgp_proto *p = conn->bgp;
|
899 |
|
900 |
DBG("BGP: connect_timeout\n");
|
901 |
if (p->p.proto_state == PS_START)
|
902 |
{ |
903 |
bgp_close_conn(conn); |
904 |
bgp_connect(p); |
905 |
} |
906 |
else
|
907 |
bgp_conn_enter_idle_state(conn); |
908 |
} |
909 |
|
910 |
static void |
911 |
bgp_sock_err(sock *sk, int err)
|
912 |
{ |
913 |
struct bgp_conn *conn = sk->data;
|
914 |
struct bgp_proto *p = conn->bgp;
|
915 |
|
916 |
/*
|
917 |
* This error hook may be called either asynchronously from main
|
918 |
* loop, or synchronously from sk_send(). But sk_send() is called
|
919 |
* only from bgp_tx() and bgp_kick_tx(), which are both called
|
920 |
* asynchronously from main loop. Moreover, they end if err hook is
|
921 |
* called. Therefore, we could suppose that it is always called
|
922 |
* asynchronously.
|
923 |
*/
|
924 |
|
925 |
bgp_store_error(p, conn, BE_SOCKET, err); |
926 |
|
927 |
if (err)
|
928 |
BGP_TRACE(D_EVENTS, "Connection lost (%M)", err);
|
929 |
else
|
930 |
BGP_TRACE(D_EVENTS, "Connection closed");
|
931 |
|
932 |
if ((conn->state == BS_ESTABLISHED) && p->gr_ready)
|
933 |
bgp_handle_graceful_restart(p); |
934 |
|
935 |
bgp_conn_enter_idle_state(conn); |
936 |
} |
937 |
|
938 |
static void |
939 |
bgp_hold_timeout(timer *t) |
940 |
{ |
941 |
struct bgp_conn *conn = t->data;
|
942 |
struct bgp_proto *p = conn->bgp;
|
943 |
|
944 |
DBG("BGP: Hold timeout\n");
|
945 |
|
946 |
/* We are already closing the connection - just do hangup */
|
947 |
if (conn->state == BS_CLOSE)
|
948 |
{ |
949 |
BGP_TRACE(D_EVENTS, "Connection stalled");
|
950 |
bgp_conn_enter_idle_state(conn); |
951 |
return;
|
952 |
} |
953 |
|
954 |
/* If there is something in input queue, we are probably congested
|
955 |
and perhaps just not processed BGP packets in time. */
|
956 |
|
957 |
if (sk_rx_ready(conn->sk) > 0) |
958 |
bgp_start_timer(conn->hold_timer, 10);
|
959 |
else
|
960 |
bgp_error(conn, 4, 0, NULL, 0); |
961 |
} |
962 |
|
963 |
static void |
964 |
bgp_keepalive_timeout(timer *t) |
965 |
{ |
966 |
struct bgp_conn *conn = t->data;
|
967 |
|
968 |
DBG("BGP: Keepalive timer\n");
|
969 |
bgp_schedule_packet(conn, NULL, PKT_KEEPALIVE);
|
970 |
|
971 |
/* Kick TX a bit faster */
|
972 |
if (ev_active(conn->tx_ev))
|
973 |
ev_run(conn->tx_ev); |
974 |
} |
975 |
|
976 |
static void |
977 |
bgp_setup_conn(struct bgp_proto *p, struct bgp_conn *conn) |
978 |
{ |
979 |
conn->sk = NULL;
|
980 |
conn->bgp = p; |
981 |
|
982 |
conn->packets_to_send = 0;
|
983 |
conn->channels_to_send = 0;
|
984 |
conn->last_channel = 0;
|
985 |
conn->last_channel_count = 0;
|
986 |
p->number_of_update_sent = 0;
|
987 |
|
988 |
conn->connect_timer = tm_new_init(p->p.pool, bgp_connect_timeout, conn, 0, 0); |
989 |
conn->hold_timer = tm_new_init(p->p.pool, bgp_hold_timeout, conn, 0, 0); |
990 |
conn->keepalive_timer = tm_new_init(p->p.pool, bgp_keepalive_timeout, conn, 0, 0); |
991 |
|
992 |
/* My personal timer */
|
993 |
conn->mrai_timer = tm_new_init(p->p.pool, bgp_mrai_timeout, conn, 0, 0); |
994 |
|
995 |
conn->tx_ev = ev_new(p->p.pool); |
996 |
conn->tx_ev->hook = bgp_kick_tx; |
997 |
conn->tx_ev->data = conn; |
998 |
} |
999 |
|
1000 |
static void |
1001 |
bgp_setup_sk(struct bgp_conn *conn, sock *s)
|
1002 |
{ |
1003 |
s->data = conn; |
1004 |
s->err_hook = bgp_sock_err; |
1005 |
s->fast_rx = 1;
|
1006 |
conn->sk = s; |
1007 |
} |
1008 |
|
1009 |
static void |
1010 |
bgp_active(struct bgp_proto *p)
|
1011 |
{ |
1012 |
int delay = MAX(1, p->cf->connect_delay_time); |
1013 |
struct bgp_conn *conn = &p->outgoing_conn;
|
1014 |
|
1015 |
BGP_TRACE(D_EVENTS, "Connect delayed by %d seconds", delay);
|
1016 |
bgp_setup_conn(p, conn); |
1017 |
bgp_conn_set_state(conn, BS_ACTIVE); |
1018 |
bgp_start_timer(conn->connect_timer, delay); |
1019 |
} |
1020 |
|
1021 |
/**
|
1022 |
* bgp_connect - initiate an outgoing connection
|
1023 |
* @p: BGP instance
|
1024 |
*
|
1025 |
* The bgp_connect() function creates a new &bgp_conn and initiates
|
1026 |
* a TCP connection to the peer. The rest of connection setup is governed
|
1027 |
* by the BGP state machine as described in the standard.
|
1028 |
*/
|
1029 |
static void |
1030 |
bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing connection */ |
1031 |
{ |
1032 |
struct bgp_conn *conn = &p->outgoing_conn;
|
1033 |
int hops = p->cf->multihop ? : 1; |
1034 |
|
1035 |
srand((unsigned int)time(NULL)); |
1036 |
|
1037 |
DBG("BGP: Connecting\n");
|
1038 |
sock *s = sk_new(p->p.pool); |
1039 |
s->type = SK_TCP_ACTIVE; |
1040 |
s->saddr = p->source_addr; |
1041 |
s->daddr = p->cf->remote_ip; |
1042 |
s->dport = p->cf->remote_port; |
1043 |
s->iface = p->neigh ? p->neigh->iface : NULL;
|
1044 |
s->vrf = p->p.vrf; |
1045 |
s->ttl = p->cf->ttl_security ? 255 : hops;
|
1046 |
s->rbsize = p->cf->enable_extended_messages ? BGP_RX_BUFFER_EXT_SIZE : BGP_RX_BUFFER_SIZE; |
1047 |
s->tbsize = p->cf->enable_extended_messages ? BGP_TX_BUFFER_EXT_SIZE : BGP_TX_BUFFER_SIZE; |
1048 |
s->tos = IP_PREC_INTERNET_CONTROL; |
1049 |
s->password = p->cf->password; |
1050 |
s->tx_hook = bgp_connected; |
1051 |
BGP_TRACE(D_EVENTS, "Connecting to %I%J from local address %I%J", s->daddr, p->cf->iface,
|
1052 |
s->saddr, ipa_is_link_local(s->saddr) ? s->iface : NULL);
|
1053 |
bgp_setup_conn(p, conn); |
1054 |
bgp_setup_sk(conn, s); |
1055 |
bgp_conn_set_state(conn, BS_CONNECT); |
1056 |
|
1057 |
if (sk_open(s) < 0) |
1058 |
goto err;
|
1059 |
|
1060 |
/* Set minimal receive TTL if needed */
|
1061 |
if (p->cf->ttl_security)
|
1062 |
if (sk_set_min_ttl(s, 256 - hops) < 0) |
1063 |
goto err;
|
1064 |
|
1065 |
DBG("BGP: Waiting for connect success\n");
|
1066 |
bgp_start_timer(conn->connect_timer, p->cf->connect_retry_time); |
1067 |
return;
|
1068 |
|
1069 |
err:
|
1070 |
sk_log_error(s, p->p.name); |
1071 |
bgp_sock_err(s, 0);
|
1072 |
return;
|
1073 |
} |
1074 |
|
1075 |
/**
|
1076 |
* bgp_find_proto - find existing proto for incoming connection
|
1077 |
* @sk: TCP socket
|
1078 |
*
|
1079 |
*/
|
1080 |
static struct bgp_proto * |
1081 |
bgp_find_proto(sock *sk) |
1082 |
{ |
1083 |
struct bgp_proto *p;
|
1084 |
|
1085 |
WALK_LIST(p, proto_list) |
1086 |
if ((p->p.proto == &proto_bgp) &&
|
1087 |
ipa_equal(p->cf->remote_ip, sk->daddr) && |
1088 |
(!p->cf->iface || (p->cf->iface == sk->iface)) && |
1089 |
(ipa_zero(p->cf->local_ip) || ipa_equal(p->cf->local_ip, sk->saddr)) && |
1090 |
(p->cf->local_port == sk->sport)) |
1091 |
return p;
|
1092 |
|
1093 |
return NULL; |
1094 |
} |
1095 |
|
1096 |
/**
|
1097 |
* bgp_incoming_connection - handle an incoming connection
|
1098 |
* @sk: TCP socket
|
1099 |
* @dummy: unused
|
1100 |
*
|
1101 |
* This function serves as a socket hook for accepting of new BGP
|
1102 |
* connections. It searches a BGP instance corresponding to the peer
|
1103 |
* which has connected and if such an instance exists, it creates a
|
1104 |
* &bgp_conn structure, attaches it to the instance and either sends
|
1105 |
* an Open message or (if there already is an active connection) it
|
1106 |
* closes the new connection by sending a Notification message.
|
1107 |
*/
|
1108 |
static int |
1109 |
bgp_incoming_connection(sock *sk, uint dummy UNUSED) |
1110 |
{ |
1111 |
struct bgp_proto *p;
|
1112 |
int acc, hops;
|
1113 |
|
1114 |
DBG("BGP: Incoming connection from %I port %d\n", sk->daddr, sk->dport);
|
1115 |
p = bgp_find_proto(sk); |
1116 |
if (!p)
|
1117 |
{ |
1118 |
log(L_WARN "BGP: Unexpected connect from unknown address %I%J (port %d)",
|
1119 |
sk->daddr, ipa_is_link_local(sk->daddr) ? sk->iface : NULL, sk->dport);
|
1120 |
rfree(sk); |
1121 |
return 0; |
1122 |
} |
1123 |
|
1124 |
/*
|
1125 |
* BIRD should keep multiple incoming connections in OpenSent state (for
|
1126 |
* details RFC 4271 8.2.1 par 3), but it keeps just one. Duplicate incoming
|
1127 |
* connections are rejected istead. The exception is the case where an
|
1128 |
* incoming connection triggers a graceful restart.
|
1129 |
*/
|
1130 |
|
1131 |
acc = (p->p.proto_state == PS_START || p->p.proto_state == PS_UP) && |
1132 |
(p->start_state >= BSS_CONNECT) && (!p->incoming_conn.sk); |
1133 |
|
1134 |
if (p->conn && (p->conn->state == BS_ESTABLISHED) && p->gr_ready)
|
1135 |
{ |
1136 |
bgp_store_error(p, NULL, BE_MISC, BEM_GRACEFUL_RESTART);
|
1137 |
bgp_handle_graceful_restart(p); |
1138 |
bgp_conn_enter_idle_state(p->conn); |
1139 |
acc = 1;
|
1140 |
|
1141 |
/* There might be separate incoming connection in OpenSent state */
|
1142 |
if (p->incoming_conn.state > BS_ACTIVE)
|
1143 |
bgp_close_conn(&p->incoming_conn); |
1144 |
} |
1145 |
|
1146 |
BGP_TRACE(D_EVENTS, "Incoming connection from %I%J (port %d) %s",
|
1147 |
sk->daddr, ipa_is_link_local(sk->daddr) ? sk->iface : NULL,
|
1148 |
sk->dport, acc ? "accepted" : "rejected"); |
1149 |
|
1150 |
if (!acc)
|
1151 |
{ |
1152 |
rfree(sk); |
1153 |
return 0; |
1154 |
} |
1155 |
|
1156 |
hops = p->cf->multihop ? : 1;
|
1157 |
|
1158 |
if (sk_set_ttl(sk, p->cf->ttl_security ? 255 : hops) < 0) |
1159 |
goto err;
|
1160 |
|
1161 |
if (p->cf->ttl_security)
|
1162 |
if (sk_set_min_ttl(sk, 256 - hops) < 0) |
1163 |
goto err;
|
1164 |
|
1165 |
if (p->cf->enable_extended_messages)
|
1166 |
{ |
1167 |
sk->rbsize = BGP_RX_BUFFER_EXT_SIZE; |
1168 |
sk->tbsize = BGP_TX_BUFFER_EXT_SIZE; |
1169 |
sk_reallocate(sk); |
1170 |
} |
1171 |
|
1172 |
bgp_setup_conn(p, &p->incoming_conn); |
1173 |
bgp_setup_sk(&p->incoming_conn, sk); |
1174 |
bgp_send_open(&p->incoming_conn); |
1175 |
return 0; |
1176 |
|
1177 |
err:
|
1178 |
sk_log_error(sk, p->p.name); |
1179 |
log(L_ERR "%s: Incoming connection aborted", p->p.name);
|
1180 |
rfree(sk); |
1181 |
return 0; |
1182 |
} |
1183 |
|
1184 |
static void |
1185 |
bgp_listen_sock_err(sock *sk UNUSED, int err)
|
1186 |
{ |
1187 |
if (err == ECONNABORTED)
|
1188 |
log(L_WARN "BGP: Incoming connection aborted");
|
1189 |
else
|
1190 |
log(L_ERR "BGP: Error on listening socket: %M", err);
|
1191 |
} |
1192 |
|
1193 |
static void |
1194 |
bgp_start_neighbor(struct bgp_proto *p)
|
1195 |
{ |
1196 |
/* Called only for single-hop BGP sessions */
|
1197 |
|
1198 |
if (ipa_zero(p->source_addr))
|
1199 |
p->source_addr = p->neigh->ifa->ip; |
1200 |
|
1201 |
if (ipa_is_link_local(p->source_addr))
|
1202 |
p->link_addr = p->source_addr; |
1203 |
else if (p->neigh->iface->llv6) |
1204 |
p->link_addr = p->neigh->iface->llv6->ip; |
1205 |
|
1206 |
bgp_initiate(p); |
1207 |
} |
1208 |
|
1209 |
static void |
1210 |
bgp_neigh_notify(neighbor *n) |
1211 |
{ |
1212 |
struct bgp_proto *p = (struct bgp_proto *) n->proto; |
1213 |
int ps = p->p.proto_state;
|
1214 |
|
1215 |
if (n != p->neigh)
|
1216 |
return;
|
1217 |
|
1218 |
if ((ps == PS_DOWN) || (ps == PS_STOP))
|
1219 |
return;
|
1220 |
|
1221 |
int prepare = (ps == PS_START) && (p->start_state == BSS_PREPARE);
|
1222 |
|
1223 |
if (n->scope <= 0) |
1224 |
{ |
1225 |
if (!prepare)
|
1226 |
{ |
1227 |
BGP_TRACE(D_EVENTS, "Neighbor lost");
|
1228 |
bgp_store_error(p, NULL, BE_MISC, BEM_NEIGHBOR_LOST);
|
1229 |
/* Perhaps also run bgp_update_startup_delay(p)? */
|
1230 |
bgp_stop(p, 0, NULL, 0); |
1231 |
} |
1232 |
} |
1233 |
else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP)) |
1234 |
{ |
1235 |
if (!prepare)
|
1236 |
{ |
1237 |
BGP_TRACE(D_EVENTS, "Link down");
|
1238 |
bgp_store_error(p, NULL, BE_MISC, BEM_LINK_DOWN);
|
1239 |
if (ps == PS_UP)
|
1240 |
bgp_update_startup_delay(p); |
1241 |
bgp_stop(p, 0, NULL, 0); |
1242 |
} |
1243 |
} |
1244 |
else
|
1245 |
{ |
1246 |
if (prepare)
|
1247 |
{ |
1248 |
BGP_TRACE(D_EVENTS, "Neighbor ready");
|
1249 |
bgp_start_neighbor(p); |
1250 |
} |
1251 |
} |
1252 |
} |
1253 |
|
1254 |
static void |
1255 |
bgp_bfd_notify(struct bfd_request *req)
|
1256 |
{ |
1257 |
struct bgp_proto *p = req->data;
|
1258 |
int ps = p->p.proto_state;
|
1259 |
|
1260 |
if (req->down && ((ps == PS_START) || (ps == PS_UP)))
|
1261 |
{ |
1262 |
BGP_TRACE(D_EVENTS, "BFD session down");
|
1263 |
bgp_store_error(p, NULL, BE_MISC, BEM_BFD_DOWN);
|
1264 |
if (ps == PS_UP)
|
1265 |
bgp_update_startup_delay(p); |
1266 |
bgp_stop(p, 0, NULL, 0); |
1267 |
} |
1268 |
} |
1269 |
|
1270 |
static void |
1271 |
bgp_update_bfd(struct bgp_proto *p, int use_bfd) |
1272 |
{ |
1273 |
if (use_bfd && !p->bfd_req)
|
1274 |
p->bfd_req = bfd_request_session(p->p.pool, p->cf->remote_ip, p->source_addr, |
1275 |
p->cf->multihop ? NULL : p->neigh->iface,
|
1276 |
bgp_bfd_notify, p); |
1277 |
|
1278 |
if (!use_bfd && p->bfd_req)
|
1279 |
{ |
1280 |
rfree(p->bfd_req); |
1281 |
p->bfd_req = NULL;
|
1282 |
} |
1283 |
} |
1284 |
|
1285 |
static void |
1286 |
bgp_reload_routes(struct channel *C)
|
1287 |
{ |
1288 |
log(L_INFO "mi trovo in bgp_reload_routes");
|
1289 |
struct bgp_proto *p = (void *) C->proto; |
1290 |
struct bgp_channel *c = (void *) C; |
1291 |
|
1292 |
ASSERT(p->conn && p->route_refresh); |
1293 |
|
1294 |
bgp_schedule_packet(p->conn, c, PKT_ROUTE_REFRESH); |
1295 |
} |
1296 |
|
1297 |
static void |
1298 |
bgp_feed_begin(struct channel *C, int initial) |
1299 |
{ |
1300 |
//log(L_INFO "mi trovo in bgp_feed_begin, initial: %d", initial);
|
1301 |
struct bgp_proto *p = (void *) C->proto; |
1302 |
struct bgp_channel *c = (void *) C; |
1303 |
|
1304 |
/* This should not happen */
|
1305 |
if (!p->conn)
|
1306 |
return;
|
1307 |
|
1308 |
if (initial && p->cf->gr_mode)
|
1309 |
c->feed_state = BFS_LOADING; |
1310 |
|
1311 |
/* It is refeed and both sides support enhanced route refresh */
|
1312 |
if (!initial && p->enhanced_refresh)
|
1313 |
{ |
1314 |
/* BoRR must not be sent before End-of-RIB */
|
1315 |
if (c->feed_state == BFS_LOADING || c->feed_state == BFS_LOADED)
|
1316 |
return;
|
1317 |
|
1318 |
c->feed_state = BFS_REFRESHING; |
1319 |
bgp_schedule_packet(p->conn, c, PKT_BEGIN_REFRESH); |
1320 |
} |
1321 |
} |
1322 |
|
1323 |
static void |
1324 |
bgp_feed_end(struct channel *C)
|
1325 |
{ |
1326 |
struct bgp_proto *p = (void *) C->proto; |
1327 |
struct bgp_channel *c = (void *) C; |
1328 |
|
1329 |
/* This should not happen */
|
1330 |
if (!p->conn)
|
1331 |
return;
|
1332 |
|
1333 |
/* Non-demarcated feed ended, nothing to do */
|
1334 |
if (c->feed_state == BFS_NONE)
|
1335 |
return;
|
1336 |
|
1337 |
/* Schedule End-of-RIB packet */
|
1338 |
if (c->feed_state == BFS_LOADING)
|
1339 |
c->feed_state = BFS_LOADED; |
1340 |
|
1341 |
/* Schedule EoRR packet */
|
1342 |
if (c->feed_state == BFS_REFRESHING)
|
1343 |
c->feed_state = BFS_REFRESHED; |
1344 |
|
1345 |
/* Kick TX hook */
|
1346 |
bgp_schedule_packet(p->conn, c, PKT_UPDATE); |
1347 |
} |
1348 |
|
1349 |
|
1350 |
static void |
1351 |
bgp_start_locked(struct object_lock *lock)
|
1352 |
{ |
1353 |
struct bgp_proto *p = lock->data;
|
1354 |
struct bgp_config *cf = p->cf;
|
1355 |
|
1356 |
if (p->p.proto_state != PS_START)
|
1357 |
{ |
1358 |
DBG("BGP: Got lock in different state %d\n", p->p.proto_state);
|
1359 |
return;
|
1360 |
} |
1361 |
|
1362 |
DBG("BGP: Got lock\n");
|
1363 |
|
1364 |
if (cf->multihop)
|
1365 |
{ |
1366 |
/* Multi-hop sessions do not use neighbor entries */
|
1367 |
bgp_initiate(p); |
1368 |
return;
|
1369 |
} |
1370 |
|
1371 |
neighbor *n = neigh_find2(&p->p, &cf->remote_ip, cf->iface, NEF_STICKY); |
1372 |
if (!n)
|
1373 |
{ |
1374 |
log(L_ERR "%s: Invalid remote address %I%J", p->p.name, cf->remote_ip, cf->iface);
|
1375 |
/* As we do not start yet, we can just disable protocol */
|
1376 |
p->p.disabled = 1;
|
1377 |
bgp_store_error(p, NULL, BE_MISC, BEM_INVALID_NEXT_HOP);
|
1378 |
proto_notify_state(&p->p, PS_DOWN); |
1379 |
return;
|
1380 |
} |
1381 |
|
1382 |
p->neigh = n; |
1383 |
|
1384 |
if (n->scope <= 0) |
1385 |
BGP_TRACE(D_EVENTS, "Waiting for %I%J to become my neighbor", cf->remote_ip, cf->iface);
|
1386 |
else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP)) |
1387 |
BGP_TRACE(D_EVENTS, "Waiting for link on %s", n->iface->name);
|
1388 |
else
|
1389 |
bgp_start_neighbor(p); |
1390 |
} |
1391 |
|
1392 |
static int |
1393 |
bgp_start(struct proto *P)
|
1394 |
{ |
1395 |
struct bgp_proto *p = (struct bgp_proto *) P; |
1396 |
struct object_lock *lock;
|
1397 |
|
1398 |
DBG("BGP: Startup.\n");
|
1399 |
p->start_state = BSS_PREPARE; |
1400 |
p->outgoing_conn.state = BS_IDLE; |
1401 |
p->incoming_conn.state = BS_IDLE; |
1402 |
p->neigh = NULL;
|
1403 |
p->bfd_req = NULL;
|
1404 |
p->gr_ready = 0;
|
1405 |
p->gr_active_num = 0;
|
1406 |
|
1407 |
p->event = ev_new(p->p.pool); |
1408 |
p->event->hook = bgp_decision; |
1409 |
p->event->data = p; |
1410 |
|
1411 |
p->startup_timer = tm_new_init(p->p.pool, bgp_startup_timeout, p, 0, 0); |
1412 |
p->gr_timer = tm_new_init(p->p.pool, bgp_graceful_restart_timeout, p, 0, 0); |
1413 |
|
1414 |
p->local_id = proto_get_router_id(P->cf); |
1415 |
if (p->rr_client)
|
1416 |
p->rr_cluster_id = p->cf->rr_cluster_id ? p->cf->rr_cluster_id : p->local_id; |
1417 |
|
1418 |
p->remote_id = 0;
|
1419 |
p->source_addr = p->cf->local_ip; |
1420 |
p->link_addr = IPA_NONE; |
1421 |
|
1422 |
/* Lock all channels when in GR recovery mode */
|
1423 |
if (p->p.gr_recovery && p->cf->gr_mode)
|
1424 |
{ |
1425 |
struct bgp_channel *c;
|
1426 |
WALK_LIST(c, p->p.channels) |
1427 |
channel_graceful_restart_lock(&c->c); |
1428 |
} |
1429 |
|
1430 |
/*
|
1431 |
* Before attempting to create the connection, we need to lock the port,
|
1432 |
* so that we are the only instance attempting to talk with that neighbor.
|
1433 |
*/
|
1434 |
|
1435 |
lock = p->lock = olock_new(P->pool); |
1436 |
lock->addr = p->cf->remote_ip; |
1437 |
lock->port = p->cf->remote_port; |
1438 |
lock->iface = p->cf->iface; |
1439 |
lock->vrf = p->cf->iface ? NULL : p->p.vrf;
|
1440 |
lock->type = OBJLOCK_TCP; |
1441 |
lock->hook = bgp_start_locked; |
1442 |
lock->data = p; |
1443 |
olock_acquire(lock); |
1444 |
|
1445 |
return PS_START;
|
1446 |
} |
1447 |
|
1448 |
extern int proto_restart; |
1449 |
|
1450 |
static int |
1451 |
bgp_shutdown(struct proto *P)
|
1452 |
{ |
1453 |
struct bgp_proto *p = (struct bgp_proto *) P; |
1454 |
uint subcode = 0;
|
1455 |
|
1456 |
char *message = NULL; |
1457 |
byte *data = NULL;
|
1458 |
uint len = 0;
|
1459 |
|
1460 |
BGP_TRACE(D_EVENTS, "Shutdown requested");
|
1461 |
|
1462 |
switch (P->down_code)
|
1463 |
{ |
1464 |
case PDC_CF_REMOVE:
|
1465 |
case PDC_CF_DISABLE:
|
1466 |
subcode = 3; // Errcode 6, 3 - peer de-configured |
1467 |
break;
|
1468 |
|
1469 |
case PDC_CF_RESTART:
|
1470 |
subcode = 6; // Errcode 6, 6 - other configuration change |
1471 |
break;
|
1472 |
|
1473 |
case PDC_CMD_DISABLE:
|
1474 |
case PDC_CMD_SHUTDOWN:
|
1475 |
subcode = 2; // Errcode 6, 2 - administrative shutdown |
1476 |
message = P->message; |
1477 |
break;
|
1478 |
|
1479 |
case PDC_CMD_RESTART:
|
1480 |
subcode = 4; // Errcode 6, 4 - administrative reset |
1481 |
message = P->message; |
1482 |
break;
|
1483 |
|
1484 |
case PDC_RX_LIMIT_HIT:
|
1485 |
case PDC_IN_LIMIT_HIT:
|
1486 |
subcode = 1; // Errcode 6, 1 - max number of prefixes reached |
1487 |
/* log message for compatibility */
|
1488 |
log(L_WARN "%s: Route limit exceeded, shutting down", p->p.name);
|
1489 |
goto limit;
|
1490 |
|
1491 |
case PDC_OUT_LIMIT_HIT:
|
1492 |
subcode = proto_restart ? 4 : 2; // Administrative reset or shutdown |
1493 |
|
1494 |
limit:
|
1495 |
bgp_store_error(p, NULL, BE_AUTO_DOWN, BEA_ROUTE_LIMIT_EXCEEDED);
|
1496 |
if (proto_restart)
|
1497 |
bgp_update_startup_delay(p); |
1498 |
else
|
1499 |
p->startup_delay = 0;
|
1500 |
goto done;
|
1501 |
} |
1502 |
|
1503 |
bgp_store_error(p, NULL, BE_MAN_DOWN, 0); |
1504 |
p->startup_delay = 0;
|
1505 |
|
1506 |
/* RFC 8203 - shutdown communication */
|
1507 |
if (message)
|
1508 |
{ |
1509 |
uint msg_len = strlen(message); |
1510 |
msg_len = MIN(msg_len, 128);
|
1511 |
|
1512 |
/* Buffer will be freed automatically by protocol shutdown */
|
1513 |
data = mb_alloc(p->p.pool, msg_len + 1);
|
1514 |
len = msg_len + 1;
|
1515 |
|
1516 |
data[0] = msg_len;
|
1517 |
memcpy(data+1, message, msg_len);
|
1518 |
} |
1519 |
|
1520 |
done:
|
1521 |
bgp_stop(p, subcode, data, len); |
1522 |
return p->p.proto_state;
|
1523 |
} |
1524 |
|
1525 |
static struct proto * |
1526 |
bgp_init(struct proto_config *CF)
|
1527 |
{ |
1528 |
struct proto *P = proto_new(CF);
|
1529 |
struct bgp_proto *p = (struct bgp_proto *) P; |
1530 |
struct bgp_config *cf = (struct bgp_config *) CF; |
1531 |
|
1532 |
P->rt_notify = bgp_rt_notify; |
1533 |
P->import_control = bgp_import_control; |
1534 |
P->neigh_notify = bgp_neigh_notify; |
1535 |
P->reload_routes = bgp_reload_routes; |
1536 |
P->feed_begin = bgp_feed_begin; |
1537 |
P->feed_end = bgp_feed_end; |
1538 |
P->rte_better = bgp_rte_better; |
1539 |
P->rte_mergable = bgp_rte_mergable; |
1540 |
P->rte_recalculate = cf->deterministic_med ? bgp_rte_recalculate : NULL;
|
1541 |
|
1542 |
p->cf = cf; |
1543 |
p->local_as = cf->local_as; |
1544 |
p->remote_as = cf->remote_as; |
1545 |
p->public_as = cf->local_as; |
1546 |
p->is_internal = (cf->local_as == cf->remote_as); |
1547 |
p->is_interior = p->is_internal || cf->confederation_member; |
1548 |
p->rs_client = cf->rs_client; |
1549 |
p->rr_client = cf->rr_client; |
1550 |
|
1551 |
/* Confederation ID is used for truly external peers */
|
1552 |
if (cf->confederation && !p->is_interior)
|
1553 |
p->public_as = cf->confederation; |
1554 |
|
1555 |
/* Add all channels */
|
1556 |
struct bgp_channel_config *cc;
|
1557 |
WALK_LIST(cc, CF->channels) |
1558 |
proto_add_channel(P, &cc->c); |
1559 |
|
1560 |
return P;
|
1561 |
} |
1562 |
|
1563 |
static void |
1564 |
bgp_channel_init(struct channel *C, struct channel_config *CF) |
1565 |
{ |
1566 |
struct bgp_channel *c = (void *) C; |
1567 |
struct bgp_channel_config *cf = (void *) CF; |
1568 |
|
1569 |
c->cf = cf; |
1570 |
c->afi = cf->afi; |
1571 |
c->desc = cf->desc; |
1572 |
|
1573 |
if (cf->igp_table_ip4)
|
1574 |
c->igp_table_ip4 = cf->igp_table_ip4->table; |
1575 |
|
1576 |
if (cf->igp_table_ip6)
|
1577 |
c->igp_table_ip6 = cf->igp_table_ip6->table; |
1578 |
} |
1579 |
|
1580 |
static int |
1581 |
bgp_channel_start(struct channel *C)
|
1582 |
{ |
1583 |
struct bgp_proto *p = (void *) C->proto; |
1584 |
struct bgp_channel *c = (void *) C; |
1585 |
ip_addr src = p->source_addr; |
1586 |
|
1587 |
if (c->igp_table_ip4)
|
1588 |
rt_lock_table(c->igp_table_ip4); |
1589 |
|
1590 |
if (c->igp_table_ip6)
|
1591 |
rt_lock_table(c->igp_table_ip6); |
1592 |
|
1593 |
c->pool = p->p.pool; // XXXX
|
1594 |
bgp_init_bucket_table(c); |
1595 |
bgp_init_prefix_table(c); |
1596 |
|
1597 |
c->next_hop_addr = c->cf->next_hop_addr; |
1598 |
c->link_addr = IPA_NONE; |
1599 |
c->packets_to_send = 0;
|
1600 |
|
1601 |
/* Try to use source address as next hop address */
|
1602 |
if (ipa_zero(c->next_hop_addr))
|
1603 |
{ |
1604 |
if (bgp_channel_is_ipv4(c) && (ipa_is_ip4(src) || c->ext_next_hop))
|
1605 |
c->next_hop_addr = src; |
1606 |
|
1607 |
if (bgp_channel_is_ipv6(c) && (ipa_is_ip6(src) || c->ext_next_hop))
|
1608 |
c->next_hop_addr = src; |
1609 |
} |
1610 |
|
1611 |
/* Use preferred addresses associated with interface / source address */
|
1612 |
if (ipa_zero(c->next_hop_addr))
|
1613 |
{ |
1614 |
/* We know the iface for single-hop, we make lookup for multihop */
|
1615 |
struct neighbor *nbr = p->neigh ?: neigh_find2(&p->p, &src, NULL, 0); |
1616 |
struct iface *iface = nbr ? nbr->iface : NULL; |
1617 |
|
1618 |
if (bgp_channel_is_ipv4(c) && iface && iface->addr4)
|
1619 |
c->next_hop_addr = iface->addr4->ip; |
1620 |
|
1621 |
if (bgp_channel_is_ipv6(c) && iface && iface->addr6)
|
1622 |
c->next_hop_addr = iface->addr6->ip; |
1623 |
} |
1624 |
|
1625 |
/* Exit if no feasible next hop address is found */
|
1626 |
if (ipa_zero(c->next_hop_addr))
|
1627 |
{ |
1628 |
log(L_WARN "%s: Missing next hop address", p->p.name);
|
1629 |
return 0; |
1630 |
} |
1631 |
|
1632 |
/* Set link-local address for IPv6 single-hop BGP */
|
1633 |
if (ipa_is_ip6(c->next_hop_addr) && p->neigh)
|
1634 |
{ |
1635 |
c->link_addr = p->link_addr; |
1636 |
|
1637 |
if (ipa_zero(c->link_addr))
|
1638 |
log(L_WARN "%s: Missing link-local address", p->p.name);
|
1639 |
} |
1640 |
|
1641 |
/* Link local address is already in c->link_addr */
|
1642 |
if (ipa_is_link_local(c->next_hop_addr))
|
1643 |
c->next_hop_addr = IPA_NONE; |
1644 |
|
1645 |
return 0; /* XXXX: Currently undefined */ |
1646 |
} |
1647 |
|
1648 |
static void |
1649 |
bgp_channel_shutdown(struct channel *C)
|
1650 |
{ |
1651 |
struct bgp_channel *c = (void *) C; |
1652 |
|
1653 |
c->next_hop_addr = IPA_NONE; |
1654 |
c->link_addr = IPA_NONE; |
1655 |
c->packets_to_send = 0;
|
1656 |
} |
1657 |
|
1658 |
static void |
1659 |
bgp_channel_cleanup(struct channel *C)
|
1660 |
{ |
1661 |
struct bgp_channel *c = (void *) C; |
1662 |
|
1663 |
if (c->igp_table_ip4)
|
1664 |
rt_unlock_table(c->igp_table_ip4); |
1665 |
|
1666 |
if (c->igp_table_ip6)
|
1667 |
rt_unlock_table(c->igp_table_ip6); |
1668 |
} |
1669 |
|
1670 |
static inline struct bgp_channel_config * |
1671 |
bgp_find_channel_config(struct bgp_config *cf, u32 afi)
|
1672 |
{ |
1673 |
struct bgp_channel_config *cc;
|
1674 |
|
1675 |
WALK_LIST(cc, cf->c.channels) |
1676 |
if (cc->afi == afi)
|
1677 |
return cc;
|
1678 |
|
1679 |
return NULL; |
1680 |
} |
1681 |
|
1682 |
struct rtable_config *
|
1683 |
bgp_default_igp_table(struct bgp_config *cf, struct bgp_channel_config *cc, u32 type) |
1684 |
{ |
1685 |
struct bgp_channel_config *cc2;
|
1686 |
struct rtable_config *tab;
|
1687 |
|
1688 |
/* First, try table connected by the channel */
|
1689 |
if (cc->c.table->addr_type == type)
|
1690 |
return cc->c.table;
|
1691 |
|
1692 |
/* Find paired channel with the same SAFI but the other AFI */
|
1693 |
u32 afi2 = cc->afi ^ 0x30000;
|
1694 |
cc2 = bgp_find_channel_config(cf, afi2); |
1695 |
|
1696 |
/* Second, try IGP table configured in the paired channel */
|
1697 |
if (cc2 && (tab = (type == NET_IP4) ? cc2->igp_table_ip4 : cc2->igp_table_ip6))
|
1698 |
return tab;
|
1699 |
|
1700 |
/* Third, try table connected by the paired channel */
|
1701 |
if (cc2 && (cc2->c.table->addr_type == type))
|
1702 |
return cc2->c.table;
|
1703 |
|
1704 |
/* Last, try default table of given type */
|
1705 |
if (tab = cf->c.global->def_tables[type])
|
1706 |
return tab;
|
1707 |
|
1708 |
cf_error("Undefined IGP table");
|
1709 |
} |
1710 |
|
1711 |
void
|
1712 |
bgp_postconfig(struct proto_config *CF)
|
1713 |
{ |
1714 |
struct bgp_config *cf = (void *) CF; |
1715 |
int internal = (cf->local_as == cf->remote_as);
|
1716 |
int interior = internal || cf->confederation_member;
|
1717 |
|
1718 |
/* Do not check templates at all */
|
1719 |
if (cf->c.class == SYM_TEMPLATE)
|
1720 |
return;
|
1721 |
|
1722 |
|
1723 |
/* EBGP direct by default, IBGP multihop by default */
|
1724 |
if (cf->multihop < 0) |
1725 |
cf->multihop = internal ? 64 : 0; |
1726 |
|
1727 |
/* Link check for single-hop BGP by default */
|
1728 |
if (cf->check_link < 0) |
1729 |
cf->check_link = !cf->multihop; |
1730 |
|
1731 |
|
1732 |
if (!cf->local_as)
|
1733 |
cf_error("Local AS number must be set");
|
1734 |
|
1735 |
if (ipa_zero(cf->remote_ip))
|
1736 |
cf_error("Neighbor must be configured");
|
1737 |
|
1738 |
if (!cf->remote_as)
|
1739 |
cf_error("Remote AS number must be set");
|
1740 |
|
1741 |
if (ipa_is_link_local(cf->remote_ip) && !cf->iface)
|
1742 |
cf_error("Link-local neighbor address requires specified interface");
|
1743 |
|
1744 |
if (!(cf->capabilities && cf->enable_as4) && (cf->remote_as > 0xFFFF)) |
1745 |
cf_error("Neighbor AS number out of range (AS4 not available)");
|
1746 |
|
1747 |
if (!internal && cf->rr_client)
|
1748 |
cf_error("Only internal neighbor can be RR client");
|
1749 |
|
1750 |
if (internal && cf->rs_client)
|
1751 |
cf_error("Only external neighbor can be RS client");
|
1752 |
|
1753 |
if (!cf->confederation && cf->confederation_member)
|
1754 |
cf_error("Confederation ID must be set for member sessions");
|
1755 |
|
1756 |
if (cf->multihop && (ipa_is_link_local(cf->local_ip) ||
|
1757 |
ipa_is_link_local(cf->remote_ip))) |
1758 |
cf_error("Multihop BGP cannot be used with link-local addresses");
|
1759 |
|
1760 |
if (cf->multihop && cf->iface)
|
1761 |
cf_error("Multihop BGP cannot be bound to interface");
|
1762 |
|
1763 |
if (cf->multihop && cf->check_link)
|
1764 |
cf_error("Multihop BGP cannot depend on link state");
|
1765 |
|
1766 |
if (cf->multihop && cf->bfd && ipa_zero(cf->local_ip))
|
1767 |
cf_error("Multihop BGP with BFD requires specified local address");
|
1768 |
|
1769 |
|
1770 |
struct bgp_channel_config *cc;
|
1771 |
WALK_LIST(cc, CF->channels) |
1772 |
{ |
1773 |
/* Handle undefined import filter */
|
1774 |
if (cc->c.in_filter == FILTER_UNDEF)
|
1775 |
if (interior)
|
1776 |
cc->c.in_filter = FILTER_ACCEPT; |
1777 |
else
|
1778 |
cf_error("EBGP requires explicit import policy");
|
1779 |
|
1780 |
/* Handle undefined export filter */
|
1781 |
if (cc->c.out_filter == FILTER_UNDEF)
|
1782 |
if (interior)
|
1783 |
cc->c.out_filter = FILTER_REJECT; |
1784 |
else
|
1785 |
cf_error("EBGP requires explicit export policy");
|
1786 |
|
1787 |
/* Disable after error incompatible with restart limit action */
|
1788 |
if ((cc->c.in_limit.action == PLA_RESTART) && cf->disable_after_error)
|
1789 |
cc->c.in_limit.action = PLA_DISABLE; |
1790 |
|
1791 |
/* Different default based on rs_client */
|
1792 |
if (!cc->missing_lladdr)
|
1793 |
cc->missing_lladdr = cf->rs_client ? MLL_IGNORE : MLL_SELF; |
1794 |
|
1795 |
/* Different default for gw_mode */
|
1796 |
if (!cc->gw_mode)
|
1797 |
cc->gw_mode = cf->multihop ? GW_RECURSIVE : GW_DIRECT; |
1798 |
|
1799 |
/* Default based on proto config */
|
1800 |
if (cc->gr_able == 0xff) |
1801 |
cc->gr_able = (cf->gr_mode == BGP_GR_ABLE); |
1802 |
|
1803 |
/* Default values of IGP tables */
|
1804 |
if ((cc->gw_mode == GW_RECURSIVE) && !cc->desc->no_igp)
|
1805 |
{ |
1806 |
if (!cc->igp_table_ip4 && (bgp_cc_is_ipv4(cc) || cc->ext_next_hop))
|
1807 |
cc->igp_table_ip4 = bgp_default_igp_table(cf, cc, NET_IP4); |
1808 |
|
1809 |
if (!cc->igp_table_ip6 && (bgp_cc_is_ipv6(cc) || cc->ext_next_hop))
|
1810 |
cc->igp_table_ip6 = bgp_default_igp_table(cf, cc, NET_IP6); |
1811 |
|
1812 |
if (cc->igp_table_ip4 && bgp_cc_is_ipv6(cc) && !cc->ext_next_hop)
|
1813 |
cf_error("Mismatched IGP table type");
|
1814 |
|
1815 |
if (cc->igp_table_ip6 && bgp_cc_is_ipv4(cc) && !cc->ext_next_hop)
|
1816 |
cf_error("Mismatched IGP table type");
|
1817 |
} |
1818 |
|
1819 |
if (cf->multihop && (cc->gw_mode == GW_DIRECT))
|
1820 |
cf_error("Multihop BGP cannot use direct gateway mode");
|
1821 |
|
1822 |
if ((cc->gw_mode == GW_RECURSIVE) && cc->c.table->sorted)
|
1823 |
cf_error("BGP in recursive mode prohibits sorted table");
|
1824 |
|
1825 |
if (cf->deterministic_med && cc->c.table->sorted)
|
1826 |
cf_error("BGP with deterministic MED prohibits sorted table");
|
1827 |
|
1828 |
if (cc->secondary && !cc->c.table->sorted)
|
1829 |
cf_error("BGP with secondary option requires sorted table");
|
1830 |
} |
1831 |
} |
1832 |
|
1833 |
static int |
1834 |
bgp_reconfigure(struct proto *P, struct proto_config *CF) |
1835 |
{ |
1836 |
struct bgp_proto *p = (void *) P; |
1837 |
struct bgp_config *new = (void *) CF; |
1838 |
struct bgp_config *old = p->cf;
|
1839 |
|
1840 |
if (proto_get_router_id(CF) != p->local_id)
|
1841 |
return 0; |
1842 |
|
1843 |
int same = !memcmp(((byte *) old) + sizeof(struct proto_config), |
1844 |
((byte *) new) + sizeof(struct proto_config), |
1845 |
// password item is last and must be checked separately
|
1846 |
OFFSETOF(struct bgp_config, password) - sizeof(struct proto_config)) |
1847 |
&& ((!old->password && !new->password) |
1848 |
|| (old->password && new->password && !strcmp(old->password, new->password))); |
1849 |
|
1850 |
/* FIXME: Move channel reconfiguration to generic protocol code ? */
|
1851 |
struct channel *C, *C2;
|
1852 |
struct bgp_channel_config *cc;
|
1853 |
|
1854 |
WALK_LIST(C, p->p.channels) |
1855 |
C->stale = 1;
|
1856 |
|
1857 |
WALK_LIST(cc, new->c.channels) |
1858 |
{ |
1859 |
C = (struct channel *) bgp_find_channel(p, cc->afi);
|
1860 |
same = proto_configure_channel(P, &C, &cc->c) && same; |
1861 |
C->stale = 0;
|
1862 |
} |
1863 |
|
1864 |
WALK_LIST_DELSAFE(C, C2, p->p.channels) |
1865 |
if (C->stale)
|
1866 |
same = proto_configure_channel(P, &C, NULL) && same;
|
1867 |
|
1868 |
|
1869 |
if (same && (p->start_state > BSS_PREPARE))
|
1870 |
bgp_update_bfd(p, new->bfd); |
1871 |
|
1872 |
/* We should update our copy of configuration ptr as old configuration will be freed */
|
1873 |
if (same)
|
1874 |
p->cf = new; |
1875 |
|
1876 |
return same;
|
1877 |
} |
1878 |
|
1879 |
#define IGP_TABLE(cf, sym) ((cf)->igp_table_##sym ? (cf)->igp_table_##sym ->table : NULL ) |
1880 |
|
1881 |
static int |
1882 |
bgp_channel_reconfigure(struct channel *C, struct channel_config *CC) |
1883 |
{ |
1884 |
struct bgp_channel *c = (void *) C; |
1885 |
struct bgp_channel_config *new = (void *) CC; |
1886 |
struct bgp_channel_config *old = c->cf;
|
1887 |
|
1888 |
if (memcmp(((byte *) old) + sizeof(struct channel_config), |
1889 |
((byte *) new) + sizeof(struct channel_config), |
1890 |
/* Remaining items must be checked separately */
|
1891 |
OFFSETOF(struct bgp_channel_config, rest) - sizeof(struct channel_config))) |
1892 |
return 0; |
1893 |
|
1894 |
/* Check change in IGP tables */
|
1895 |
if ((IGP_TABLE(old, ip4) != IGP_TABLE(new, ip4)) ||
|
1896 |
(IGP_TABLE(old, ip6) != IGP_TABLE(new, ip6))) |
1897 |
return 0; |
1898 |
|
1899 |
c->cf = new; |
1900 |
return 1; |
1901 |
} |
1902 |
|
1903 |
static void |
1904 |
bgp_copy_config(struct proto_config *dest UNUSED, struct proto_config *src UNUSED) |
1905 |
{ |
1906 |
/* Just a shallow copy */
|
1907 |
} |
1908 |
|
1909 |
|
1910 |
/**
|
1911 |
* bgp_error - report a protocol error
|
1912 |
* @c: connection
|
1913 |
* @code: error code (according to the RFC)
|
1914 |
* @subcode: error sub-code
|
1915 |
* @data: data to be passed in the Notification message
|
1916 |
* @len: length of the data
|
1917 |
*
|
1918 |
* bgp_error() sends a notification packet to tell the other side that a protocol
|
1919 |
* error has occurred (including the data considered erroneous if possible) and
|
1920 |
* closes the connection.
|
1921 |
*/
|
1922 |
void
|
1923 |
bgp_error(struct bgp_conn *c, uint code, uint subcode, byte *data, int len) |
1924 |
{ |
1925 |
struct bgp_proto *p = c->bgp;
|
1926 |
|
1927 |
if (c->state == BS_CLOSE)
|
1928 |
return;
|
1929 |
|
1930 |
bgp_log_error(p, BE_BGP_TX, "Error", code, subcode, data, ABS(len));
|
1931 |
bgp_store_error(p, c, BE_BGP_TX, (code << 16) | subcode);
|
1932 |
bgp_conn_enter_close_state(c); |
1933 |
|
1934 |
c->notify_code = code; |
1935 |
c->notify_subcode = subcode; |
1936 |
c->notify_data = data; |
1937 |
c->notify_size = (len > 0) ? len : 0; |
1938 |
bgp_schedule_packet(c, NULL, PKT_NOTIFICATION);
|
1939 |
|
1940 |
if (code != 6) |
1941 |
{ |
1942 |
bgp_update_startup_delay(p); |
1943 |
bgp_stop(p, 0, NULL, 0); |
1944 |
} |
1945 |
} |
1946 |
|
1947 |
/**
|
1948 |
* bgp_store_error - store last error for status report
|
1949 |
* @p: BGP instance
|
1950 |
* @c: connection
|
1951 |
* @class: error class (BE_xxx constants)
|
1952 |
* @code: error code (class specific)
|
1953 |
*
|
1954 |
* bgp_store_error() decides whether given error is interesting enough
|
1955 |
* and store that error to last_error variables of @p
|
1956 |
*/
|
1957 |
void
|
1958 |
bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code) |
1959 |
{ |
1960 |
/* During PS_UP, we ignore errors on secondary connection */
|
1961 |
if ((p->p.proto_state == PS_UP) && c && (c != p->conn))
|
1962 |
return;
|
1963 |
|
1964 |
/* During PS_STOP, we ignore any errors, as we want to report
|
1965 |
* the error that caused transition to PS_STOP
|
1966 |
*/
|
1967 |
if (p->p.proto_state == PS_STOP)
|
1968 |
return;
|
1969 |
|
1970 |
p->last_error_class = class; |
1971 |
p->last_error_code = code; |
1972 |
} |
1973 |
|
1974 |
static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" }; |
1975 |
static char *bgp_err_classes[] = { "", "Error: ", "Socket: ", "Received: ", "BGP Error: ", "Automatic shutdown: ", ""}; |
1976 |
static char *bgp_misc_errors[] = { "", "Neighbor lost", "Invalid next hop", "Kernel MD5 auth failed", "No listening socket", "Link down", "BFD session down", "Graceful restart"}; |
1977 |
static char *bgp_auto_errors[] = { "", "Route limit exceeded"}; |
1978 |
|
1979 |
static const char * |
1980 |
bgp_last_errmsg(struct bgp_proto *p)
|
1981 |
{ |
1982 |
switch (p->last_error_class)
|
1983 |
{ |
1984 |
case BE_MISC:
|
1985 |
return bgp_misc_errors[p->last_error_code];
|
1986 |
case BE_SOCKET:
|
1987 |
return (p->last_error_code == 0) ? "Connection closed" : strerror(p->last_error_code); |
1988 |
case BE_BGP_RX:
|
1989 |
case BE_BGP_TX:
|
1990 |
return bgp_error_dsc(p->last_error_code >> 16, p->last_error_code & 0xFF); |
1991 |
case BE_AUTO_DOWN:
|
1992 |
return bgp_auto_errors[p->last_error_code];
|
1993 |
default:
|
1994 |
return ""; |
1995 |
} |
1996 |
} |
1997 |
|
1998 |
static const char * |
1999 |
bgp_state_dsc(struct bgp_proto *p)
|
2000 |
{ |
2001 |
if (p->p.proto_state == PS_DOWN)
|
2002 |
return "Down"; |
2003 |
|
2004 |
int state = MAX(p->incoming_conn.state, p->outgoing_conn.state);
|
2005 |
if ((state == BS_IDLE) && (p->start_state >= BSS_CONNECT) && p->cf->passive)
|
2006 |
return "Passive"; |
2007 |
|
2008 |
return bgp_state_names[state];
|
2009 |
} |
2010 |
|
2011 |
static void |
2012 |
bgp_get_status(struct proto *P, byte *buf)
|
2013 |
{ |
2014 |
struct bgp_proto *p = (struct bgp_proto *) P; |
2015 |
|
2016 |
const char *err1 = bgp_err_classes[p->last_error_class]; |
2017 |
const char *err2 = bgp_last_errmsg(p); |
2018 |
|
2019 |
if (P->proto_state == PS_DOWN)
|
2020 |
bsprintf(buf, "%s%s", err1, err2);
|
2021 |
else
|
2022 |
bsprintf(buf, "%-14s%s%s", bgp_state_dsc(p), err1, err2);
|
2023 |
} |
2024 |
|
2025 |
static void |
2026 |
bgp_show_afis(int code, char *s, u32 *afis, uint count) |
2027 |
{ |
2028 |
buffer b; |
2029 |
LOG_BUFFER_INIT(b); |
2030 |
|
2031 |
buffer_puts(&b, s); |
2032 |
|
2033 |
for (u32 *af = afis; af < (afis + count); af++)
|
2034 |
{ |
2035 |
const struct bgp_af_desc *desc = bgp_get_af_desc(*af); |
2036 |
if (desc)
|
2037 |
buffer_print(&b, " %s", desc->name);
|
2038 |
else
|
2039 |
buffer_print(&b, " <%u/%u>", BGP_AFI(*af), BGP_SAFI(*af));
|
2040 |
} |
2041 |
|
2042 |
if (b.pos == b.end)
|
2043 |
strcpy(b.end - 32, " ... <too long>"); |
2044 |
|
2045 |
cli_msg(code, b.start); |
2046 |
} |
2047 |
|
2048 |
static void |
2049 |
bgp_show_capabilities(struct bgp_proto *p UNUSED, struct bgp_caps *caps) |
2050 |
{ |
2051 |
struct bgp_af_caps *ac;
|
2052 |
uint any_mp_bgp = 0;
|
2053 |
uint any_gr_able = 0;
|
2054 |
uint any_add_path = 0;
|
2055 |
uint any_ext_next_hop = 0;
|
2056 |
u32 *afl1 = alloca(caps->af_count * sizeof(u32));
|
2057 |
u32 *afl2 = alloca(caps->af_count * sizeof(u32));
|
2058 |
uint afn1, afn2; |
2059 |
|
2060 |
WALK_AF_CAPS(caps, ac) |
2061 |
{ |
2062 |
any_mp_bgp |= ac->ready; |
2063 |
any_gr_able |= ac->gr_able; |
2064 |
any_add_path |= ac->add_path; |
2065 |
any_ext_next_hop |= ac->ext_next_hop; |
2066 |
} |
2067 |
|
2068 |
if (any_mp_bgp)
|
2069 |
{ |
2070 |
cli_msg(-1006, " Multiprotocol"); |
2071 |
|
2072 |
afn1 = 0;
|
2073 |
WALK_AF_CAPS(caps, ac) |
2074 |
if (ac->ready)
|
2075 |
afl1[afn1++] = ac->afi; |
2076 |
|
2077 |
bgp_show_afis(-1006, " AF announced:", afl1, afn1); |
2078 |
} |
2079 |
|
2080 |
if (caps->route_refresh)
|
2081 |
cli_msg(-1006, " Route refresh"); |
2082 |
|
2083 |
if (any_ext_next_hop)
|
2084 |
{ |
2085 |
cli_msg(-1006, " Extended next hop"); |
2086 |
|
2087 |
afn1 = 0;
|
2088 |
WALK_AF_CAPS(caps, ac) |
2089 |
if (ac->ext_next_hop)
|
2090 |
afl1[afn1++] = ac->afi; |
2091 |
|
2092 |
bgp_show_afis(-1006, " IPv6 nexthop:", afl1, afn1); |
2093 |
} |
2094 |
|
2095 |
if (caps->ext_messages)
|
2096 |
cli_msg(-1006, " Extended message"); |
2097 |
|
2098 |
if (caps->gr_aware)
|
2099 |
cli_msg(-1006, " Graceful restart"); |
2100 |
|
2101 |
if (any_gr_able)
|
2102 |
{ |
2103 |
/* Continues from gr_aware */
|
2104 |
cli_msg(-1006, " Restart time: %u", caps->gr_time); |
2105 |
if (caps->gr_flags & BGP_GRF_RESTART)
|
2106 |
cli_msg(-1006, " Restart recovery"); |
2107 |
|
2108 |
afn1 = afn2 = 0;
|
2109 |
WALK_AF_CAPS(caps, ac) |
2110 |
{ |
2111 |
if (ac->gr_able)
|
2112 |
afl1[afn1++] = ac->afi; |
2113 |
|
2114 |
if (ac->gr_af_flags & BGP_GRF_FORWARDING)
|
2115 |
afl2[afn2++] = ac->afi; |
2116 |
} |
2117 |
|
2118 |
bgp_show_afis(-1006, " AF supported:", afl1, afn1); |
2119 |
bgp_show_afis(-1006, " AF preserved:", afl2, afn2); |
2120 |
} |
2121 |
|
2122 |
if (caps->as4_support)
|
2123 |
cli_msg(-1006, " 4-octet AS numbers"); |
2124 |
|
2125 |
if (any_add_path)
|
2126 |
{ |
2127 |
cli_msg(-1006, " ADD-PATH"); |
2128 |
|
2129 |
afn1 = afn2 = 0;
|
2130 |
WALK_AF_CAPS(caps, ac) |
2131 |
{ |
2132 |
if (ac->add_path & BGP_ADD_PATH_RX)
|
2133 |
afl1[afn1++] = ac->afi; |
2134 |
|
2135 |
if (ac->add_path & BGP_ADD_PATH_TX)
|
2136 |
afl2[afn2++] = ac->afi; |
2137 |
} |
2138 |
|
2139 |
bgp_show_afis(-1006, " RX:", afl1, afn1); |
2140 |
bgp_show_afis(-1006, " TX:", afl2, afn2); |
2141 |
} |
2142 |
|
2143 |
if (caps->enhanced_refresh)
|
2144 |
cli_msg(-1006, " Enhanced refresh"); |
2145 |
} |
2146 |
|
2147 |
static void |
2148 |
bgp_show_proto_info(struct proto *P)
|
2149 |
{ |
2150 |
struct bgp_proto *p = (struct bgp_proto *) P; |
2151 |
|
2152 |
cli_msg(-1006, " BGP state: %s", bgp_state_dsc(p)); |
2153 |
cli_msg(-1006, " Neighbor address: %I%J", p->cf->remote_ip, p->cf->iface); |
2154 |
cli_msg(-1006, " Neighbor AS: %u", p->remote_as); |
2155 |
|
2156 |
if (p->gr_active_num)
|
2157 |
cli_msg(-1006, " Neighbor graceful restart active"); |
2158 |
|
2159 |
if (P->proto_state == PS_START)
|
2160 |
{ |
2161 |
struct bgp_conn *oc = &p->outgoing_conn;
|
2162 |
|
2163 |
if ((p->start_state < BSS_CONNECT) &&
|
2164 |
(tm_active(p->startup_timer))) |
2165 |
cli_msg(-1006, " Error wait: %t/%u", |
2166 |
tm_remains(p->startup_timer), p->startup_delay); |
2167 |
|
2168 |
if ((oc->state == BS_ACTIVE) &&
|
2169 |
(tm_active(oc->connect_timer))) |
2170 |
cli_msg(-1006, " Connect delay: %t/%u", |
2171 |
tm_remains(oc->connect_timer), p->cf->connect_delay_time); |
2172 |
|
2173 |
if (p->gr_active_num && tm_active(p->gr_timer))
|
2174 |
cli_msg(-1006, " Restart timer: %t/-", |
2175 |
tm_remains(p->gr_timer)); |
2176 |
} |
2177 |
else if (P->proto_state == PS_UP) |
2178 |
{ |
2179 |
cli_msg(-1006, " Neighbor ID: %R", p->remote_id); |
2180 |
cli_msg(-1006, " Local capabilities"); |
2181 |
bgp_show_capabilities(p, p->conn->local_caps); |
2182 |
cli_msg(-1006, " Neighbor capabilities"); |
2183 |
bgp_show_capabilities(p, p->conn->remote_caps); |
2184 |
cli_msg(-1006, " Session: %s%s%s%s%s", |
2185 |
p->is_internal ? "internal" : "external", |
2186 |
p->cf->multihop ? " multihop" : "", |
2187 |
p->rr_client ? " route-reflector" : "", |
2188 |
p->rs_client ? " route-server" : "", |
2189 |
p->as4_session ? " AS4" : ""); |
2190 |
cli_msg(-1006, " Source address: %I", p->source_addr); |
2191 |
cli_msg(-1006, " Hold timer: %t/%u", |
2192 |
tm_remains(p->conn->hold_timer), p->conn->hold_time); |
2193 |
cli_msg(-1006, " Keepalive timer: %t/%u", |
2194 |
tm_remains(p->conn->keepalive_timer), p->conn->keepalive_time); |
2195 |
} |
2196 |
|
2197 |
if ((p->last_error_class != BE_NONE) &&
|
2198 |
(p->last_error_class != BE_MAN_DOWN)) |
2199 |
{ |
2200 |
const char *err1 = bgp_err_classes[p->last_error_class]; |
2201 |
const char *err2 = bgp_last_errmsg(p); |
2202 |
cli_msg(-1006, " Last error: %s%s", err1, err2); |
2203 |
} |
2204 |
|
2205 |
{ |
2206 |
struct bgp_channel *c;
|
2207 |
WALK_LIST(c, p->p.channels) |
2208 |
{ |
2209 |
channel_show_info(&c->c); |
2210 |
|
2211 |
if (c->c.channel_state == CS_UP)
|
2212 |
{ |
2213 |
if (ipa_zero(c->link_addr))
|
2214 |
cli_msg(-1006, " BGP Next hop: %I", c->next_hop_addr); |
2215 |
else
|
2216 |
cli_msg(-1006, " BGP Next hop: %I %I", c->next_hop_addr, c->link_addr); |
2217 |
} |
2218 |
|
2219 |
if (c->igp_table_ip4)
|
2220 |
cli_msg(-1006, " IGP IPv4 table: %s", c->igp_table_ip4->name); |
2221 |
|
2222 |
if (c->igp_table_ip6)
|
2223 |
cli_msg(-1006, " IGP IPv6 table: %s", c->igp_table_ip6->name); |
2224 |
} |
2225 |
} |
2226 |
} |
2227 |
|
2228 |
// Next three function could be usefull in some situations
|
2229 |
void
|
2230 |
channel_show_info_mine(struct channel *c)
|
2231 |
{ |
2232 |
log(L_INFO " Channel %s", c->name);
|
2233 |
//log(L_INFO " State: %s", c_states[c->channel_state]);
|
2234 |
log(L_INFO " Table: %s", c->table->name);
|
2235 |
log(L_INFO " Preference: %d", c->preference);
|
2236 |
log(L_INFO " Input filter: %s", filter_name(c->in_filter));
|
2237 |
log(L_INFO " Output filter: %s", filter_name(c->out_filter));
|
2238 |
|
2239 |
/*if (graceful_restart_state == GRS_ACTIVE)
|
2240 |
log(L_INFO " GR recovery: %s%s",
|
2241 |
c->gr_lock ? " pending" : "",
|
2242 |
c->gr_wait ? " waiting" : "");*/
|
2243 |
|
2244 |
//channel_show_limit(&c->rx_limit, "Receive limit:");
|
2245 |
//channel_show_limit(&c->in_limit, "Import limit:");
|
2246 |
//channel_show_limit(&c->out_limit, "Export limit:");
|
2247 |
|
2248 |
//if (c->channel_state != CS_DOWN)
|
2249 |
// channel_show_stats(c);
|
2250 |
} |
2251 |
|
2252 |
static void |
2253 |
bgp_show_capabilities_mine(struct bgp_proto *p UNUSED, struct bgp_caps *caps) |
2254 |
{ |
2255 |
struct bgp_af_caps *ac;
|
2256 |
uint any_mp_bgp = 0;
|
2257 |
uint any_gr_able = 0;
|
2258 |
uint any_add_path = 0;
|
2259 |
uint any_ext_next_hop = 0;
|
2260 |
u32 *afl1 = alloca(caps->af_count * sizeof(u32));
|
2261 |
u32 *afl2 = alloca(caps->af_count * sizeof(u32));
|
2262 |
uint afn1, afn2; |
2263 |
|
2264 |
WALK_AF_CAPS(caps, ac) |
2265 |
{ |
2266 |
any_mp_bgp |= ac->ready; |
2267 |
any_gr_able |= ac->gr_able; |
2268 |
any_add_path |= ac->add_path; |
2269 |
any_ext_next_hop |= ac->ext_next_hop; |
2270 |
} |
2271 |
|
2272 |
if (any_mp_bgp)
|
2273 |
{ |
2274 |
log(L_INFO " Multiprotocol");
|
2275 |
|
2276 |
afn1 = 0;
|
2277 |
WALK_AF_CAPS(caps, ac) |
2278 |
if (ac->ready)
|
2279 |
afl1[afn1++] = ac->afi; |
2280 |
|
2281 |
//bgp_show_afis(-1006, " AF announced:", afl1, afn1);
|
2282 |
} |
2283 |
|
2284 |
if (caps->route_refresh)
|
2285 |
log(L_INFO " Route refresh");
|
2286 |
|
2287 |
if (any_ext_next_hop)
|
2288 |
{ |
2289 |
log(L_INFO " Extended next hop");
|
2290 |
|
2291 |
afn1 = 0;
|
2292 |
WALK_AF_CAPS(caps, ac) |
2293 |
if (ac->ext_next_hop)
|
2294 |
afl1[afn1++] = ac->afi; |
2295 |
|
2296 |
//bgp_show_afis(-1006, " IPv6 nexthop:", afl1, afn1);
|
2297 |
} |
2298 |
|
2299 |
if (caps->ext_messages)
|
2300 |
log(L_INFO " Extended message");
|
2301 |
|
2302 |
if (caps->gr_aware)
|
2303 |
log(L_INFO " Graceful restart");
|
2304 |
|
2305 |
if (any_gr_able)
|
2306 |
{ |
2307 |
/* Continues from gr_aware */
|
2308 |
log(L_INFO " Restart time: %u", caps->gr_time);
|
2309 |
if (caps->gr_flags & BGP_GRF_RESTART)
|
2310 |
log(L_INFO " Restart recovery");
|
2311 |
|
2312 |
afn1 = afn2 = 0;
|
2313 |
WALK_AF_CAPS(caps, ac) |
2314 |
{ |
2315 |
if (ac->gr_able)
|
2316 |
afl1[afn1++] = ac->afi; |
2317 |
|
2318 |
if (ac->gr_af_flags & BGP_GRF_FORWARDING)
|
2319 |
afl2[afn2++] = ac->afi; |
2320 |
} |
2321 |
|
2322 |
//bgp_show_afis(-1006, " AF supported:", afl1, afn1);
|
2323 |
//bgp_show_afis(-1006, " AF preserved:", afl2, afn2);
|
2324 |
} |
2325 |
|
2326 |
if (caps->as4_support)
|
2327 |
log(L_INFO " 4-octet AS numbers");
|
2328 |
|
2329 |
if (any_add_path)
|
2330 |
{ |
2331 |
log(L_INFO " ADD-PATH");
|
2332 |
|
2333 |
afn1 = afn2 = 0;
|
2334 |
WALK_AF_CAPS(caps, ac) |
2335 |
{ |
2336 |
if (ac->add_path & BGP_ADD_PATH_RX)
|
2337 |
afl1[afn1++] = ac->afi; |
2338 |
|
2339 |
if (ac->add_path & BGP_ADD_PATH_TX)
|
2340 |
afl2[afn2++] = ac->afi; |
2341 |
} |
2342 |
|
2343 |
//bgp_show_afis(-1006, " RX:", afl1, afn1);
|
2344 |
//bgp_show_afis(-1006, " TX:", afl2, afn2);
|
2345 |
} |
2346 |
|
2347 |
if (caps->enhanced_refresh)
|
2348 |
log(L_INFO " Enhanced refresh");
|
2349 |
} |
2350 |
|
2351 |
void
|
2352 |
bgp_show_proto_info_mine(struct bgp_proto *P)
|
2353 |
{ |
2354 |
struct bgp_proto *p = P;
|
2355 |
|
2356 |
log(L_INFO " BGP state: %s", bgp_state_dsc(p));
|
2357 |
log(L_INFO " Neighbor address: %I%J", p->cf->remote_ip, p->cf->iface);
|
2358 |
log(L_INFO " Neighbor AS: %u", p->remote_as);
|
2359 |
|
2360 |
if (p->gr_active_num)
|
2361 |
log(L_INFO " Neighbor graceful restart active");
|
2362 |
|
2363 |
if (P->p.proto_state == PS_START)
|
2364 |
{ |
2365 |
struct bgp_conn *oc = &p->outgoing_conn;
|
2366 |
|
2367 |
if ((p->start_state < BSS_CONNECT) &&
|
2368 |
(tm_active(p->startup_timer))) |
2369 |
log(L_INFO " Error wait: %t/%u",
|
2370 |
tm_remains(p->startup_timer), p->startup_delay); |
2371 |
|
2372 |
if ((oc->state == BS_ACTIVE) &&
|
2373 |
(tm_active(oc->connect_timer))) |
2374 |
log(L_INFO " Connect delay: %t/%u",
|
2375 |
tm_remains(oc->connect_timer), p->cf->connect_delay_time); |
2376 |
|
2377 |
if (p->gr_active_num && tm_active(p->gr_timer))
|
2378 |
log(L_INFO " Restart timer: %t/-",
|
2379 |
tm_remains(p->gr_timer)); |
2380 |
} |
2381 |
else if (P->p.proto_state == PS_UP) |
2382 |
{ |
2383 |
log(L_INFO " Neighbor ID: %R", p->remote_id);
|
2384 |
log(L_INFO " Local capabilities");
|
2385 |
bgp_show_capabilities_mine(p, p->conn->local_caps); |
2386 |
log(L_INFO " Neighbor capabilities");
|
2387 |
bgp_show_capabilities_mine(p, p->conn->remote_caps); |
2388 |
log(L_INFO " Session: %s%s%s%s%s",
|
2389 |
p->is_internal ? "internal" : "external", |
2390 |
p->cf->multihop ? " multihop" : "", |
2391 |
p->rr_client ? " route-reflector" : "", |
2392 |
p->rs_client ? " route-server" : "", |
2393 |
p->as4_session ? " AS4" : ""); |
2394 |
log(L_INFO " Source address: %I", p->source_addr);
|
2395 |
log(L_INFO " Hold timer: %t/%u",
|
2396 |
tm_remains(p->conn->hold_timer), p->conn->hold_time); |
2397 |
log(L_INFO " Keepalive timer: %t/%u",
|
2398 |
tm_remains(p->conn->keepalive_timer), p->conn->keepalive_time); |
2399 |
} |
2400 |
|
2401 |
if ((p->last_error_class != BE_NONE) &&
|
2402 |
(p->last_error_class != BE_MAN_DOWN)) |
2403 |
{ |
2404 |
const char *err1 = bgp_err_classes[p->last_error_class]; |
2405 |
const char *err2 = bgp_last_errmsg(p); |
2406 |
log(L_INFO " Last error: %s%s", err1, err2);
|
2407 |
} |
2408 |
|
2409 |
{ |
2410 |
struct bgp_channel *c;
|
2411 |
WALK_LIST(c, p->p.channels) |
2412 |
{ |
2413 |
channel_show_info_mine(&c->c); |
2414 |
|
2415 |
if (c->c.channel_state == CS_UP)
|
2416 |
{ |
2417 |
if (ipa_zero(c->link_addr))
|
2418 |
log(L_INFO " BGP Next hop: %I", c->next_hop_addr);
|
2419 |
else
|
2420 |
log(L_INFO " BGP Next hop: %I %I", c->next_hop_addr, c->link_addr);
|
2421 |
} |
2422 |
|
2423 |
if (c->igp_table_ip4)
|
2424 |
log(L_INFO " IGP IPv4 table: %s", c->igp_table_ip4->name);
|
2425 |
|
2426 |
if (c->igp_table_ip6)
|
2427 |
log(L_INFO " IGP IPv6 table: %s", c->igp_table_ip6->name);
|
2428 |
} |
2429 |
} |
2430 |
} |
2431 |
|
2432 |
struct channel_class channel_bgp = {
|
2433 |
.channel_size = sizeof(struct bgp_channel), |
2434 |
.config_size = sizeof(struct bgp_channel_config), |
2435 |
.init = bgp_channel_init, |
2436 |
.start = bgp_channel_start, |
2437 |
.shutdown = bgp_channel_shutdown, |
2438 |
.cleanup = bgp_channel_cleanup, |
2439 |
.reconfigure = bgp_channel_reconfigure, |
2440 |
}; |
2441 |
|
2442 |
struct protocol proto_bgp = {
|
2443 |
.name = "BGP",
|
2444 |
.template = "bgp%d",
|
2445 |
.attr_class = EAP_BGP, |
2446 |
.preference = DEF_PREF_BGP, |
2447 |
.channel_mask = NB_IP | NB_VPN | NB_FLOW, |
2448 |
.proto_size = sizeof(struct bgp_proto), |
2449 |
.config_size = sizeof(struct bgp_config), |
2450 |
.postconfig = bgp_postconfig, |
2451 |
.init = bgp_init, |
2452 |
.start = bgp_start, |
2453 |
.shutdown = bgp_shutdown, |
2454 |
.reconfigure = bgp_reconfigure, |
2455 |
.copy_config = bgp_copy_config, |
2456 |
.get_status = bgp_get_status, |
2457 |
.get_attr = bgp_get_attr, |
2458 |
.get_route_info = bgp_get_route_info, |
2459 |
.show_proto_info = bgp_show_proto_info |
2460 |
}; |