Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / dbdes.c @ 9669362f

History | View | Annotate | Download (8.57 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
void
12
ospf_dbdes_tx(struct ospf_neighbor *n)
13
{
14
  struct ospf_dbdes_packet *pkt;
15
  struct ospf_packet *op;
16
  struct ospf_iface *ifa;
17
  u16 length;
18
  struct proto *p;
19
  u16 i,j;
20
  u8 *aa,*bb;
21

    
22
  ifa=n->ifa;
23

    
24
  p=(struct proto *)(ifa->proto);
25

    
26
  switch(n->state)
27
  {
28
    case NEIGHBOR_EXSTART:                /* Send empty packets */
29
      n->myimms.bit.i=1;
30
      pkt=(struct ospf_dbdes_packet *)(ifa->ip_sk->tbuf);
31
      op=(struct ospf_packet *)pkt;
32
      fill_ospf_pkt_hdr(ifa, pkt, DBDES);
33
      pkt->iface_mtu=htons(ifa->iface->mtu);        /*FIXME NOT for VLINK! */
34
      pkt->options= ifa->options;
35
      pkt->imms=n->myimms;
36
      pkt->ddseq=htonl(n->dds);
37
      length=sizeof(struct ospf_dbdes_packet);
38
      op->length=htons(length);
39
      ospf_pkt_finalize(ifa, op);
40
      sk_send_to(ifa->ip_sk,length, n->ip, OSPF_PROTO);
41
      debug("%s: DB_DES (I) sent to %I.\n", p->name, n->rid);
42
      break;
43

    
44
    case NEIGHBOR_EXCHANGE:
45
      n->myimms.bit.i=0;
46

    
47
      if(((n->myimms.bit.ms) && (n->dds==n->ddr+1)) ||
48
         ((!(n->myimms.bit.ms)) && (n->dds==n->ddr)))
49
      {
50
        snode *sn;                        /* Send next */
51
        struct ospf_lsa_header *lsa;
52

    
53
        pkt=n->ldbdes;
54
        op=(struct ospf_packet *)pkt;
55
        
56
        fill_ospf_pkt_hdr(ifa, pkt, DBDES);
57
        pkt->iface_mtu=htons(ifa->iface->mtu);
58
        pkt->options= ifa->options;
59
        pkt->ddseq=htonl(n->dds);
60

    
61
        j=i=(ifa->iface->mtu-sizeof(struct ospf_dbdes_packet)-SIPH)/
62
                sizeof(struct ospf_lsa_header);        /* Number of lsaheaders */
63
        lsa=(n->ldbdes+sizeof(struct ospf_dbdes_packet));
64

    
65
        if(n->myimms.bit.m)
66
        {
67
          sn=s_get(&(n->dbsi));
68

    
69
          DBG("Number of LSA: %d\n", j);
70
          for(;i>0;i--)
71
          {
72
            struct top_hash_entry *en;
73
          
74
            en=(struct top_hash_entry *)sn;
75
            htonlsah(&(en->lsa), lsa);
76
            DBG("Working on: %d\n", i);
77
            DBG("\tX%01x %08I %08I %p\n", en->lsa.type, en->lsa.id,
78
              en->lsa.rt, en->lsa_body);
79

    
80
            if(sn==STAIL(n->ifa->oa->lsal))
81
            {
82
              break;        /* Should set some flag? */
83
              i--;
84
              }
85
            sn=sn->next;
86
            lsa++;
87
          }
88

    
89
          if(sn==STAIL(n->ifa->oa->lsal))
90
          {
91
            DBG("Number of LSA NOT sent: %d\n", i);
92
            DBG("M bit unset.\n");
93
            n->myimms.bit.m=0;        /* Unset more bit */
94
          }
95
          else s_put(&(n->dbsi),sn);
96
        }
97

    
98
        pkt->imms.byte=n->myimms.byte;
99

    
100
        length=(j-i)*sizeof(struct ospf_lsa_header)+
101
                sizeof(struct ospf_dbdes_packet);
102
        op->length=htons(length);
103
        
104
        ospf_pkt_finalize(ifa, op);
105
        DBG("%s: DB_DES (M) sent to %I.\n", p->name, n->rid);
106
      }
107

    
108
    case NEIGHBOR_LOADING:
109
    case NEIGHBOR_FULL:
110
      aa=ifa->ip_sk->tbuf;
111
      bb=n->ldbdes;
112
      op=n->ldbdes;
113
      length=ntohs(op->length);
114

    
115
      for(i=0; i<length; i++)
116
      {
117
        *(aa+i)=*(bb+i);        /* Copy last sent packet again */
118
      }
119

    
120
      DBG("%s: DB_DES sending to %I.\n", p->name, n->rid);
121
      sk_send_to(ifa->ip_sk,length, n->ip, OSPF_PROTO);
122
      debug("%s: DB_DES (M) sent to %I.\n", p->name, n->rid);
123
      if(n->myimms.bit.ms) tm_start(n->rxmt_timer,ifa->rxmtint);
124
      else
125
      {
126
        if((n->myimms.bit.m==0) && (n->imms.bit.m==0) &&
127
          (n->state==NEIGHBOR_EXCHANGE))
128
        {
129
          ospf_neigh_sm(n, INM_EXDONE);
130
          if(n->myimms.bit.ms) tm_stop(n->rxmt_timer);
131
          else tm_start(n->rxmt_timer,ifa->rxmtint);
132
        }
133
      }
134
      break;
135

    
136
    default:                                /* Ignore it */
137
      die("Bug in dbdes sending\n");
138
      break;
139
  }
140
}
141

    
142
void
143
rxmt_timer_hook(timer *timer)
144
{
145
  struct ospf_iface *ifa;
146
  struct proto *p;
147
  struct ospf_neighbor *n;
148

    
149
  n=(struct ospf_neighbor *)timer->data;
150
  ifa=n->ifa;
151
  p=(struct proto *)(ifa->proto);
152
  DBG("%s: RXMT timer fired on interface %s for neigh: %I.\n",
153
    p->name, ifa->iface->name, n->rid);
154
  if(n->state<NEIGHBOR_LOADING) ospf_dbdes_tx(n);
155
  else
156
  {
157
    tm_stop(n->rxmt_timer);
158
           /* FIXME I should dealloc ldbdes */
159
  }
160
}
161

    
162
void
163
ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct proto *p,
164
  struct ospf_neighbor *n)
165
{
166
  struct ospf_lsa_header *plsa,lsa;
167
  struct top_hash_entry *he,*sn;
168
  struct top_graph *gr;
169
  struct ospf_packet *op;
170
  int i,j;
171

    
172
  gr=n->ifa->oa->gr;
173
  op=(struct ospf_packet *)ps;
174

    
175
  plsa=(void *)(ps+1);
176

    
177
  j=(ntohs(op->length)-sizeof(struct ospf_dbdes_packet))/
178
    sizeof( struct ospf_lsa_header);
179

    
180
  for(i=0;i<j;i++)
181
  {
182
    ntohlsah(plsa+i, &lsa);
183
    if(((he=ospf_hash_find(gr,lsa.id,lsa.rt,lsa.type))==NULL)||
184
      (lsa_comp(&lsa, &(he->lsa))==1))
185
    {
186
      /* Is this condition necessary? */
187
      if(ospf_hash_find(n->lsrqh,lsa.id,lsa.rt,lsa.type)==NULL)
188
      {
189
        sn=ospf_hash_get(n->lsrqh,lsa.id,lsa.rt,lsa.type);
190
        ntohlsah(plsa+i, &(sn->lsa));
191
        s_add_tail(&(n->lsrql), SNODE sn);
192
      }
193
      /* FIXME and the next part of condition? */
194
    }
195
  }
196
}
197

    
198
void
199
ospf_dbdes_rx(struct ospf_dbdes_packet *ps, struct proto *p,
200
  struct ospf_iface *ifa, u16 size)
201
{
202
  u32 nrid, myrid;
203
  struct ospf_neighbor *n;
204
  u8 i;
205

    
206
  nrid=ntohl(((struct ospf_packet *)ps)->routerid);
207

    
208
  myrid=p->cf->global->router_id;
209

    
210
  if((n=find_neigh(ifa, nrid))==NULL)
211
  {
212
    debug("%s: Received dbdes from unknown neigbor! (%I)\n", p->name,
213
      nrid);
214
    return ;
215
  }
216

    
217
  if(ifa->iface->mtu<size)
218
  {
219
    debug("%s: Received dbdes larger than MTU from (%I)!\n", p->name, nrid);
220
    return ;
221
  }
222

    
223
  switch(n->state)
224
  {
225
    case NEIGHBOR_DOWN:
226
    case NEIGHBOR_ATTEMPT:
227
    case NEIGHBOR_2WAY:
228
        debug("%s: Received dbdes from %I in bad state.\n", p->name, nrid);
229
        return;
230
      break;
231
    case NEIGHBOR_INIT:
232
        ospf_neigh_sm(n, INM_2WAYREC);
233
        if(n->state!=NEIGHBOR_EXSTART) return;
234
    case NEIGHBOR_EXSTART:
235
        if((ps->imms.bit.m && ps->imms.bit.ms && ps->imms.bit.i)
236
          && (n->rid > myrid) &&
237
          (size == sizeof(struct ospf_dbdes_packet)))
238
        {
239
          /* I'm slave! */
240
          n->dds=ntohl(ps->ddseq);
241
          n->ddr=ntohl(ps->ddseq);
242
          n->options=ps->options;
243
          n->myimms.bit.ms=0;
244
          n->imms.byte=ps->imms.byte;
245
          debug("%s: I'm slave to %I. \n", p->name, nrid);
246
          ospf_neigh_sm(n, INM_NEGDONE);
247
          tm_stop(n->rxmt_timer);
248
          ospf_dbdes_tx(n);
249
          break;
250
        }
251
        else
252
        {
253
          if(((ps->imms.bit.i==0) && (ps->imms.bit.ms==0)) &&
254
            (n->rid < myrid) && (n->dds == ntohl(ps->ddseq)))
255
          {
256
            /* I'm master! */
257
            n->options=ps->options;
258
            n->ddr=ntohl(ps->ddseq)-1;
259
            n->imms.byte=ps->imms.byte;
260
            debug("%s: I'm master to %I. \n", p->name, nrid);
261
            ospf_neigh_sm(n, INM_NEGDONE);
262
          }
263
          else
264
          {
265
            DBG("%s: Nothing happend to %I (imms=%u)\n", p->name, nrid,
266
              ps->imms.byte);
267
            break;
268
          }
269
        }
270
    case NEIGHBOR_EXCHANGE:
271
        if((ps->imms.byte==n->imms.byte) && (ps->options=n->options) &&
272
          (ntohl(ps->ddseq)==n->ddr))
273
        {
274
          /* Duplicate packet */
275
          debug("%s: Received duplicate dbdes from (%I)!\n", p->name, nrid);
276
          if(n->imms.bit.ms==0)
277
          {
278
            ospf_dbdes_tx(n);
279
          }
280
          return;
281
        }
282

    
283
        n->ddr=ntohl(ps->ddseq);
284

    
285
        if(ps->imms.bit.ms!=n->imms.bit.ms) /* M/S bit differs */
286
        {
287
          DBG("SEQMIS-BIT-MS\n");
288
          ospf_neigh_sm(n, INM_SEQMIS);
289
          break;
290
        }
291

    
292
        if(ps->imms.bit.i)        /* I bit is set */
293
        {
294
          DBG("SEQMIS-BIT-I\n");
295
          ospf_neigh_sm(n, INM_SEQMIS);
296
          break;
297
        }
298

    
299
        n->imms.byte=ps->imms.byte;
300

    
301
        if(ps->options!=n->options)        /* Options differs */
302
        {
303
          DBG("SEQMIS-OPT\n");
304
          ospf_neigh_sm(n, INM_SEQMIS);
305
          break;
306
        }
307

    
308
        if(n->myimms.bit.ms)
309
        {
310
          if(ntohl(ps->ddseq)!=n->dds)                /* MASTER */
311
          {
312
            DBG("SEQMIS-MASTER\n");
313
            ospf_neigh_sm(n, INM_SEQMIS);
314
            break;
315
          }
316
          n->dds++;
317
          DBG("Incrementing dds\n");
318
          ospf_dbdes_reqladd(ps,p,n);
319
          if((n->myimms.bit.m==0) && (ps->imms.bit.m==0))
320
          {
321
            ospf_neigh_sm(n, INM_EXDONE);
322
          }
323
          else
324
          {
325
            ospf_dbdes_tx(n);
326
          }
327

    
328
        }
329
        else
330
        {
331
          if(ntohl(ps->ddseq)!=(n->dds+1))        /* SLAVE */
332
          {
333
            DBG("SEQMIS-SLAVE\n");
334
            ospf_neigh_sm(n, INM_SEQMIS);
335
            break;
336
          }
337
          n->ddr=ntohl(ps->ddseq);
338
          n->dds=ntohl(ps->ddseq);
339
          ospf_dbdes_reqladd(ps,p,n);
340
          ospf_dbdes_tx(n);
341
        }
342

    
343
      break;
344
    case NEIGHBOR_LOADING:
345
    case NEIGHBOR_FULL:
346
        if((ps->imms.byte==n->imms.byte) && (ps->options=n->options) &&
347
          (ps->ddseq==n->dds)) /* Only duplicate are accepted */
348
        {
349
          debug("%s: Received duplicate dbdes from (%I)!\n", p->name, nrid);
350
          return;
351
        }
352
        else
353
        {
354
          ospf_neigh_sm(n, INM_SEQMIS);
355
        }
356
      break;
357
    defaut:
358
      die("%s: Received dbdes from %I in unknown state.\n", p->name, nrid);
359
      break;
360
   }
361
}
362