Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (9.09 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
/**
12
 * ospf_dbdes_tx - transmit database description packet
13
 * @n: neighbor
14
 *
15
 * Sending of database description packet is described in 10.6 of RFC 2328.
16
 * Reception of each packet is acknoledged in sequence number of another.
17
 * When I send a packet to neighbor I keep a copy in buffer. If neighbor
18
 * does not reply, I don't create new packet but I just send content
19
 * of buffer.
20
 */
21
void
22
ospf_dbdes_tx(struct ospf_neighbor *n)
23
{
24
  struct ospf_dbdes_packet *pkt;
25
  struct ospf_packet *op;
26
  struct ospf_iface *ifa=n->ifa;
27
  struct ospf_area *oa=ifa->oa;
28
  u16 length;
29
  struct proto *p;
30
  u16 i,j;
31
  u8 *aa,*bb;
32

    
33
  if((oa->rt==NULL)||(EMPTY_LIST(oa->lsal))) originate_rt_lsa(oa);
34
    oa->origrt=0;
35

    
36

    
37
  p=(struct proto *)(ifa->proto);
38

    
39
  switch(n->state)
40
  {
41
    case NEIGHBOR_EXSTART:                /* Send empty packets */
42
      n->myimms.bit.i=1;
43
      pkt=(struct ospf_dbdes_packet *)(ifa->ip_sk->tbuf);
44
      op=(struct ospf_packet *)pkt;
45
      fill_ospf_pkt_hdr(ifa, pkt, DBDES_P);
46
      pkt->iface_mtu=htons(ifa->iface->mtu);        /* FIXME NOT for VLINK! */
47
      pkt->options= ifa->options;
48
      pkt->imms=n->myimms;
49
      pkt->ddseq=htonl(n->dds);
50
      length=sizeof(struct ospf_dbdes_packet);
51
      op->length=htons(length);
52
      ospf_pkt_finalize(ifa, op);
53
      sk_send_to(ifa->ip_sk,length, n->ip, OSPF_PROTO);
54
      OSPF_TRACE(D_PACKETS, "DB_DES (I) sent to %I via %s.", n->ip,
55
        ifa->iface->name);
56
      break;
57

    
58
    case NEIGHBOR_EXCHANGE:
59
      n->myimms.bit.i=0;
60

    
61
      if(((n->myimms.bit.ms) && (n->dds==n->ddr+1)) ||
62
         ((!(n->myimms.bit.ms)) && (n->dds==n->ddr)))
63
      {
64
        snode *sn;                        /* Send next */
65
        struct ospf_lsa_header *lsa;
66

    
67
        pkt=n->ldbdes;
68
        op=(struct ospf_packet *)pkt;
69
        
70
        fill_ospf_pkt_hdr(ifa, pkt, DBDES_P);
71
        pkt->iface_mtu=htons(ifa->iface->mtu);
72
        pkt->options= ifa->options;
73
        pkt->ddseq=htonl(n->dds);
74

    
75
        j=i=(ifa->iface->mtu-sizeof(struct ospf_dbdes_packet)-SIPH)/
76
                sizeof(struct ospf_lsa_header);        /* Number of lsaheaders */
77
        lsa=(n->ldbdes+sizeof(struct ospf_dbdes_packet));
78

    
79
        if(n->myimms.bit.m)
80
        {
81
          sn=s_get(&(n->dbsi));
82

    
83
          DBG("Number of LSA: %d\n", j);
84
          for(;i>0;i--)
85
          {
86
            struct top_hash_entry *en;
87
          
88
            en=(struct top_hash_entry *)sn;
89
            htonlsah(&(en->lsa), lsa);
90
            DBG("Working on: %d\n", i);
91
            DBG("\tX%01x %-1I %-1I %p\n", en->lsa.type, en->lsa.id,
92
              en->lsa.rt, en->lsa_body);
93

    
94
            if(sn==STAIL(n->ifa->oa->lsal))
95
            {
96
              i--;
97
              break;        /* Should set some flag? */
98
              }
99
            sn=sn->next;
100
            lsa++;
101
          }
102

    
103
          if(sn==STAIL(n->ifa->oa->lsal))
104
          {
105
            DBG("Number of LSA NOT sent: %d\n", i);
106
            DBG("M bit unset.\n");
107
            n->myimms.bit.m=0;        /* Unset more bit */
108
          }
109
          else s_put(&(n->dbsi),sn);
110
        }
111

    
112
        pkt->imms.byte=n->myimms.byte;
113

    
114
        length=(j-i)*sizeof(struct ospf_lsa_header)+
115
                sizeof(struct ospf_dbdes_packet);
116
        op->length=htons(length);
117
        
118
        ospf_pkt_finalize(ifa, op);
119
        DBG("%s: DB_DES (M) sent to %I.\n", p->name, n->ip);
120
      }
121

    
122
    case NEIGHBOR_LOADING:
123
    case NEIGHBOR_FULL:
124
      aa=ifa->ip_sk->tbuf;
125
      bb=n->ldbdes;
126
      op=n->ldbdes;
127
      length=ntohs(op->length);
128

    
129
      for(i=0; i<length; i++)
130
      {
131
        *(aa+i)=*(bb+i);        /* Copy last sent packet again */
132
      }
133

    
134
      sk_send_to(ifa->ip_sk,length, n->ip, OSPF_PROTO);
135
      OSPF_TRACE(D_PACKETS, "DB_DES (M) sent to %I via %s.", n->ip,
136
        ifa->iface->name);
137
      if(n->myimms.bit.ms) tm_start(n->rxmt_timer,ifa->rxmtint);
138
      else
139
      {
140
        if((n->myimms.bit.m==0) && (n->imms.bit.m==0) &&
141
          (n->state==NEIGHBOR_EXCHANGE))
142
        {
143
          ospf_neigh_sm(n, INM_EXDONE);
144
          if(n->myimms.bit.ms) tm_stop(n->rxmt_timer);
145
          else tm_start(n->rxmt_timer,ifa->rxmtint);
146
        }
147
      }
148
      break;
149

    
150
    default:                                /* Ignore it */
151
      bug("Bug in dbdes sending");
152
      break;
153
  }
154
}
155

    
156
void
157
rxmt_timer_hook(timer *timer)
158
{
159
  struct ospf_iface *ifa;
160
  struct proto *p;
161
  struct ospf_neighbor *n;
162

    
163
  n=(struct ospf_neighbor *)timer->data;
164
  ifa=n->ifa;
165
  p=(struct proto *)(ifa->proto);
166
  DBG("%s: RXMT timer fired on interface %s for neigh: %I.\n",
167
    p->name, ifa->iface->name, n->ip);
168
  if(n->state<NEIGHBOR_LOADING) ospf_dbdes_tx(n);
169
  else
170
  {
171
    tm_stop(n->rxmt_timer);
172
  }
173
}
174

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

    
185
  gr=n->ifa->oa->gr;
186
  op=(struct ospf_packet *)ps;
187

    
188
  plsa=(void *)(ps+1);
189

    
190
  j=(ntohs(op->length)-sizeof(struct ospf_dbdes_packet))/
191
    sizeof( struct ospf_lsa_header);
192

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

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

    
218
  nrid=ntohl(((struct ospf_packet *)ps)->routerid);
219

    
220
  myrid=p->cf->global->router_id;
221

    
222
  if((n=find_neigh(ifa, nrid))==NULL)
223
  {
224
    OSPF_TRACE(D_PACKETS, "Received dbdes from unknown neigbor! %I.",
225
      nrid);
226
    return ;
227
  }
228

    
229
  if(ifa->iface->mtu<size)
230
  {
231
    OSPF_TRACE(D_PACKETS, "Received dbdes larger than MTU from %I!", n->ip);
232
    return ;
233
  }
234

    
235
  OSPF_TRACE(D_PACKETS, "Received dbdes from %I via %s.", n->ip,
236
    ifa->iface->name);
237
  ospf_neigh_sm(n, INM_HELLOREC);
238

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

    
299
        n->ddr=ntohl(ps->ddseq);
300

    
301
        if(ps->imms.bit.ms!=n->imms.bit.ms) /* M/S bit differs */
302
        {
303
          DBG("SEQMIS-BIT-MS\n");
304
          ospf_neigh_sm(n, INM_SEQMIS);
305
          break;
306
        }
307

    
308
        if(ps->imms.bit.i)        /* I bit is set */
309
        {
310
          DBG("SEQMIS-BIT-I\n");
311
          ospf_neigh_sm(n, INM_SEQMIS);
312
          break;
313
        }
314

    
315
        n->imms.byte=ps->imms.byte;
316

    
317
        if(ps->options!=n->options)        /* Options differs */
318
        {
319
          DBG("SEQMIS-OPT\n");
320
          ospf_neigh_sm(n, INM_SEQMIS);
321
          break;
322
        }
323

    
324
        if(n->myimms.bit.ms)
325
        {
326
          if(ntohl(ps->ddseq)!=n->dds)                /* MASTER */
327
          {
328
            DBG("SEQMIS-MASTER\n");
329
            ospf_neigh_sm(n, INM_SEQMIS);
330
            break;
331
          }
332
          n->dds++;
333
          DBG("Incrementing dds\n");
334
          ospf_dbdes_reqladd(ps,p,n);
335
          if((n->myimms.bit.m==0) && (ps->imms.bit.m==0))
336
          {
337
            ospf_neigh_sm(n, INM_EXDONE);
338
          }
339
          else
340
          {
341
            ospf_dbdes_tx(n);
342
          }
343

    
344
        }
345
        else
346
        {
347
          if(ntohl(ps->ddseq)!=(n->dds+1))        /* SLAVE */
348
          {
349
            DBG("SEQMIS-SLAVE\n");
350
            ospf_neigh_sm(n, INM_SEQMIS);
351
            break;
352
          }
353
          n->ddr=ntohl(ps->ddseq);
354
          n->dds=ntohl(ps->ddseq);
355
          ospf_dbdes_reqladd(ps,p,n);
356
          ospf_dbdes_tx(n);
357
        }
358

    
359
      break;
360
    case NEIGHBOR_LOADING:
361
    case NEIGHBOR_FULL:
362
        if((ps->imms.byte==n->imms.byte) && (ps->options=n->options) &&
363
          (ps->ddseq==n->dds)) /* Only duplicate are accepted */
364
        {
365
          OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.",n->ip);
366
          return;
367
        }
368
        else
369
        {
370
          DBG("SEQMIS-FULL\n");
371
          ospf_neigh_sm(n, INM_SEQMIS);
372
        }
373
      break;
374
    defaut:
375
      bug("%s: Received dbdes from %I in undefined state.", p->name, n->ip);
376
      break;
377
   }
378
}
379