Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (8.65 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=n->ifa;
17
  u16 length;
18
  struct proto *p;
19
  u16 i,j;
20
  u8 *aa,*bb;
21

    
22
  p=(struct proto *)(ifa->proto);
23

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

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

    
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_P);
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)-SIPH)/
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
            DBG("\tX%01x %08I %08I %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
              i--;
82
              break;        /* Should set some flag? */
83
              }
84
            sn=sn->next;
85
            lsa++;
86
          }
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
          else s_put(&(n->dbsi),sn);
95
        }
96

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
222
  debug("%s: Received dbdes from %I via %s.\n", p->name, n->ip,
223
    ifa->iface->name);
224

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

    
285
        n->ddr=ntohl(ps->ddseq);
286

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

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

    
301
        n->imms.byte=ps->imms.byte;
302

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

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

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

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