neighbor.c 15.6 KB
Newer Older
1 2 3
/*
 *	BIRD -- OSPF
 *
4
 *	(c) 1999 - 2004 Ondrej Filip <feela@network.cz>
5 6 7 8 9 10
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

#include "ospf.h"

Ondřej Filip's avatar
Ondřej Filip committed
11 12 13 14 15 16 17 18 19 20 21 22
char *ospf_ns[] = { "    down",
  " attempt",
  "    init",
  "    2way",
  " exstart",
  "exchange",
  " loading",
  "    full"
};

const char *ospf_inm[] =
  { "hello received", "neighbor start", "2-way received",
Ondřej Filip's avatar
Ondřej Filip committed
23 24
  "negotiation done", "exstart done", "bad ls request", "load done",
  "adjacency ok?", "sequence mismatch", "1-way received", "kill neighbor",
Ondřej Filip's avatar
Ondřej Filip committed
25 26
  "inactivity timer", "line down"
};
Ondřej Filip's avatar
Ondřej Filip committed
27

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
static void neigh_chstate(struct ospf_neighbor *n, u8 state);
static struct ospf_neighbor *electbdr(list nl);
static struct ospf_neighbor *electdr(list nl);
static void neighbor_timer_hook(timer * timer);
static void rxmt_timer_hook(timer * timer);
static void ackd_timer_hook(timer * t);

static void
init_lists(struct ospf_neighbor *n)
{
  s_init_list(&(n->lsrql));
  n->lsrqh = ospf_top_new(n->pool);
  s_init(&(n->lsrqi), &(n->lsrql));

  s_init_list(&(n->lsrtl));
  n->lsrth = ospf_top_new(n->pool);
  s_init(&(n->lsrti), &(n->lsrtl));
}
46

Ondřej Zajíček's avatar
Ondřej Zajíček committed
47
/* Resets LSA request and retransmit lists.
48 49 50 51 52 53 54 55 56 57
 * We do not reset DB summary list iterator here, 
 * it is reset during entering EXCHANGE state.
 */
static void
reset_lists(struct ospf_neighbor *n)
{
  ospf_top_free(n->lsrqh);
  ospf_top_free(n->lsrth);
  init_lists(n);
}
58 59 60 61

struct ospf_neighbor *
ospf_neighbor_new(struct ospf_iface *ifa)
{
62
  struct proto *p = (struct proto *) (ifa->oa->po);
63
  struct proto_ospf *po = ifa->oa->po;
64 65 66 67 68 69 70
  struct pool *pool = rp_new(p->pool, "OSPF Neighbor");
  struct ospf_neighbor *n = mb_allocz(pool, sizeof(struct ospf_neighbor));

  n->pool = pool;
  n->ifa = ifa;
  add_tail(&ifa->neigh_list, NODE n);
  n->adj = 0;
71
  n->csn = 0;
Ondřej Filip's avatar
Ondřej Filip committed
72
  n->state = NEIGHBOR_DOWN;
73

74 75 76
  init_lists(n);
  s_init(&(n->dbsi), &(po->lsal));

77 78 79 80 81 82 83 84 85 86 87 88
  n->inactim = tm_new(pool);
  n->inactim->data = n;
  n->inactim->randomize = 0;
  n->inactim->hook = neighbor_timer_hook;
  n->inactim->recurrent = 0;
  DBG("%s: Installing inactivity timer.\n", p->name);

  n->rxmt_timer = tm_new(pool);
  n->rxmt_timer->data = n;
  n->rxmt_timer->randomize = 0;
  n->rxmt_timer->hook = rxmt_timer_hook;
  n->rxmt_timer->recurrent = ifa->rxmtint;
Ondřej Filip's avatar
Ondřej Filip committed
89
  tm_start(n->rxmt_timer, n->ifa->rxmtint);
90 91 92 93 94 95
  DBG("%s: Installing rxmt timer.\n", p->name);

  n->ackd_timer = tm_new(pool);
  n->ackd_timer->data = n;
  n->ackd_timer->randomize = 0;
  n->ackd_timer->hook = ackd_timer_hook;
Ondřej Filip's avatar
Ondřej Filip committed
96
  n->ackd_timer->recurrent = ifa->rxmtint / 2;
97 98
  init_list(&n->ackl[ACKL_DIRECT]);
  init_list(&n->ackl[ACKL_DELAY]);
Ondřej Filip's avatar
Ondřej Filip committed
99
  tm_start(n->ackd_timer, n->ifa->rxmtint / 2);
100 101
  DBG("%s: Installing ackd timer.\n", p->name);

Ondřej Filip's avatar
Ondřej Filip committed
102
  return (n);
103 104
}

105 106 107 108 109
/**
 * neigh_chstate - handles changes related to new or lod state of neighbor
 * @n: OSPF neighbor
 * @state: new state
 *
110
 * Many actions have to be taken acording to a change of state of a neighbor. It
111 112 113
 * starts rxmt timers, call interface state machine etc.
 */

114
static void
115 116
neigh_chstate(struct ospf_neighbor *n, u8 state)
{
117
  u8 oldstate;
118

Ondřej Filip's avatar
Ondřej Filip committed
119
  oldstate = n->state;
120

Ondřej Filip's avatar
Ondřej Filip committed
121
  if (oldstate != state)
122
  {
Ondřej Filip's avatar
Ondřej Filip committed
123 124 125
    struct ospf_iface *ifa = n->ifa;
    struct proto_ospf *po = ifa->oa->po;
    struct proto *p = &po->proto;
Ondřej Filip's avatar
Ondřej Filip committed
126

Ondřej Filip's avatar
Ondřej Filip committed
127
    n->state = state;
Ondřej Filip's avatar
Ondřej Filip committed
128

Ondřej Filip's avatar
Ondřej Filip committed
129 130
    OSPF_TRACE(D_EVENTS, "Neighbor %I changes state from \"%s\" to \"%s\".",
	       n->ip, ospf_ns[oldstate], ospf_ns[state]);
Ondřej Filip's avatar
Ondřej Filip committed
131

Ondřej Filip's avatar
Ondřej Filip committed
132
    if ((state == NEIGHBOR_2WAY) && (oldstate < NEIGHBOR_2WAY))
Ondřej Filip's avatar
Ondřej Filip committed
133
      ospf_iface_sm(ifa, ISM_NEICH);
Ondřej Filip's avatar
Ondřej Filip committed
134
    if ((state < NEIGHBOR_2WAY) && (oldstate >= NEIGHBOR_2WAY))
Ondřej Filip's avatar
Ondřej Filip committed
135
      ospf_iface_sm(ifa, ISM_NEICH);
Ondřej Filip's avatar
Ondřej Filip committed
136

Ondřej Filip's avatar
Ondřej Filip committed
137
    if (oldstate == NEIGHBOR_FULL)	/* Decrease number of adjacencies */
138
    {
139
      ifa->fadj--;
140
      schedule_rt_lsa(ifa->oa);
141
      if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa);
142
      schedule_net_lsa(ifa);
143
    }
Ondřej Filip's avatar
Ondřej Filip committed
144 145

    if (state == NEIGHBOR_FULL)	/* Increase number of adjacencies */
146
    {
147
      ifa->fadj++;
148
      schedule_rt_lsa(ifa->oa);
149
      if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa);
150
      schedule_net_lsa(ifa);
151
    }
Ondřej Filip's avatar
Ondřej Filip committed
152
    if (state == NEIGHBOR_EXSTART)
153
    {
Ondřej Filip's avatar
Ondřej Filip committed
154
      if (n->adj == 0)		/* First time adjacency */
155
      {
Ondřej Filip's avatar
Ondřej Filip committed
156
	n->dds = random_u32();
157 158
      }
      n->dds++;
Ondřej Filip's avatar
Ondřej Filip committed
159 160 161 162
      n->myimms.byte = 0;
      n->myimms.bit.ms = 1;
      n->myimms.bit.m = 1;
      n->myimms.bit.i = 1;
163
    }
Ondřej Filip's avatar
Ondřej Filip committed
164 165
    if (state > NEIGHBOR_EXSTART)
      n->myimms.bit.i = 0;
166 167 168
  }
}

169
static struct ospf_neighbor *
170 171
electbdr(list nl)
{
Ondřej Filip's avatar
Ondřej Filip committed
172
  struct ospf_neighbor *neigh, *n1, *n2;
173 174
  u32 nid;

Ondřej Filip's avatar
Ondřej Filip committed
175 176
  n1 = NULL;
  n2 = NULL;
177
  WALK_LIST(neigh, nl)			/* First try those decl. themselves */
178
  {
179 180 181 182 183 184
#ifdef OSPFv2
    nid = ipa_to_u32(neigh->ip);
#else /* OSPFv3 */
    nid = neigh->rid;
#endif

Ondřej Filip's avatar
Ondřej Filip committed
185
    if (neigh->state >= NEIGHBOR_2WAY)	/* Higher than 2WAY */
186 187
      if (neigh->priority > 0)		/* Eligible */
	if (neigh->dr != nid)		/* And not decl. itself DR */
188
	{
189
	  if (neigh->bdr == nid)	/* Declaring BDR */
Ondřej Filip's avatar
Ondřej Filip committed
190 191 192 193 194 195 196 197 198
	  {
	    if (n1 != NULL)
	    {
	      if (neigh->priority > n1->priority)
		n1 = neigh;
	      else if (neigh->priority == n1->priority)
		if (neigh->rid > n1->rid)
		  n1 = neigh;
	    }
199
	    else
Ondřej Filip's avatar
Ondřej Filip committed
200 201 202 203 204 205 206 207 208 209 210 211 212 213
	    {
	      n1 = neigh;
	    }
	  }
	  else			/* And NOT declaring BDR */
	  {
	    if (n2 != NULL)
	    {
	      if (neigh->priority > n2->priority)
		n2 = neigh;
	      else if (neigh->priority == n2->priority)
		if (neigh->rid > n2->rid)
		  n2 = neigh;
	    }
214
	    else
Ondřej Filip's avatar
Ondřej Filip committed
215 216 217 218 219
	    {
	      n2 = neigh;
	    }
	  }
	}
220
  }
Ondřej Filip's avatar
Ondřej Filip committed
221 222
  if (n1 == NULL)
    n1 = n2;
223

Ondřej Filip's avatar
Ondřej Filip committed
224
  return (n1);
225 226
}

227
static struct ospf_neighbor *
228 229
electdr(list nl)
{
Ondřej Filip's avatar
Ondřej Filip committed
230
  struct ospf_neighbor *neigh, *n;
231 232
  u32 nid;

233 234 235
  n = NULL;
  WALK_LIST(neigh, nl)			/* And now DR */
  {
236
#ifdef OSPFv2
237
    nid = ipa_to_u32(neigh->ip);
238
#else /* OSPFv3 */
239
    nid = neigh->rid;
240
#endif
241

Ondřej Filip's avatar
Ondřej Filip committed
242
    if (neigh->state >= NEIGHBOR_2WAY)	/* Higher than 2WAY */
243 244
      if (neigh->priority > 0)		/* Eligible */
	if (neigh->dr == nid)		/* And declaring itself DR */
245
	{
Ondřej Filip's avatar
Ondřej Filip committed
246 247 248 249 250 251 252 253
	  if (n != NULL)
	  {
	    if (neigh->priority > n->priority)
	      n = neigh;
	    else if (neigh->priority == n->priority)
	      if (neigh->rid > n->rid)
		n = neigh;
	  }
254
	  else
Ondřej Filip's avatar
Ondřej Filip committed
255 256 257 258
	  {
	    n = neigh;
	  }
	}
259 260
  }

Ondřej Filip's avatar
Ondřej Filip committed
261
  return (n);
262 263
}

264
static int
265 266 267 268 269 270
can_do_adj(struct ospf_neighbor *n)
{
  struct ospf_iface *ifa;
  struct proto *p;
  int i;

Ondřej Filip's avatar
Ondřej Filip committed
271
  ifa = n->ifa;
272
  p = (struct proto *) (ifa->oa->po);
Ondřej Filip's avatar
Ondřej Filip committed
273
  i = 0;
274

Ondřej Filip's avatar
Ondřej Filip committed
275
  switch (ifa->type)
276
  {
Ondřej Filip's avatar
Ondřej Filip committed
277
  case OSPF_IT_PTP:
278
  case OSPF_IT_PTMP:
Ondřej Filip's avatar
Ondřej Filip committed
279 280 281 282 283 284 285 286
  case OSPF_IT_VLINK:
    i = 1;
    break;
  case OSPF_IT_BCAST:
  case OSPF_IT_NBMA:
    switch (ifa->state)
    {
    case OSPF_IS_DOWN:
287
    case OSPF_IS_LOOP:
288
      bug("%s: Iface %s in down state?", p->name, ifa->ifname);
289
      break;
Ondřej Filip's avatar
Ondřej Filip committed
290
    case OSPF_IS_WAITING:
291
      DBG("%s: Neighbor? on iface %s\n", p->name, ifa->ifname);
Ondřej Filip's avatar
Ondřej Filip committed
292 293 294 295 296 297 298 299 300 301 302
      break;
    case OSPF_IS_DROTHER:
      if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
	  && (n->state >= NEIGHBOR_2WAY))
	i = 1;
      break;
    case OSPF_IS_PTP:
    case OSPF_IS_BACKUP:
    case OSPF_IS_DR:
      if (n->state >= NEIGHBOR_2WAY)
	i = 1;
303 304
      break;
    default:
305
      bug("%s: Iface %s in unknown state?", p->name, ifa->ifname);
306
      break;
Ondřej Filip's avatar
Ondřej Filip committed
307 308 309
    }
    break;
  default:
310
    bug("%s: Iface %s is unknown type?", p->name, ifa->ifname);
Ondřej Filip's avatar
Ondřej Filip committed
311
    break;
312
  }
313
  DBG("%s: Iface %s can_do_adj=%d\n", p->name, ifa->ifname, i);
314 315 316
  return i;
}

317 318 319 320 321
/**
 * ospf_neigh_sm - ospf neighbor state machine
 * @n: neighor
 * @event: actual event
 *
322 323 324 325 326
 * This part implements the neighbor state machine as described in 10.3 of
 * RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
 * used. We discover neighbors on nonbroadcast networks in the
 * same way as on broadcast networks. The only difference is in
 * sending hello packets. These are sent to IPs listed in
327 328
 * @ospf_iface->nbma_list .
 */
329 330 331
void
ospf_neigh_sm(struct ospf_neighbor *n, int event)
{
332 333
  struct proto_ospf *po = n->ifa->oa->po;
  struct proto *p = &po->proto;
334

335
  DBG("Neighbor state machine for neighbor %I, event '%s'\n", n->ip,
Ondřej Filip's avatar
Ondřej Filip committed
336
	     ospf_inm[event]);
Ondřej Filip's avatar
Ondřej Filip committed
337

Ondřej Filip's avatar
Ondřej Filip committed
338
  switch (event)
339
  {
Ondřej Filip's avatar
Ondřej Filip committed
340 341 342 343 344 345 346 347 348 349 350
  case INM_START:
    neigh_chstate(n, NEIGHBOR_ATTEMPT);
    /* NBMA are used different way */
    break;
  case INM_HELLOREC:
    switch (n->state)
    {
    case NEIGHBOR_ATTEMPT:
    case NEIGHBOR_DOWN:
      neigh_chstate(n, NEIGHBOR_INIT);
    default:
351
      tm_start(n->inactim, n->ifa->deadint);	/* Restart inactivity timer */
352
      break;
Ondřej Filip's avatar
Ondřej Filip committed
353 354 355 356 357 358 359 360 361 362 363 364
    }
    break;
  case INM_2WAYREC:
    if (n->state < NEIGHBOR_2WAY)
      neigh_chstate(n, NEIGHBOR_2WAY);
    if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
      neigh_chstate(n, NEIGHBOR_EXSTART);
    break;
  case INM_NEGDONE:
    if (n->state == NEIGHBOR_EXSTART)
    {
      neigh_chstate(n, NEIGHBOR_EXCHANGE);
365 366 367

      /* Reset DB summary list iterator */
      s_get(&(n->dbsi));
368
      s_init(&(n->dbsi), &po->lsal);
369

Ondřej Filip's avatar
Ondřej Filip committed
370
      while (!EMPTY_LIST(n->ackl[ACKL_DELAY]))
371
      {
Ondřej Filip's avatar
Ondřej Filip committed
372 373 374 375
	struct lsah_n *no;
	no = (struct lsah_n *) HEAD(n->ackl[ACKL_DELAY]);
	rem_node(NODE no);
	mb_free(no);
376
      }
Ondřej Filip's avatar
Ondřej Filip committed
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
    }
    else
      bug("NEGDONE and I'm not in EXSTART?");
    break;
  case INM_EXDONE:
    neigh_chstate(n, NEIGHBOR_LOADING);
    break;
  case INM_LOADDONE:
    neigh_chstate(n, NEIGHBOR_FULL);
    break;
  case INM_ADJOK:
    switch (n->state)
    {
    case NEIGHBOR_2WAY:
      /* Can In build adjacency? */
      if (can_do_adj(n))
393
      {
Ondřej Filip's avatar
Ondřej Filip committed
394
	neigh_chstate(n, NEIGHBOR_EXSTART);
395 396 397
      }
      break;
    default:
Ondřej Filip's avatar
Ondřej Filip committed
398 399 400
      if (n->state >= NEIGHBOR_EXSTART)
	if (!can_do_adj(n))
	{
401
	  reset_lists(n);
Ondřej Filip's avatar
Ondřej Filip committed
402 403
	  neigh_chstate(n, NEIGHBOR_2WAY);
	}
404
      break;
Ondřej Filip's avatar
Ondřej Filip committed
405 406 407 408 409 410
    }
    break;
  case INM_SEQMIS:
  case INM_BADLSREQ:
    if (n->state >= NEIGHBOR_EXCHANGE)
    {
411
      reset_lists(n);
Ondřej Filip's avatar
Ondřej Filip committed
412 413 414 415 416 417
      neigh_chstate(n, NEIGHBOR_EXSTART);
    }
    break;
  case INM_KILLNBR:
  case INM_LLDOWN:
  case INM_INACTTIM:
418
    reset_lists(n);
Ondřej Filip's avatar
Ondřej Filip committed
419 420 421
    neigh_chstate(n, NEIGHBOR_DOWN);
    break;
  case INM_1WAYREC:
422
    reset_lists(n);
Ondřej Filip's avatar
Ondřej Filip committed
423 424 425 426 427
    neigh_chstate(n, NEIGHBOR_INIT);
    break;
  default:
    bug("%s: INM - Unknown event?", p->name);
    break;
428 429 430
  }
}

431 432 433 434
/**
 * bdr_election - (Backup) Designed Router election
 * @ifa: actual interface
 *
435
 * When the wait timer fires, it is time to elect (Backup) Designated Router.
436
 * Structure describing me is added to this list so every electing router
437
 * has the same list. Backup Designated Router is elected before Designated
438 439
 * Router. This process is described in 9.4 of RFC 2328.
 */
440
void
441
bdr_election(struct ospf_iface *ifa)
442
{
443 444
  struct proto_ospf *po = ifa->oa->po;
  u32 myid = po->router_id;
Ondřej Filip's avatar
Ondřej Filip committed
445
  struct ospf_neighbor *neigh, *ndr, *nbdr, me;
446 447
  int doadj;

448
  DBG("(B)DR election.\n");
449

Ondřej Filip's avatar
Ondřej Filip committed
450 451 452
  me.state = NEIGHBOR_2WAY;
  me.rid = myid;
  me.priority = ifa->priority;
453
  me.ip = ifa->addr->ip;
454

455 456 457 458 459 460
#ifdef OSPFv2
  me.dr = ipa_to_u32(ifa->drip);
  me.bdr = ipa_to_u32(ifa->bdrip);
#else /* OSPFv3 */
  me.dr = ifa->drid;
  me.bdr = ifa->bdrid;
461
  me.iface_id = ifa->iface_id;
462 463
#endif

Ondřej Filip's avatar
Ondřej Filip committed
464
  add_tail(&ifa->neigh_list, NODE & me);
465

Ondřej Filip's avatar
Ondřej Filip committed
466 467
  nbdr = electbdr(ifa->neigh_list);
  ndr = electdr(ifa->neigh_list);
468

Ondřej Filip's avatar
Ondřej Filip committed
469 470
  if (ndr == NULL)
    ndr = nbdr;
471

472
  /* 9.4. (4) */
Ondřej Filip's avatar
Ondřej Filip committed
473 474 475 476
  if (((ifa->drid == myid) && (ndr != &me))
      || ((ifa->drid != myid) && (ndr == &me))
      || ((ifa->bdrid == myid) && (nbdr != &me))
      || ((ifa->bdrid != myid) && (nbdr == &me)))
477
  {
478
#ifdef OSPFv2
479 480
    me.dr = ndr ? ipa_to_u32(ndr->ip) : 0;
    me.bdr = nbdr ? ipa_to_u32(nbdr->ip) : 0;
481 482 483 484
#else /* OSPFv3 */
    me.dr = ndr ? ndr->rid : 0;
    me.bdr = nbdr ? nbdr->rid : 0;
#endif
Ondřej Filip's avatar
Ondřej Filip committed
485 486 487

    nbdr = electbdr(ifa->neigh_list);
    ndr = electdr(ifa->neigh_list);
488

489 490
    if (ndr == NULL)
      ndr = nbdr;
491 492
  }

493 494 495 496 497 498 499 500 501 502 503
  u32 odrid = ifa->drid;
  u32 obdrid = ifa->bdrid;
 
  ifa->drid = ndr ? ndr->rid : 0;
  ifa->drip = ndr ? ndr->ip  : IPA_NONE;
  ifa->bdrid = nbdr ? nbdr->rid : 0;
  ifa->bdrip = nbdr ? nbdr->ip  : IPA_NONE;

#ifdef OSPFv3
  ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
#endif
504

505
  DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
506

507 508
  doadj = ((ifa->drid != odrid) || (ifa->bdrid != obdrid));

Ondřej Filip's avatar
Ondřej Filip committed
509 510
  if (myid == ifa->drid)
    ospf_iface_chstate(ifa, OSPF_IS_DR);
511 512
  else
  {
Ondřej Filip's avatar
Ondřej Filip committed
513 514 515 516
    if (myid == ifa->bdrid)
      ospf_iface_chstate(ifa, OSPF_IS_BACKUP);
    else
      ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
517 518
  }

Ondřej Filip's avatar
Ondřej Filip committed
519
  rem_node(NODE & me);
520

Ondřej Filip's avatar
Ondřej Filip committed
521
  if (doadj)
522
  {
Ondřej Filip's avatar
Ondřej Filip committed
523
    WALK_LIST(neigh, ifa->neigh_list)
524 525 526 527 528 529 530 531 532 533
    {
      ospf_neigh_sm(neigh, INM_ADJOK);
    }
  }
}

struct ospf_neighbor *
find_neigh(struct ospf_iface *ifa, u32 rid)
{
  struct ospf_neighbor *n;
534 535 536 537 538
  WALK_LIST(n, ifa->neigh_list)
    if (n->rid == rid)
      return n;
  return NULL;
}
539

540 541 542 543 544 545 546
struct ospf_neighbor *
find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
{
  struct ospf_neighbor *n;
  WALK_LIST(n, ifa->neigh_list)
    if (ipa_equal(n->ip, ip))
      return n;
547 548 549
  return NULL;
}

550
/* Neighbor is inactive for a long time. Remove it. */
551
static void
Ondřej Filip's avatar
Ondřej Filip committed
552
neighbor_timer_hook(timer * timer)
553
{
554 555 556
  struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
  struct ospf_iface *ifa = n->ifa;
  struct proto *p = &ifa->oa->po->proto;
557

558 559
  OSPF_TRACE(D_EVENTS, "Inactivity timer fired on interface %s for neighbor %I.",
	     ifa->ifname, n->ip);
560 561 562 563 564 565
  ospf_neigh_remove(n);
}

void
ospf_neigh_remove(struct ospf_neighbor *n)
{
566 567
  struct ospf_iface *ifa = n->ifa;
  struct proto *p = &ifa->oa->po->proto;
568

569 570 571 572 573 574 575
  if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
  {
    struct nbma_node *nn = find_nbma_node(ifa, n->ip);
    if (nn)
      nn->found = 0;
  }

576
  s_get(&(n->dbsi));
577 578
  neigh_chstate(n, NEIGHBOR_DOWN);
  rem_node(NODE n);
579
  rfree(n->pool);
Ondřej Filip's avatar
Ondřej Filip committed
580
  OSPF_TRACE(D_EVENTS, "Deleting neigbor.");
581
}
582

583 584 585 586 587 588 589 590 591
static void
ospf_neigh_bfd_hook(struct bfd_request *req)
{
  struct ospf_neighbor *n = req->data;
  struct proto *p = &n->ifa->oa->po->proto;

  if (req->down)
  {
    OSPF_TRACE(D_EVENTS, "BFD session down for %I on %s",
592
	       n->ip, n->ifa->ifname);
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612

    ospf_neigh_remove(n);
  }
}

void
ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd)
{
  if (use_bfd && !n->bfd_req)
    n->bfd_req = bfd_request_session(n->pool, n->ip, n->ifa->addr->ip, n->ifa->iface,
				     ospf_neigh_bfd_hook, n);

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


613 614 615
void
ospf_sh_neigh_info(struct ospf_neighbor *n)
{
Ondřej Filip's avatar
Ondřej Filip committed
616 617 618 619 620 621
  struct ospf_iface *ifa = n->ifa;
  char *pos = "other";
  char etime[6];
  int exp, sec, min;

  exp = n->inactim->expires - now;
622 623
  sec = exp % 60;
  min = exp / 60;
Ondřej Filip's avatar
Ondřej Filip committed
624 625 626 627 628 629 630 631 632 633 634
  if (min > 59)
  {
    bsprintf(etime, "-Inf-");
  }
  else
  {
    bsprintf(etime, "%02u:%02u", min, sec);
  }

  if (n->rid == ifa->drid)
    pos = "dr   ";
635
  else if (n->rid == ifa->bdrid)
Ondřej Filip's avatar
Ondřej Filip committed
636
    pos = "bdr  ";
637 638
  else if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_PTMP) ||
	   (n->ifa->type == OSPF_IT_VLINK))
Ondřej Filip's avatar
Ondřej Filip committed
639 640
    pos = "ptp  ";

641
  cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
642
	  ospf_ns[n->state], pos, etime, ifa->ifname, n->ip);
643
}
644

645
static void
Ondřej Filip's avatar
Ondřej Filip committed
646
rxmt_timer_hook(timer * timer)
647
{
Ondřej Filip's avatar
Ondřej Filip committed
648
  struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
649
  // struct proto *p = &n->ifa->oa->po->proto;
650 651 652
  struct top_hash_entry *en;

  DBG("%s: RXMT timer fired on interface %s for neigh: %I.\n",
653
      p->name, n->ifa->ifname, n->ip);
654 655 656 657 658

  if(n->state < NEIGHBOR_EXSTART) return;

  if (n->state == NEIGHBOR_EXSTART)
  {
659
    ospf_dbdes_send(n, 1);
660 661 662 663
    return;
  }

  if ((n->state == NEIGHBOR_EXCHANGE) && n->myimms.bit.ms)	/* I'm master */
664
    ospf_dbdes_send(n, 0);
665

666

667 668
  if (n->state < NEIGHBOR_FULL)	
    ospf_lsreq_send(n);	/* EXCHANGE or LOADING */
669 670
  else
  {
671
    if (!EMPTY_SLIST(n->lsrtl))	/* FULL */
672 673 674 675 676 677
    {
      list uplist;
      slab *upslab;
      struct l_lsr_head *llsh;

      init_list(&uplist);
Ondřej Filip's avatar
Ondřej Filip committed
678
      upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
679

680
      WALK_SLIST(en, n->lsrtl)
681
      {
Ondřej Filip's avatar
Ondřej Filip committed
682 683 684 685 686 687
	if ((SNODE en)->next == (SNODE en))
	  bug("RTList is cycled");
	llsh = sl_alloc(upslab);
	llsh->lsh.id = en->lsa.id;
	llsh->lsh.rt = en->lsa.rt;
	llsh->lsh.type = en->lsa.type;
688 689
	DBG("Working on ID: %R, RT: %R, Type: %u\n",
	    en->lsa.id, en->lsa.rt, en->lsa.type);
Ondřej Filip's avatar
Ondřej Filip committed
690
	add_tail(&uplist, NODE llsh);
691
      }
692
      ospf_lsupd_send_list(n, &uplist);
693 694 695 696 697
      rfree(upslab);
    }
  }
}

698
static void
Ondřej Filip's avatar
Ondřej Filip committed
699
ackd_timer_hook(timer * t)
700
{
Ondřej Filip's avatar
Ondřej Filip committed
701
  struct ospf_neighbor *n = t->data;
702
  ospf_lsack_send(n, ACKL_DELAY);
703
}