Statistics
| Branch: | Revision:

iof-bird-daemon / proto / bgp / bgp.c @ 54e55169

History | View | Annotate | Download (17.6 KB)

1
/*
2
 *        BIRD -- The Border Gateway Protocol
3
 *
4
 *        (c) 2000 Martin Mares <mj@ucw.cz>
5
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8

    
9
/**
10
 * DOC: Border Gateway Protocol
11
 *
12
 * The BGP protocol is implemented in three parts: |bgp.c| which takes care of the
13
 * connection and most of the interface with BIRD core, |packets.c| handling
14
 * both incoming and outgoing BGP packets and |attrs.c| containing functions for
15
 * manipulation with BGP attribute lists.
16
 *
17
 * As opposed to the other existing routing daemons, BIRD has a sophisticated core
18
 * architecture which is able to keep all the information needed by BGP in the
19
 * primary routing table, therefore no complex data structures like a central
20
 * BGP table are needed. This increases memory footprint of a BGP router with
21
 * many connections, but not too much and, which is more important, it makes
22
 * BGP much easier to implement.
23
 *
24
 * Each instance of BGP (corresponding to one BGP peer) is described by a &bgp_proto
25
 * structure to which are attached individual connections represented by &bgp_connection
26
 * (usually, there exists only one connection, but during BGP session setup, there
27
 * can be more of them). The connections are handled according to the BGP state machine
28
 * defined in the RFC with all the timers and all the parameters configurable.
29
 *
30
 * In incoming direction, we listen on the connection's socket and each time we receive
31
 * some input, we pass it to bgp_rx(). It decodes packet headers and the markers and
32
 * passes complete packets to bgp_rx_packet() which distributes the packet according
33
 * to its type.
34
 *
35
 * In outgoing direction, we gather all the routing updates and sort them to buckets
36
 * (&bgp_bucket) according to their attributes (we keep a hash table for fast comparison
37
 * of &rta's and a &fib which helps us to find if we already have another route for
38
 * the same destination queued for sending, so that we can replace it with the new one
39
 * immediately instead of sending both updates). There also exists a special bucket holding
40
 * all the route withdrawals which cannot be queued anywhere else as they don't have any
41
 * attributes. If we have any packet to send (due to either new routes or the connection
42
 * tracking code wanting to send a Open, KeepAlive or Notification message), we call
43
 * bgp_schedule_packet() which sets the corresponding bit in a @packet_to_send
44
 * bit field in &bgp_conn and as soon as the transmit socket buffer becomes empty,
45
 * we call bgp_fire_tx(). It inspects state of all the packet type bits and calls
46
 * the corresponding bgp_create_xx() functions, eventually rescheduling the same packet
47
 * type if we have more data of the same type to send.
48
 *
49
 * The processing of attributes consists of two functions: bgp_decode_attrs() for checking
50
 * of the attribute blocks and translating them to the language of BIRD's extended attributes
51
 * and bgp_encode_attrs() which does the converse. Both functions are built around a
52
 * @bgp_attr_table array describing all important characteristics of all known attributes.
53
 * Unknown transitive attributes are attached to the route as %EAF_TYPE_OPAQUE byte streams.
54
 */
55

    
56
#undef LOCAL_DEBUG
57

    
58
#include "nest/bird.h"
59
#include "nest/iface.h"
60
#include "nest/protocol.h"
61
#include "nest/route.h"
62
#include "nest/locks.h"
63
#include "conf/conf.h"
64
#include "lib/socket.h"
65
#include "lib/resource.h"
66

    
67
#include "bgp.h"
68

    
69
struct linpool *bgp_linpool;                /* Global temporary pool */
70
static sock *bgp_listen_sk;                /* Global listening socket */
71
static int bgp_counter;                        /* Number of protocol instances using the listening socket */
72
static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established" };
73

    
74
static void bgp_connect(struct bgp_proto *p);
75
static void bgp_initiate(struct bgp_proto *p);
76
static void bgp_setup_listen_sk(void);
77

    
78
void
79
bgp_close(struct bgp_proto *p)
80
{
81
  ASSERT(bgp_counter);
82
  bgp_counter--;
83
  if (!bgp_counter)
84
    {
85
      rfree(bgp_listen_sk);
86
      bgp_listen_sk = NULL;
87
      rfree(bgp_linpool);
88
      bgp_linpool = NULL;
89
    }
90
}
91

    
92
/**
93
 * bgp_start_timer - start a BGP timer
94
 * @t: timer
95
 * @value: time to fire (0 to disable the timer)
96
 *
97
 * This functions calls tm_start() on @t with time @value and the
98
 * amount of randomization suggested by the BGP standard. Please use
99
 * it for all BGP timers.
100
 */
101
void
102
bgp_start_timer(timer *t, int value)
103
{
104
  if (value)
105
    {
106
      /* The randomization procedure is specified in RFC 1771: 9.2.3.3 */
107
      t->randomize = value / 4;
108
      tm_start(t, value - t->randomize);
109
    }
110
  else
111
    tm_stop(t);
112
}
113

    
114
/**
115
 * bgp_close_conn - close a BGP connection
116
 * @conn: connection to close
117
 *
118
 * This function takes a connection described by the &bgp_conn structure,
119
 * closes its socket and frees all resources associated with it.
120
 *
121
 * If the connection is being closed due to a protocol error, adjust
122
 * the connection restart timer as well according to the error recovery
123
 * policy set in the configuration.
124
 *
125
 * If the connection was marked as primary, it shuts down the protocol as well.
126
 */
127
void
128
bgp_close_conn(struct bgp_conn *conn)
129
{
130
  struct bgp_proto *p = conn->bgp;
131
  struct bgp_config *cf = p->cf;
132

    
133
  DBG("BGP: Closing connection\n");
134
  conn->packets_to_send = 0;
135
  rfree(conn->connect_retry_timer);
136
  conn->connect_retry_timer = NULL;
137
  rfree(conn->keepalive_timer);
138
  conn->keepalive_timer = NULL;
139
  rfree(conn->hold_timer);
140
  conn->hold_timer = NULL;
141
  sk_close(conn->sk);
142
  conn->sk = NULL;
143
  conn->state = BS_IDLE;
144
  if (conn->error_flag > 1)
145
    {
146
      if (cf->disable_after_error)
147
        p->p.disabled = 1;
148
      if (p->last_connect && (bird_clock_t)(p->last_connect + cf->error_amnesia_time) < now)
149
        p->startup_delay = 0;
150
      if (!p->startup_delay)
151
        p->startup_delay = cf->error_delay_time_min;
152
      else
153
        {
154
          p->startup_delay *= 2;
155
          if (p->startup_delay > cf->error_delay_time_max)
156
            p->startup_delay = cf->error_delay_time_max;
157
        }
158
    }
159
  if (conn->primary)
160
    {
161
      bgp_close(p);
162
      p->conn = NULL;
163
      proto_notify_state(&p->p, PS_DOWN);
164
    }
165
  else if (conn->error_flag > 1)
166
    bgp_initiate(p);
167
}
168

    
169
static int
170
bgp_graceful_close_conn(struct bgp_conn *c)
171
{
172
  switch (c->state)
173
    {
174
    case BS_IDLE:
175
      return 0;
176
    case BS_CONNECT:
177
    case BS_ACTIVE:
178
      bgp_close_conn(c);
179
      return 1;
180
    case BS_OPENSENT:
181
    case BS_OPENCONFIRM:
182
    case BS_ESTABLISHED:
183
      bgp_error(c, 6, 0, NULL, 0);
184
      return 1;
185
    default:
186
      bug("bgp_graceful_close_conn: Unknown state %d", c->state);
187
    }
188
}
189

    
190
static void
191
bgp_send_open(struct bgp_conn *conn)
192
{
193
  DBG("BGP: Sending open\n");
194
  conn->sk->rx_hook = bgp_rx;
195
  conn->sk->tx_hook = bgp_tx;
196
  tm_stop(conn->connect_retry_timer);
197
  bgp_schedule_packet(conn, PKT_OPEN);
198
  conn->state = BS_OPENSENT;
199
  bgp_start_timer(conn->hold_timer, conn->bgp->cf->initial_hold_time);
200
}
201

    
202
static void
203
bgp_connected(sock *sk)
204
{
205
  struct bgp_conn *conn = sk->data;
206
  struct bgp_proto *p = conn->bgp;
207

    
208
  BGP_TRACE(D_EVENTS, "Connected");
209
  bgp_send_open(conn);
210
}
211

    
212
static void
213
bgp_connect_timeout(timer *t)
214
{
215
  struct bgp_conn *conn = t->data;
216
  struct bgp_proto *p = conn->bgp;
217

    
218
  DBG("BGP: connect_timeout\n");
219
  bgp_close_conn(conn);
220
  bgp_connect(p);
221
}
222

    
223
static void
224
bgp_sock_err(sock *sk, int err)
225
{
226
  struct bgp_conn *conn = sk->data;
227
  struct bgp_proto *p = conn->bgp;
228

    
229
  if (err)
230
    BGP_TRACE(D_EVENTS, "Connection lost (%M)", err);
231
  else
232
    BGP_TRACE(D_EVENTS, "Connection closed");
233
  switch (conn->state)
234
    {
235
    case BS_CONNECT:
236
    case BS_OPENSENT:
237
      sk_close(conn->sk);
238
      conn->sk = NULL;
239
      conn->state = BS_ACTIVE;
240
      bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time);
241
      break;
242
    case BS_OPENCONFIRM:
243
    case BS_ESTABLISHED:
244
      bgp_close_conn(conn);
245
      break;
246
    default:
247
      bug("bgp_sock_err called in invalid state %d", conn->state);
248
    }
249
}
250

    
251
static void
252
bgp_hold_timeout(timer *t)
253
{
254
  struct bgp_conn *conn = t->data;
255

    
256
  DBG("BGP: Hold timeout, closing connection\n");
257
  bgp_error(conn, 4, 0, NULL, 0);
258
}
259

    
260
static void
261
bgp_keepalive_timeout(timer *t)
262
{
263
  struct bgp_conn *conn = t->data;
264

    
265
  DBG("BGP: Keepalive timer\n");
266
  bgp_schedule_packet(conn, PKT_KEEPALIVE);
267
}
268

    
269
static void
270
bgp_setup_conn(struct bgp_proto *p, struct bgp_conn *conn)
271
{
272
  timer *t;
273

    
274
  conn->sk = NULL;
275
  conn->bgp = p;
276
  conn->packets_to_send = 0;
277
  conn->error_flag = 0;
278
  conn->primary = 0;
279

    
280
  t = conn->connect_retry_timer = tm_new(p->p.pool);
281
  t->hook = bgp_connect_timeout;
282
  t->data = conn;
283
  t = conn->hold_timer = tm_new(p->p.pool);
284
  t->hook = bgp_hold_timeout;
285
  t->data = conn;
286
  t = conn->keepalive_timer = tm_new(p->p.pool);
287
  t->hook = bgp_keepalive_timeout;
288
  t->data = conn;
289
}
290

    
291
static void
292
bgp_setup_sk(struct bgp_proto *p, struct bgp_conn *conn, sock *s)
293
{
294
  s->data = conn;
295
  s->ttl = p->cf->multihop ? : 1;
296
  s->rbsize = BGP_RX_BUFFER_SIZE;
297
  s->tbsize = BGP_TX_BUFFER_SIZE;
298
  s->err_hook = bgp_sock_err;
299
  s->tos = IP_PREC_INTERNET_CONTROL;
300
  conn->sk = s;
301
}
302

    
303
/**
304
 * bgp_connect - initiate an outgoing connection
305
 * @p: BGP instance
306
 *
307
 * The bgp_connect() function creates a new &bgp_conn and initiates
308
 * a TCP connection to the peer. The rest of connection setup is governed
309
 * by the BGP state machine as described in the standard.
310
 */
311
static void
312
bgp_connect(struct bgp_proto *p)        /* Enter Connect state and start establishing connection */
313
{
314
  sock *s;
315
  struct bgp_conn *conn = &p->outgoing_conn;
316

    
317
  DBG("BGP: Connecting\n");
318
  p->last_connect = now;
319
  s = sk_new(p->p.pool);
320
  s->type = SK_TCP_ACTIVE;
321
  if (ipa_nonzero(p->cf->source_addr))
322
    s->saddr = p->cf->source_addr;
323
  else
324
    s->saddr = p->local_addr;
325
  s->daddr = p->cf->remote_ip;
326
  s->dport = BGP_PORT;
327
  BGP_TRACE(D_EVENTS, "Connecting to %I from local address %I", s->daddr, s->saddr);
328
  bgp_setup_conn(p, conn);
329
  bgp_setup_sk(p, conn, s);
330
  s->tx_hook = bgp_connected;
331
  conn->state = BS_CONNECT;
332
  if (sk_open(s))
333
    {
334
      bgp_sock_err(s, 0);
335
      return;
336
    }
337
  DBG("BGP: Waiting for connect success\n");
338
  bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time);
339
}
340

    
341
static void
342
bgp_initiate(struct bgp_proto *p)
343
{
344
  unsigned delay;
345

    
346
  delay = p->cf->start_delay_time;
347
  if (p->startup_delay > delay)
348
    delay = p->startup_delay;
349
  if (delay)
350
    {
351
      BGP_TRACE(D_EVENTS, "Connect delayed by %d seconds", delay);
352
      bgp_setup_conn(p, &p->outgoing_conn);
353
      bgp_start_timer(p->outgoing_conn.connect_retry_timer, delay);
354
    }
355
  else
356
    bgp_connect(p);
357
}
358

    
359
/**
360
 * bgp_incoming_connection - handle an incoming connection
361
 * @sk: TCP socket
362
 * @dummy: unused
363
 *
364
 * This function serves as a socket hook for accepting of new BGP
365
 * connections. It searches a BGP instance corresponding to the peer
366
 * which has connected and if such an instance exists, it creates a
367
 * &bgp_conn structure, attaches it to the instance and either sends
368
 * an Open message or (if there already is an active connection) it
369
 * closes the new connection by sending a Notification message.
370
 */
371
static int
372
bgp_incoming_connection(sock *sk, int dummy)
373
{
374
  struct proto_config *pc;
375
  node *n;
376
  int match = 0;
377

    
378
  DBG("BGP: Incoming connection from %I port %d\n", sk->daddr, sk->dport);
379
  WALK_LIST(pc, config->protos)
380
    if (pc->protocol == &proto_bgp && pc->proto)
381
      {
382
        struct bgp_proto *p = (struct bgp_proto *) pc->proto;
383
        if (ipa_equal(p->cf->remote_ip, sk->daddr))
384
          {
385
            match = 1;
386
            if (p->p.proto_state == PS_START || p->p.proto_state == PS_UP)
387
              {
388
                BGP_TRACE(D_EVENTS, "Incoming connection from %I port %d", sk->daddr, sk->dport);
389
                if (p->incoming_conn.sk)
390
                  {
391
                    DBG("BGP: But one incoming connection already exists, how is that possible?\n");
392
                    break;
393
                  }
394
                bgp_setup_conn(p, &p->incoming_conn);
395
                bgp_setup_sk(p, &p->incoming_conn, sk);
396
                bgp_send_open(&p->incoming_conn);
397
                return 0;
398
              }
399
          }
400
      }
401
  if (!match)
402
    log(L_AUTH "BGP: Unauthorized connect from %I port %d", sk->daddr, sk->dport);
403
  rfree(sk);
404
  return 0;
405
}
406

    
407
static void
408
bgp_setup_listen_sk(void)
409
{
410
  if (!bgp_listen_sk)
411
    {
412
      sock *s = sk_new(&root_pool);
413
      DBG("BGP: Creating incoming socket\n");
414
      s->type = SK_TCP_PASSIVE;
415
      s->sport = BGP_PORT;
416
      s->tos = IP_PREC_INTERNET_CONTROL;
417
      s->ttl = 1;
418
      s->rbsize = BGP_RX_BUFFER_SIZE;
419
      s->tbsize = BGP_TX_BUFFER_SIZE;
420
      s->rx_hook = bgp_incoming_connection;
421
      if (sk_open(s))
422
        {
423
          log(L_ERR "Unable to open incoming BGP socket");
424
          rfree(s);
425
        }
426
      else
427
        bgp_listen_sk = s;
428
    }
429
}
430

    
431
static void
432
bgp_start_neighbor(struct bgp_proto *p)
433
{
434
  p->local_addr = p->neigh->iface->addr->ip;
435
  DBG("BGP: local=%I remote=%I\n", p->local_addr, p->next_hop);
436
  bgp_initiate(p);
437
}
438

    
439
static void
440
bgp_neigh_notify(neighbor *n)
441
{
442
  struct bgp_proto *p = (struct bgp_proto *) n->proto;
443

    
444
  if (n->iface)
445
    {
446
      BGP_TRACE(D_EVENTS, "Neighbor found");
447
      bgp_start_neighbor(p);
448
    }
449
  else
450
    {
451
      BGP_TRACE(D_EVENTS, "Neighbor lost");
452
      /* Send cease packets, but don't wait for them to be delivered */
453
      bgp_graceful_close_conn(&p->outgoing_conn);
454
      bgp_graceful_close_conn(&p->incoming_conn);
455
      proto_notify_state(&p->p, PS_DOWN);
456
    }
457
}
458

    
459
static void
460
bgp_start_locked(struct object_lock *lock)
461
{
462
  struct bgp_proto *p = lock->data;
463
  struct bgp_config *cf = p->cf;
464

    
465
  DBG("BGP: Got lock\n");
466
  p->local_id = cf->c.global->router_id;
467
  p->next_hop = cf->multihop ? cf->multihop_via : cf->remote_ip;
468
  p->neigh = neigh_find(&p->p, &p->next_hop, NEF_STICKY);
469
  if (!p->neigh)
470
    {
471
      log(L_ERR "%s: Invalid next hop %I", p->p.name, p->next_hop);
472
      p->p.disabled = 1;
473
      proto_notify_state(&p->p, PS_DOWN);
474
    }
475
  else if (p->neigh->iface)
476
    bgp_start_neighbor(p);
477
  else
478
    BGP_TRACE(D_EVENTS, "Waiting for %I to become my neighbor", p->next_hop);
479
}
480

    
481
static int
482
bgp_start(struct proto *P)
483
{
484
  struct bgp_proto *p = (struct bgp_proto *) P;
485
  struct object_lock *lock;
486

    
487
  DBG("BGP: Startup.\n");
488
  p->outgoing_conn.state = BS_IDLE;
489
  p->incoming_conn.state = BS_IDLE;
490
  p->startup_delay = 0;
491

    
492
  bgp_counter++;
493
  bgp_setup_listen_sk();
494
  if (!bgp_linpool)
495
    bgp_linpool = lp_new(&root_pool, 4080);
496

    
497
  /*
498
   *  Before attempting to create the connection, we need to lock the
499
   *  port, so that are sure we're the only instance attempting to talk
500
   *  with that neighbor.
501
   */
502

    
503
  lock = p->lock = olock_new(P->pool);
504
  lock->addr = p->cf->remote_ip;
505
  lock->type = OBJLOCK_TCP;
506
  lock->port = BGP_PORT;
507
  lock->iface = NULL;
508
  lock->hook = bgp_start_locked;
509
  lock->data = p;
510
  olock_acquire(lock);
511
  return PS_START;
512
}
513

    
514
static int
515
bgp_shutdown(struct proto *P)
516
{
517
  struct bgp_proto *p = (struct bgp_proto *) P;
518

    
519
  BGP_TRACE(D_EVENTS, "Shutdown requested");
520

    
521
  /*
522
   *  We want to send the Cease notification message to all connections
523
   *  we have open, but we don't want to wait for all of them to complete.
524
   *  We are willing to handle the primary connection carefully, but for
525
   *  the others we just try to send the packet and if there is no buffer
526
   *  space free, we'll gracefully finish.
527
   */
528

    
529
  proto_notify_state(&p->p, PS_STOP);
530
  if (!p->conn)
531
    {
532
      if (p->outgoing_conn.state != BS_IDLE)
533
        p->outgoing_conn.primary = 1;        /* Shuts protocol down after connection close */
534
      else if (p->incoming_conn.state != BS_IDLE)
535
        p->incoming_conn.primary = 1;
536
    }
537
  if (bgp_graceful_close_conn(&p->outgoing_conn) || bgp_graceful_close_conn(&p->incoming_conn))
538
    return p->p.proto_state;
539
  else
540
    {
541
      /* No connections open, shutdown automatically */
542
      bgp_close(p);
543
      return PS_DOWN;
544
    }
545
}
546

    
547
static struct proto *
548
bgp_init(struct proto_config *C)
549
{
550
  struct bgp_config *c = (struct bgp_config *) C;
551
  struct proto *P = proto_new(C, sizeof(struct bgp_proto));
552
  struct bgp_proto *p = (struct bgp_proto *) P;
553

    
554
  P->rt_notify = bgp_rt_notify;
555
  P->rte_better = bgp_rte_better;
556
  P->import_control = bgp_import_control;
557
  P->neigh_notify = bgp_neigh_notify;
558
  p->cf = c;
559
  p->local_as = c->local_as;
560
  p->remote_as = c->remote_as;
561
  p->is_internal = (c->local_as == c->remote_as);
562
  return P;
563
}
564

    
565
/**
566
 * bgp_error - report a protocol error
567
 * @c: connection
568
 * @code: error code (according to the RFC)
569
 * @subcode: error subcode
570
 * @data: data to be passed in the Notification message
571
 * @len: length of the data
572
 *
573
 * bgp_error() sends a notification packet to tell the other side that a protocol
574
 * error has occured (including the data considered erroneous if possible) and
575
 * closes the connection.
576
 */
577
void
578
bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len)
579
{
580
  if (c->error_flag)
581
    return;
582
  bgp_log_error(c->bgp, "Error", code, subcode, data, (len > 0) ? len : -len);
583
  c->error_flag = 1 + (code != 6);
584
  c->notify_code = code;
585
  c->notify_subcode = subcode;
586
  c->notify_data = data;
587
  c->notify_size = (len > 0) ? len : 0;
588
  if (c->primary)
589
    proto_notify_state(&c->bgp->p, PS_STOP);
590
  bgp_schedule_packet(c, PKT_NOTIFICATION);
591
}
592

    
593
void
594
bgp_check(struct bgp_config *c)
595
{
596
  if (!c->local_as)
597
    cf_error("Local AS number must be set");
598
  if (!c->remote_as)
599
    cf_error("Neighbor must be configured");
600
}
601

    
602
static void
603
bgp_get_status(struct proto *P, byte *buf)
604
{
605
  struct bgp_proto *p = (struct bgp_proto *) P;
606

    
607
  if (P->proto_state == PS_DOWN)
608
    buf[0] = 0;
609
  else
610
    strcpy(buf, bgp_state_names[MAX(p->incoming_conn.state, p->outgoing_conn.state)]);
611
}
612

    
613
static int
614
bgp_reconfigure(struct proto *P, struct proto_config *C)
615
{
616
  struct bgp_config *new = (struct bgp_config *) C;
617
  struct bgp_proto *p = (struct bgp_proto *) P;
618
  struct bgp_config *old = p->cf;
619

    
620
  return !memcmp(((byte *) old) + sizeof(struct proto_config),
621
                 ((byte *) new) + sizeof(struct proto_config),
622
                 sizeof(struct bgp_config) - sizeof(struct proto_config));
623
}
624

    
625
struct protocol proto_bgp = {
626
  name:                        "BGP",
627
  template:                "bgp%d",
628
  attr_class:                EAP_BGP,
629
  init:                        bgp_init,
630
  start:                bgp_start,
631
  shutdown:                bgp_shutdown,
632
  get_status:                bgp_get_status,
633
  get_attr:                bgp_get_attr,
634
  reconfigure:                bgp_reconfigure,
635
  get_route_info:        bgp_get_route_info,
636
};