]>
Commit | Line | Data |
---|---|---|
4364b47e OF |
1 | /* |
2 | * BIRD -- OSPF | |
3 | * | |
30147b89 | 4 | * (c) 1999-2000 Ondrej Filip <feela@network.cz> |
4364b47e OF |
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; | |
394920a0 | 16 | struct ospf_iface *ifa=n->ifa; |
4364b47e OF |
17 | u16 length; |
18 | struct proto *p; | |
30147b89 OF |
19 | u16 i,j; |
20 | u8 *aa,*bb; | |
4364b47e | 21 | |
4364b47e OF |
22 | p=(struct proto *)(ifa->proto); |
23 | ||
24 | switch(n->state) | |
25 | { | |
26 | case NEIGHBOR_EXSTART: /* Send empty packets */ | |
96501dfe | 27 | n->myimms.bit.i=1; |
963ea03d OF |
28 | pkt=(struct ospf_dbdes_packet *)(ifa->ip_sk->tbuf); |
29 | op=(struct ospf_packet *)pkt; | |
89d6782d | 30 | fill_ospf_pkt_hdr(ifa, pkt, DBDES_P); |
496c819f | 31 | pkt->iface_mtu=htons(ifa->iface->mtu); /* FIXME NOT for VLINK! */ |
4364b47e OF |
32 | pkt->options= ifa->options; |
33 | pkt->imms=n->myimms; | |
910e557b | 34 | pkt->ddseq=htonl(n->dds); |
4364b47e OF |
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); | |
394920a0 OF |
39 | debug("%s: DB_DES (I) sent to %I via %s.\n", p->name, n->ip, |
40 | ifa->iface->name); | |
30147b89 OF |
41 | break; |
42 | ||
43 | case NEIGHBOR_EXCHANGE: | |
96501dfe | 44 | n->myimms.bit.i=0; |
5f743d96 | 45 | |
910e557b OF |
46 | if(((n->myimms.bit.ms) && (n->dds==n->ddr+1)) || |
47 | ((!(n->myimms.bit.ms)) && (n->dds==n->ddr))) | |
30147b89 OF |
48 | { |
49 | snode *sn; /* Send next */ | |
ce17d4c1 | 50 | struct ospf_lsa_header *lsa; |
963ea03d OF |
51 | |
52 | pkt=n->ldbdes; | |
53 | op=(struct ospf_packet *)pkt; | |
30147b89 | 54 | |
89d6782d | 55 | fill_ospf_pkt_hdr(ifa, pkt, DBDES_P); |
963ea03d | 56 | pkt->iface_mtu=htons(ifa->iface->mtu); |
30147b89 | 57 | pkt->options= ifa->options; |
910e557b | 58 | pkt->ddseq=htonl(n->dds); |
30147b89 | 59 | |
5f743d96 | 60 | j=i=(ifa->iface->mtu-sizeof(struct ospf_dbdes_packet)-SIPH)/ |
ce17d4c1 | 61 | sizeof(struct ospf_lsa_header); /* Number of lsaheaders */ |
30147b89 OF |
62 | lsa=(n->ldbdes+sizeof(struct ospf_dbdes_packet)); |
63 | ||
910e557b OF |
64 | if(n->myimms.bit.m) |
65 | { | |
2560c886 | 66 | sn=s_get(&(n->dbsi)); |
910e557b | 67 | |
2560c886 OF |
68 | DBG("Number of LSA: %d\n", j); |
69 | for(;i>0;i--) | |
70 | { | |
71 | struct top_hash_entry *en; | |
30147b89 | 72 | |
2560c886 OF |
73 | en=(struct top_hash_entry *)sn; |
74 | htonlsah(&(en->lsa), lsa); | |
75 | DBG("Working on: %d\n", i); | |
5f743d96 | 76 | DBG("\tX%01x %08I %08I %p\n", en->lsa.type, en->lsa.id, |
2560c886 OF |
77 | en->lsa.rt, en->lsa_body); |
78 | ||
d8852b36 | 79 | if(sn==STAIL(n->ifa->oa->lsal)) |
2560c886 | 80 | { |
5f743d96 | 81 | i--; |
0884f492 | 82 | break; /* Should set some flag? */ |
2560c886 OF |
83 | } |
84 | sn=sn->next; | |
85 | lsa++; | |
86 | } | |
963ea03d | 87 | |
d8852b36 | 88 | if(sn==STAIL(n->ifa->oa->lsal)) |
30147b89 | 89 | { |
2560c886 OF |
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 */ | |
30147b89 | 93 | } |
5f743d96 | 94 | else s_put(&(n->dbsi),sn); |
910e557b | 95 | } |
963ea03d | 96 | |
96501dfe | 97 | pkt->imms.byte=n->myimms.byte; |
30147b89 | 98 | |
963ea03d | 99 | length=(j-i)*sizeof(struct ospf_lsa_header)+ |
ce17d4c1 | 100 | sizeof(struct ospf_dbdes_packet); |
30147b89 | 101 | op->length=htons(length); |
96501dfe | 102 | |
30147b89 | 103 | ospf_pkt_finalize(ifa, op); |
394920a0 | 104 | DBG("%s: DB_DES (M) sent to %I.\n", p->name, n->ip); |
30147b89 OF |
105 | } |
106 | ||
910e557b OF |
107 | case NEIGHBOR_LOADING: |
108 | case NEIGHBOR_FULL: | |
30147b89 OF |
109 | aa=ifa->ip_sk->tbuf; |
110 | bb=n->ldbdes; | |
963ea03d | 111 | op=n->ldbdes; |
30147b89 OF |
112 | length=ntohs(op->length); |
113 | ||
5f743d96 | 114 | for(i=0; i<length; i++) |
30147b89 | 115 | { |
96501dfe | 116 | *(aa+i)=*(bb+i); /* Copy last sent packet again */ |
30147b89 | 117 | } |
04c6319a | 118 | |
30147b89 | 119 | sk_send_to(ifa->ip_sk,length, n->ip, OSPF_PROTO); |
394920a0 OF |
120 | debug("%s: DB_DES (M) sent to %I via %s.\n", p->name, n->ip, |
121 | ifa->iface->name); | |
910e557b OF |
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; | |
4364b47e | 134 | |
4364b47e | 135 | default: /* Ignore it */ |
df49d4e1 | 136 | die("Bug in dbdes sending"); |
4364b47e OF |
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 | ||
910e557b OF |
148 | n=(struct ospf_neighbor *)timer->data; |
149 | ifa=n->ifa; | |
4364b47e | 150 | p=(struct proto *)(ifa->proto); |
9669362f | 151 | DBG("%s: RXMT timer fired on interface %s for neigh: %I.\n", |
353f3261 | 152 | p->name, ifa->iface->name, n->ip); |
910e557b | 153 | if(n->state<NEIGHBOR_LOADING) ospf_dbdes_tx(n); |
2560c886 OF |
154 | else |
155 | { | |
156 | tm_stop(n->rxmt_timer); | |
2560c886 | 157 | } |
910e557b OF |
158 | } |
159 | ||
910e557b OF |
160 | void |
161 | ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct proto *p, | |
162 | struct ospf_neighbor *n) | |
163 | { | |
164 | struct ospf_lsa_header *plsa,lsa; | |
165 | struct top_hash_entry *he,*sn; | |
166 | struct top_graph *gr; | |
6d2b3211 OF |
167 | struct ospf_packet *op; |
168 | int i,j; | |
910e557b OF |
169 | |
170 | gr=n->ifa->oa->gr; | |
6d2b3211 | 171 | op=(struct ospf_packet *)ps; |
910e557b OF |
172 | |
173 | plsa=(void *)(ps+1); | |
6d2b3211 OF |
174 | |
175 | j=(ntohs(op->length)-sizeof(struct ospf_dbdes_packet))/ | |
176 | sizeof( struct ospf_lsa_header); | |
177 | ||
178 | for(i=0;i<j;i++) | |
179 | { | |
95eb1dba | 180 | ntohlsah(plsa+i, &lsa); |
95eb1dba OF |
181 | if(((he=ospf_hash_find(gr,lsa.id,lsa.rt,lsa.type))==NULL)|| |
182 | (lsa_comp(&lsa, &(he->lsa))==1)) | |
183 | { | |
394acced | 184 | /* Is this condition necessary? */ |
95eb1dba OF |
185 | if(ospf_hash_find(n->lsrqh,lsa.id,lsa.rt,lsa.type)==NULL) |
186 | { | |
187 | sn=ospf_hash_get(n->lsrqh,lsa.id,lsa.rt,lsa.type); | |
188 | ntohlsah(plsa+i, &(sn->lsa)); | |
189 | s_add_tail(&(n->lsrql), SNODE sn); | |
190 | } | |
191 | } | |
6d2b3211 | 192 | } |
4364b47e OF |
193 | } |
194 | ||
195 | void | |
196 | ospf_dbdes_rx(struct ospf_dbdes_packet *ps, struct proto *p, | |
197 | struct ospf_iface *ifa, u16 size) | |
198 | { | |
199 | u32 nrid, myrid; | |
200 | struct ospf_neighbor *n; | |
201 | u8 i; | |
202 | ||
203 | nrid=ntohl(((struct ospf_packet *)ps)->routerid); | |
204 | ||
205 | myrid=p->cf->global->router_id; | |
206 | ||
207 | if((n=find_neigh(ifa, nrid))==NULL) | |
208 | { | |
394920a0 | 209 | debug("%s: Received dbdes from unknown neigbor! %I\n", p->name, |
4364b47e OF |
210 | nrid); |
211 | return ; | |
212 | } | |
213 | ||
214 | if(ifa->iface->mtu<size) | |
215 | { | |
353f3261 | 216 | debug("%s: Received dbdes larger than MTU from %I!\n", p->name, n->ip); |
4364b47e OF |
217 | return ; |
218 | } | |
219 | ||
394920a0 OF |
220 | debug("%s: Received dbdes from %I via %s.\n", p->name, n->ip, |
221 | ifa->iface->name); | |
353f3261 | 222 | |
4364b47e OF |
223 | switch(n->state) |
224 | { | |
225 | case NEIGHBOR_DOWN: | |
226 | case NEIGHBOR_ATTEMPT: | |
227 | case NEIGHBOR_2WAY: | |
4364b47e OF |
228 | return; |
229 | break; | |
230 | case NEIGHBOR_INIT: | |
231 | ospf_neigh_sm(n, INM_2WAYREC); | |
232 | if(n->state!=NEIGHBOR_EXSTART) return; | |
233 | case NEIGHBOR_EXSTART: | |
04c6319a OF |
234 | if((ps->imms.bit.m && ps->imms.bit.ms && ps->imms.bit.i) |
235 | && (n->rid > myrid) && | |
4364b47e OF |
236 | (size == sizeof(struct ospf_dbdes_packet))) |
237 | { | |
238 | /* I'm slave! */ | |
910e557b OF |
239 | n->dds=ntohl(ps->ddseq); |
240 | n->ddr=ntohl(ps->ddseq); | |
4364b47e | 241 | n->options=ps->options; |
04c6319a | 242 | n->myimms.bit.ms=0; |
04c6319a | 243 | n->imms.byte=ps->imms.byte; |
353f3261 | 244 | debug("%s: I'm slave to %I. \n", p->name, n->ip); |
4364b47e | 245 | ospf_neigh_sm(n, INM_NEGDONE); |
910e557b OF |
246 | tm_stop(n->rxmt_timer); |
247 | ospf_dbdes_tx(n); | |
248 | break; | |
4364b47e OF |
249 | } |
250 | else | |
251 | { | |
04c6319a | 252 | if(((ps->imms.bit.i==0) && (ps->imms.bit.ms==0)) && |
910e557b | 253 | (n->rid < myrid) && (n->dds == ntohl(ps->ddseq))) |
4364b47e OF |
254 | { |
255 | /* I'm master! */ | |
256 | n->options=ps->options; | |
910e557b | 257 | n->ddr=ntohl(ps->ddseq)-1; |
04c6319a | 258 | n->imms.byte=ps->imms.byte; |
44724025 | 259 | debug("%s: I'm master to %I. \n", p->name, nrid); |
4364b47e OF |
260 | ospf_neigh_sm(n, INM_NEGDONE); |
261 | } | |
262 | else | |
263 | { | |
353f3261 | 264 | DBG("%s: Nothing happend to %I (imms=%u)\n", p->name, n->ip, |
910e557b | 265 | ps->imms.byte); |
4364b47e OF |
266 | break; |
267 | } | |
268 | } | |
394920a0 | 269 | if(ps->imms.bit.i) break; |
4364b47e | 270 | case NEIGHBOR_EXCHANGE: |
04c6319a | 271 | if((ps->imms.byte==n->imms.byte) && (ps->options=n->options) && |
910e557b | 272 | (ntohl(ps->ddseq)==n->ddr)) |
4364b47e OF |
273 | { |
274 | /* Duplicate packet */ | |
353f3261 | 275 | debug("%s: Received duplicate dbdes from %I!\n", p->name, n->ip); |
04c6319a | 276 | if(n->imms.bit.ms==0) |
4364b47e OF |
277 | { |
278 | ospf_dbdes_tx(n); | |
279 | } | |
280 | return; | |
281 | } | |
282 | ||
910e557b OF |
283 | n->ddr=ntohl(ps->ddseq); |
284 | ||
285 | if(ps->imms.bit.ms!=n->imms.bit.ms) /* M/S bit differs */ | |
4364b47e | 286 | { |
394920a0 | 287 | debug("SEQMIS-BIT-MS\n"); |
4364b47e OF |
288 | ospf_neigh_sm(n, INM_SEQMIS); |
289 | break; | |
290 | } | |
291 | ||
04c6319a | 292 | if(ps->imms.bit.i) /* I bit is set */ |
4364b47e | 293 | { |
394920a0 | 294 | debug("SEQMIS-BIT-I\n"); |
4364b47e OF |
295 | ospf_neigh_sm(n, INM_SEQMIS); |
296 | break; | |
297 | } | |
298 | ||
2560c886 OF |
299 | n->imms.byte=ps->imms.byte; |
300 | ||
4364b47e OF |
301 | if(ps->options!=n->options) /* Options differs */ |
302 | { | |
394920a0 | 303 | debug("SEQMIS-OPT\n"); |
4364b47e OF |
304 | ospf_neigh_sm(n, INM_SEQMIS); |
305 | break; | |
306 | } | |
307 | ||
04c6319a | 308 | if(n->myimms.bit.ms) |
4364b47e | 309 | { |
910e557b | 310 | if(ntohl(ps->ddseq)!=n->dds) /* MASTER */ |
4364b47e | 311 | { |
394920a0 | 312 | debug("SEQMIS-MASTER\n"); |
4364b47e OF |
313 | ospf_neigh_sm(n, INM_SEQMIS); |
314 | break; | |
315 | } | |
910e557b OF |
316 | n->dds++; |
317 | DBG("Incrementing dds\n"); | |
318 | ospf_dbdes_reqladd(ps,p,n); | |
319 | if((n->myimms.bit.m==0) && (ps->imms.bit.m==0)) | |
320 | { | |
321 | ospf_neigh_sm(n, INM_EXDONE); | |
322 | } | |
323 | else | |
324 | { | |
325 | ospf_dbdes_tx(n); | |
326 | } | |
327 | ||
4364b47e OF |
328 | } |
329 | else | |
330 | { | |
2560c886 | 331 | if(ntohl(ps->ddseq)!=(n->dds+1)) /* SLAVE */ |
4364b47e | 332 | { |
394920a0 | 333 | debug("SEQMIS-SLAVE\n"); |
4364b47e OF |
334 | ospf_neigh_sm(n, INM_SEQMIS); |
335 | break; | |
336 | } | |
2560c886 OF |
337 | n->ddr=ntohl(ps->ddseq); |
338 | n->dds=ntohl(ps->ddseq); | |
910e557b OF |
339 | ospf_dbdes_reqladd(ps,p,n); |
340 | ospf_dbdes_tx(n); | |
4364b47e OF |
341 | } |
342 | ||
4364b47e OF |
343 | break; |
344 | case NEIGHBOR_LOADING: | |
345 | case NEIGHBOR_FULL: | |
04c6319a | 346 | if((ps->imms.byte==n->imms.byte) && (ps->options=n->options) && |
4364b47e OF |
347 | (ps->ddseq==n->dds)) /* Only duplicate are accepted */ |
348 | { | |
353f3261 | 349 | debug("%s: Received duplicate dbdes from %I!\n", p->name, n->ip); |
4364b47e OF |
350 | return; |
351 | } | |
352 | else | |
353 | { | |
394920a0 | 354 | debug("SEQMIS-FULL\n"); |
4364b47e OF |
355 | ospf_neigh_sm(n, INM_SEQMIS); |
356 | } | |
357 | break; | |
358 | defaut: | |
df49d4e1 | 359 | die("%s: Received dbdes from %I in unknown state.", p->name, n->ip); |
4364b47e OF |
360 | break; |
361 | } | |
362 | } | |
363 |