Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / lsack.c @ 035f6acb

History | View | Annotate | Download (5.36 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
/* Note, that h is in network endianity! */
12
void
13
ospf_lsack_direct_tx(struct ospf_neighbor *n,struct ospf_lsa_header *h)
14
{
15
  struct ospf_packet *op;
16
  struct ospf_lsack_packet *pk;
17
  sock *sk=n->ifa->ip_sk;
18
  struct proto *p=&n->ifa->proto->proto;
19
  u16 len;
20

    
21
  DBG("Sending direct ACK to %I for Type: %u, ID: %I, RT: %I\n",n->rid,
22
    h->type, ntohl(h->id), ntohl(h->rt));
23

    
24
  pk=(struct ospf_lsack_packet *)sk->tbuf;
25
  op=(struct ospf_packet *)sk->tbuf;
26

    
27
  fill_ospf_pkt_hdr(n->ifa, pk, LSACK_P);
28

    
29
  memcpy(pk+1,h,sizeof(struct ospf_lsa_header));
30
  len=sizeof(struct ospf_lsack_packet)+sizeof(struct ospf_lsa_header);
31
  op->length=htons(len);
32
  ospf_pkt_finalize(n->ifa, op);
33
  sk_send_to(sk,len, n->ip, OSPF_PROTO);
34
  OSPF_TRACE(D_PACKETS, "LS ack sent to %I", n->ip);
35
}
36

    
37
void
38
ospf_lsa_delay(struct ospf_neighbor *n,struct ospf_lsa_header *h,
39
  struct proto *p)
40
{
41
  struct lsah_n *no;
42

    
43
  no=mb_alloc(n->pool,sizeof(struct lsah_n));
44
  memcpy(&no->lsa,h,sizeof(struct ospf_lsa_header));
45
  add_tail(&n->ackl, NODE no);
46
  DBG("Adding delay ack for %I, ID: %I, RT: %I, Type: %u\n",n->rid,
47
    ntohl(h->id), ntohl(h->rt),h->type);
48
}
49

    
50
void
51
ackd_timer_hook(timer *t)
52
{
53
  struct ospf_neighbor *n=t->data;
54
  if(!EMPTY_LIST(n->ackl)) ospf_lsack_delay_tx(n);
55
}
56

    
57
void
58
ospf_lsack_delay_tx(struct ospf_neighbor *n)
59
{
60
  struct ospf_packet *op;
61
  struct ospf_lsack_packet *pk;
62
  sock *sk;
63
  u16 len,i=0;
64
  struct ospf_lsa_header *h;
65
  struct lsah_n *no;
66
  struct ospf_iface *ifa=n->ifa;
67
  struct proto *p=&n->ifa->proto->proto;
68

    
69
  OSPF_TRACE(D_PACKETS, "LS ack sent to %I (delayed)",n->ip);
70

    
71
  if(ifa->type==OSPF_IT_BCAST)
72
  {
73
    sk=ifa->hello_sk;
74
  }
75
  else
76
  {
77
    sk=ifa->ip_sk;
78
  }
79

    
80
  pk=(struct ospf_lsack_packet *)sk->tbuf;
81
  op=(struct ospf_packet *)sk->tbuf;
82

    
83
  fill_ospf_pkt_hdr(n->ifa, pk, LSACK_P);
84
  h=(struct ospf_lsa_header *)(pk+1);
85

    
86
  while(!EMPTY_LIST(n->ackl))
87
  {
88
    no=(struct lsah_n *)HEAD(n->ackl);
89
    memcpy(h+i,&no->lsa, sizeof(struct ospf_lsa_header));
90
    i++;
91
    DBG("Iter %u ID: %I, RT: %I, Type: %u\n",i, ntohl((h+i)->id),
92
      ntohl((h+i)->rt),(h+i)->type);
93
    rem_node(NODE no);
94
    mb_free(no);
95
    if((i*sizeof(struct ospf_lsa_header)+sizeof(struct ospf_lsack_packet)+SIPH)>
96
      n->ifa->iface->mtu)
97
    {
98
      if(!EMPTY_LIST(n->ackl))
99
      {
100
        len=sizeof(struct ospf_lsack_packet)+i*sizeof(struct ospf_lsa_header);
101
        op->length=htons(len);
102
        ospf_pkt_finalize(n->ifa, op);
103
        DBG("Sending and continuing! Len=%u\n",len);
104
        if(ifa->type==OSPF_IT_BCAST)
105
        {
106
          if((ifa->state==OSPF_IS_DR)||(ifa->state==OSPF_IS_BACKUP))
107
          {
108
            sk_send_to(sk ,len, AllSPFRouters, OSPF_PROTO);
109
          }
110
          else
111
          {
112
            sk_send_to(sk ,len, AllDRouters, OSPF_PROTO);
113
          }
114
        }
115
        else
116
        {
117
          if((ifa->state==OSPF_IS_DR)||(ifa->state==OSPF_IS_BACKUP))
118
          {
119
            sk_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
120
          }
121
          else
122
          {
123
            sk_send_to_bdr(sk, len, ifa);
124
          }
125
        }
126

    
127
        fill_ospf_pkt_hdr(n->ifa, pk, LSACK_P);
128
        i=0;
129
      }
130
    }
131
  }
132

    
133
  len=sizeof(struct ospf_lsack_packet)+i*sizeof(struct ospf_lsa_header);
134
  op->length=htons(len);
135
  ospf_pkt_finalize(n->ifa, op);
136
  DBG("Sending! Len=%u\n",len);
137
  if(ifa->type==OSPF_IT_BCAST)
138
  {
139
    if((ifa->state==OSPF_IS_DR)||(ifa->state==OSPF_IS_BACKUP))
140
    {
141
      sk_send_to(sk ,len, AllSPFRouters, OSPF_PROTO);
142
    }
143
    else
144
    {
145
      sk_send_to(sk ,len, AllDRouters, OSPF_PROTO);
146
    }
147
  }
148
  else
149
  {
150
    sk_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
151
  }
152
}
153

    
154
void
155
ospf_lsack_rx(struct ospf_lsack_packet *ps, struct proto *p,
156
  struct ospf_iface *ifa, u16 size)
157
{
158
  u32 nrid, myrid;
159
  struct ospf_neighbor *n;
160
  struct ospf_lsa_header lsa,*plsa;
161
  int length;
162
  u16 nolsa,i;
163
  struct top_hash_entry *en;
164
  u16 lenn=ntohs(ps->ospf_packet.length);
165

    
166
  nrid=ntohl(ps->ospf_packet.routerid);
167

    
168
  myrid=p->cf->global->router_id;
169

    
170
  if((n=find_neigh(ifa, nrid))==NULL)
171
  {
172
    OSPF_TRACE(D_PACKETS, "Received LS ack from unknown neigbor! (%I)",
173
      nrid);
174
    return ;
175
  }
176

    
177
  OSPF_TRACE(D_PACKETS, "Received LS ack from %I", n->ip);
178
  ospf_neigh_sm(n, INM_HELLOREC);
179

    
180
  if(n->state<NEIGHBOR_EXCHANGE) return;
181

    
182
  nolsa=(lenn-sizeof(struct ospf_lsack_packet))/
183
    sizeof(struct ospf_lsa_header);
184

    
185
  if((nolsa<1)||((lenn-sizeof(struct ospf_lsack_packet))!=
186
    (nolsa*sizeof(struct ospf_lsa_header))))
187
  {
188
    log("%s: Received corrupted LS ack from %I", p->name, n->ip);
189
    return;
190
  }
191

    
192
  plsa=(struct ospf_lsa_header *)(ps+1);
193

    
194
  for(i=0;i<nolsa;i++)
195
  {
196
    ntohlsah(plsa+i,&lsa);
197
    if((en=ospf_hash_find_header(n->lsrth,&lsa))==NULL) continue;
198

    
199
    if(lsa_comp(&lsa,&en->lsa)!=CMP_SAME)
200
    {
201
      if((lsa.sn==LSA_MAXSEQNO)&&(lsa.age==LSA_MAXAGE)) continue;
202

    
203
      OSPF_TRACE(D_PACKETS, "Strange LS acknoledgement from %I",n->ip);
204
      OSPF_TRACE(D_PACKETS, "Id: %I, Rt: %I, Type: %u",
205
        lsa.id,lsa.rt,lsa.type);
206
      OSPF_TRACE(D_PACKETS, "I have: Age: %4u, Seqno: 0x%08x, Sum: %u",
207
        en->lsa.age, en->lsa.sn, en->lsa.checksum);
208
      OSPF_TRACE(D_PACKETS, "He has: Age: %4u, Seqno: 0x%08x, Sum: %u",
209
        lsa.age,lsa.sn,lsa.checksum);
210
      continue;
211
    }
212

    
213
    DBG("Deleting LS Id: %I RT: %I Type: %u from LS Retl for neighbor %I\n",
214
      lsa.id,lsa.rt,lsa.type,n->rid);
215
    s_rem_node(SNODE en);
216
    if(en->lsa_body!=NULL) mb_free(en->lsa_body);
217
    en->lsa_body=NULL;
218
    ospf_hash_delete(n->lsrth,en);
219
  }  
220
}