Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / neighbor.c @ 551d4443

History | View | Annotate | Download (9.4 KB)

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

    
9
#include "ospf.h"
10

    
11
char *ospf_ns[]={"down", "attempt", "init", "2way", "exstart", "exchange",
12
  "loading", "full"};
13

    
14
const char *ospf_inm[]={ "hello received", "neighbor start", "2-way received",
15
  "negotiation done", "exstart done", "bad ls request", "load done",
16
  "adjacency ok?", "sequence mismatch", "1-way received", "kill neighbor",
17
  "inactivity timer", "line down" };
18

    
19
void
20
neigh_chstate(struct ospf_neighbor *n, u8 state)
21
{
22
  struct ospf_iface *ifa;
23
  struct proto *p;
24
  u8 oldstate;
25

    
26
  oldstate=n->state;
27

    
28
  if(oldstate!=state)
29
  {
30
    ifa=n->ifa;
31
    n->state=state;
32
    if((state==NEIGHBOR_2WAY) && (oldstate<NEIGHBOR_2WAY))
33
      ospf_int_sm(n->ifa, ISM_NEICH);
34
    if((state<NEIGHBOR_2WAY) && (oldstate>=NEIGHBOR_2WAY))
35
      ospf_int_sm(n->ifa, ISM_NEICH);
36
    if(oldstate==NEIGHBOR_FULL)        /* Decrease number of adjacencies */
37
    {
38
      ifa->fadj--;
39
      n->state=state;
40
      originate_rt_lsa(ifa->oa,ifa->oa->po);
41
      originate_net_lsa(ifa,ifa->oa->po);
42
    }
43
    p=(struct proto *)(ifa->proto);
44
  
45
    debug("%s: Neighbor %I changes state from \"%s\" to \"%s\".\n",
46
      p->name, n->ip, ospf_ns[oldstate], ospf_ns[state]);
47
    if(state==NEIGHBOR_FULL)        /* Increase number of adjacencies */
48
    {
49
      ifa->fadj++;
50
      originate_rt_lsa(n->ifa->oa,n->ifa->oa->po);
51
      originate_net_lsa(ifa,ifa->oa->po);
52
    }
53
    if(oldstate>=NEIGHBOR_EXSTART && state<NEIGHBOR_EXSTART)
54
    {
55
      tm_stop(n->rxmt_timer);
56
      /* Stop RXMT timers */
57
    }
58
    if(state==NEIGHBOR_EXSTART)
59
    {
60
      if(n->adj==0)        /* First time adjacency */
61
      {
62
        n->dds=random_u32();
63
      }
64
      n->dds++;
65
      n->myimms.byte=0;
66
      n->myimms.bit.ms=1;
67
      n->myimms.bit.m=1;
68
      n->myimms.bit.i=1;
69
      tm_start(n->rxmt_timer,1);        /* Or some other number ? */
70
    }
71
    if(state<NEIGHBOR_EXCHANGE) tm_stop(n->lsrr_timer);
72
  }
73
}
74

    
75
struct ospf_neighbor *
76
electbdr(list nl)
77
{
78
  struct ospf_neighbor *neigh,*n1,*n2;
79

    
80
  n1=NULL;
81
  n2=NULL;
82
  WALK_LIST (neigh, nl)                /* First try those decl. themselves */
83
  {
84
    if(neigh->state>=NEIGHBOR_2WAY)        /* Higher than 2WAY */
85
      if(neigh->priority>0)                /* Eligible */
86
        if(neigh->rid!=neigh->dr)        /* And not declaring itself DR */
87
        {
88
          if(neigh->rid==neigh->bdr)        /* Declaring BDR */
89
          {
90
            if(n1!=NULL)
91
            {
92
              if(neigh->priority>n1->priority) n1=neigh;
93
              else if(neigh->priority==n1->priority)
94
                  if(neigh->rid>n1->rid) n1=neigh;
95
            }
96
            else
97
            {
98
              n1=neigh;
99
            }
100
          }
101
          else                                /* And NOT declaring BDR */
102
          {
103
            if(n2!=NULL)
104
            {
105
              if(neigh->priority>n2->priority) n2=neigh;
106
              else if(neigh->priority==n2->priority)
107
                  if(neigh->rid>n2->rid) n2=neigh;
108
            }
109
            else
110
            {
111
              n2=neigh;
112
            }
113
          }
114
      }
115
  }
116
  if(n1==NULL) n1=n2;
117

    
118
  return(n1);
119
}
120

    
121
struct ospf_neighbor *
122
electdr(list nl)
123
{
124
  struct ospf_neighbor *neigh,*n;
125

    
126
  n=NULL;
127
  WALK_LIST (neigh, nl)        /* And now DR */
128
  {
129
    if(neigh->state>=NEIGHBOR_2WAY)        /* Higher than 2WAY */
130
      if(neigh->priority>0)                /* Eligible */
131
        if(neigh->rid==neigh->dr)        /* And declaring itself DR */
132
        {
133
          if(n!=NULL)
134
          {
135
            if(neigh->priority>n->priority) n=neigh;
136
            else if(neigh->priority==n->priority)
137
                if(neigh->rid>n->rid) n=neigh;
138
          }
139
          else
140
          {
141
            n=neigh;
142
          }
143
      }
144
  }
145

    
146
  return(n);
147
}
148

    
149
int
150
can_do_adj(struct ospf_neighbor *n)
151
{
152
  struct ospf_iface *ifa;
153
  struct proto *p;
154
  int i;
155

    
156
  ifa=n->ifa;
157
  p=(struct proto *)(ifa->proto);
158
  i=0;
159

    
160
  switch(ifa->type)
161
  {
162
    case OSPF_IT_PTP:
163
    case OSPF_IT_VLINK:
164
      i=1;
165
      break;
166
    case OSPF_IT_BCAST:
167
    case OSPF_IT_NBMA:
168
      switch(ifa->state)
169
      {
170
        case OSPF_IS_DOWN:
171
          die("%s: Iface %s in down state?", p->name, ifa->iface->name);
172
          break;
173
        case OSPF_IS_WAITING:
174
          DBG("%s: Neighbor? on iface %s\n",p->name, ifa->iface->name);
175
          break;
176
        case OSPF_IS_DROTHER:
177
          if(((n->rid==ifa->drid) || (n->rid==ifa->bdrid))
178
            && (n->state==NEIGHBOR_2WAY)) i=1;
179
          break;
180
        case OSPF_IS_PTP:
181
        case OSPF_IS_BACKUP:
182
        case OSPF_IS_DR:
183
          if(n->state==NEIGHBOR_2WAY) i=1;
184
          break;
185
        default:
186
          die("%s: Iface %s in unknown state?",p->name, ifa->iface->name);
187
          break;
188
      }
189
      break;
190
    default:
191
      die("%s: Iface %s is unknown type?",p->name, ifa->iface->name);
192
      break;
193
  }
194
  DBG("%s: Iface %s can_do_adj=%d\n",p->name, ifa->iface->name,i);
195
  return i;
196
}
197

    
198
void
199
ospf_neigh_sm(struct ospf_neighbor *n, int event)
200
        /* Interface state machine */
201
{
202
  struct proto *p=(struct proto *)(n->ifa->proto);
203
  struct proto_ospf *po=n->ifa->proto;
204

    
205
  DBG("%s: Neighbor state machine for neighbor %I, event \"%s\".\n",
206
    p->name, n->rid, ospf_inm[event]);
207

    
208
  switch(event)
209
  {
210
    case INM_START:
211
      neigh_chstate(n,NEIGHBOR_ATTEMPT);
212
      /* FIXME No NBMA now */
213
      break;
214
    case INM_HELLOREC:
215
      switch(n->state)
216
      {
217
        case NEIGHBOR_ATTEMPT:
218
        case NEIGHBOR_DOWN:
219
          neigh_chstate(n,NEIGHBOR_INIT);
220
        default:
221
          restart_inactim(n);
222
          break;
223
      }
224
      break;
225
    case INM_2WAYREC:
226
      if(n->state<NEIGHBOR_2WAY)
227
      {
228
        /* Can In build adjacency? */
229
        neigh_chstate(n,NEIGHBOR_2WAY);
230
        if(can_do_adj(n))
231
        {
232
          neigh_chstate(n,NEIGHBOR_EXSTART);
233
        }
234
      }
235
      break;
236
    case INM_NEGDONE:
237
      if(n->state==NEIGHBOR_EXSTART)
238
      {
239
        neigh_chstate(n,NEIGHBOR_EXCHANGE);
240
        s_init_list(&(n->lsrql));
241
        n->lsrqh=ospf_top_new(n->ifa->proto);
242
        s_init_list(&(n->lsrtl));
243
        n->lsrth=ospf_top_new(n->ifa->proto);
244
        s_init(&(n->dbsi), &(n->ifa->oa->lsal));
245
        s_init(&(n->lsrqi), &(n->lsrql));
246
        s_init(&(n->lsrti), &(n->lsrtl));
247
        tm_start(n->lsrr_timer,n->ifa->rxmtint);
248
        tm_start(n->ackd_timer,n->ifa->rxmtint/2);
249
      }
250
      else die("NEGDONE and I'm not in EXSTART?\n");
251
      break;
252
    case INM_EXDONE:
253
        neigh_chstate(n,NEIGHBOR_LOADING);
254
      break;
255
    case INM_LOADDONE:
256
        neigh_chstate(n,NEIGHBOR_FULL);
257
      break;
258
    case INM_ADJOK:
259
        switch(n->state)
260
        {
261
          case NEIGHBOR_2WAY:
262
        /* Can In build adjacency? */
263
            if(can_do_adj(n))
264
            {
265
              neigh_chstate(n,NEIGHBOR_EXSTART);
266
            }
267
            break;
268
          default:
269
            if(n->state>=NEIGHBOR_EXSTART)
270
              if(!can_do_adj(n))
271
              {
272
                neigh_chstate(n,NEIGHBOR_2WAY);
273
              }
274
            break;
275
        }
276
      break;
277
    case INM_SEQMIS:
278
    case INM_BADLSREQ:
279
      debug("%s: Bad LS req!\n", p->name);
280
      if(n->state>=NEIGHBOR_EXCHANGE)
281
      {
282
        neigh_chstate(n,NEIGHBOR_EXSTART);
283
      }
284
      break;
285
    case INM_KILLNBR:
286
    case INM_LLDOWN:
287
    case INM_INACTTIM:
288
      neigh_chstate(n,NEIGHBOR_DOWN);
289
      break;
290
    case INM_1WAYREC:
291
      neigh_chstate(n,NEIGHBOR_INIT);
292
      break;
293
    default:
294
      die("%s: INM - Unknown event?",p->name);
295
      break;
296
  }
297
}
298

    
299
void
300
bdr_election(struct ospf_iface *ifa, struct proto *p)
301
{
302
  struct ospf_neighbor *neigh,*ndr,*nbdr,me,*tmp;
303
  u32 myid, ndrid, nbdrid;
304
  int doadj;
305

    
306
  p=(struct proto *)(ifa->proto);
307

    
308
  DBG("%s: (B)DR election.\n",p->name);
309

    
310
  myid=p->cf->global->router_id;
311

    
312
  me.state=NEIGHBOR_2WAY;
313
  me.rid=myid;
314
  me.priority=ifa->priority;
315
  me.dr=ifa->drid;
316
  me.bdr=ifa->bdrid;
317

    
318
  add_tail(&ifa->neigh_list, NODE &me);
319

    
320
  nbdr=electbdr(ifa->neigh_list);
321
  ndr=electdr(ifa->neigh_list);
322

    
323
  if(ndr==NULL) ndr=nbdr;
324

    
325
  if(((ifa->drid==myid) && (ndr->rid!=myid))
326
    || ((ifa->drid!=myid) && (ndr->rid==myid))
327
    || ((ifa->bdrid==myid) && (nbdr->rid!=myid)) 
328
    || ((ifa->bdrid!=myid) && (nbdr->rid==myid)))
329
  {
330
    if(ndr==NULL) ifa->drid=me.dr=0;
331
    else ifa->drid=me.dr=ndr->rid;
332

    
333
    if(nbdr==NULL) ifa->bdrid=me.bdr=0;
334
    else ifa->bdrid=me.bdr=nbdr->rid;
335

    
336
    nbdr=electbdr(ifa->neigh_list);
337
    ndr=electdr(ifa->neigh_list);
338
  }
339

    
340
  if(ndr==NULL) ifa->drid=0;
341
  if(ndr==NULL) ndrid=0;
342
  else ndrid=ndr->rid;
343

    
344
  if(nbdr==NULL) nbdrid=0;
345
  else nbdrid=nbdr->rid;
346

    
347
  doadj=0;
348
  if((ifa->drid!=ndrid) || (ifa->bdrid!=nbdrid)) doadj=1;
349
  ifa->drid=ndrid;
350
  if((tmp=find_neigh(ifa,ndrid))==NULL) die("Error i BDR election.\n");
351
  ifa->drip=tmp->ip;
352
  ifa->bdrid=nbdrid;
353
  if((tmp=find_neigh(ifa,nbdrid))==NULL) die("Error i BDR election.\n");
354
  ifa->bdrip=tmp->ip;
355

    
356
  DBG("%s: DR=%I, BDR=%I\n",p->name, ifa->drid, ifa->bdrid);
357

    
358
  if(myid==ifa->drid) iface_chstate(ifa, OSPF_IS_DR);
359
  else
360
  {
361
    if(myid==ifa->bdrid) iface_chstate(ifa, OSPF_IS_BACKUP);
362
    else iface_chstate(ifa, OSPF_IS_DROTHER);
363
  }
364

    
365
  rem_node(NODE &me);
366

    
367
  if(doadj)
368
  {
369
    WALK_LIST (neigh, ifa->neigh_list)
370
    {
371
      ospf_neigh_sm(neigh, INM_ADJOK);
372
    }
373
  }
374
}
375

    
376
struct ospf_neighbor *
377
find_neigh(struct ospf_iface *ifa, u32 rid)
378
{
379
  struct ospf_neighbor *n;
380

    
381
  WALK_LIST (n, ifa->neigh_list)
382
    if(n->rid == rid)
383
      return n;
384
  return NULL;
385
}
386

    
387
struct ospf_neighbor *
388
find_neigh_noifa(struct proto_ospf *po, u32 rid)
389
{
390
  struct ospf_neighbor *n;
391
  struct ospf_iface *ifa;
392

    
393
  WALK_LIST (ifa, po->iface_list)
394
    if((n=find_neigh(ifa, rid))!=NULL)
395
      return n;
396
  return NULL;
397
}
398

    
399
struct ospf_area *
400
ospf_find_area(struct proto_ospf *po, u32 aid)
401
{
402
  struct ospf_area *oa;
403
  WALK_LIST(NODE oa,po->area_list)
404
    if(((struct ospf_area *)oa)->areaid==aid) return oa;
405
  return NULL;
406
}
407

    
408