Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / iface.c @ 035f6acb

History | View | Annotate | Download (13 KB)

1
/*
2
 *        BIRD -- OSPF
3
 *
4
 *        (c) 1999 - 2000 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_is[]={ "down", "loop", "waiting", "point-to-point", "drother",
12
  "backup", "dr" };
13

    
14
char *ospf_ism[]={ "interface up", "wait timer fired", "backup seen",
15
  "neighbor change", "loop indicated", "unloop indicated", "interface down"};   
16

    
17
char *ospf_it[]={ "broadcast", "nbma", "point-to-point", "virtual link" };
18

    
19
/**
20
 * iface_chstate - handle changes of interface state
21
 * @ifa: OSPF interface
22
 * @state: new state
23
 *
24
 * Many actions must be taken according to interface state changes. New network
25
 * LSAs must be originated, flushed, new multicast sockets to listen for messages for
26
 * %ALLDROUTERS have to be opened, etc.
27
 */
28
void
29
iface_chstate(struct ospf_iface *ifa, u8 state)
30
{
31
  struct proto_ospf *po=ifa->proto;
32
  struct proto *p=&po->proto;
33
  u8 oldstate;
34

    
35
  if(ifa->state!=state)
36
  {
37
    OSPF_TRACE(D_EVENTS, "Changing state of iface: %s from \"%s\" into \"%s\".",
38
      ifa->iface->name, ospf_is[ifa->state], ospf_is[state]);
39
    oldstate=ifa->state;
40
    ifa->state=state;
41
    if(ifa->iface->flags & IF_MULTICAST)
42
    {
43
      if((state==OSPF_IS_BACKUP)||(state==OSPF_IS_DR))
44
      {
45
        if((ifa->dr_sk==NULL)&&(ifa->type!=OSPF_IT_NBMA))
46
        {
47
          DBG("%s: Adding new multicast socket for (B)DR\n", p->name);
48
          ifa->dr_sk=sk_new(p->pool);
49
          ifa->dr_sk->type=SK_IP_MC;
50
          ifa->dr_sk->sport=0;
51
          ifa->dr_sk->dport=OSPF_PROTO;
52
          ifa->dr_sk->saddr=ipa_from_u32(0);
53
          ifa->dr_sk->daddr=AllDRouters;
54
          ifa->dr_sk->tos=IP_PREC_INTERNET_CONTROL;
55
          ifa->dr_sk->ttl=1;
56
          ifa->dr_sk->rx_hook=ospf_rx_hook;
57
          ifa->dr_sk->tx_hook=ospf_tx_hook;
58
          ifa->dr_sk->err_hook=ospf_err_hook;
59
          ifa->dr_sk->iface=ifa->iface;
60
          ifa->dr_sk->rbsize=ifa->iface->mtu;
61
          ifa->dr_sk->tbsize=ifa->iface->mtu;
62
          ifa->dr_sk->data=(void *)ifa;
63
          if(sk_open(ifa->dr_sk)!=0)
64
          {
65
            DBG("%s: SK_OPEN: new? mc open failed.\n", p->name);
66
          }
67
        }
68
      }
69
      else
70
      {
71
        if(ifa->dr_sk!=NULL)
72
        {
73
          if (ifa->dr_sk->rbuf)
74
            mb_free(ifa->dr_sk->rbuf);
75
          if (ifa->dr_sk->tbuf)
76
            mb_free(ifa->dr_sk->tbuf);
77
          rfree(ifa->dr_sk);
78
          ifa->dr_sk=NULL;
79
        }
80
      }
81
      if((oldstate==OSPF_IS_DR)&&(ifa->nlsa!=NULL))
82
      {
83
        ifa->nlsa->lsa.age=LSA_MAXAGE;
84
        if(state>=OSPF_IS_WAITING)
85
        {
86
          net_flush_lsa(ifa->nlsa,po,ifa->oa);
87
        }
88
        if(can_flush_lsa(ifa->oa)) flush_lsa(ifa->nlsa,ifa->oa);
89
        ifa->nlsa=NULL;
90
      }
91
    }
92
  }
93
}
94

    
95
void
96
downint(struct ospf_iface *ifa)
97
{
98
  struct ospf_neighbor *n,*nx;
99
  struct proto *p=&ifa->proto->proto;
100
  struct proto_ospf *po=ifa->proto;
101

    
102
  WALK_LIST_DELSAFE(n,nx,ifa->neigh_list)
103
  {
104
    OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
105
    ospf_neigh_remove(n);
106
  }
107
  rem_node(NODE ifa);
108
  if(ifa->hello_sk!=NULL)
109
  {
110
    if (ifa->hello_sk->rbuf)
111
      mb_free(ifa->hello_sk->rbuf);
112
    if (ifa->hello_sk->tbuf)
113
      mb_free(ifa->hello_sk->tbuf);
114
    rfree(ifa->hello_sk);
115
  }
116
  if(ifa->dr_sk!=NULL)
117
  {
118
    if (ifa->dr_sk->rbuf)
119
      mb_free(ifa->dr_sk->rbuf);
120
    if (ifa->dr_sk->tbuf)
121
      mb_free(ifa->dr_sk->tbuf);
122
    rfree(ifa->dr_sk);
123
  }
124
  if(ifa->ip_sk!=NULL)
125
  {
126
    if (ifa->ip_sk->rbuf)
127
      mb_free(ifa->ip_sk->rbuf);
128
    if (ifa->ip_sk->tbuf)
129
      mb_free(ifa->ip_sk->tbuf);
130
    rfree(ifa->ip_sk);
131
  }
132
  if(ifa->wait_timer!=NULL)
133
  {
134
    tm_stop(ifa->wait_timer);
135
    rfree(ifa->wait_timer);
136
  }
137
  if(ifa->hello_timer!=NULL)
138
  {
139
    tm_stop(ifa->hello_timer);
140
    rfree(ifa->hello_timer);
141
  }
142
  if(ifa->poll_timer!=NULL)
143
  {
144
    tm_stop(ifa->poll_timer);
145
    rfree(ifa->poll_timer);
146
  }
147
  rfree(ifa->lock);
148
  mb_free(ifa);
149
}
150

    
151
/**
152
 * ospf_int_sm - OSPF interface state machine
153
 * @ifa: OSPF interface
154
 * @event: event comming to state machine
155
 *
156
 * This fully respect 9.3 of RFC 2328 except we don't use %LOOP state of
157
 * interface.
158
 */
159
void
160
ospf_int_sm(struct ospf_iface *ifa, int event)
161
{
162
  struct proto *p=(struct proto *)(ifa->proto);
163
  struct proto_ospf *po=ifa->proto;
164
  struct ospf_area *oa=ifa->oa;
165

    
166
  OSPF_TRACE(D_EVENTS, "SM on iface %s. Event is \"%s\".",
167
    ifa->iface->name, ospf_ism[event]);
168

    
169
  switch(event)
170
  {
171
    case ISM_UP:
172
      if(ifa->state==OSPF_IS_DOWN)
173
      {
174
        /* Now, nothing should be adjacent */
175
        restart_hellotim(ifa);
176
        restart_polltim(ifa);
177
        if((ifa->type==OSPF_IT_PTP) || (ifa->type==OSPF_IT_VLINK))
178
        {
179
          iface_chstate(ifa, OSPF_IS_PTP);
180
        }
181
        else
182
        {
183
          if(ifa->priority==0)
184
          {
185
            iface_chstate(ifa, OSPF_IS_DROTHER);
186
          } 
187
          else
188
          {
189
             iface_chstate(ifa, OSPF_IS_WAITING);
190
             restart_waittim(ifa);
191
          }
192
        }
193
      }
194
      schedule_rt_lsa(ifa->oa);
195
      break;
196
    case ISM_BACKS:
197
    case ISM_WAITF:
198
      if(ifa->state==OSPF_IS_WAITING)
199
      {
200
        bdr_election(ifa);
201
      }
202
      break;
203
    case ISM_NEICH:
204
      if((ifa->state==OSPF_IS_DROTHER) || (ifa->state==OSPF_IS_DR) ||
205
        (ifa->state==OSPF_IS_BACKUP))
206
      {
207
        bdr_election(ifa);
208
        schedule_rt_lsa(ifa->oa);
209
      }
210
      break;
211
    case ISM_DOWN:
212
      iface_chstate(ifa, OSPF_IS_DOWN);
213
      downint(ifa);
214
      schedule_rt_lsa(oa);
215
      break;
216
    case ISM_LOOP:        /* Useless? */
217
      iface_chstate(ifa, OSPF_IS_LOOP);
218
      downint(ifa);
219
      schedule_rt_lsa(ifa->oa);
220
      break;
221
    case ISM_UNLOOP:
222
      iface_chstate(ifa, OSPF_IS_DOWN);
223
      schedule_rt_lsa(ifa->oa);
224
      break;
225
    default:
226
      bug("%s: ISM - Unknown event?",p->name);
227
      break;
228
  }
229
        
230
}
231

    
232
sock *
233
ospf_open_mc_socket(struct ospf_iface *ifa)
234
{
235
  sock *mcsk;
236
  struct proto *p;
237

    
238
  p=(struct proto *)(ifa->proto);
239

    
240
  mcsk=sk_new(p->pool);
241
  mcsk->type=SK_IP_MC;
242
  mcsk->sport=0;
243
  mcsk->dport=OSPF_PROTO;
244
  mcsk->saddr=ipa_from_u32(0);
245
  mcsk->daddr=AllSPFRouters;
246
  mcsk->tos=IP_PREC_INTERNET_CONTROL;
247
  mcsk->ttl=1;
248
  mcsk->rx_hook=ospf_rx_hook;
249
  mcsk->tx_hook=ospf_tx_hook;
250
  mcsk->err_hook=ospf_err_hook;
251
  mcsk->iface=ifa->iface;
252
  mcsk->rbsize=ifa->iface->mtu;
253
  mcsk->tbsize=ifa->iface->mtu;
254
  mcsk->data=(void *)ifa;
255
  if(sk_open(mcsk)!=0)
256
  {
257
    DBG("%s: SK_OPEN: mc open failed.\n",p->name);
258
    return(NULL);
259
  }
260
  DBG("%s: SK_OPEN: mc opened.\n",p->name);
261
  return(mcsk);
262
}
263

    
264
sock *
265
ospf_open_ip_socket(struct ospf_iface *ifa)
266
{
267
  sock *ipsk;
268
  struct proto *p;
269

    
270
  p=(struct proto *)(ifa->proto);
271

    
272
  ipsk=sk_new(p->pool);
273
  ipsk->type=SK_IP;
274
  ipsk->dport=OSPF_PROTO;
275
  ipsk->saddr=ifa->iface->addr->ip;
276
  ipsk->tos=IP_PREC_INTERNET_CONTROL;
277
  ipsk->ttl=1;
278
  ipsk->rx_hook=ospf_rx_hook;
279
  ipsk->tx_hook=ospf_tx_hook;
280
  ipsk->err_hook=ospf_err_hook;
281
  ipsk->iface=ifa->iface;
282
  ipsk->rbsize=ifa->iface->mtu;
283
  ipsk->tbsize=ifa->iface->mtu;
284
  ipsk->data=(void *)ifa;
285
  if(sk_open(ipsk)!=0)
286
  {
287
    DBG("%s: SK_OPEN: ip open failed.\n",p->name);
288
    return(NULL);
289
  }
290
  DBG("%s: SK_OPEN: ip opened.\n",p->name);
291
  return(ipsk);
292
}
293

    
294
u8
295
ospf_iface_clasify(struct iface *ifa, struct proto *p)
296
{
297
  DBG("%s: Iface flags=%x.\n", p->name, ifa->flags);
298
  if((ifa->flags & (IF_MULTIACCESS|IF_MULTICAST))==
299
    (IF_MULTIACCESS|IF_MULTICAST))
300
  {
301
     DBG("%s: Clasifying BCAST.\n", p->name);
302
     return OSPF_IT_BCAST;
303
  }
304
  if((ifa->flags & (IF_MULTIACCESS|IF_MULTICAST))==
305
    IF_MULTIACCESS)
306
  {
307
    DBG("%s: Clasifying NBMA.\n", p->name);
308
    return OSPF_IT_NBMA;
309
  }
310
  DBG("%s: Clasifying P-T-P.\n", p->name);
311
  return OSPF_IT_PTP;
312
}
313

    
314
struct ospf_iface*
315
find_iface(struct proto_ospf *p, struct iface *what)
316
{
317
  struct ospf_iface *i;
318

    
319
  WALK_LIST (i, p->iface_list)
320
    if ((i)->iface == what)
321
      return i;
322
  return NULL;
323
}
324

    
325
void
326
ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
327
{
328
  struct proto_ospf *po=(struct proto_ospf *)p;
329
  struct ospf_config *c=(struct ospf_config *)(p->cf);
330
  struct ospf_area_config *ac;
331
  struct ospf_iface_patt *ip=NULL;
332
  struct ospf_iface *ifa;
333
  struct object_lock *lock;
334
  struct nbma_node *nbma,*nb;
335
  u8 i;
336
  sock *mcsk;
337

    
338

    
339
  DBG("%s: If notify called\n", p->name);
340
  if (iface->flags & IF_IGNORE)
341
    return;
342

    
343
  if(flags & IF_CHANGE_UP)
344
  {
345
    WALK_LIST(ac, c->area_list)
346
    {
347
      if(ip=(struct ospf_iface_patt *)
348
        iface_patt_match(&ac->patt_list, iface)) break;
349
    }
350

    
351
    if(ip)
352
    {
353
      OSPF_TRACE(D_EVENTS, "Using interface %s.", iface->name);
354

    
355
      ifa=mb_allocz(p->pool, sizeof(struct ospf_iface));
356
      ifa->proto=po;
357
      ifa->iface=iface;
358
   
359
      ifa->an=ac->areaid;
360
      ifa->cost=ip->cost;
361
      ifa->rxmtint=ip->rxmtint;
362
      ifa->inftransdelay=ip->inftransdelay;
363
      ifa->priority=ip->priority;
364
      ifa->helloint=ip->helloint;
365
      ifa->pollint=ip->pollint;
366
      ifa->strictnbma=ip->strictnbma;
367
      ifa->waitint=ip->waitint;
368
      ifa->deadc=ip->deadc;
369
      ifa->stub=ip->stub;
370
      ifa->autype=ip->autype;
371
      memcpy(ifa->aukey,ip->password,8);
372
      ifa->options=2;        /* FIXME what options? */
373
   
374
      if(ip->type==OSPF_IT_UNDEF)
375
        ifa->type=ospf_iface_clasify(ifa->iface, (struct proto *)ifa->proto);
376
      else ifa->type=ip->type;
377

    
378
      init_list(&ifa->neigh_list);
379
      init_list(&ifa->nbma_list);
380
      WALK_LIST(nb,ip->nbma_list)
381
      {
382
        nbma=mb_alloc(p->pool,sizeof(struct nbma_node));
383
        nbma->ip=nb->ip;
384
        nbma->eligible=nb->eligible;
385
        add_tail(&ifa->nbma_list, NODE nbma);
386
      }
387
      
388
      /* Add hello timer */
389
      ifa->hello_timer=tm_new(p->pool);
390
      ifa->hello_timer->data=ifa;
391
      ifa->hello_timer->randomize=0;
392
      ifa->hello_timer->hook=hello_timer_hook;
393
      ifa->hello_timer->recurrent=ifa->helloint;
394
      DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
395
   
396
      if(ifa->type==OSPF_IT_NBMA)
397
      {
398
        ifa->poll_timer=tm_new(p->pool);
399
        ifa->poll_timer->data=ifa;
400
        ifa->poll_timer->randomize=0;
401
        ifa->poll_timer->hook=poll_timer_hook;
402
        ifa->poll_timer->recurrent=ifa->pollint;
403
        DBG("%s: Installing poll timer. (%u)\n", p->name, ifa->pollint);
404
      }
405
      else ifa->poll_timer=NULL;
406
   
407
      ifa->wait_timer=tm_new(p->pool);
408
      ifa->wait_timer->data=ifa;
409
      ifa->wait_timer->randomize=0;
410
      ifa->wait_timer->hook=wait_timer_hook;
411
      ifa->wait_timer->recurrent=0;
412
      DBG("%s: Installing wait timer. (%u)\n", p->name, ifa->waitint);
413
      add_tail(&((struct proto_ospf *)p)->iface_list, NODE ifa);
414
      ifa->state=OSPF_IS_DOWN;
415

    
416
      lock = olock_new( p->pool );
417
      lock->addr = AllSPFRouters;
418
      lock->type = OBJLOCK_IP;
419
      lock->port = OSPF_PROTO;
420
      lock->iface = iface;
421
      lock->data = ifa;
422
      lock->hook = ospf_ifa_add;
423
      addifa_rtlsa(ifa);
424
      olock_acquire(lock);
425
    }
426
  }
427

    
428
  if(flags & IF_CHANGE_DOWN)
429
  {
430
    if((ifa=find_iface((struct proto_ospf *)p, iface))!=NULL)
431
    {
432
      OSPF_TRACE(D_EVENTS, "Killing interface %s.", iface->name);
433
      ospf_int_sm(ifa, ISM_DOWN);
434
    }
435
  }
436

    
437
  if(flags & IF_CHANGE_MTU)
438
  {
439
    if((ifa=find_iface((struct proto_ospf *)p, iface))!=NULL)
440
    {
441
      OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s.", iface->name);
442
      /* FIXME: change MTU */
443
    }
444
  }
445
}
446

    
447
void
448
ospf_iface_info(struct ospf_iface *ifa)
449
{
450
  int x;
451
  char *strict="(strict)";
452

    
453
  if((ifa->type!=OSPF_IT_NBMA)||(ifa->strictnbma==0)) strict="";
454
  cli_msg(-1015,"Interface \"%s\":", ifa->iface->name);
455
  cli_msg(-1015,"\tArea: %I (%u)", ifa->oa->areaid, ifa->oa->areaid);
456
  cli_msg(-1015,"\tType: %s %s", ospf_it[ifa->type], strict);
457
  cli_msg(-1015,"\tState: %s %s", ospf_is[ifa->state],
458
    ifa->stub ? "(stub)" : "");
459
  cli_msg(-1015,"\tPriority: %u", ifa->priority);
460
  cli_msg(-1015,"\tCost: %u", ifa->cost);
461
  cli_msg(-1015,"\tHello timer: %u", ifa->helloint);
462
  if(ifa->type==OSPF_IT_NBMA)
463
  {
464
    cli_msg(-1015,"\tPoll timer: %u", ifa->pollint);
465
  }
466
  cli_msg(-1015,"\tWait timer: %u", ifa->waitint);
467
  cli_msg(-1015,"\tDead timer: %u", ifa->deadc*ifa->helloint);
468
  cli_msg(-1015,"\tRetransmit timer: %u", ifa->rxmtint);
469
  if((ifa->type==OSPF_IT_BCAST)||(ifa->type==OSPF_IT_NBMA))
470
  {
471
    cli_msg(-1015,"\tDesigned router (ID): %I", ifa->drid);
472
    cli_msg(-1015,"\tDesigned router (IP): %I", ifa->drip);
473
    cli_msg(-1015,"\tBackup designed router (ID): %I", ifa->bdrid);
474
    cli_msg(-1015,"\tBackup designed router (IP): %I", ifa->bdrip);
475
  }
476
}
477

    
478
void
479
ospf_ifa_add(struct object_lock *lock)
480
{
481
  struct ospf_iface *ifa=lock->data;
482
  struct proto_ospf *po=ifa->proto;
483
  struct iface *iface=lock->iface;
484
  struct proto *p=&po->proto;
485

    
486
  ifa->ioprob=OSPF_I_OK;
487

    
488
  if(ifa->type!=OSPF_IT_NBMA)
489
  {
490
    if((ifa->hello_sk=ospf_open_mc_socket(ifa))==NULL)
491
    {
492
      log("%s: Huh? could not open mc socket on interface %s?", p->name,
493
        iface->name);
494
      log("%s: Declaring as stub.", p->name);
495
      ifa->stub=1;
496
      ifa->ioprob += OSPF_I_MC;
497
    }
498
    ifa->dr_sk=NULL;
499
  }
500

    
501
  if((ifa->ip_sk=ospf_open_ip_socket(ifa))==NULL)
502
  {
503
    log("%s: Huh? could not open ip socket on interface %s?", p->name,
504
      iface->name);
505
    log("%s: Declaring as stub.", p->name);
506
    ifa->stub=1;
507
    ifa->ioprob += OSPF_I_IP;
508
  }
509
  ifa->lock = lock;
510

    
511
  ifa->state=OSPF_IS_DOWN;
512
  ospf_int_sm(ifa, ISM_UP);
513
}
514

    
515
void
516
schedule_net_lsa(struct ospf_iface *ifa)
517
{
518
  ifa->orignet=1;
519
}