Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / dbdes.c @ 44724025

History | View | Annotate | Download (8.62 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 %I.\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==STAIL(n->ifa->oa->lsal))
80
            {
81
              break;        /* Should set some flag? */
82
              }
83
            sn=sn->next;
84
            lsa++;
85
          }
86
          i--;
87

    
88
          if(sn==STAIL(n->ifa->oa->lsal))
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 to %I.\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: %I.\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
      /* FIXME and the next part of condition? */
203
    }
204
  }
205
}
206

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

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

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

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

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

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

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

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

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

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

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

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

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

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