Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / lsupd.c @ 2c971094

History | View | Annotate | Download (8.39 KB)

1
/*
2
 *        BIRD -- OSPF
3
 *
4
 *        (c) 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_lsupd_tx(struct ospf_neighbor *n)
13
{
14
  /* FIXME Go on! */
15
}
16

    
17
void
18
flood_lsa(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
19
  struct ospf_lsa_header *hh, struct proto_ospf *po, struct ospf_iface *iff)
20
{
21
  struct ospf_iface *ifa;
22
  struct ospf_neighbor *nn;
23
  struct top_hash_entry *en;
24
  int ret;
25

    
26
  /* pg 148 */
27
  WALK_LIST(NODE ifa,po->iface_list)
28
  {
29
    if(hh->type==LSA_T_EXT)
30
    {
31
      if(ifa->type==OSPF_IT_VLINK) continue;
32
      if(ifa->oa->stub) continue;
33
    }
34
    else
35
    {
36
      if(iff->oa->areaid==BACKBONE)
37
      {
38
        if((ifa->type!=OSPF_IT_VLINK)&&(ifa->oa!=iff->oa)) continue;
39
      }
40
      else
41
      {
42
        if(ifa->oa!=iff->oa) continue;
43
      }
44
    }
45
    ret=0;
46
    WALK_LIST(NODE nn, ifa->neigh_list)
47
    {
48
      if(nn->state<NEIGHBOR_EXCHANGE) continue;
49
      if(nn->state<NEIGHBOR_FULL)
50
      {
51

    
52
        if((en=ospf_hash_find_header(nn->lsrqh,hh))!=NULL)
53
        {
54
          switch(lsa_comp(hh,&en->lsa))
55
          {
56
            case CMP_OLDER:
57
              continue;
58
              break;
59
            case CMP_SAME:
60
              s_rem_node(SNODE en);
61
              DBG("Removing from lsreq list for neigh %u\n", nn->rid);
62
              ospf_hash_delete(nn->lsrqh,en);
63
              if(EMPTY_SLIST(nn->lsrql)) ospf_neigh_sm(nn, INM_LOADDONE);
64
              continue;
65
              break;
66
            case CMP_NEWER:
67
              s_rem_node(SNODE en);
68
              DBG("Removing from lsreq list for neigh %u\n", nn->rid);
69
              ospf_hash_delete(nn->lsrqh,en);
70
              if(EMPTY_SLIST(nn->lsrql)) ospf_neigh_sm(nn, INM_LOADDONE);
71
              break;
72
            default: bug("Bug in lsa_comp?\n");
73
          }
74
        }
75
      }
76
      if(nn==n) continue;
77
      en=ospf_hash_get_header(nn->lsrth, hh);
78
      s_add_tail(&nn->lsrtl, SNODE en);
79
      ret=1;
80
    }
81
    if(ret==0) continue;
82
    if(ifa==iff)
83
    {
84
      if((n->rid==iff->drid)||n->rid==iff->bdrid) continue;
85
      if(iff->state=OSPF_IS_BACKUP) continue;
86
    }
87
    /* FIXME directly flood */
88
    {
89
      sock *sk;
90
      ip_addr to;
91
      u16 len;
92
      struct ospf_lsupd_packet *pk;
93
      struct ospf_packet *op;
94

    
95
      if(ifa->type==OSPF_IT_NBMA)  sk=iff->ip_sk;
96
      else sk=iff->hello_sk;        /* FIXME is this tru for PTP? */
97

    
98
      pk=(struct ospf_lsupd_packet *)sk->tbuf;
99
      op=(struct ospf_packet *)sk->tbuf;
100

    
101
      fill_ospf_pkt_hdr(ifa, pk, LSUPD);
102
      pk->lsano=htonl(1);
103
      memcpy(pk+1,hn,ntohs(hn->length));
104
      len=sizeof(struct ospf_lsupd_packet)+ntohs(hn->length);
105
      op->length=htons(len);
106
      ospf_pkt_finalize(ifa, op);
107

    
108
      if(ifa->type==OSPF_IT_NBMA)
109
      {
110
        struct ospf_neighbor *nnn;
111
        WALK_LIST(NODE nnn,ifa->neigh_list)
112
        {
113
          if(nnn->state>NEIGHBOR_EXSTART)
114
            sk_send_to(sk,len, nnn->ip, OSPF_PROTO);
115
        }
116
      }
117
      else
118
      {
119
        if((ifa->state==OSPF_IS_BACKUP)||(ifa->state==OSPF_IS_DR))
120
          sk_send_to(sk,len, AllSPFRouters, OSPF_PROTO);
121
        else sk_send_to(sk,len, AllDRouters, OSPF_PROTO);
122
      }
123
    }
124
  }
125
}
126

    
127
void                /* I send all I received in LSREQ */
128
ospf_lsupd_tx_list(struct ospf_neighbor *n, list *l)
129
{
130
  struct l_lsr_head *llsh;
131
  u16 len;
132
  u32 lsano;
133
  struct top_hash_entry *en;
134
  struct ospf_lsupd_packet *pk;
135
  struct ospf_packet *op;
136
  void *pktpos;
137
  u8 ii;
138
  u8 *jj=n->ifa->ip_sk->tbuf;
139

    
140
  if(HEAD(*l)==NULL) return;
141

    
142
  pk=(struct ospf_lsupd_packet *)n->ifa->ip_sk->tbuf;
143
  op=(struct ospf_packet *)n->ifa->ip_sk->tbuf;
144

    
145
  DBG("LSupd: 1st packet\n");
146
       
147
  fill_ospf_pkt_hdr(n->ifa, pk, LSUPD);
148
  len=SIPH+sizeof(struct ospf_lsupd_packet);
149
  lsano=0;
150
  pktpos=(pk+1);
151

    
152
  WALK_LIST(llsh, *l)
153
  {
154
    en=ospf_hash_find(n->ifa->oa->gr,llsh->lsh.id,llsh->lsh.rt,llsh->lsh.type);
155
    DBG("Sending ID=%u, Type=%u, RT=%u\n", llsh->lsh.id, llsh->lsh.type,
156
      llsh->lsh.rt);
157
    if((len+sizeof(struct ospf_lsa_header)+en->lsa.length)>n->ifa->iface->mtu)
158
    {
159
      pk->lsano=htonl(lsano);
160
      op->length=htons(len);
161
      ospf_pkt_finalize(n->ifa, op);
162
                       
163
      for(ii=0;ii<(len-SIPH);ii+=4)
164
        DBG("Out dump: %d,%d,%d,%d\n", *(jj+ii), *(jj+ii+1), *(jj+ii+2), *(jj+ii+3));
165

    
166
      sk_send_to(n->ifa->ip_sk,len, n->ip, OSPF_PROTO);
167

    
168
      DBG("LSupd: next packet\n");
169
      fill_ospf_pkt_hdr(n->ifa, pk, LSUPD);
170
      len=SIPH+sizeof(struct ospf_lsupd_packet);
171
      lsano=0;
172
      pktpos=(pk+1);
173
    }
174
    htonlsah(&(en->lsa), pktpos);
175
    pktpos=pktpos+sizeof(struct ospf_lsa_header);
176
    htonlsab(en->lsa_body, pktpos, en->lsa.type, en->lsa.length);
177
    pktpos=pktpos+en->lsa.length-sizeof(struct ospf_lsa_header);
178
    len=len+en->lsa.length;
179
    lsano++;
180
  }
181
  pk->lsano=htonl(lsano);
182
  op->length=htons(len-SIPH);
183
  ospf_pkt_finalize(n->ifa, op);
184

    
185
  for(ii=0;ii<(len-SIPH);ii+=4)
186
    DBG("Out dump: %d,%d,%d,%d\n", *(jj+ii), *(jj+ii+1), *(jj+ii+2), *(jj+ii+3));
187

    
188
  sk_send_to(n->ifa->ip_sk,len, n->ip, OSPF_PROTO);
189
  DBG("LSupd: sent\n");
190
}
191

    
192
void
193
ospf_lsupd_rx(struct ospf_lsupd_packet *ps, struct proto *p,
194
  struct ospf_iface *ifa, u16 size)
195
{
196
  u32 area,nrid,myrid;
197
  struct ospf_neighbor *n,*ntmp;
198
  struct ospf_lsa_header *lsa;
199
  struct ospf_area *oa;
200
  struct proto_ospf *po=(struct proto_ospf *)p;
201
  u16 length;
202
  u8 i;
203

    
204
  nrid=ntohl(ps->ospf_packet.routerid);
205

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

    
208
  if((n=find_neigh(ifa, nrid))==NULL)
209
  {
210
    debug("%s: Received lsupd from unknown neigbor! (%u)\n", p->name,
211
      nrid);
212
    return ;
213
  }
214
  if(n->state<NEIGHBOR_EXCHANGE)
215
  {
216
    debug("%s: Received lsupd in lesser state than EXCHANGE from (%u)\n",
217
      p->name);
218
    return;
219
  }
220

    
221
  lsa=(struct ospf_lsa_header *)(ps+1);
222
  area=htonl(ps->ospf_packet.areaid);
223
  oa=ospf_find_area((struct proto_ospf *)p,area);
224
  for(i=0;i<ntohl(ps->lsano);i++,
225
    lsa=(struct ospf_lsa_header *)(((u8 *)lsa)+ntohs(lsa->length)))
226
  {
227
    struct ospf_lsa_header lsatmp;
228
    struct top_hash_entry *lsadb;
229
    /* pg 143 (1) */
230
    if(lsa->checksum!=lsasum_check(lsa,NULL,po))
231
    {
232
      log("Received bad lsa checksum from %u\n",n->rid);
233
      continue;
234
    }
235
    /* pg 143 (2) */
236
    if((lsa->type<LSA_T_RT)||(lsa->type>LSA_T_EXT))
237
    {
238
      log("Unknown LSA type from %u\n",n->rid);
239
      continue;
240
    }
241
    /* pg 143 (3) */
242
    if((lsa->type==LSA_T_EXT)&&oa->stub)
243
    {
244
      log("Received External LSA in stub area from %u\n",n->rid);
245
      continue;
246
    }
247
    ntohlsah(lsa,&lsatmp);
248
    DBG("Processing update Type: %u ID: %u RT: %u\n",lsatmp.type,
249
        lsatmp.id, lsatmp.rt);
250
    lsadb=ospf_hash_find_header(oa->gr, &lsatmp);
251

    
252
    /* pg 143 (4) */
253
    if((lsatmp.age==LSA_MAXAGE)&&(lsadb==NULL))
254
    {
255
      struct ospf_neighbor *n=NULL;
256
      struct ospf_iface *ifa=NULL;
257
      int flag=0;
258

    
259
      WALK_LIST(NODE ifa,po->iface_list)
260
        WALK_LIST(NODE ntmp,ifa->neigh_list)
261
          if((ntmp->state==NEIGHBOR_EXCHANGE)&&
262
            (ntmp->state==NEIGHBOR_LOADING))
263
            flag=1;
264

    
265
      if(flag==0)
266
      {
267
        add_ack_list(n,lsa);
268
        continue;
269
      }
270
    }
271
    /* pg 144 (5) */
272
    if((lsadb==NULL)||(lsa_comp(&lsatmp,&lsadb->lsa)==CMP_NEWER))
273
    {
274
       struct ospf_iface *ift=NULL;
275
       void *body;
276

    
277

    
278
      /* pg 144 (5a) */
279
      if(lsadb && ((lsadb->inst_t-now)<MINLSARRIVAL)) continue;
280

    
281
      flood_lsa(n,lsa,&lsatmp,po,ifa);
282

    
283
      /* Remove old from all ret lists */
284
      /* pg 144 (5c) */
285
      if(lsadb)
286
        WALK_LIST(NODE ift,po->iface_list)
287
          WALK_LIST(NODE ntmp,ift->neigh_list)
288
          {
289
            struct top_hash_entry *en;
290
            if(ntmp->state>NEIGHBOR_EXSTART)
291
              if((en=ospf_hash_find_header(ntmp->lsrth,&lsadb->lsa))!=NULL)
292
              {
293
                s_rem_node(SNODE en);
294
                ospf_hash_delete(ntmp->lsrth,en);
295
              }
296
          }
297

    
298
      /* pg 144 (5d) */
299
      body=mb_alloc(p->pool,lsatmp.length-sizeof(struct ospf_lsa_header));
300
      ntohlsab(lsa+1,body,lsatmp.type,
301
        lsatmp.length-sizeof(struct ospf_lsa_header));
302
      lsadb=lsa_install_new(&lsatmp,body, oa);
303
      DBG("New LSA installed in DB\n");
304

    
305
      /* FIXME 144 (5e) ack */
306
      /* FIXME 145 (5f) self originated? */
307

    
308
      continue;
309
    }
310

    
311
    /* FIXME pg145 (6)?? */
312

    
313
    /* pg145 (7) */
314
    if(lsa_comp(&lsatmp,&lsadb->lsa)==CMP_SAME)
315
    {
316
        struct top_hash_entry *en;
317
        if((en=ospf_hash_find_header(n->lsrth,&lsadb->lsa))!=NULL)
318
          s_rem_node(SNODE en);
319
        /* FIXME ack_lsa() */
320
        continue;
321
    }
322

    
323
    /* pg145 (8) */
324
    if((lsadb->lsa.age==LSA_MAXAGE)&&(lsadb->lsa.sn==LSA_MAXSEQNO)) continue;
325

    
326
    {
327
      list l;
328
      struct l_lsr_head llsh;
329
      init_list(&l);
330
      memcpy(&llsh.lsh,&lsadb->lsa,sizeof(struct ospf_lsa_header));
331
      add_tail(&l, NODE &llsh);
332
      ospf_lsupd_tx_list(n, &l);
333
    }
334
  }
335
}
336