Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / dbdes.c @ 394acced

History | View | Annotate | Download (8.56 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 for %u.\n", p->name, n->rid);
42
      break;
43

    
44
    case NEIGHBOR_EXCHANGE:
45
      n->myimms.bit.i=0;
46
      if(((n->myimms.bit.ms) && (n->dds==n->ddr+1)) ||
47
         ((!(n->myimms.bit.ms)) && (n->dds==n->ddr)))
48
      {
49
        snode *sn;                        /* Send next */
50
        struct ospf_lsa_header *lsa;
51

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

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

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

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

    
79
            if(sn->next==NULL)
80
            {
81
              break;        /* Should set some flag? */
82
              }
83
            sn=sn->next;
84
            lsa++;
85
          }
86
          i--;
87

    
88
          if(sn->next==NULL)
89
          {
90
            DBG("Number of LSA NOT sent: %d\n", i);
91
            DBG("M bit unset.\n");
92
            n->myimms.bit.m=0;        /* Unset more bit */
93
          }
94

    
95
          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
      }
106

    
107
    case NEIGHBOR_LOADING:
108
    case NEIGHBOR_FULL:
109

    
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<ifa->iface->mtu; i++)
116
      {
117
        *(aa+i)=*(bb+i);        /* Copy last sent packet again */
118
      }
119

    
120
      {
121
        u8 ii;
122
        u8 *jj=ifa->ip_sk->tbuf;
123

    
124
        for(ii=0;ii<length;ii+=4)
125
        {
126
          DBG("Out dump: %d,%d,%d,%d\n", *(jj+ii), *(jj+ii+1), *(jj+ii+2), *(jj+ii+3));
127
        }
128
      }
129

    
130
      sk_send_to(ifa->ip_sk,length, n->ip, OSPF_PROTO);
131
      debug("%s: DB_DES sent for %u.\n", p->name, n->rid);
132
      if(n->myimms.bit.ms) tm_start(n->rxmt_timer,ifa->rxmtint);
133
      else
134
      {
135
        if((n->myimms.bit.m==0) && (n->imms.bit.m==0) &&
136
          (n->state==NEIGHBOR_EXCHANGE))
137
        {
138
          ospf_neigh_sm(n, INM_EXDONE);
139
          if(n->myimms.bit.ms) tm_stop(n->rxmt_timer);
140
          else tm_start(n->rxmt_timer,ifa->rxmtint);
141
        }
142
      }
143
      break;
144

    
145
    default:                                /* Ignore it */
146
      die("Bug in dbdes sending\n");
147
      break;
148
  }
149
}
150

    
151
void
152
rxmt_timer_hook(timer *timer)
153
{
154
  struct ospf_iface *ifa;
155
  struct proto *p;
156
  struct ospf_neighbor *n;
157

    
158
  n=(struct ospf_neighbor *)timer->data;
159
  ifa=n->ifa;
160
  p=(struct proto *)(ifa->proto);
161
  debug("%s: RXMT timer fired on interface %s for neigh: %u.\n",
162
    p->name, ifa->iface->name, n->rid);
163
  if(n->state<NEIGHBOR_LOADING) ospf_dbdes_tx(n);
164
  else
165
  {
166
    tm_stop(n->rxmt_timer);
167
           /* FIXME I should dealloc ldbdes */
168
  }
169
}
170

    
171
void
172
ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct proto *p,
173
  struct ospf_neighbor *n)
174
{
175
  struct ospf_lsa_header *plsa,lsa;
176
  struct top_hash_entry *he,*sn;
177
  struct top_graph *gr;
178
  struct ospf_packet *op;
179
  int i,j;
180

    
181
  gr=n->ifa->oa->gr;
182
  op=(struct ospf_packet *)ps;
183

    
184
  plsa=(void *)(ps+1);
185

    
186
  j=(ntohs(op->length)-sizeof(struct ospf_dbdes_packet))/
187
    sizeof( struct ospf_lsa_header);
188

    
189
  for(i=0;i<j;i++)
190
  {
191
    ntohlsah(plsa+i, &lsa);
192
    if(((he=ospf_hash_find(gr,lsa.id,lsa.rt,lsa.type))==NULL)||
193
      (lsa_comp(&lsa, &(he->lsa))==1))
194
    {
195
      /* Is this condition necessary? */
196
      if(ospf_hash_find(n->lsrqh,lsa.id,lsa.rt,lsa.type)==NULL)
197
      {
198
        sn=ospf_hash_get(n->lsrqh,lsa.id,lsa.rt,lsa.type);
199
        ntohlsah(plsa+i, &(sn->lsa));
200
        s_add_tail(&(n->lsrql), SNODE sn);
201
      }
202
    }
203
  }
204
}
205

    
206
void
207
ospf_dbdes_rx(struct ospf_dbdes_packet *ps, struct proto *p,
208
  struct ospf_iface *ifa, u16 size)
209
{
210
  u32 nrid, myrid;
211
  struct ospf_neighbor *n;
212
  u8 i;
213

    
214
  nrid=ntohl(((struct ospf_packet *)ps)->routerid);
215

    
216
  myrid=p->cf->global->router_id;
217

    
218
  if((n=find_neigh(ifa, nrid))==NULL)
219
  {
220
    debug("%s: Received dbdes from unknown neigbor! (%u)\n", p->name,
221
      nrid);
222
    return ;
223
  }
224

    
225
  if(ifa->iface->mtu<size)
226
  {
227
    debug("%s: Received dbdes larger than MTU from (%u)!\n", p->name, nrid);
228
    return ;
229
  }
230

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

    
291
        n->ddr=ntohl(ps->ddseq);
292

    
293
        if(ps->imms.bit.ms!=n->imms.bit.ms) /* M/S bit differs */
294
        {
295
          DBG("SEQMIS-BIT-MS\n");
296
          ospf_neigh_sm(n, INM_SEQMIS);
297
          break;
298
        }
299

    
300
        if(ps->imms.bit.i)        /* I bit is set */
301
        {
302
          DBG("SEQMIS-BIT-I\n");
303
          ospf_neigh_sm(n, INM_SEQMIS);
304
          break;
305
        }
306

    
307
        n->imms.byte=ps->imms.byte;
308

    
309
        if(ps->options!=n->options)        /* Options differs */
310
        {
311
          DBG("SEQMIS-OPT\n");
312
          ospf_neigh_sm(n, INM_SEQMIS);
313
          break;
314
        }
315

    
316
        if(n->myimms.bit.ms)
317
        {
318
          if(ntohl(ps->ddseq)!=n->dds)                /* MASTER */
319
          {
320
            DBG("SEQMIS-MASTER\n");
321
            ospf_neigh_sm(n, INM_SEQMIS);
322
            break;
323
          }
324
          n->dds++;
325
          DBG("Incrementing dds\n");
326
          ospf_dbdes_reqladd(ps,p,n);
327
          if((n->myimms.bit.m==0) && (ps->imms.bit.m==0))
328
          {
329
            ospf_neigh_sm(n, INM_EXDONE);
330
          }
331
          else
332
          {
333
            ospf_dbdes_tx(n);
334
          }
335

    
336
        }
337
        else
338
        {
339
          if(ntohl(ps->ddseq)!=(n->dds+1))        /* SLAVE */
340
          {
341
            DBG("SEQMIS-SLAVE\n");
342
            ospf_neigh_sm(n, INM_SEQMIS);
343
            break;
344
          }
345
          n->ddr=ntohl(ps->ddseq);
346
          n->dds=ntohl(ps->ddseq);
347
          ospf_dbdes_reqladd(ps,p,n);
348
          ospf_dbdes_tx(n);
349
        }
350

    
351
      break;
352
    case NEIGHBOR_LOADING:
353
    case NEIGHBOR_FULL:
354
        if((ps->imms.byte==n->imms.byte) && (ps->options=n->options) &&
355
          (ps->ddseq==n->dds)) /* Only duplicate are accepted */
356
        {
357
          debug("%s: Received duplicate dbdes from (%u)!\n", p->name, nrid);
358
          return;
359
        }
360
        else
361
        {
362
          ospf_neigh_sm(n, INM_SEQMIS);
363
        }
364
      break;
365
    defaut:
366
      die("%s: Received dbdes from %u in unknown state. (%u)\n", p->name, nrid);
367
      break;
368
   }
369
}
370