Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (10.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_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 *p;
23

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

    
69
void
70
downint(struct ospf_iface *ifa)
71
{
72
  struct ospf_neighbor *n,*nx;
73
  struct proto *p=&ifa->proto->proto;
74
  struct proto_ospf *po=ifa->proto;
75

    
76
  WALK_LIST_DELSAFE(n,nx,ifa->neigh_list)
77
  {
78
    debug("%s: Removing neighbor %I\n", p->name, n->ip);
79
    ospf_neigh_remove(n);
80
  }
81
  rem_node(NODE ifa);
82
  if(ifa->hello_sk!=NULL)
83
  {
84
    rfree(ifa->hello_sk);
85
  }
86
  if(ifa->dr_sk!=NULL)
87
  {
88
    rfree(ifa->dr_sk);
89
  }
90
  if(ifa->ip_sk!=NULL)
91
  {
92
    rfree(ifa->ip_sk);
93
  }
94
  if(ifa->wait_timer!=NULL)
95
  {
96
    tm_stop(ifa->wait_timer);
97
    rfree(ifa->wait_timer);
98
  }
99
  if(ifa->hello_timer!=NULL)
100
  {
101
    tm_stop(ifa->hello_timer);
102
    rfree(ifa->hello_timer);
103
  }
104
  mb_free(ifa);
105
}
106

    
107
void
108
ospf_int_sm(struct ospf_iface *ifa, int event)
109
{
110
  struct proto *p=(struct proto *)(ifa->proto);
111
  struct proto_ospf *po=ifa->proto;
112
  struct ospf_area *oa=ifa->oa;
113

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

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

    
180
sock *
181
ospf_open_mc_socket(struct ospf_iface *ifa)
182
{
183
  sock *mcsk;
184
  struct proto *p;
185

    
186
  p=(struct proto *)(ifa->proto);
187

    
188
  mcsk=sk_new(p->pool);
189
  mcsk->type=SK_IP_MC;
190
  mcsk->dport=OSPF_PROTO;
191
  mcsk->saddr=AllSPFRouters;
192
  mcsk->daddr=AllSPFRouters;
193
  mcsk->tos=IP_PREC_INTERNET_CONTROL;
194
  mcsk->ttl=1;
195
  mcsk->rx_hook=ospf_rx_hook;
196
  mcsk->tx_hook=ospf_tx_hook;
197
  mcsk->err_hook=ospf_err_hook;
198
  mcsk->iface=ifa->iface;
199
  mcsk->rbsize=ifa->iface->mtu;
200
  mcsk->tbsize=ifa->iface->mtu;
201
  mcsk->data=(void *)ifa;
202
  if(sk_open(mcsk)!=0)
203
  {
204
    DBG("%s: SK_OPEN: mc open failed.\n",p->name);
205
    return(NULL);
206
  }
207
  DBG("%s: SK_OPEN: mc opened.\n",p->name);
208
  return(mcsk);
209
}
210

    
211
sock *
212
ospf_open_ip_socket(struct ospf_iface *ifa)
213
{
214
  sock *ipsk;
215
  struct proto *p;
216

    
217
  p=(struct proto *)(ifa->proto);
218

    
219
  ipsk=sk_new(p->pool);
220
  ipsk->type=SK_IP;
221
  ipsk->dport=OSPF_PROTO;
222
  ipsk->saddr=ifa->iface->addr->ip;
223
  ipsk->tos=IP_PREC_INTERNET_CONTROL;
224
  ipsk->ttl=1;
225
  ipsk->rx_hook=ospf_rx_hook;
226
  ipsk->tx_hook=ospf_tx_hook;
227
  ipsk->err_hook=ospf_err_hook;
228
  ipsk->iface=ifa->iface;
229
  ipsk->rbsize=ifa->iface->mtu;
230
  ipsk->tbsize=ifa->iface->mtu;
231
  ipsk->data=(void *)ifa;
232
  if(sk_open(ipsk)!=0)
233
  {
234
    DBG("%s: SK_OPEN: ip open failed.\n",p->name);
235
    return(NULL);
236
  }
237
  DBG("%s: SK_OPEN: ip opened.\n",p->name);
238
  return(ipsk);
239
}
240

    
241
/* 
242
 * This will later decide, wheter use iface for OSPF or not
243
 * depending on config
244
 */
245
u8
246
is_good_iface(struct proto *p, struct iface *iface)
247
{
248
  if(iface->flags & IF_UP)
249
  {
250
    if(!(iface->flags & IF_IGNORE)) return 1;
251
  }
252
  return 0;
253
}
254

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

    
277
void
278
ospf_add_timers(struct ospf_iface *ifa, pool *pool)
279
{
280
  struct proto *p;
281

    
282
  p=(struct proto *)(ifa->proto);
283
  /* Add hello timer */
284
  ifa->hello_timer=tm_new(pool);
285
  ifa->hello_timer->data=ifa;
286
  ifa->hello_timer->randomize=0;
287
  if(ifa->helloint==0) ifa->helloint=HELLOINT_D;
288
  ifa->hello_timer->hook=hello_timer_hook;
289
  ifa->hello_timer->recurrent=ifa->helloint;
290
  DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
291

    
292
  ifa->wait_timer=tm_new(pool);
293
  ifa->wait_timer->data=ifa;
294
  ifa->wait_timer->randomize=0;
295
  ifa->wait_timer->hook=wait_timer_hook;
296
  ifa->wait_timer->recurrent=0;
297
  if(ifa->waitint==0) ifa->waitint= WAIT_DMH*ifa->helloint;
298
  DBG("%s: Installing wait timer. (%u)\n", p->name, ifa->waitint);
299

    
300
  if(ifa->rxmtint==0) ifa->rxmtint=RXMTINT_D;
301
}
302

    
303
void
304
ospf_iface_default(struct ospf_iface *ifa)
305
{
306
  u8 i;
307

    
308
  ifa->oa=NULL;
309
  ifa->an=0;                /* FIXME This should respect config */
310
  ifa->cost=COST_D;
311
  ifa->rxmtint=RXMTINT_D;
312
  ifa->inftransdelay=INFTRANSDELAY_D;
313
  ifa->priority=PRIORITY_D;
314
  ifa->helloint=HELLOINT_D;
315
  ifa->deadc=DEADC_D;
316
  ifa->autype=0;
317
  for(i=0;i<8;i++) ifa->aukey[i]=0;
318
  ifa->options=2;
319
  ifa->drip=ipa_from_u32(0x00000000);
320
  ifa->drid=0;
321
  ifa->bdrip=ipa_from_u32(0x00000000);
322
  ifa->bdrid=0;
323
  ifa->type=ospf_iface_clasify(ifa->iface, (struct proto *)ifa->proto);
324
}
325

    
326
struct ospf_iface*
327
find_iface(struct proto_ospf *p, struct iface *what)
328
{
329
  struct ospf_iface *i;
330

    
331
  WALK_LIST (i, p->iface_list)
332
    if ((i)->iface == what)
333
      return i;
334
  return NULL;
335
}
336

    
337
void
338
ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
339
{
340
  struct ospf_iface *ifa;
341
  sock *mcsk;
342

    
343
  struct ospf_config *c;
344
  c=(struct ospf_config *)(p->cf);
345

    
346
  DBG("%s: If notify called\n", p->name);
347
  if (iface->flags & IF_IGNORE)
348
    return;
349

    
350
  if((flags & IF_CHANGE_UP) && is_good_iface(p, iface))
351
  {
352
    debug("%s: using interface %s.\n", p->name, iface->name);
353
    /* FIXME: Latter I'll use config - this is incorrect */
354
    ifa=mb_allocz(p->pool, sizeof(struct ospf_iface));
355
    ifa->proto=(struct proto_ospf *)p;
356
    ifa->iface=iface;
357
    ospf_iface_default(ifa);
358
    if(ifa->type!=OSPF_IT_NBMA)
359
    {
360
      if((ifa->hello_sk=ospf_open_mc_socket(ifa))==NULL)
361
      {
362
        log("%s: Huh? could not open mc socket on interface %s?", p->name,
363
          iface->name);
364
        mb_free(ifa);
365
        log("%s: Ignoring this interface.", p->name);
366
        return;
367
      }
368
      ifa->dr_sk=NULL;
369

    
370
      if((ifa->ip_sk=ospf_open_ip_socket(ifa))==NULL)
371
      {
372
        log("%s: Huh? could not open ip socket on interface %s?", p->name,
373
          iface->name);
374
        mb_free(ifa);
375
        log("%s: Ignoring this interface", p->name);
376
        return;
377
      }
378

    
379
      init_list(&(ifa->neigh_list));
380
    }
381
    /* FIXME: This should read config */
382
    ifa->helloint=0;
383
    ifa->waitint=0;
384
    ospf_add_timers(ifa,p->pool);
385
    add_tail(&((struct proto_ospf *)p)->iface_list, NODE ifa);
386
    ifa->state=OSPF_IS_DOWN;
387
    ifa->nlsa=NULL;
388
    ifa->fadj=0;
389
    ospf_int_sm(ifa, ISM_UP);
390
  }
391

    
392
  if(flags & IF_CHANGE_DOWN)
393
  {
394
    if((ifa=find_iface((struct proto_ospf *)p, iface))!=NULL)
395
    {
396
      debug("%s: killing interface %s.\n", p->name, iface->name);
397
      ospf_int_sm(ifa, ISM_DOWN);
398
    }
399
  }
400

    
401
  if(flags & IF_CHANGE_MTU)
402
  {
403
    if((ifa=find_iface((struct proto_ospf *)p, iface))!=NULL)
404
    {
405
      debug("%s: changing MTU on interface %s.\n", p->name, iface->name);
406
      /* FIXME: change MTU */
407
    }
408
  }
409
}
410

    
411
void
412
ospf_iface_info(struct ospf_iface *ifa)
413
{
414
  int x;
415
  cli_msg(-1015,"Interface \"%s\":", ifa->iface->name);
416
  cli_msg(-1015,"\tArea: %I (%u)", ifa->oa->areaid, ifa->oa->areaid);
417
  cli_msg(-1015,"\tType: %s", ospf_it[ifa->type]);
418
  cli_msg(-1015,"\tState: %s", ospf_is[ifa->state]);
419
  cli_msg(-1015,"\tPriority: %u", ifa->priority);
420
  cli_msg(-1015,"\tCost: %u", ifa->cost);
421
  cli_msg(-1015,"\tHello timer: %u", ifa->helloint);
422
  cli_msg(-1015,"\tWait timer: %u", ifa->waitint);
423
  cli_msg(-1015,"\tDead timer: %u", ifa->deadc*ifa->helloint);
424
  cli_msg(-1015,"\tRetransmit timer: %u", ifa->rxmtint);
425
  cli_msg(-1015,"\tDesigned router (ID): %I", ifa->drid);
426
  cli_msg(-1015,"\tDesigned router (IP): %I", ifa->drip);
427
  cli_msg(-1015,"\tBackup designed router (ID): %I", ifa->bdrid);
428
  cli_msg(-1015,"\tBackup designed router (IP): %I", ifa->bdrip);
429
}