Revision 1a61882d

View differences:

proto/ospf/ospf.c
95 95
  po->disp_timer->hook = ospf_disp;
96 96
  po->disp_timer->recurrent = po->tick;
97 97
  tm_start(po->disp_timer, 1);
98

  
99
  fib_init(&po->efib, p->pool, sizeof(struct extfib), 16, init_efib);
100 98
  init_list(&(po->iface_list));
101 99
  init_list(&(po->area_list));
100
  fib_init(&po->rtf[0], p->pool, sizeof(ort), 16, ospf_rt_initort);
101
  fib_init(&po->rtf[1], p->pool, sizeof(ort), 16, ospf_rt_initort);
102 102
  po->areano = 0;
103 103
  if (EMPTY_LIST(c->area_list))
104 104
  {
......
133 133
      antmp->hidden = anet->hidden;
134 134
      add_tail(&oa->net_list, NODE antmp);
135 135
    }
136
    fib_init(&oa->infib, po->proto.pool, sizeof(struct infib), 16,
137
	     init_infib);
138 136
  }
139 137
  return PS_UP;
140 138
}
......
191 189
static int
192 190
ospf_rte_better(struct rte *new, struct rte *old)
193 191
{
192
  /* FIXME this is wrong */
194 193
  if (new->u.ospf.metric1 == LSINFINITY)
195 194
    return 0;
196 195

  
proto/ospf/ospf.h
248 248

  
249 249
struct vebb
250 250
{
251
#ifdef _BIG_ENDIAN
252
  u8 padding:5;
253
  u8 v:1;
254
  u8 e:1;
255
  u8 b:1;
256
#else
251 257
  u8 b:1;
252 258
  u8 e:1;
253 259
  u8 v:1;
254 260
  u8 padding:5;
261
#endif
255 262
};
256 263

  
257 264
union veb
......
263 270
struct ospf_lsa_rt
264 271
{
265 272
  union veb veb;
266
#define LSA_RT_V 5
267
#define LSA_RT_E 6
268
#define LSA_RT_B 7
269 273
  u8 padding;
270 274
  u16 links;
271 275
};
......
432 436
  int stub;
433 437
  int trcap;			/* Transit capability? */
434 438
  struct proto_ospf *po;
435
  struct fib infib;		/* FIB for intra-area routes */
436 439
  unsigned tick;
437 440
};
438 441

  
......
445 448
  list iface_list;		/* Interfaces we really use */
446 449
  list area_list;
447 450
  int areano;			/* Number of area I belong to */
448
  struct fib efib;		/* FIB for external routes */
451
  struct fib rtf[2];		/* Routing tables */
449 452
  int rfc1583;			/* RFC1583 compatibility */
450 453
  int ebit;			/* Did I originate any ext lsa? */
451 454
};
proto/ospf/rt.c
1 1
/*
2
 *	BIRD -- OSPF
3
 *
4
 *	(c) 2000--2004 Ondrej Filip <feela@network.cz>
5
 *
6
 *	Can be freely distributed and used under the terms of the GNU GPL.
2
 * BIRD -- OSPF
3
 * 
4
 * (c) 2000--2004 Ondrej Filip <feela@network.cz>
5
 * 
6
 * Can be freely distributed and used under the terms of the GNU GPL.
7 7
 */
8 8

  
9 9
#include "ospf.h"
10
static void add_cand(list * l, struct top_hash_entry *en,
11
		     struct top_hash_entry *par, u16 dist,
12
		     struct ospf_area *oa);
13
static void calc_next_hop(struct top_hash_entry *en,
14
			  struct top_hash_entry *par, struct ospf_area *oa);
15
static void ospf_ext_spfa(struct proto_ospf *po);
10
static void
11
add_cand(list * l, struct top_hash_entry *en,
12
	 struct top_hash_entry *par, u16 dist, struct ospf_area *oa);
13
static void
14
calc_next_hop(struct top_hash_entry *en,
15
	      struct top_hash_entry *par, struct ospf_area *oa);
16
static void ospf_ext_spfa(struct ospf_area *oa);
17
static void rt_sync(struct proto_ospf *po);
18

  
19
static void
20
fill_ri(orta * orta)
21
{
22
  orta->type = RTS_DUMMY;
23
  orta->capa = 0;
24
#define ORTA_ASBR 1
25
#define ORTA_ABR 2
26
  orta->oa = NULL;
27
  orta->metric1 = LSINFINITY;
28
  orta->metric2 = LSINFINITY;
29
  orta->nh = ipa_from_u32(0);
30
  orta->ifa = NULL;
31
  orta->ar = NULL;
32
  orta->tag = 0;
33
}
16 34

  
17 35
void
18
init_infib(struct fib_node *fn)
36
ospf_rt_initort(struct fib_node *fn)
19 37
{
20
  struct infib *f = (struct infib *) fn;
38
  ort *ri = (ort *) fn;
39
  fill_ri(&ri->n);
40
  ri->dest = ORT_UNDEF;
41
  memcpy(&ri->o, &ri->n, sizeof(orta));
42
}
21 43

  
22
  f->metric = LSINFINITY;
23
  f->oldmetric = LSINFINITY;
24
  f->en = NULL;
25
  f->olden = NULL;
44
/* If new is better return 1 */
45
static int
46
ri_better(struct proto_ospf *po, orta * new, orta * old)
47
{
48
  int newtype = new->type;
49
  int oldtype = old->type;
50

  
51
  if (old->type == RTS_DUMMY)
52
    return 1;
53

  
54
  if (old->metric1 == LSINFINITY)
55
    return 1;
56

  
57
  if (po->rfc1583)
58
  {
59
    if ((newtype == RTS_OSPF) && (new->oa->areaid == 0)) newtype = RTS_OSPF_IA;
60
    if ((oldtype == RTS_OSPF) && (old->oa->areaid == 0)) oldtype = RTS_OSPF_IA;
61
  }
62
  
63
  if (new->type < old->type)
64
    return 1;
65

  
66
  if (new->metric2 < old->metric2)
67
  {
68
    if (old->metric2 == LSINFINITY)
69
      return 0;			/* Old is E1, new is E2 */
70

  
71
    return 1;			/* Both are E2 */
72
  }
73
  if (new->metric2 > old->metric2)
74
  {
75
    if (new->metric2 == LSINFINITY)
76
      return 1;			/* New is E1, old is E2 */
77

  
78
    return 0;			/* Both are E2 */
79
  }
80

  
81
  /*
82
   * E2 metrics are the same. It means that: 1) Paths are E2 with same
83
   * metric 2) Paths are E1.
84
   */
85
  if (new->metric1 < old->metric1)
86
    return 1;
87

  
88
  if (new->metric1 > old->metric1)
89
    return 0;
90

  
91
  /* Metric 1 are the same */
92
  if (new->oa->areaid > old->oa->areaid) return 1;	/* Larger AREAID is preffered */
93

  
94
  return 0;			/* Old is shorter or same */
26 95
}
27 96

  
28
void
29
init_efib(struct fib_node *fn)
97
static void
98
ri_install(struct proto_ospf *po, ip_addr prefix, int pxlen, int dest,
99
	   orta * new)
30 100
{
31
  struct extfib *f = (struct extfib *) fn;
32

  
33
  f->metric = LSINFINITY;
34
  f->metric2 = LSINFINITY;
35
  f->nh = ipa_from_u32(0);
36
  f->nhi = NULL;
37
  f->oldmetric = LSINFINITY;
38
  f->oldmetric2 = LSINFINITY;
39
  f->oldnh = ipa_from_u32(0);
101
  ort *old = (ort *) fib_get(&po->rtf[dest], &prefix, pxlen);
102

  
103
  if (ri_better(po, new, &old->n))
104
  {
105
    memcpy(&old->n, new, sizeof(orta));
106
  }
40 107
}
41 108

  
42 109
/**
......
49 116
 * and latter parts of routing table calculation look directly into LSA
50 117
 * Database. This function is invoked from ospf_disp().
51 118
 */
52
void
119
static void
53 120
ospf_rt_spfa(struct ospf_area *oa)
54 121
{
55 122
  u32 i, *rts;
56 123
  struct ospf_lsa_rt *rt;
57 124
  struct ospf_lsa_rt_link *rtl, *rr;
58
  struct fib *in = &oa->infib;
59
  struct infib *nf;
60
  struct fib_iterator fit;
61 125
  struct proto *p = &oa->po->proto;
62 126
  struct proto_ospf *po = oa->po;
63
  ip_addr ip;
64 127
  struct ospf_lsa_net *ln;
65

  
66
  OSPF_TRACE(D_EVENTS, "Starting routing table calculation for area %I",
67
	     oa->areaid);
128
  orta nf;
68 129

  
69 130
  if (oa->rt == NULL)
70 131
    return;
71 132

  
133
  OSPF_TRACE(D_EVENTS, "Starting routing table calculation for area %I",
134
	     oa->areaid);
135

  
72 136
  if (oa->rt->dist != LSINFINITY)
73 137
    ospf_age(oa);
74 138

  
75
  FIB_WALK(in, nftmp)
76
  {
77
    nf = (struct infib *) nftmp;
78
    nf->metric = LSINFINITY;
79
    nf->en = NULL;
80
  }
81
  FIB_WALK_END;
82

  
83 139
  init_list(&oa->cand);		/* Empty list of candidates */
84 140
  oa->trcap = 0;
85 141

  
......
95 151
  {
96 152
    struct top_hash_entry *act, *tmp;
97 153
    node *n;
98
    u16 met;
99 154

  
100 155
    n = HEAD(oa->cand);
101 156
    act = SKIP_BACK(struct top_hash_entry, cn, n);
......
111 166
      rt = (struct ospf_lsa_rt *) act->lsa_body;
112 167
      if (rt->veb.bit.v)
113 168
	oa->trcap = 1;
169
      if (rt->veb.bit.b || rt->veb.bit.e)
170
      {
171
	nf.type = RTS_OSPF;
172
	nf.capa = 0;
173
        if (rt->veb.bit.b) nf.capa |= ORTA_ABR;
174
        if (rt->veb.bit.e) nf.capa |= ORTA_ASBR;
175
	nf.metric1 = act->dist;
176
	nf.metric2 = LSINFINITY;
177
	nf.oa = oa;
178
	nf.ar = act;
179
	nf.nh = act->nh;
180
	nf.ifa = act->nhi;
181
	ri_install(po, ipa_from_u32(act->lsa.id), 32, ORT_ROUTER, &nf);
182
      }
114 183
      rr = (struct ospf_lsa_rt_link *) (rt + 1);
115 184
      DBG("  Number of links: %u\n", rt->links);
116 185
      for (i = 0; i < rt->links; i++)
......
121 190
	switch (rtl->type)
122 191
	{
123 192
	case LSART_STUB:
124
	  /* This violates rfc2328! but I hope it's also correct. */
193
	  /*
194
	   * This violates rfc2328! but I hope
195
	   * it's also correct.
196
	   */
125 197
	  DBG("\n");
126
	  ip = ipa_from_u32(rtl->id);
127
	  nf = fib_get(in, &ip, ipa_mklen(ipa_from_u32(rtl->data)));
128
	  if (nf->metric > (met = act->dist + rtl->metric))
129
	  {
130
	    DBG("       Adding stub route....\n");
131
	    if (oa->rt == act)
132
	      break;
133
	    if (act->nhi == NULL)
134
	      break;
135
	    nf->metric = met;
136
	    nf->en = act;
137
	    DBG("            Adding stub route: %I\n", ip);
138
	    DBG("            Next hop=%I\n", nf->en->nh);
139
	  }
140
	  else
141
	    DBG("            NOT adding stub route: %I\n", ip);
198
	  if (act == oa->rt)
199
	    continue;
200
	  if (!act->nhi)
201
	    continue;
202
	  nf.type = RTS_OSPF;
203
	  nf.capa = 0;
204
	  nf.metric1 = act->dist + rtl->metric;
205
	  nf.metric2 = LSINFINITY;
206
	  nf.oa = oa;
207
	  nf.ar = act;
208
	  nf.nh = act->nh;
209
	  nf.ifa = act->nhi;
210
	  ri_install(po, ipa_from_u32(rtl->id),
211
		     ipa_mklen(ipa_from_u32(rtl->data)), ORT_NET, &nf);
142 212
	  break;
143
	case LSART_VLNK:
213

  
214
	case LSART_VLNK:	/* FIXME !!!!!!!! */
144 215
	  DBG("Ignoring\n");
145 216
	  continue;
146 217
	  break;
......
167 238
      break;
168 239
    case LSA_T_NET:
169 240
      ln = act->lsa_body;
170
      ip = ipa_and(ipa_from_u32(act->lsa.id), ln->netmask);
171
      nf = fib_get(in, &ip, ipa_mklen(ln->netmask));
172
      if (nf->metric > act->dist)
173
      {
174
	nf->metric = act->dist;
175
	nf->en = act;
176
	DBG("    Adding into routing table\n");
177
      }
241
      nf.type = RTS_OSPF;
242
      nf.capa = 0;
243
      nf.metric1 = act->dist;
244
      nf.metric2 = LSINFINITY;
245
      nf.oa = oa;
246
      nf.ar = act;
247
      nf.nh = act->nh;
248
      nf.ifa = act->nhi;
249
      ri_install(po, ipa_and(ipa_from_u32(act->lsa.id), ln->netmask),
250
		 ipa_mklen(ln->netmask), ORT_NET, &nf);
251

  
178 252
      rts = (u32 *) (ln + 1);
179 253
      for (i = 0; i < (act->lsa.length - sizeof(struct ospf_lsa_header) -
180 254
		       sizeof(struct ospf_lsa_net)) / sizeof(u32); i++)
......
190 264
      break;
191 265
    }
192 266
  }
193
  /* Now sync our fib with nest's */
194
  DBG("Now syncing my rt table with nest's\n");
195
  FIB_ITERATE_INIT(&fit, in);
196
again:
197
  FIB_ITERATE_START(in, &fit, nftmp)
198
  {
199
    nf = (struct infib *) nftmp;
200
    if (nf->metric == LSINFINITY)
201
    {
202
      net *ne;
203
      struct top_hash_entry *en = nf->en;
204
      ln = en->lsa_body;
205

  
206
      ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
207
      if ((en != NULL) && (en->nhi != NULL))
208
	DBG("Deleting rt entry %I\n     (P: %x, GW: %I, Iface: %s)\n",
209
	    nf->fn.prefix, en, en->nh, en->nhi->name);
210
      rte_update(p->table, ne, p, NULL);
211

  
212
      /* Now delete my fib */
213
      FIB_ITERATE_PUT(&fit, nftmp);
214
      fib_delete(in, nftmp);
215
      goto again;
216
    }
217
    else
218
    {
219
      /* Update routing table */
220
      if (ipa_equal(nf->en->nh, ipa_from_u32(0)))
221
      {
222
	struct top_hash_entry *en = nf->en;
223
	struct ospf_neighbor *neigh;
224
	neighbor *nn;
225

  
226
	if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL)
227
	{
228
	  goto skip;
229
	}
230
	nn = neigh_find(p, &neigh->ip, 0);
231
	DBG("     Next hop calculated: %I\n", nn->addr);
232
	en->nh = nn->addr;
233
	en->nhi = nn->iface;
234
      }
235

  
236
      if ((nf->en != nf->olden) || (nf->metric != nf->oldmetric))
237
      {
238
	net *ne;
239
	rta a0;
240
	rte *e;
241
	struct top_hash_entry *en = nf->en;
242
	ln = en->lsa_body;
243

  
244
	bzero(&a0, sizeof(a0));
245

  
246
	a0.proto = p;
247
	a0.source = RTS_OSPF;
248
	a0.scope = SCOPE_UNIVERSE;
249
	a0.cast = RTC_UNICAST;
250
	if (ipa_to_u32(en->nh) == 0)
251
	  a0.dest = RTD_DEVICE;
252
	else
253
	  a0.dest = RTD_ROUTER;
254
	a0.flags = 0;
255
	a0.aflags = 0;
256
	a0.iface = en->nhi;
257
	a0.gw = en->nh;
258

  
259
	ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
260
	e = rte_get_temp(&a0);
261
	e->u.ospf.metric1 = nf->metric;
262
	e->u.ospf.metric2 = LSINFINITY;
263
	e->u.ospf.tag = 0;
264
	e->pflags = 0;
265
	e->net = ne;
266
	e->pref = p->preference;
267
	DBG("Modifying rt entry %I\n     (GW: %I, Iface: %s)\n",
268
	    nf->fn.prefix, en->nh, en->nhi->name);
269
	rte_update(p->table, ne, p, e);
270

  
271
	nf->olden = nf->en;
272
	nf->oldmetric = nf->metric;
273
      }
274
    }
275

  
276
  }
277
skip:
278
  FIB_ITERATE_END(nftmp);
279
  ospf_ext_spfa(po);
280 267
}
281 268

  
282 269

  
283 270
void
284 271
ospf_rt_spf(struct proto_ospf *po)
285 272
{
273
  struct proto *p = &po->proto;
286 274
  struct ospf_area *oa;
275
  int i;
276
  ort *ri;
277

  
278
  OSPF_TRACE(D_EVENTS, "Starting routing table calculation");
279

  
280
  /* Invalidate old routing table */
281
  for (i = 0; i < 2; i++)
282
    FIB_WALK(&po->rtf[i], nftmp)
283
  {
284
    ri = (ort *) nftmp;
285
    memcpy(&ri->o, &ri->n, sizeof(orta));	/* Backup old data */
286
    fill_ri(&ri->n);
287
  }
288
  FIB_WALK_END;
289

  
290

  
287 291
  WALK_LIST(oa, po->area_list)
288 292
  {
289 293
    ospf_rt_spfa(oa);
290 294
  }
295

  
296
  if (po->areano > 1)
297
  {
298
    //ospf_rt_sum(oa);
299
  }
300
  else
301
  {
302
    WALK_LIST(oa, po->area_list)
303
    {
304
      //if (oa->id == 0) ospf_rt_sum(oa);
305
    }
306

  
307
    WALK_LIST(oa, po->area_list)
308
    {
309
      //if (oa->trcap == 1) ospf_rt_sum(oa);
310
    }
311
  }
312
  WALK_LIST(oa, po->area_list)
313
  {
314
    if (!oa->stub)
315
    {
316
      ospf_ext_spfa(oa);
317
      break;
318
    }
319
  }
320
  rt_sync(po);
291 321
}
292 322

  
293 323

  
......
300 330
 * Inter- and Intra-area paths are always prefered over externals.
301 331
 */
302 332
static void
303
ospf_ext_spfa(struct proto_ospf *po)	/* FIXME looking into inter-area */
333
ospf_ext_spfa(struct ospf_area *oa)
304 334
{
305
  struct top_hash_entry *en, *etmp, *absr;
306
  struct fib *ef = &po->efib;
307
  struct extfib *nf;
308
  struct infib *inf;
309
  struct fib_iterator fit;
310
  struct ospf_area *oa = NULL, *atmp, *absroa;
335
  struct proto_ospf *po = oa->po;
336
  ort *nf1, *nf2;
337
  orta nfa;
338
  struct top_hash_entry *en;
311 339
  struct proto *p = &po->proto;
312 340
  struct ospf_lsa_ext *le;
313 341
  struct ospf_lsa_ext_tos *lt;
314 342
  int mlen;
315
  ip_addr ip, nnh;
316
  struct iface *nnhi = NULL;
317
  u16 met, met2;
318
  u32 tag;
343
  ip_addr ip, nh, rtid;
344
  struct iface *nhi = NULL;
345
  int met1, met2;
319 346
  neighbor *nn;
347
  struct ospf_lsa_rt *rt;
320 348

  
321
  OSPF_TRACE(D_EVENTS, "Starting routing table calculation for ext routes");
322

  
323
  FIB_WALK(ef, nftmp)
324
  {
325
    nf = (struct extfib *) nftmp;
326
    nf->metric = LSINFINITY;
327
    nf->metric2 = LSINFINITY;
328
  }
329
  FIB_WALK_END;
330

  
331
  WALK_LIST(oa, po->area_list)
332
  {
333
    if (!oa->stub)
334
      break;
335
  }
336 349

  
337
  if (oa == NULL)
338
    return;
350
  OSPF_TRACE(D_EVENTS, "Starting routing table calculation for ext routes");
339 351

  
340 352
  WALK_SLIST(en, oa->lsal)
341 353
  {
......
362 374
	  p->name, en->lsa.id, en->lsa.rt, en->lsa.type, le->netmask);
363 375
      continue;
364 376
    }
377
    nhi = NULL;
378
    nh = IPA_NONE;
365 379

  
366
    nf = NULL;
380
    met1 = LSINFINITY;
381
    met2 = LSINFINITY;
367 382

  
368
    WALK_LIST(atmp, po->area_list)
369
    {
370
      if ((nf = fib_find(&atmp->infib, &ip, mlen)) != NULL)
371
	break;
372
    }
373

  
374
    if (nf != NULL)
375
      continue;			/* Some intra area path exists */
383
    rtid = ipa_from_u32(en->lsa.rt);
376 384

  
377
    absr = NULL;
378
    absroa = NULL;
379
    nnhi = NULL;
380
    nnh = IPA_NONE;
385
    if (!(nf1 = fib_find(&po->rtf[ORT_ROUTER], &rtid, 32)))
386
      continue;			/* No AS boundary router found */
381 387

  
382
    met = 0;
383
    met2 = 0;
384
    tag = 0;
388
    if (nf1->n.metric1 == LSINFINITY)
389
      continue;			/* distance is INF */
385 390

  
386
    WALK_LIST(atmp, po->area_list)	/*
387
					 * Find shortest path
388
					 * to advertising router 
389
					 */
390
    {
391
      if ((etmp =
392
	   ospf_hash_find(atmp->gr, en->lsa.rt, en->lsa.rt,
393
			  LSA_T_RT)) != NULL)
394
      {
395
	if ((absr == NULL) || (absr->dist > etmp->dist) ||
396
	    ((etmp->dist == absr->dist) && (absroa->areaid < atmp->areaid)))
397
	{
398
	  absr = etmp;
399
	  absroa = atmp;
400
	  break;
401
	}
402
      }
403
    }
404

  
405
    if ((absr == NULL) || (absr->dist == LSINFINITY) ||
406
	(((struct ospf_lsa_rt *) (absr->lsa_body))->veb.bit.e == 0))
407
    {
408
      DBG("ASBR is null or its dist=INF\n");
409
      continue;
410
    }
391
    if (!(nf1->n.capa & ORTA_ASBR))
392
      continue;			/* It is not ASBR */
411 393

  
412 394
    if (ipa_compare(lt->fwaddr, ipa_from_u32(0)) == 0)
413 395
    {
414
      if (lt->etos > 0)		/* FW address == 0 */
415
      {
416
	met = absr->dist;
396
      if (lt->etos > 0)
397
      {				/* FW address == 0 */
398
	met1 = nf1->n.metric1;
417 399
	met2 = lt->metric;
418 400
      }
419 401
      else
420 402
      {
421
	met = absr->dist + lt->metric;
403
	met1 = nf1->n.metric1 + lt->metric;
422 404
	met2 = LSINFINITY;
423 405
      }
424
      tag = lt->tag;
406
      nh = nf1->n.nh;
407
      nhi = nf1->n.ifa;
425 408
    }
426
    else			/* FW address !=0 */
427
    {
428
      inf = NULL;
429
      WALK_LIST(atmp, po->area_list)
430
      {
431
	if ((inf = fib_route(&atmp->infib, lt->fwaddr, 32)) != NULL)
432
	{
433
	  break;
434
	}
435
      }
436

  
437
      if (inf == NULL)
409
    else
410
    {				/* FW address !=0 */
411
      if (!(nf2 = fib_route(&po->rtf[ORT_NET], lt->fwaddr, 32)))
438 412
      {
439 413
	DBG("Cannot find network route (GW=%I)\n", lt->fwaddr);
440 414
	continue;
441 415
      }
442

  
443 416
      if (lt->etos > 0)
444 417
      {
445
	met = inf->metric;
418
	met1 = nf2->n.metric1;
446 419
	met2 = lt->metric;
447 420
      }
448 421
      else
449 422
      {
450
	met = inf->metric + lt->metric;
423
	met1 = nf2->n.metric1 + lt->metric;
451 424
	met2 = LSINFINITY;
452 425
      }
453
      tag = lt->tag;
454 426

  
455 427
      if ((nn = neigh_find(p, &lt->fwaddr, 0)) != NULL)
456 428
      {
457
	nnh = lt->fwaddr;
458
	nnhi = nn->iface;
429
	nh = lt->fwaddr;
430
	nhi = nn->iface;
459 431
      }
460 432
      else
461 433
      {
462
	nnh = inf->en->nh;
463
	nnhi = inf->en->nhi;
434
	nh = nf2->n.nh;
435
	nhi = nf2->n.ifa;
464 436
      }
465 437
    }
466 438

  
467
    nf = fib_get(ef, &ip, mlen);
468
    if ((nf->metric == LSINFINITY) ||	/* nf is new */
469
	((met < nf->metric) && (nf->metric2 == met2)) ||	/* both E1 or E2
470
								 * with same metric */
471
	((met2 < nf->metric2) && (nf->metric2 != LSINFINITY)) ||	/* E2 smaller and
472
									 * 1st is not E1 */
473
	((nf->metric2 != LSINFINITY) && (met2 == LSINFINITY)))	/* 2nd is E1 and
474
								 * 1st is E2 */
475
    {
476
      if (nf->metric != LSINFINITY)
477
	OSPF_TRACE(D_EVENTS,
478
		   "Rewriting %I/%d met=%d, met2=%d, nmet=%d, nmet2=%d",
479
		   ip, mlen, nf->metric, nf->metric2, met, met2);
480
      nf->metric = met;
481
      nf->metric2 = met2;
482
      nf->tag = tag;
483

  
484
      if (nnhi != NULL)
485
      {
486
	nf->nh = nnh;
487
	nf->nhi = nnhi;
488
      }
489
      else
490
      {
491
	if (ipa_compare(absr->nh, ipa_from_u32(0)) == 0)
492
	{
493
	  struct ospf_neighbor *neigh;
494

  
495
	  if ((neigh = find_neigh_noifa(po, absr->lsa.rt)) == NULL)
496
	  {
497
	    DBG("Cannot find neighbor\n");
498
	    nf->metric = LSINFINITY;	/* delete this route */
499
	    continue;
500
	  }
501
	  nn = neigh_find(p, &neigh->ip, 0);
502
	  DBG("     Next hop calculated: %I\n", nn->addr);
503
	  nf->nh = nn->addr;
504
	  nf->nhi = nn->iface;
505
	}
506
	else
507
	{
508
	  nf->nh = absr->nh;
509
	  nf->nhi = absr->nhi;
510
	}
511
      }
512
    }
439
    nfa.type = RTS_OSPF_EXT;
440
    nfa.capa = 0;
441
    nfa.metric1 = met1;
442
    nfa.metric2 = met2;
443
    nfa.oa = oa;
444
    nfa.ar = nf1->n.ar;
445
    nfa.nh = nh;
446
    nfa.ifa = nhi;
447
    nfa.tag = lt->tag;
448
    ri_install(po, ip, mlen, ORT_NET, &nfa);
513 449
  }
514 450

  
515
  DBG("Now syncing my rt table with nest's\n");
516
  FIB_ITERATE_INIT(&fit, ef);
517
noch:
518
  FIB_ITERATE_START(ef, &fit, nftmp)
519
  {
520
    nf = (struct extfib *) nftmp;
521
    if (nf->metric == LSINFINITY)
522
    {
523
      net *ne;
524

  
525
      ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
526
      DBG("Deleting rt entry %I\n     (IP: %I, GW: %I)\n",
527
	  nf->fn.prefix, ip, nf->nh);
528
      rte_update(p->table, ne, p, NULL);
529

  
530
      /* Now delete my fib */
531
      FIB_ITERATE_PUT(&fit, nftmp);
532
      fib_delete(ef, nftmp);
533
      goto noch;
534
    }
535
    else
536
      if ((nf->metric != nf->oldmetric) || (nf->metric2 != nf->oldmetric2) ||
537
	  (!ipa_equal(nf->nh, nf->oldnh)) || (nf->tag != nf->oldtag))
538
    {
539
      net *ne;
540
      rta a0;
541
      rte *e;
542

  
543
      bzero(&a0, sizeof(a0));
544

  
545
      a0.proto = p;
546
      a0.source = RTS_OSPF_EXT;
547
      a0.scope = SCOPE_UNIVERSE;
548
      a0.cast = RTC_UNICAST;
549
      a0.dest = RTD_ROUTER;
550
      a0.flags = 0;
551
      a0.aflags = 0;
552
      a0.iface = nf->nhi;
553
      a0.gw = nf->nh;
554
      ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
555
      e = rte_get_temp(&a0);
556
      e->u.ospf.metric1 = nf->metric;
557
      e->u.ospf.metric2 = nf->metric2;
558
      e->u.ospf.tag = nf->tag;
559
      e->pflags = 0;
560
      e->net = ne;
561
      e->pref = p->preference;
562
      DBG("Modifying rt entry %I\n     (IP: %I, GW: %I)\n",
563
	  nf->fn.prefix, ip, nf->nh);
564
      rte_update(p->table, ne, p, e);
565

  
566
      nf->oldmetric = nf->metric;
567
      nf->oldmetric2 = nf->metric2;
568
      nf->oldnh = nf->nh;
569
      nf->oldtag = nf->tag;
570
    }
571
  }
572
  FIB_ITERATE_END(nftmp);
573 451
}
574 452

  
575 453
/* Add LSA into list of candidates in Dijkstra's algorithm */
......
592 470
  if (dist >= en->dist)
593 471
    return;
594 472
  /*
595
   * FIXME The line above is not a bug, but we don't support
596
   * multiple next hops. I'll start as soon as nest will
473
   * FIXME The line above is not a bug, but we don't support multiple
474
   * next hops. I'll start as soon as nest will
597 475
   */
598 476
  DBG("     Adding candidate: rt: %I, id: %I, type: %u\n", en->lsa.rt,
599 477
      en->lsa.id, en->lsa.type);
......
606 484
  if (!en->nhi)
607 485
    return;			/* We cannot find next hop, ignore it */
608 486

  
609
  if (en->color == CANDIDATE)	/* We found a shorter path */
610
  {
487
  if (en->color == CANDIDATE)
488
  {				/* We found a shorter path */
611 489
    rem_node(&en->cn);
612 490
  }
613

  
614 491
  en->dist = dist;
615 492
  en->color = CANDIDATE;
616 493

  
......
694 571
	if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL)
695 572
	  return;
696 573
	en->nhi = neigh->ifa->iface;
697
	en->nh = neigh->ip;	/* Yes, neighbor is it's own next hop */
574
	en->nh = neigh->ip;	/* Yes, neighbor is it's
575
				 * own next hop */
698 576
	return;
699 577
      }
700 578
    }
701

  
702 579
    if (par->lsa.type == LSA_T_NET)
703 580
    {
704 581
      if (en->lsa.type == LSA_T_NET)
......
708 585
      if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL)
709 586
	return;
710 587
      en->nhi = neigh->ifa->iface;
711
      en->nh = neigh->ip;	/* Yes, neighbor is it's own next hop */
588
      en->nh = neigh->ip;	/* Yes, neighbor is it's own
589
				 * next hop */
712 590
      return;
713 591
    }
714
    else			/* Parent is some RT neighbor */
715
    {
592
    else
593
    {				/* Parent is some RT neighbor */
716 594
      log(L_ERR "Router's parent has no next hop. (EN=%I, PAR=%I)",
717 595
	  en->lsa.id, par->lsa.id);
718 596
      /* I hoped this would never happen */
......
723 601
  en->nhi = par->nhi;
724 602
  DBG("     Next hop calculated: %I.\n", en->nh);
725 603
}
604

  
605
static void
606
rt_sync(struct proto_ospf *po)
607
{
608
  struct proto *p = &po->proto;
609
  struct fib_iterator fit;
610
  struct fib *fib = &po->rtf[ORT_NET];
611
  ort *nf;
612

  
613
  DBG("Now syncing my rt table with nest's\n");
614
  FIB_ITERATE_INIT(&fit, fib);
615
again:
616
  FIB_ITERATE_START(fib, &fit, nftmp)
617
  {
618
    nf = (ort *) nftmp;
619
    if (nf->n.metric1 == LSINFINITY)
620
    {
621
      net *ne;
622

  
623
      ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
624
      DBG("Deleting rt entry %I\n     (IP: %I, GW: %I)\n",
625
	  nf->fn.prefix, ip, nf->nh);
626
      rte_update(p->table, ne, p, NULL);
627

  
628
      /* Now delete my fib */
629
      FIB_ITERATE_PUT(&fit, nftmp);
630
      fib_delete(fib, nftmp);
631
      goto again;
632
    }
633
    else if (memcmp(&nf->n, &nf->o, sizeof(orta)))
634
    {				/* Some difference */
635
      net *ne;
636
      rta a0;
637
      rte *e;
638

  
639
      bzero(&a0, sizeof(a0));
640

  
641
      a0.proto = p;
642
      a0.source = nf->n.type;
643
      a0.scope = SCOPE_UNIVERSE;
644
      a0.cast = RTC_UNICAST;
645
      a0.dest = RTD_ROUTER;
646
      a0.flags = 0;
647
      a0.aflags = 0;
648
      a0.iface = nf->n.ifa;
649
      a0.gw = nf->n.nh;
650
      ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
651
      e = rte_get_temp(&a0);
652
      e->u.ospf.metric1 = nf->n.metric1;
653
      e->u.ospf.metric2 = nf->n.metric2;
654
      e->u.ospf.tag = nf->n.tag;
655
      e->pflags = 0;
656
      e->net = ne;
657
      e->pref = p->preference;
658
      DBG("Modifying rt entry %I\n     (IP: %I, GW: %I)\n",
659
	  nf->fn.prefix, ip, nf->nh);
660
      rte_update(p->table, ne, p, e);
661
    }
662
  }
663
  FIB_ITERATE_END(nftmp);
664
}
proto/ospf/rt.h
10 10
#ifndef _BIRD_OSPF_RT_H_
11 11
#define _BIRD_OSPF_RT_H_
12 12

  
13
struct infib
13
typedef struct orta
14 14
{
15
  struct fib_node fn;
16
  u16 metric;
17
  u16 oldmetric;
18
  struct top_hash_entry *en;
19
  struct top_hash_entry *olden;
20
};
15
  int type;
16
  int capa;
17
  struct ospf_area *oa;
18
  int metric1;
19
  int metric2;
20
  ip_addr nh;			/* Next hop */
21
  struct iface *ifa;		/* Outgoing interface */
22
  struct top_hash_entry *ar;	/* Advertising router */
23
  u32 tag;
24
}
25
orta;
21 26

  
22
struct extfib
27
typedef struct ort
23 28
{
24 29
  struct fib_node fn;
25
  u16 metric;
26
  u16 metric2;
27
  ip_addr nh;
28
  u32 tag;
29
  struct iface *nhi;
30
  u16 oldmetric;
31
  u16 oldmetric2;
32
  ip_addr oldnh;
33
  u32 oldtag;
34
};
30
  int dest;
31
#define ORT_UNDEF -1
32
#define ORT_ROUTER 1
33
#define ORT_NET 0
34
  orta n;
35
  orta o;
36
}
37
ort;
35 38

  
36 39
void ospf_rt_spf(struct proto_ospf *po);
37
void init_infib(struct fib_node *fn);
38
void init_efib(struct fib_node *fn);
40
void ospf_rt_initort(struct fib_node *fn);
41

  
39 42

  
40 43
#endif /* _BIRD_OSPF_RT_H_ */

Also available in: Unified diff