bgp.c 43.7 KB
Newer Older
Martin Mareš's avatar
Martin Mareš committed
1 2 3 4 5 6 7 8
/*
 *	BIRD -- The Border Gateway Protocol
 *
 *	(c) 2000 Martin Mares <mj@ucw.cz>
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

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

66
#undef LOCAL_DEBUG
Martin Mareš's avatar
Martin Mareš committed
67 68 69 70 71

#include "nest/bird.h"
#include "nest/iface.h"
#include "nest/protocol.h"
#include "nest/route.h"
72
#include "nest/cli.h"
73
#include "nest/locks.h"
Martin Mareš's avatar
Martin Mareš committed
74
#include "conf/conf.h"
75
#include "lib/socket.h"
76
#include "lib/resource.h"
Martin Mareš's avatar
Martin Mareš committed
77
#include "lib/string.h"
Martin Mareš's avatar
Martin Mareš committed
78 79 80

#include "bgp.h"

Ondřej Zajíček's avatar
Ondřej Zajíček committed
81

82
struct linpool *bgp_linpool;		/* Global temporary pool */
83 84 85
static sock *bgp_listen_sk;		/* Global listening socket */
static int bgp_counter;			/* Number of protocol instances using the listening socket */

Ondřej Zajíček's avatar
Ondřej Zajíček committed
86
static void bgp_close(struct bgp_proto *p, int apply_md5);
87
static void bgp_connect(struct bgp_proto *p);
88
static void bgp_active(struct bgp_proto *p);
89
static sock *bgp_setup_listen_sk(ip_addr addr, unsigned port, u32 flags);
90
static void bgp_update_bfd(struct bgp_proto *p, int use_bfd);
Martin Mareš's avatar
Martin Mareš committed
91

92

Ondřej Zajíček's avatar
Ondřej Zajíček committed
93 94 95 96 97 98 99 100 101 102 103 104 105
/**
 * bgp_open - open a BGP instance
 * @p: BGP instance
 *
 * This function allocates and configures shared BGP resources.
 * Should be called as the last step during initialization
 * (when lock is acquired and neighbor is ready).
 * When error, state changed to PS_DOWN, -1 is returned and caller
 * should return immediately.
 */
static int
bgp_open(struct bgp_proto *p)
{
106
  struct config *cfg = p->cf->c.global;
107 108
  int errcode;

Ondřej Zajíček's avatar
Ondřej Zajíček committed
109
  if (!bgp_listen_sk)
110
    bgp_listen_sk = bgp_setup_listen_sk(cfg->listen_bgp_addr, cfg->listen_bgp_port, cfg->listen_bgp_flags);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
111

112 113
  if (!bgp_listen_sk)
    {
114 115
      errcode = BEM_NO_SOCKET;
      goto err;
116 117
    }

Ondřej Zajíček's avatar
Ondřej Zajíček committed
118 119 120
  if (!bgp_linpool)
    bgp_linpool = lp_new(&root_pool, 4080);

121 122
  bgp_counter++;

Ondřej Zajíček's avatar
Ondřej Zajíček committed
123
  if (p->cf->password)
124 125 126 127 128 129 130
    if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, p->cf->password) < 0)
      {
	sk_log_error(bgp_listen_sk, p->p.name);
	bgp_close(p, 0);
	errcode = BEM_INVALID_MD5;
	goto err;
      }
Ondřej Zajíček's avatar
Ondřej Zajíček committed
131 132

  return 0;
133 134 135 136 137 138

err:
  p->p.disabled = 1;
  bgp_store_error(p, NULL, BE_MISC, errcode);
  proto_notify_state(&p->p, PS_DOWN);
  return -1;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
139 140
}

141 142 143 144 145
static void
bgp_startup(struct bgp_proto *p)
{
  BGP_TRACE(D_EVENTS, "Started");
  p->start_state = p->cf->capabilities ? BSS_CONNECT : BSS_CONNECT_NOCAP;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
146 147 148

  if (!p->cf->passive)
    bgp_active(p);
149 150 151 152 153 154 155 156 157 158 159 160
}

static void
bgp_startup_timeout(timer *t)
{
  bgp_startup(t->data);
}


static void
bgp_initiate(struct bgp_proto *p)
{
161 162 163 164
  int rv = bgp_open(p);
  if (rv < 0)
    return;

165 166 167
  if (p->cf->bfd)
    bgp_update_bfd(p, p->cf->bfd);

168 169
  if (p->startup_delay)
    {
170
      p->start_state = BSS_DELAY;
171
      BGP_TRACE(D_EVENTS, "Startup delayed by %d seconds due to errors", p->startup_delay);
172 173 174 175 176 177
      bgp_start_timer(p->startup_timer, p->startup_delay);
    }
  else
    bgp_startup(p);
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
178 179 180 181 182 183 184 185 186
/**
 * bgp_close - close a BGP instance
 * @p: BGP instance
 * @apply_md5: 0 to disable unsetting MD5 auth
 *
 * This function frees and deconfigures shared BGP resources.
 * @apply_md5 is set to 0 when bgp_close is called as a cleanup
 * from failed bgp_open().
 */
187
static void
Ondřej Zajíček's avatar
Ondřej Zajíček committed
188
bgp_close(struct bgp_proto *p, int apply_md5)
189 190 191
{
  ASSERT(bgp_counter);
  bgp_counter--;
192

Ondřej Zajíček's avatar
Ondřej Zajíček committed
193
  if (p->cf->password && apply_md5)
194 195
    if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, NULL) < 0)
      sk_log_error(bgp_listen_sk, p->p.name);
196

197 198 199 200
  if (!bgp_counter)
    {
      rfree(bgp_listen_sk);
      bgp_listen_sk = NULL;
201 202
      rfree(bgp_linpool);
      bgp_linpool = NULL;
203 204 205
    }
}

Martin Mareš's avatar
Martin Mareš committed
206 207 208 209 210 211 212 213 214
/**
 * bgp_start_timer - start a BGP timer
 * @t: timer
 * @value: time to fire (0 to disable the timer)
 *
 * This functions calls tm_start() on @t with time @value and the
 * amount of randomization suggested by the BGP standard. Please use
 * it for all BGP timers.
 */
215
void
216 217
bgp_start_timer(timer *t, int value)
{
218
  if (value)
Martin Mareš's avatar
Martin Mareš committed
219 220 221 222 223
    {
      /* The randomization procedure is specified in RFC 1771: 9.2.3.3 */
      t->randomize = value / 4;
      tm_start(t, value - t->randomize);
    }
224 225 226 227
  else
    tm_stop(t);
}

Martin Mareš's avatar
Martin Mareš committed
228 229 230 231 232 233 234
/**
 * bgp_close_conn - close a BGP connection
 * @conn: connection to close
 *
 * This function takes a connection described by the &bgp_conn structure,
 * closes its socket and frees all resources associated with it.
 */
235 236 237
void
bgp_close_conn(struct bgp_conn *conn)
{
238
  // struct bgp_proto *p = conn->bgp;
239 240 241 242 243 244 245 246 247

  DBG("BGP: Closing connection\n");
  conn->packets_to_send = 0;
  rfree(conn->connect_retry_timer);
  conn->connect_retry_timer = NULL;
  rfree(conn->keepalive_timer);
  conn->keepalive_timer = NULL;
  rfree(conn->hold_timer);
  conn->hold_timer = NULL;
248
  rfree(conn->sk);
249
  conn->sk = NULL;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
  rfree(conn->tx_ev);
  conn->tx_ev = NULL;
}


/**
 * bgp_update_startup_delay - update a startup delay
 * @p: BGP instance
 *
 * This function updates a startup delay that is used to postpone next BGP connect.
 * It also handles disable_after_error and might stop BGP instance when error
 * happened and disable_after_error is on.
 *
 * It should be called when BGP protocol error happened.
 */
void
266
bgp_update_startup_delay(struct bgp_proto *p)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
267 268 269
{
  struct bgp_config *cf = p->cf;

270
  DBG("BGP: Updating startup delay\n");
Ondřej Zajíček's avatar
Ondřej Zajíček committed
271

272
  if (p->last_proto_error && ((now - p->last_proto_error) >= (int) cf->error_amnesia_time))
273 274
    p->startup_delay = 0;

Ondřej Zajíček's avatar
Ondřej Zajíček committed
275 276 277 278 279 280 281
  p->last_proto_error = now;

  if (cf->disable_after_error)
    {
      p->startup_delay = 0;
      p->p.disabled = 1;
      return;
282
    }
Ondřej Zajíček's avatar
Ondřej Zajíček committed
283 284 285 286

  if (!p->startup_delay)
    p->startup_delay = cf->error_delay_time_min;
  else
287
    p->startup_delay = MIN(2 * p->startup_delay, cf->error_delay_time_max);
288 289
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
290
static void
291
bgp_graceful_close_conn(struct bgp_conn *conn, unsigned subcode)
292
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
293
  switch (conn->state)
294 295
    {
    case BS_IDLE:
Ondřej Zajíček's avatar
Ondřej Zajíček committed
296 297
    case BS_CLOSE:
      return;
298 299
    case BS_CONNECT:
    case BS_ACTIVE:
Ondřej Zajíček's avatar
Ondřej Zajíček committed
300 301
      bgp_conn_enter_idle_state(conn);
      return;
302 303 304
    case BS_OPENSENT:
    case BS_OPENCONFIRM:
    case BS_ESTABLISHED:
305
      bgp_error(conn, 6, subcode, NULL, 0);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
306
      return;
307
    default:
Ondřej Zajíček's avatar
Ondřej Zajíček committed
308
      bug("bgp_graceful_close_conn: Unknown state %d", conn->state);
309 310 311
    }
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
312 313 314 315 316 317
static void
bgp_down(struct bgp_proto *p)
{
  if (p->start_state > BSS_PREPARE)
    bgp_close(p, 1);

318
  BGP_TRACE(D_EVENTS, "Down");
Ondřej Zajíček's avatar
Ondřej Zajíček committed
319 320 321 322 323 324 325 326 327 328
  proto_notify_state(&p->p, PS_DOWN);
}

static void
bgp_decision(void *vp)
{
  struct bgp_proto *p = vp;

  DBG("BGP: Decision start\n");
  if ((p->p.proto_state == PS_START)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
329
      && (p->outgoing_conn.state == BS_IDLE)
330
      && (p->incoming_conn.state != BS_OPENCONFIRM)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
331
      && (!p->cf->passive))
332
    bgp_active(p);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
333 334 335 336 337 338 339

  if ((p->p.proto_state == PS_STOP)
      && (p->outgoing_conn.state == BS_IDLE)
      && (p->incoming_conn.state == BS_IDLE))
    bgp_down(p);
}

340 341
void
bgp_stop(struct bgp_proto *p, unsigned subcode)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
342 343
{
  proto_notify_state(&p->p, PS_STOP);
344 345
  bgp_graceful_close_conn(&p->outgoing_conn, subcode);
  bgp_graceful_close_conn(&p->incoming_conn, subcode);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
346 347 348
  ev_schedule(p->event);
}

349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
static inline void
bgp_conn_set_state(struct bgp_conn *conn, unsigned new_state)
{
  if (conn->bgp->p.mrtdump & MD_STATES)
    mrt_dump_bgp_state_change(conn, conn->state, new_state);

  conn->state = new_state;
}

void
bgp_conn_enter_openconfirm_state(struct bgp_conn *conn)
{
  /* Really, most of the work is done in bgp_rx_open(). */
  bgp_conn_set_state(conn, BS_OPENCONFIRM);
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
365 366 367 368
void
bgp_conn_enter_established_state(struct bgp_conn *conn)
{
  struct bgp_proto *p = conn->bgp;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
369

Ondřej Zajíček's avatar
Ondřej Zajíček committed
370 371 372
  BGP_TRACE(D_EVENTS, "BGP session established");
  DBG("BGP: UP!!!\n");

373 374
  /* For multi-hop BGP sessions */
  if (ipa_zero(p->source_addr))
375
    p->source_addr = conn->sk->saddr;
376

377 378
  conn->sk->fast_rx = 0;

Ondřej Zajíček's avatar
Ondřej Zajíček committed
379 380 381
  p->conn = conn;
  p->last_error_class = 0;
  p->last_error_code = 0;
382 383
  p->feed_state = BFS_NONE;
  p->load_state = BFS_NONE;
384 385 386
  bgp_init_bucket_table(p);
  bgp_init_prefix_table(p, 8);

387 388 389 390 391 392 393 394 395 396 397 398 399 400
  int peer_gr_ready = conn->peer_gr_aware && !(conn->peer_gr_flags & BGP_GRF_RESTART);

  if (p->p.gr_recovery && !peer_gr_ready)
    proto_graceful_restart_unlock(&p->p);

  if (p->p.gr_recovery && (p->cf->gr_mode == BGP_GR_ABLE) && peer_gr_ready)
    p->p.gr_wait = 1;

  if (p->gr_active)
    tm_stop(p->gr_timer);

  if (p->gr_active && (!conn->peer_gr_able || !(conn->peer_gr_aflags & BGP_GRF_FORWARDING)))
    bgp_graceful_restart_done(p);

401 402 403 404 405 406
  /* GR capability implies that neighbor will send End-of-RIB */
  if (conn->peer_gr_aware)
    p->load_state = BFS_LOADING;

  /* proto_notify_state() will likely call bgp_feed_begin(), setting p->feed_state */

407
  bgp_conn_set_state(conn, BS_ESTABLISHED);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
408 409 410 411 412 413 414 415 416 417
  proto_notify_state(&p->p, PS_UP);
}

static void
bgp_conn_leave_established_state(struct bgp_proto *p)
{
  BGP_TRACE(D_EVENTS, "BGP session closed");
  p->conn = NULL;

  if (p->p.proto_state == PS_UP)
418
    bgp_stop(p, 0);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
419 420 421 422 423 424 425 426
}

void
bgp_conn_enter_close_state(struct bgp_conn *conn)
{
  struct bgp_proto *p = conn->bgp;
  int os = conn->state;

427
  bgp_conn_set_state(conn, BS_CLOSE);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
428 429 430
  tm_stop(conn->keepalive_timer);
  conn->sk->rx_hook = NULL;

431 432 433
  /* Timeout for CLOSE state, if we cannot send notification soon then we just hangup */
  bgp_start_timer(conn->hold_timer, 10);

Ondřej Zajíček's avatar
Ondřej Zajíček committed
434 435 436 437 438 439 440 441 442 443 444
  if (os == BS_ESTABLISHED)
    bgp_conn_leave_established_state(p);
}

void
bgp_conn_enter_idle_state(struct bgp_conn *conn)
{
  struct bgp_proto *p = conn->bgp;
  int os = conn->state;

  bgp_close_conn(conn);
445
  bgp_conn_set_state(conn, BS_IDLE);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
446 447 448 449 450 451
  ev_schedule(p->event);

  if (os == BS_ESTABLISHED)
    bgp_conn_leave_established_state(p);
}

452 453 454 455 456 457 458 459 460 461 462
/**
 * bgp_handle_graceful_restart - handle detected BGP graceful restart
 * @p: BGP instance
 *
 * This function is called when a BGP graceful restart of the neighbor is
 * detected (when the TCP connection fails or when a new TCP connection
 * appears). The function activates processing of the restart - starts routing
 * table refresh cycle and activates BGP restart timer. The protocol state goes
 * back to %PS_START, but changing BGP state back to %BS_IDLE is left for the
 * caller.
 */
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
void
bgp_handle_graceful_restart(struct bgp_proto *p)
{
  ASSERT(p->conn && (p->conn->state == BS_ESTABLISHED) && p->gr_ready);

  BGP_TRACE(D_EVENTS, "Neighbor graceful restart detected%s",
	    p->gr_active ? " - already pending" : "");
  proto_notify_state(&p->p, PS_START);

  if (p->gr_active)
    rt_refresh_end(p->p.main_ahook->table, p->p.main_ahook);

  p->gr_active = 1;
  bgp_start_timer(p->gr_timer, p->conn->peer_gr_time);
  rt_refresh_begin(p->p.main_ahook->table, p->p.main_ahook);
}

480 481 482 483 484 485 486 487 488 489
/**
 * bgp_graceful_restart_done - finish active BGP graceful restart
 * @p: BGP instance
 *
 * This function is called when the active BGP graceful restart of the neighbor
 * should be finished - either successfully (the neighbor sends all paths and
 * reports end-of-RIB on the new session) or unsuccessfully (the neighbor does
 * not support BGP graceful restart on the new session). The function ends
 * routing table refresh cycle and stops BGP restart timer.
 */
490 491 492 493 494 495 496 497 498
void
bgp_graceful_restart_done(struct bgp_proto *p)
{
  BGP_TRACE(D_EVENTS, "Neighbor graceful restart done");
  p->gr_active = 0;
  tm_stop(p->gr_timer);
  rt_refresh_end(p->p.main_ahook->table, p->p.main_ahook);
}

499 500 501 502 503 504 505 506 507
/**
 * bgp_graceful_restart_timeout - timeout of graceful restart 'restart timer'
 * @t: timer
 *
 * This function is a timeout hook for @gr_timer, implementing BGP restart time
 * limit for reestablisment of the BGP session after the graceful restart. When
 * fired, we just proceed with the usual protocol restart.
 */

508 509 510 511 512 513 514 515 516
static void
bgp_graceful_restart_timeout(timer *t)
{
  struct bgp_proto *p = t->data;

  BGP_TRACE(D_EVENTS, "Neighbor graceful restart timeout");
  bgp_stop(p, 0);
}

517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557

/**
 * bgp_refresh_begin - start incoming enhanced route refresh sequence
 * @p: BGP instance
 *
 * This function is called when an incoming enhanced route refresh sequence is
 * started by the neighbor, demarcated by the BoRR packet. The function updates
 * the load state and starts the routing table refresh cycle. Note that graceful
 * restart also uses routing table refresh cycle, but RFC 7313 and load states
 * ensure that these two sequences do not overlap.
 */
void
bgp_refresh_begin(struct bgp_proto *p)
{
  if (p->load_state == BFS_LOADING)
    { log(L_WARN "%s: BEGIN-OF-RR received before END-OF-RIB, ignoring", p->p.name); return; }

  p->load_state = BFS_REFRESHING;
  rt_refresh_begin(p->p.main_ahook->table, p->p.main_ahook);
}

/**
 * bgp_refresh_end - finish incoming enhanced route refresh sequence
 * @p: BGP instance
 *
 * This function is called when an incoming enhanced route refresh sequence is
 * finished by the neighbor, demarcated by the EoRR packet. The function updates
 * the load state and ends the routing table refresh cycle. Routes not received
 * during the sequence are removed by the nest.
 */
void
bgp_refresh_end(struct bgp_proto *p)
{
  if (p->load_state != BFS_REFRESHING)
    { log(L_WARN "%s: END-OF-RR received without prior BEGIN-OF-RR, ignoring", p->p.name); return; }

  p->load_state = BFS_NONE;
  rt_refresh_end(p->p.main_ahook->table, p->p.main_ahook);
}


558 559 560
static void
bgp_send_open(struct bgp_conn *conn)
{
561
  conn->start_state = conn->bgp->start_state;
562 563

  // Default values, possibly changed by receiving capabilities.
564
  conn->advertised_as = 0;
565 566 567
  conn->peer_refresh_support = 0;
  conn->peer_as4_support = 0;
  conn->peer_add_path = 0;
568
  conn->peer_enhanced_refresh_support = 0;
569 570 571 572 573
  conn->peer_gr_aware = 0;
  conn->peer_gr_able = 0;
  conn->peer_gr_time = 0;
  conn->peer_gr_flags = 0;
  conn->peer_gr_aflags = 0;
574
  conn->peer_ext_messages_support = 0;
575

576 577
  DBG("BGP: Sending open\n");
  conn->sk->rx_hook = bgp_rx;
578
  conn->sk->tx_hook = bgp_tx;
579
  tm_stop(conn->connect_retry_timer);
Martin Mareš's avatar
Martin Mareš committed
580
  bgp_schedule_packet(conn, PKT_OPEN);
581
  bgp_conn_set_state(conn, BS_OPENSENT);
582
  bgp_start_timer(conn->hold_timer, conn->bgp->cf->initial_hold_time);
583 584
}

585 586
static void
bgp_connected(sock *sk)
587 588
{
  struct bgp_conn *conn = sk->data;
Martin Mareš's avatar
Martin Mareš committed
589
  struct bgp_proto *p = conn->bgp;
590

Martin Mareš's avatar
Martin Mareš committed
591
  BGP_TRACE(D_EVENTS, "Connected");
592 593 594 595 596 597
  bgp_send_open(conn);
}

static void
bgp_connect_timeout(timer *t)
{
598
  struct bgp_conn *conn = t->data;
Martin Mareš's avatar
Martin Mareš committed
599
  struct bgp_proto *p = conn->bgp;
600

Martin Mareš's avatar
Martin Mareš committed
601
  DBG("BGP: connect_timeout\n");
Ondřej Zajíček's avatar
Ondřej Zajíček committed
602 603 604 605 606 607 608
  if (p->p.proto_state == PS_START)
    {
      bgp_close_conn(conn);
      bgp_connect(p);
    }
  else
    bgp_conn_enter_idle_state(conn);
609 610 611
}

static void
612
bgp_sock_err(sock *sk, int err)
613 614
{
  struct bgp_conn *conn = sk->data;
Martin Mareš's avatar
Martin Mareš committed
615
  struct bgp_proto *p = conn->bgp;
616

617 618 619 620 621 622 623 624 625
  /*
   * This error hook may be called either asynchronously from main
   * loop, or synchronously from sk_send().  But sk_send() is called
   * only from bgp_tx() and bgp_kick_tx(), which are both called
   * asynchronously from main loop. Moreover, they end if err hook is
   * called. Therefore, we could suppose that it is always called
   * asynchronously.
   */

Ondřej Zajíček's avatar
Ondřej Zajíček committed
626 627
  bgp_store_error(p, conn, BE_SOCKET, err);

628 629 630 631
  if (err)
    BGP_TRACE(D_EVENTS, "Connection lost (%M)", err);
  else
    BGP_TRACE(D_EVENTS, "Connection closed");
Ondřej Zajíček's avatar
Ondřej Zajíček committed
632

633 634 635
  if ((conn->state == BS_ESTABLISHED) && p->gr_ready)
    bgp_handle_graceful_restart(p);

Ondřej Zajíček's avatar
Ondřej Zajíček committed
636
  bgp_conn_enter_idle_state(conn);
637 638
}

639 640 641 642
static void
bgp_hold_timeout(timer *t)
{
  struct bgp_conn *conn = t->data;
643
  struct bgp_proto *p = conn->bgp;
644

645 646
  DBG("BGP: Hold timeout\n");

647 648 649 650 651 652 653 654
  /* We are already closing the connection - just do hangup */
  if (conn->state == BS_CLOSE)
  {
    BGP_TRACE(D_EVENTS, "Connection stalled");
    bgp_conn_enter_idle_state(conn);
    return;
  }

655 656 657 658 659 660 661
  /* If there is something in input queue, we are probably congested
     and perhaps just not processed BGP packets in time. */

  if (sk_rx_ready(conn->sk) > 0)
    bgp_start_timer(conn->hold_timer, 10);
  else
    bgp_error(conn, 4, 0, NULL, 0);
662 663 664 665 666 667 668 669 670 671 672
}

static void
bgp_keepalive_timeout(timer *t)
{
  struct bgp_conn *conn = t->data;

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

673
static void
674
bgp_setup_conn(struct bgp_proto *p, struct bgp_conn *conn)
675 676 677
{
  timer *t;

678
  conn->sk = NULL;
679
  conn->bgp = p;
Martin Mareš's avatar
Martin Mareš committed
680
  conn->packets_to_send = 0;
681 682 683

  t = conn->connect_retry_timer = tm_new(p->p.pool);
  t->hook = bgp_connect_timeout;
684 685
  t->data = conn;
  t = conn->hold_timer = tm_new(p->p.pool);
686
  t->hook = bgp_hold_timeout;
687 688
  t->data = conn;
  t = conn->keepalive_timer = tm_new(p->p.pool);
689
  t->hook = bgp_keepalive_timeout;
690
  t->data = conn;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
691 692 693
  conn->tx_ev = ev_new(p->p.pool);
  conn->tx_ev->hook = bgp_kick_tx;
  conn->tx_ev->data = conn;
694 695
}

696
static void
697
bgp_setup_sk(struct bgp_conn *conn, sock *s)
698 699 700
{
  s->data = conn;
  s->err_hook = bgp_sock_err;
701
  s->fast_rx = 1;
702 703 704
  conn->sk = s;
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
705
static void
706
bgp_active(struct bgp_proto *p)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
707
{
708
  int delay = MAX(1, p->cf->connect_delay_time);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
709 710 711 712
  struct bgp_conn *conn = &p->outgoing_conn;

  BGP_TRACE(D_EVENTS, "Connect delayed by %d seconds", delay);
  bgp_setup_conn(p, conn);
713
  bgp_conn_set_state(conn, BS_ACTIVE);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
714 715 716
  bgp_start_timer(conn->connect_retry_timer, delay);
}

Martin Mareš's avatar
Martin Mareš committed
717 718 719 720 721 722 723 724
/**
 * bgp_connect - initiate an outgoing connection
 * @p: BGP instance
 *
 * The bgp_connect() function creates a new &bgp_conn and initiates
 * a TCP connection to the peer. The rest of connection setup is governed
 * by the BGP state machine as described in the standard.
 */
725 726 727 728
static void
bgp_connect(struct bgp_proto *p)	/* Enter Connect state and start establishing connection */
{
  sock *s;
729
  struct bgp_conn *conn = &p->outgoing_conn;
730
  int hops = p->cf->multihop ? : 1;
731 732 733 734

  DBG("BGP: Connecting\n");
  s = sk_new(p->p.pool);
  s->type = SK_TCP_ACTIVE;
735
  s->saddr = p->source_addr;
736
  s->daddr = p->cf->remote_ip;
737
  s->dport = p->cf->remote_port;
738
  s->iface = p->neigh ? p->neigh->iface : NULL;
739
  s->ttl = p->cf->ttl_security ? 255 : hops;
740 741
  s->rbsize = p->cf->enable_extended_messages ? BGP_RX_BUFFER_EXT_SIZE : BGP_RX_BUFFER_SIZE;
  s->tbsize = p->cf->enable_extended_messages ? BGP_TX_BUFFER_EXT_SIZE : BGP_TX_BUFFER_SIZE;
742 743 744
  s->tos = IP_PREC_INTERNET_CONTROL;
  s->password = p->cf->password;
  s->tx_hook = bgp_connected;
745
  BGP_TRACE(D_EVENTS, "Connecting to %I%J from local address %I%J", s->daddr, p->cf->iface,
Ondřej Zajíček's avatar
Ondřej Zajíček committed
746
	    s->saddr, ipa_is_link_local(s->saddr) ? s->iface : NULL);
747
  bgp_setup_conn(p, conn);
748
  bgp_setup_sk(conn, s);
749
  bgp_conn_set_state(conn, BS_CONNECT);
750 751

  if (sk_open(s) < 0)
752
    goto err;
753 754 755 756

  /* Set minimal receive TTL if needed */
  if (p->cf->ttl_security)
    if (sk_set_min_ttl(s, 256 - hops) < 0)
757
      goto err;
758

759 760
  DBG("BGP: Waiting for connect success\n");
  bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time);
761 762 763 764 765 766
  return;

 err:
  sk_log_error(s, p->p.name);
  bgp_sock_err(s, 0);
  return;
767 768
}

769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
/**
 * bgp_find_proto - find existing proto for incoming connection
 * @sk: TCP socket
 *
 */
static struct bgp_proto *
bgp_find_proto(sock *sk)
{
  struct proto_config *pc;

  WALK_LIST(pc, config->protos)
    if ((pc->protocol == &proto_bgp) && pc->proto)
      {
	struct bgp_proto *p = (struct bgp_proto *) pc->proto;
	if (ipa_equal(p->cf->remote_ip, sk->daddr) &&
	    (!ipa_is_link_local(sk->daddr) || (p->cf->iface == sk->iface)))
	  return p;
      }

  return NULL;
}

Martin Mareš's avatar
Martin Mareš committed
791 792 793 794 795 796 797 798 799 800 801 802
/**
 * bgp_incoming_connection - handle an incoming connection
 * @sk: TCP socket
 * @dummy: unused
 *
 * This function serves as a socket hook for accepting of new BGP
 * connections. It searches a BGP instance corresponding to the peer
 * which has connected and if such an instance exists, it creates a
 * &bgp_conn structure, attaches it to the instance and either sends
 * an Open message or (if there already is an active connection) it
 * closes the new connection by sending a Notification message.
 */
803
static int
Martin Mareš's avatar
Martin Mareš committed
804
bgp_incoming_connection(sock *sk, int dummy UNUSED)
805
{
806 807
  struct bgp_proto *p;
  int acc, hops;
808

809
  DBG("BGP: Incoming connection from %I port %d\n", sk->daddr, sk->dport);
810 811 812 813 814 815 816 817 818
  p = bgp_find_proto(sk);
  if (!p)
    {
      log(L_WARN "BGP: Unexpected connect from unknown address %I%J (port %d)",
	  sk->daddr, ipa_is_link_local(sk->daddr) ? sk->iface : NULL, sk->dport);
      rfree(sk);
      return 0;
    }

819 820 821 822 823 824 825
  /*
   * BIRD should keep multiple incoming connections in OpenSent state (for
   * details RFC 4271 8.2.1 par 3), but it keeps just one. Duplicate incoming
   * connections are rejected istead. The exception is the case where an
   * incoming connection triggers a graceful restart.
   */

826 827
  acc = (p->p.proto_state == PS_START || p->p.proto_state == PS_UP) &&
    (p->start_state >= BSS_CONNECT) && (!p->incoming_conn.sk);
828

829 830 831 832 833 834
  if (p->conn && (p->conn->state == BS_ESTABLISHED) && p->gr_ready)
    {
      bgp_store_error(p, NULL, BE_MISC, BEM_GRACEFUL_RESTART);
      bgp_handle_graceful_restart(p);
      bgp_conn_enter_idle_state(p->conn);
      acc = 1;
835 836 837 838

      /* There might be separate incoming connection in OpenSent state */
      if (p->incoming_conn.state > BS_ACTIVE)
	bgp_close_conn(&p->incoming_conn);
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
    }

  BGP_TRACE(D_EVENTS, "Incoming connection from %I%J (port %d) %s",
	    sk->daddr, ipa_is_link_local(sk->daddr) ? sk->iface : NULL,
	    sk->dport, acc ? "accepted" : "rejected");

  if (!acc)
    {
      rfree(sk);
      return 0;
    }

  hops = p->cf->multihop ? : 1;

  if (sk_set_ttl(sk, p->cf->ttl_security ? 255 : hops) < 0)
    goto err;

  if (p->cf->ttl_security)
    if (sk_set_min_ttl(sk, 256 - hops) < 0)
      goto err;

860 861 862 863 864 865 866
  if (p->cf->enable_extended_messages)
    {
      sk->rbsize = BGP_RX_BUFFER_EXT_SIZE;
      sk->tbsize = BGP_TX_BUFFER_EXT_SIZE;
      sk_reallocate(sk);
    }

867 868 869 870 871 872 873 874
  bgp_setup_conn(p, &p->incoming_conn);
  bgp_setup_sk(&p->incoming_conn, sk);
  bgp_send_open(&p->incoming_conn);
  return 0;

err:
  sk_log_error(sk, p->p.name);
  log(L_ERR "%s: Incoming connection aborted", p->p.name);
875 876 877 878
  rfree(sk);
  return 0;
}

879
static void
880
bgp_listen_sock_err(sock *sk UNUSED, int err)
881 882 883 884
{
  if (err == ECONNABORTED)
    log(L_WARN "BGP: Incoming connection aborted");
  else
885
    log(L_ERR "BGP: Error on listening socket: %M", err);
886 887
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
888
static sock *
889
bgp_setup_listen_sk(ip_addr addr, unsigned port, u32 flags)
890
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
891
  sock *s = sk_new(&root_pool);
892
  DBG("BGP: Creating listening socket\n");
Ondřej Zajíček's avatar
Ondřej Zajíček committed
893
  s->type = SK_TCP_PASSIVE;
894
  s->ttl = 255;
895 896
  s->saddr = addr;
  s->sport = port ? port : BGP_PORT;
897
  s->flags = flags ? 0 : SKF_V6ONLY;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
898 899 900 901
  s->tos = IP_PREC_INTERNET_CONTROL;
  s->rbsize = BGP_RX_BUFFER_SIZE;
  s->tbsize = BGP_TX_BUFFER_SIZE;
  s->rx_hook = bgp_incoming_connection;
902
  s->err_hook = bgp_listen_sock_err;
903 904

  if (sk_open(s) < 0)
905
    goto err;
906 907

  return s;
908 909 910 911 912 913

 err:
  sk_log_error(s, "BGP");
  log(L_ERR "BGP: Cannot open listening socket");
  rfree(s);
  return NULL;
914 915 916 917 918
}

static void
bgp_start_neighbor(struct bgp_proto *p)
{
919 920 921
  /* Called only for single-hop BGP sessions */

  if (ipa_zero(p->source_addr))
Ondřej Zajíček's avatar
Ondřej Zajíček committed
922
    p->source_addr = p->neigh->ifa->ip;
923

924 925 926
#ifdef IPV6
  {
    struct ifa *a;
927
    p->local_link = IPA_NONE;
928 929 930 931 932 933
    WALK_LIST(a, p->neigh->iface->addrs)
      if (a->scope == SCOPE_LINK)
        {
	  p->local_link = a->ip;
	  break;
	}
934 935 936 937

    if (! ipa_nonzero(p->local_link))
      log(L_WARN "%s: Missing link local address on interface %s", p->p.name,  p->neigh->iface->name);

938 939 940
    DBG("BGP: Selected link-level address %I\n", p->local_link);
  }
#endif
Ondřej Zajíček's avatar
Ondřej Zajíček committed
941

942
  bgp_initiate(p);
943 944 945 946 947 948
}

static void
bgp_neigh_notify(neighbor *n)
{
  struct bgp_proto *p = (struct bgp_proto *) n->proto;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
949 950 951 952
  int ps = p->p.proto_state;

  if (n != p->neigh)
    return;
953

Ondřej Zajíček's avatar
Ondřej Zajíček committed
954
  if ((ps == PS_DOWN) || (ps == PS_STOP))
955 956
    return;

Ondřej Zajíček's avatar
Ondřej Zajíček committed
957 958 959
  int prepare = (ps == PS_START) && (p->start_state == BSS_PREPARE);

  if (n->scope <= 0)
960
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977
      if (!prepare)
        {
	  BGP_TRACE(D_EVENTS, "Neighbor lost");
	  bgp_store_error(p, NULL, BE_MISC, BEM_NEIGHBOR_LOST);
	  /* Perhaps also run bgp_update_startup_delay(p)? */
	  bgp_stop(p, 0);
	}
    }
  else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP))
    {
      if (!prepare)
        {
	  BGP_TRACE(D_EVENTS, "Link down");
	  bgp_store_error(p, NULL, BE_MISC, BEM_LINK_DOWN);
	  if (ps == PS_UP)
	    bgp_update_startup_delay(p);
	  bgp_stop(p, 0);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
978
	}
979 980 981
    }
  else
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
982
      if (prepare)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
983
	{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
984 985
	  BGP_TRACE(D_EVENTS, "Neighbor ready");
	  bgp_start_neighbor(p);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
986
	}
987 988 989
    }
}

990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
static void
bgp_bfd_notify(struct bfd_request *req)
{
  struct bgp_proto *p = req->data;
  int ps = p->p.proto_state;

  if (req->down && ((ps == PS_START) || (ps == PS_UP)))
    {
      BGP_TRACE(D_EVENTS, "BFD session down");
      bgp_store_error(p, NULL, BE_MISC, BEM_BFD_DOWN);
      if (ps == PS_UP)
	bgp_update_startup_delay(p);
      bgp_stop(p, 0);
    }
}

static void
bgp_update_bfd(struct bgp_proto *p, int use_bfd)
{
  if (use_bfd && !p->bfd_req)
    p->bfd_req = bfd_request_session(p->p.pool, p->cf->remote_ip, p->source_addr,
				     p->cf->multihop ? NULL : p->neigh->iface,
				     bgp_bfd_notify, p);

  if (!use_bfd && p->bfd_req)
    {
      rfree(p->bfd_req);
      p->bfd_req = NULL;
    }
}

1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
static int
bgp_reload_routes(struct proto *P)
{
  struct bgp_proto *p = (struct bgp_proto *) P;
  if (!p->conn || !p->conn->peer_refresh_support)
    return 0;

  bgp_schedule_packet(p->conn, PKT_ROUTE_REFRESH);
  return 1;
}

1032
static void
1033
bgp_feed_begin(struct proto *P, int initial)
1034 1035
{
  struct bgp_proto *p = (struct bgp_proto *) P;
1036 1037 1038

  /* This should not happen */
  if (!p->conn)
1039 1040
    return;

1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
  if (initial && p->cf->gr_mode)
    p->feed_state = BFS_LOADING;

  /* It is refeed and both sides support enhanced route refresh */
  if (!initial && p->cf->enable_refresh &&
      p->conn->peer_enhanced_refresh_support)
    {
      /* BoRR must not be sent before End-of-RIB */
      if (p->feed_state == BFS_LOADING || p->feed_state == BFS_LOADED)
	return;

      p->feed_state = BFS_REFRESHING;
      bgp_schedule_packet(p->conn, PKT_BEGIN_REFRESH);
    }
}

static void
bgp_feed_end(struct proto *P)
{
  struct bgp_proto *p = (struct bgp_proto *) P;

  /* This should not happen */
  if (!p->conn)
    return;

  /* Non-demarcated feed ended, nothing to do */
  if (p->feed_state == BFS_NONE)
    return;

  /* Schedule End-of-RIB packet */
  if (p->feed_state == BFS_LOADING)
    p->feed_state = BFS_LOADED;

  /* Schedule EoRR packet */
  if (p->feed_state == BFS_REFRESHING)
    p->feed_state = BFS_REFRESHED;

  /* Kick TX hook */
1079 1080 1081
  bgp_schedule_packet(p->conn, PKT_UPDATE);
}

1082

1083 1084 1085 1086 1087 1088
static void
bgp_start_locked(struct object_lock *lock)
{
  struct bgp_proto *p = lock->data;
  struct bgp_config *cf = p->cf;

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1089 1090 1091
  if (p->p.proto_state != PS_START)
    {
      DBG("BGP: Got lock in different state %d\n", p->p.proto_state);
1092
      return;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1093 1094
    }

1095
  DBG("BGP: Got lock\n");
1096

1097
  if (cf->multihop)
1098
    {
1099 1100 1101
      /* Multi-hop sessions do not use neighbor entries */
      bgp_initiate(p);
      return;
1102 1103
    }

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1104 1105
  neighbor *n = neigh_find2(&p->p, &cf->remote_ip, cf->iface, NEF_STICKY);
  if (!n)
1106
    {
1107
      log(L_ERR "%s: Invalid remote address %I%J", p->p.name, cf->remote_ip, cf->iface);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1108
      /* As we do not start yet, we can just disable protocol */
1109
      p->p.disabled = 1;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1110
      bgp_store_error(p, NULL, BE_MISC, BEM_INVALID_NEXT_HOP);
1111
      proto_notify_state(&p->p, PS_DOWN);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1112
      return;
1113
    }
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1114 1115 1116 1117

  p->neigh = n;

  if (n->scope <= 0)
1118
    BGP_TRACE(D_EVENTS, "Waiting for %I%J to become my neighbor", cf->remote_ip, cf->iface);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1119 1120 1121 1122
  else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP))
    BGP_TRACE(D_EVENTS, "Waiting for link on %s", n->iface->name);
  else
    bgp_start_neighbor(p);
1123 1124
}

Martin Mareš's avatar
Martin Mareš committed
1125 1126 1127
static int
bgp_start(struct proto *P)
{
1128 1129 1130
  struct bgp_proto *p = (struct bgp_proto *) P;
  struct object_lock *lock;

1131
  DBG("BGP: Startup.\n");
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1132
  p->start_state = BSS_PREPARE;
1133 1134
  p->outgoing_conn.state = BS_IDLE;
  p->incoming_conn.state = BS_IDLE;
1135
  p->neigh = NULL;
1136
  p->bfd_req = NULL;
1137 1138
  p->gr_ready = 0;
  p->gr_active = 0;
1139

1140 1141
  rt_lock_table(p->igp_table);

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1142 1143 1144
  p->event = ev_new(p->p.pool);
  p->event->hook = bgp_decision;
  p->event->data = p;
1145

1146 1147 1148 1149
  p->startup_timer = tm_new(p->p.pool);
  p->startup_timer->hook = bgp_startup_timeout;
  p->startup_timer->data = p;

1150 1151 1152 1153
  p->gr_timer = tm_new(p->p.pool);
  p->gr_timer->hook = bgp_graceful_restart_timeout;
  p->gr_timer->data = p;

1154 1155 1156 1157
  p->local_id = proto_get_router_id(P->cf);
  if (p->rr_client)
    p->rr_cluster_id = p->cf->rr_cluster_id ? p->cf->rr_cluster_id : p->local_id;

1158 1159 1160
  p->remote_id = 0;
  p->source_addr = p->cf->source_addr;

1161
  if (p->p.gr_recovery && p->cf->gr_mode)
1162 1163
    proto_graceful_restart_lock(P);

1164 1165 1166 1167 1168 1169 1170 1171
  /*
   *  Before attempting to create the connection, we need to lock the
   *  port, so that are sure we're the only instance attempting to talk
   *  with that neighbor.
   */

  lock = p->lock = olock_new(P->pool);
  lock->addr = p->cf->remote_ip;
1172
  lock->port = p->cf->remote_port;
1173
  lock->iface = p->cf->iface;
1174 1175 1176 1177
  lock->type = OBJLOCK_TCP;
  lock->hook = bgp_start_locked;
  lock->data = p;
  olock_acquire(lock);
1178

1179
  return PS_START;