Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / iface.c @ fef1badf

History | View | Annotate | Download (11.2 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_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
void
20
iface_chstate(struct ospf_iface *ifa, u8 state)
21
{
22
  struct proto_ospf *po=ifa->proto;
23
  struct proto *p=&po->proto;
24
  u8 oldstate;
25

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

    
81
void
82
downint(struct ospf_iface *ifa)
83
{
84
  struct ospf_neighbor *n,*nx;
85
  struct proto *p=&ifa->proto->proto;
86
  struct proto_ospf *po=ifa->proto;
87

    
88
  WALK_LIST_DELSAFE(n,nx,ifa->neigh_list)
89
  {
90
    debug("%s: Removing neighbor %I\n", p->name, n->ip);
91
    ospf_neigh_remove(n);
92
  }
93
  rem_node(NODE ifa);
94
  if(ifa->hello_sk!=NULL)
95
  {
96
    rfree(ifa->hello_sk);
97
  }
98
  if(ifa->dr_sk!=NULL)
99
  {
100
    rfree(ifa->dr_sk);
101
  }
102
  if(ifa->ip_sk!=NULL)
103
  {
104
    rfree(ifa->ip_sk);
105
  }
106
  if(ifa->wait_timer!=NULL)
107
  {
108
    tm_stop(ifa->wait_timer);
109
    rfree(ifa->wait_timer);
110
  }
111
  if(ifa->hello_timer!=NULL)
112
  {
113
    tm_stop(ifa->hello_timer);
114
    rfree(ifa->hello_timer);
115
  }
116
  rfree(ifa->lock);
117
  mb_free(ifa);
118
}
119

    
120
void
121
ospf_int_sm(struct ospf_iface *ifa, int event)
122
{
123
  struct proto *p=(struct proto *)(ifa->proto);
124
  struct proto_ospf *po=ifa->proto;
125
  struct ospf_area *oa=ifa->oa;
126

    
127
  debug("%s: SM on iface %s. Event is \"%s\".\n",
128
    p->name, ifa->iface->name, ospf_ism[event]);
129

    
130
  switch(event)
131
  {
132
    case ISM_UP:
133
      if(ifa->state==OSPF_IS_DOWN)
134
      {
135
        /* Now, nothing should be adjacent */
136
        restart_hellotim(ifa);
137
        if((ifa->type==OSPF_IT_PTP) || (ifa->type==OSPF_IT_VLINK))
138
        {
139
          iface_chstate(ifa, OSPF_IS_PTP);
140
        }
141
        else
142
        {
143
          if(ifa->priority==0)
144
          {
145
            iface_chstate(ifa, OSPF_IS_DROTHER);
146
          } 
147
          else
148
          {
149
             iface_chstate(ifa, OSPF_IS_WAITING);
150
             restart_waittim(ifa);
151
          }
152
        }
153
        addifa_rtlsa(ifa);
154
      }
155
      schedule_rt_lsa(ifa->oa);
156
      break;
157
    case ISM_BACKS:
158
    case ISM_WAITF:
159
      if(ifa->state==OSPF_IS_WAITING)
160
      {
161
        bdr_election(ifa ,p);
162
      }
163
      break;
164
    case ISM_NEICH:
165
      if((ifa->state==OSPF_IS_DROTHER) || (ifa->state==OSPF_IS_DR) ||
166
        (ifa->state==OSPF_IS_BACKUP))
167
      {
168
        bdr_election(ifa ,p);
169
        schedule_rt_lsa(ifa->oa);
170
      }
171
      break;
172
    case ISM_DOWN:
173
      iface_chstate(ifa, OSPF_IS_DOWN);
174
      downint(ifa);
175
      schedule_rt_lsa(oa);
176
      break;
177
    case ISM_LOOP:        /* Useless? */
178
      iface_chstate(ifa, OSPF_IS_LOOP);
179
      downint(ifa);
180
      schedule_rt_lsa(ifa->oa);
181
      break;
182
    case ISM_UNLOOP:
183
      iface_chstate(ifa, OSPF_IS_DOWN);
184
      schedule_rt_lsa(ifa->oa);
185
      break;
186
    default:
187
      bug("%s: ISM - Unknown event?",p->name);
188
      break;
189
  }
190
        
191
}
192

    
193
sock *
194
ospf_open_mc_socket(struct ospf_iface *ifa)
195
{
196
  sock *mcsk;
197
  struct proto *p;
198

    
199
  p=(struct proto *)(ifa->proto);
200

    
201
  mcsk=sk_new(p->pool);
202
  mcsk->type=SK_IP_MC;
203
  mcsk->dport=OSPF_PROTO;
204
  mcsk->saddr=AllSPFRouters;
205
  mcsk->daddr=AllSPFRouters;
206
  mcsk->tos=IP_PREC_INTERNET_CONTROL;
207
  mcsk->ttl=1;
208
  mcsk->rx_hook=ospf_rx_hook;
209
  mcsk->tx_hook=ospf_tx_hook;
210
  mcsk->err_hook=ospf_err_hook;
211
  mcsk->iface=ifa->iface;
212
  mcsk->rbsize=ifa->iface->mtu;
213
  mcsk->tbsize=ifa->iface->mtu;
214
  mcsk->data=(void *)ifa;
215
  if(sk_open(mcsk)!=0)
216
  {
217
    DBG("%s: SK_OPEN: mc open failed.\n",p->name);
218
    return(NULL);
219
  }
220
  DBG("%s: SK_OPEN: mc opened.\n",p->name);
221
  return(mcsk);
222
}
223

    
224
sock *
225
ospf_open_ip_socket(struct ospf_iface *ifa)
226
{
227
  sock *ipsk;
228
  struct proto *p;
229

    
230
  p=(struct proto *)(ifa->proto);
231

    
232
  ipsk=sk_new(p->pool);
233
  ipsk->type=SK_IP;
234
  ipsk->dport=OSPF_PROTO;
235
  ipsk->saddr=ifa->iface->addr->ip;
236
  ipsk->tos=IP_PREC_INTERNET_CONTROL;
237
  ipsk->ttl=1;
238
  ipsk->rx_hook=ospf_rx_hook;
239
  ipsk->tx_hook=ospf_tx_hook;
240
  ipsk->err_hook=ospf_err_hook;
241
  ipsk->iface=ifa->iface;
242
  ipsk->rbsize=ifa->iface->mtu;
243
  ipsk->tbsize=ifa->iface->mtu;
244
  ipsk->data=(void *)ifa;
245
  if(sk_open(ipsk)!=0)
246
  {
247
    DBG("%s: SK_OPEN: ip open failed.\n",p->name);
248
    return(NULL);
249
  }
250
  DBG("%s: SK_OPEN: ip opened.\n",p->name);
251
  return(ipsk);
252
}
253

    
254
/* Of course, it's NOT true now */
255
u8
256
ospf_iface_clasify(struct iface *ifa, struct proto *p)
257
{
258
  DBG("%s: Iface flags=%x.\n", p->name, ifa->flags);
259
  if((ifa->flags & (IF_MULTIACCESS|IF_MULTICAST))==
260
    (IF_MULTIACCESS|IF_MULTICAST))
261
  {
262
     DBG("%s: Clasifying BCAST.\n", p->name);
263
     return OSPF_IT_BCAST;
264
  }
265
  if((ifa->flags & (IF_MULTIACCESS|IF_MULTICAST))==
266
    IF_MULTIACCESS)
267
  {
268
    DBG("%s: Clasifying NBMA.\n", p->name);
269
    return OSPF_IT_NBMA;
270
  }
271
  DBG("%s: Clasifying P-T-P.\n", p->name);
272
  return OSPF_IT_PTP;
273
}
274

    
275
struct ospf_iface*
276
find_iface(struct proto_ospf *p, struct iface *what)
277
{
278
  struct ospf_iface *i;
279

    
280
  WALK_LIST (i, p->iface_list)
281
    if ((i)->iface == what)
282
      return i;
283
  return NULL;
284
}
285

    
286
void
287
ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
288
{
289
  struct proto_ospf *po=(struct proto_ospf *)p;
290
  struct ospf_config *c=(struct ospf_config *)(p->cf);
291
  struct ospf_area_config *ac;
292
  struct ospf_iface_patt *ip=NULL;
293
  struct ospf_iface *ifa;
294
  struct object_lock *lock;
295

    
296
  DBG("%s: If notify called\n", p->name);
297
  if (iface->flags & IF_IGNORE)
298
    return;
299

    
300
  if(flags & IF_CHANGE_UP)
301
  {
302
    debug("%s: using interface %s.\n", p->name, iface->name);
303
    WALK_LIST(ac, c->area_list)
304
    {
305
      if(ip=(struct ospf_iface_patt *)
306
        iface_patt_match(&ac->patt_list, iface)) break;
307
    }
308

    
309
    if(ip)
310
    {
311
      lock = olock_new( p->pool );
312
      lock->addr = AllSPFRouters;
313
      lock->type = OBJLOCK_UDP;
314
      lock->port = OSPF_PROTO;
315
      lock->iface = iface;
316
      lock->data = p;
317
      lock->hook = ospf_ifa_add;
318
      olock_acquire(lock);
319
    }
320
  }
321

    
322
  if(flags & IF_CHANGE_DOWN)
323
  {
324
    if((ifa=find_iface((struct proto_ospf *)p, iface))!=NULL)
325
    {
326
      debug("%s: killing interface %s.\n", p->name, iface->name);
327
      ospf_int_sm(ifa, ISM_DOWN);
328
    }
329
  }
330

    
331
  if(flags & IF_CHANGE_MTU)
332
  {
333
    if((ifa=find_iface((struct proto_ospf *)p, iface))!=NULL)
334
    {
335
      debug("%s: changing MTU on interface %s.\n", p->name, iface->name);
336
      /* FIXME: change MTU */
337
    }
338
  }
339
}
340

    
341
void
342
ospf_iface_info(struct ospf_iface *ifa)
343
{
344
  int x;
345
  cli_msg(-1015,"Interface \"%s\":", ifa->iface->name);
346
  cli_msg(-1015,"\tArea: %I (%u)", ifa->oa->areaid, ifa->oa->areaid);
347
  cli_msg(-1015,"\tType: %s", ospf_it[ifa->type]);
348
  cli_msg(-1015,"\tState: %s", ospf_is[ifa->state]);
349
  cli_msg(-1015,"\tPriority: %u", ifa->priority);
350
  cli_msg(-1015,"\tCost: %u", ifa->cost);
351
  cli_msg(-1015,"\tHello timer: %u", ifa->helloint);
352
  cli_msg(-1015,"\tWait timer: %u", ifa->waitint);
353
  cli_msg(-1015,"\tDead timer: %u", ifa->deadc*ifa->helloint);
354
  cli_msg(-1015,"\tRetransmit timer: %u", ifa->rxmtint);
355
  if((ifa->type==OSPF_IT_BCAST)||(ifa->type==OSPF_IT_NBMA))
356
  {
357
    cli_msg(-1015,"\tDesigned router (ID): %I", ifa->drid);
358
    cli_msg(-1015,"\tDesigned router (IP): %I", ifa->drip);
359
    cli_msg(-1015,"\tBackup designed router (ID): %I", ifa->bdrid);
360
    cli_msg(-1015,"\tBackup designed router (IP): %I", ifa->bdrip);
361
  }
362
}
363

    
364
void
365
ospf_ifa_add(struct object_lock *lock)
366
{
367
  struct proto_ospf *po=lock->data;
368
  struct iface *iface=lock->iface;
369
  struct proto *p=&po->proto;
370
  struct nbma_node *nbma,*nb;
371
  u8 i;
372
  sock *mcsk;
373
  struct ospf_iface *ifa;
374
  struct ospf_config *c=(struct ospf_config *)(p->cf);
375
  struct ospf_area_config *ac;
376
  struct ospf_iface_patt *ip=NULL;
377

    
378
  WALK_LIST(ac, c->area_list)
379
  {
380
    if(ip=(struct ospf_iface_patt *)
381
      iface_patt_match(&ac->patt_list, iface)) break;
382
  }
383

    
384
  if(!ip)
385
  {
386
    bug("After lock I cannot find pattern.");
387
  }
388

    
389
  ifa=mb_allocz(p->pool, sizeof(struct ospf_iface));
390
  ifa->proto=po;
391
  ifa->iface=iface;
392

    
393
  ifa->an=ac->areaid;
394
  ifa->cost=ip->cost;
395
  ifa->rxmtint=ip->rxmtint;
396
  ifa->inftransdelay=ip->inftransdelay;
397
  ifa->priority=ip->priority;
398
  ifa->helloint=ip->helloint;
399
  ifa->waitint=ip->waitint;
400
  ifa->deadc=ip->deadc;
401
  ifa->autype=0;        /* FIXME add authentification */
402
  for(i=0;i<8;i++) ifa->aukey[i]=0;
403
  ifa->options=2;        /* FIXME what options? */
404

    
405
  if(ip->type==OSPF_IT_UNDEF)
406
    ifa->type=ospf_iface_clasify(ifa->iface, (struct proto *)ifa->proto);
407
  else ifa->type=ip->type;
408

    
409
  if(ifa->type!=OSPF_IT_NBMA)
410
  {
411
    if((ifa->hello_sk=ospf_open_mc_socket(ifa))==NULL)
412
    {
413
      log("%s: Huh? could not open mc socket on interface %s?", p->name,
414
        iface->name);
415
          mb_free(ifa);
416
          log("%s: Ignoring this interface.", p->name);
417
          rfree(lock);
418
          return;
419
    }
420
    ifa->dr_sk=NULL;
421
  }
422

    
423
  if((ifa->ip_sk=ospf_open_ip_socket(ifa))==NULL)
424
  {
425
    log("%s: Huh? could not open ip socket on interface %s?", p->name,
426
      iface->name);
427
        mb_free(ifa);
428
        log("%s: Ignoring this interface", p->name);
429
        rfree(lock);
430
        return;
431
  }
432
  ifa->lock = lock;
433

    
434
  init_list(&ifa->neigh_list);
435
  init_list(&ifa->nbma_list);
436
  WALK_LIST(nb,ip->nbma_list)
437
  {
438
    nbma=mb_alloc(p->pool,sizeof(struct nbma_node));
439
    nbma->ip=nb->ip;
440
    add_tail(&ifa->nbma_list, NODE nbma);
441
  }
442
  
443
  /* Add hello timer */
444
  ifa->hello_timer=tm_new(p->pool);
445
  ifa->hello_timer->data=ifa;
446
  ifa->hello_timer->randomize=0;
447
  ifa->hello_timer->hook=hello_timer_hook;
448
  ifa->hello_timer->recurrent=ifa->helloint;
449
  DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
450

    
451
  ifa->wait_timer=tm_new(p->pool);
452
  ifa->wait_timer->data=ifa;
453
  ifa->wait_timer->randomize=0;
454
  ifa->wait_timer->hook=wait_timer_hook;
455
  ifa->wait_timer->recurrent=0;
456
  DBG("%s: Installing wait timer. (%u)\n", p->name, ifa->waitint);
457
  add_tail(&((struct proto_ospf *)p)->iface_list, NODE ifa);
458
  ifa->state=OSPF_IS_DOWN;
459
  ospf_int_sm(ifa, ISM_UP);
460
}