Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / dbdes.c @ 23d67029

History | View | Annotate | Download (9.27 KB)

1
/*
2
 *        BIRD -- OSPF
3
 *
4
 *        (c) 1999--2004 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_send - transmit database description packet
13
 * @n: neighbor
14
 *
15
 * Sending of a database description packet is described in 10.6 of RFC 2328.
16
 * Reception of each packet is acknowledged in the sequence number of another.
17
 * When I send a packet to a neighbor I keep a copy in a buffer. If the neighbor
18
 * does not reply, I don't create a new packet but just send the content
19
 * of the buffer.
20
 */
21
void
22
ospf_dbdes_send(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
  struct proto_ospf *po = oa->po;
29
  struct proto *p = &po->proto;
30
  u16 length, i, j;
31

    
32
  if ((oa->rt == NULL) || (EMPTY_LIST(po->lsal)))
33
    originate_rt_lsa(oa);
34

    
35
  switch (n->state)
36
  {
37
  case NEIGHBOR_EXSTART:        /* Send empty packets */
38
    n->myimms.bit.i = 1;
39
    pkt = (struct ospf_dbdes_packet *) (ifa->ip_sk->tbuf);
40
    op = (struct ospf_packet *) pkt;
41
    ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
42
    pkt->iface_mtu = htons(ifa->iface->mtu);
43
    pkt->options = oa->opt.byte;
44
    pkt->imms = n->myimms;
45
    pkt->ddseq = htonl(n->dds);
46
    length = sizeof(struct ospf_dbdes_packet);
47
    op->length = htons(length);
48
    ospf_send_to(ifa->ip_sk, n->ip, ifa);
49
    OSPF_TRACE(D_PACKETS, "DB_DES (I) sent to %I via %s.", n->ip,
50
               ifa->iface->name);
51
    break;
52

    
53
  case NEIGHBOR_EXCHANGE:
54
    n->myimms.bit.i = 0;
55

    
56
    if (((n->myimms.bit.ms) && (n->dds == n->ddr + 1)) ||
57
        ((!(n->myimms.bit.ms)) && (n->dds == n->ddr)))
58
    {
59
      snode *sn;                /* Send next */
60
      struct ospf_lsa_header *lsa;
61

    
62
      pkt = n->ldbdes;
63
      op = (struct ospf_packet *) pkt;
64

    
65
      ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
66
      pkt->iface_mtu = htons(ifa->iface->mtu);
67
      pkt->options = oa->opt.byte;
68
      pkt->ddseq = htonl(n->dds);
69

    
70
      j = i = (ospf_pkt_maxsize(ifa) - sizeof(struct ospf_dbdes_packet)) / sizeof(struct ospf_lsa_header);        /* Number of possible lsaheaders to send */
71
      lsa = (n->ldbdes + sizeof(struct ospf_dbdes_packet));
72

    
73
      if (n->myimms.bit.m)
74
      {
75
        sn = s_get(&(n->dbsi));
76

    
77
        DBG("Number of LSA: %d\n", j);
78
        for (; i > 0; i--)
79
        {
80
          struct top_hash_entry *en= (struct top_hash_entry *) sn;
81
          int send = 1;
82

    
83
          /* Don't send ext LSA into stub areas */
84
          if (oa->stub && (en->lsa.type == LSA_T_EXT)) send = 0;
85
          /* Don't send ext LSAs through VLINK  */
86
          if ((ifa->type == OSPF_IT_VLINK) && (en->lsa.type == LSA_T_EXT)) send = 0;;
87
          /* Don't send LSA of other areas */
88
          if ((en->lsa.type != LSA_T_EXT) && (en->oa != oa)) send = 0;
89

    
90
          if (send)
91
          {
92
            htonlsah(&(en->lsa), lsa);
93
            DBG("Working on: %d\n", i);
94
            DBG("\tX%01x %-1I %-1I %p\n", en->lsa.type, en->lsa.id,
95
                en->lsa.rt, en->lsa_body);
96

    
97
            lsa++;
98
          }
99
          else i++;        /* No lsa added */
100

    
101
          if (sn == STAIL(po->lsal))
102
          {
103
            i--;
104
            break;
105
          }
106

    
107
          sn = sn->next;
108
        }
109

    
110
        if (sn == STAIL(po->lsal))
111
        {
112
          DBG("Number of LSA NOT sent: %d\n", i);
113
          DBG("M bit unset.\n");
114
          n->myimms.bit.m = 0;        /* Unset more bit */
115
        }
116
        else
117
          s_put(&(n->dbsi), sn);
118
      }
119

    
120
      pkt->imms.byte = n->myimms.byte;
121

    
122
      length = (j - i) * sizeof(struct ospf_lsa_header) +
123
        sizeof(struct ospf_dbdes_packet);
124
      op->length = htons(length);
125

    
126
      DBG("%s: DB_DES (M) prepared for %I.\n", p->name, n->ip);
127
    }
128

    
129
  case NEIGHBOR_LOADING:
130
  case NEIGHBOR_FULL:
131
    pkt = n->ldbdes;
132
    length = ntohs(((struct ospf_packet *) n->ldbdes)->length);
133

    
134
    if (!length)
135
    {
136
      OSPF_TRACE(D_PACKETS, "No packet in my buffer for repeating");
137
      ospf_neigh_sm(n, INM_KILLNBR);
138
      return;
139
    }
140

    
141
    memcpy(ifa->ip_sk->tbuf, n->ldbdes, length);
142
    /* Copy last sent packet again */
143

    
144
    ospf_send_to(ifa->ip_sk, n->ip, n->ifa);
145

    
146
    if(n->myimms.bit.ms) tm_start(n->rxmt_timer, n->ifa->rxmtint);                /* Restart timer */
147

    
148
    OSPF_TRACE(D_PACKETS, "DB_DES (M) sent to %I via %s.", n->ip,
149
               ifa->iface->name);
150

    
151
    DBG("DB_DES PS=%u, M=%u\n", ntohl(pkt->ddseq), pkt->imms.bit.m);
152

    
153
    if (!n->myimms.bit.ms)
154
    {
155
      if ((n->myimms.bit.m == 0) && (n->imms.bit.m == 0) &&
156
          (n->state == NEIGHBOR_EXCHANGE))
157
      {
158
        ospf_neigh_sm(n, INM_EXDONE);
159
      }
160
    }
161
    break;
162

    
163
  default:                        /* Ignore it */
164
    break;
165
  }
166
}
167

    
168
static void
169
ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct ospf_neighbor *n)
170
{
171
  struct ospf_lsa_header *plsa, lsa;
172
  struct top_hash_entry *he, *sn;
173
  struct ospf_area *oa = n->ifa->oa;
174
  struct top_graph *gr = oa->po->gr;
175
  struct ospf_packet *op;
176
  int i, j;
177

    
178
  op = (struct ospf_packet *) ps;
179

    
180
  plsa = (void *) (ps + 1);
181

    
182
  j = (ntohs(op->length) - sizeof(struct ospf_dbdes_packet)) /
183
    sizeof(struct ospf_lsa_header);
184

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

    
202
void
203
ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
204
                   struct ospf_iface *ifa, struct ospf_neighbor *n)
205
{
206
  struct proto *p = &ifa->oa->po->proto;
207
  u32 myrid = p->cf->global->router_id;
208
  unsigned int size = ntohs(ps->ospf_packet.length);
209

    
210
  OSPF_TRACE(D_PACKETS, "Received dbdes from %I via %s.", n->ip,
211
             ifa->iface->name);
212

    
213
  DBG("DB_DES PS=%u, M=%u SIZE=%u\n", ntohl(ps->ddseq), ps->imms.bit.m, size);
214

    
215
  ospf_neigh_sm(n, INM_HELLOREC);
216

    
217
  switch (n->state)
218
  {
219
  case NEIGHBOR_DOWN:
220
  case NEIGHBOR_ATTEMPT:
221
  case NEIGHBOR_2WAY:
222
    return;
223
    break;
224
  case NEIGHBOR_INIT:
225
    ospf_neigh_sm(n, INM_2WAYREC);
226
    if (n->state != NEIGHBOR_EXSTART)
227
      return;
228
  case NEIGHBOR_EXSTART:
229
    if ((ps->imms.bit.m && ps->imms.bit.ms && ps->imms.bit.i)
230
        && (n->rid > myrid) && (size == sizeof(struct ospf_dbdes_packet)))
231
    {
232
      /* I'm slave! */
233
      n->dds = ntohl(ps->ddseq);
234
      n->ddr = ntohl(ps->ddseq);
235
      n->options = ps->options;
236
      n->myimms.bit.ms = 0;
237
      n->imms.byte = ps->imms.byte;
238
      OSPF_TRACE(D_PACKETS, "I'm slave to %I.", n->ip);
239
      ospf_neigh_sm(n, INM_NEGDONE);
240
      ospf_dbdes_send(n);
241
      break;
242
    }
243

    
244
    if (((ps->imms.bit.i == 0) && (ps->imms.bit.ms == 0)) &&
245
        (n->rid < myrid) && (n->dds == ntohl(ps->ddseq)))
246
    {
247
      /* I'm master! */
248
      n->options = ps->options;
249
      n->ddr = ntohl(ps->ddseq) - 1;        /* It will be set corectly a few lines down */
250
      n->imms.byte = ps->imms.byte;
251
      OSPF_TRACE(D_PACKETS, "I'm master to %I.", n->ip);
252
      ospf_neigh_sm(n, INM_NEGDONE);
253
    }
254
    else
255
    {
256
      DBG("%s: Nothing happend to %I (imms=%u)\n", p->name, n->ip,
257
          ps->imms.byte);
258
      break;
259
    }
260
  case NEIGHBOR_EXCHANGE:
261
    if ((ps->imms.byte == n->imms.byte) && (ps->options == n->options) &&
262
        (ntohl(ps->ddseq) == n->ddr))
263
    {
264
      /* Duplicate packet */
265
      OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
266
      if (n->imms.bit.ms == 0)
267
      {
268
        ospf_dbdes_send(n);
269
      }
270
      return;
271
    }
272

    
273
    n->ddr = ntohl(ps->ddseq);
274

    
275
    if (ps->imms.bit.ms != n->imms.bit.ms)        /* M/S bit differs */
276
    {
277
      OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit MS)",
278
                 n->ip);
279
      ospf_neigh_sm(n, INM_SEQMIS);
280
      break;
281
    }
282

    
283
    if (ps->imms.bit.i)                /* I bit is set */
284
    {
285
      OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit I)",
286
                 n->ip);
287
      ospf_neigh_sm(n, INM_SEQMIS);
288
      break;
289
    }
290

    
291
    n->imms.byte = ps->imms.byte;
292

    
293
    if (ps->options != n->options)        /* Options differs */
294
    {
295
      OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (options)",
296
                 n->ip);
297
      ospf_neigh_sm(n, INM_SEQMIS);
298
      break;
299
    }
300

    
301
    if (n->myimms.bit.ms)
302
    {
303
      if (ntohl(ps->ddseq) != n->dds)        /* MASTER */
304
      {
305
        OSPF_TRACE(D_PACKETS,
306
                   "dbdes - sequence mismatch neighbor %I (master)", n->ip);
307
        ospf_neigh_sm(n, INM_SEQMIS);
308
        break;
309
      }
310
      n->dds++;
311
      DBG("Incrementing dds\n");
312
      ospf_dbdes_reqladd(ps, n);
313
      if ((n->myimms.bit.m == 0) && (ps->imms.bit.m == 0))
314
      {
315
        ospf_neigh_sm(n, INM_EXDONE);
316
      }
317
      else
318
      {
319
        ospf_dbdes_send(n);
320
      }
321

    
322
    }
323
    else
324
    {
325
      if (ntohl(ps->ddseq) != (n->dds + 1))        /* SLAVE */
326
      {
327
        OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)",
328
                   n->ip);
329
        ospf_neigh_sm(n, INM_SEQMIS);
330
        break;
331
      }
332
      n->ddr = ntohl(ps->ddseq);
333
      n->dds = ntohl(ps->ddseq);
334
      ospf_dbdes_reqladd(ps, n);
335
      ospf_dbdes_send(n);
336
    }
337

    
338
    break;
339
  case NEIGHBOR_LOADING:
340
  case NEIGHBOR_FULL:
341
    if ((ps->imms.byte == n->imms.byte) && (ps->options == n->options)
342
        && (ntohl(ps->ddseq) == n->ddr))
343
      /* Only duplicate are accepted */
344
    {
345
      OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
346
      return;
347
    }
348
    else
349
    {
350
      OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (full)",
351
                 n->ip);
352
      DBG("PS=%u, DDR=%u, DDS=%u\n", ntohl(ps->ddseq), n->ddr, n->dds);
353
      ospf_neigh_sm(n, INM_SEQMIS);
354
    }
355
    break;
356
  default:
357
    bug("Received dbdes from %I in undefined state.", n->ip);
358
  }
359
}