]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/dbdes.c
4 * (c) 1999 - 2000 Ondrej Filip <feela@network.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
12 * ospf_dbdes_tx - transmit database description packet
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
22 ospf_dbdes_tx(struct ospf_neighbor
*n
)
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
;
33 if((oa
->rt
==NULL
)||(EMPTY_LIST(oa
->lsal
))) originate_rt_lsa(oa
);
37 p
=(struct proto
*)(ifa
->proto
);
41 case NEIGHBOR_EXSTART
: /* Send empty packets */
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
;
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
,
58 case NEIGHBOR_EXCHANGE
:
61 if(((n
->myimms
.bit
.ms
) && (n
->dds
==n
->ddr
+1)) ||
62 ((!(n
->myimms
.bit
.ms
)) && (n
->dds
==n
->ddr
)))
64 snode
*sn
; /* Send next */
65 struct ospf_lsa_header
*lsa
;
68 op
=(struct ospf_packet
*)pkt
;
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
);
75 j
=i
=(ifa
->iface
->mtu
-sizeof(struct ospf_dbdes_packet
)-SIPH
)/
76 sizeof(struct ospf_lsa_header
); /* Number of possible lsaheaders to send */
77 lsa
=(n
->ldbdes
+sizeof(struct ospf_dbdes_packet
));
83 DBG("Number of LSA: %d\n", j
);
86 struct top_hash_entry
*en
;
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
);
94 if(sn
==STAIL(n
->ifa
->oa
->lsal
))
97 break; /* Should set some flag? */
103 if(sn
==STAIL(n
->ifa
->oa
->lsal
))
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 */
109 else s_put(&(n
->dbsi
),sn
);
112 pkt
->imms
.byte
=n
->myimms
.byte
;
114 length
=(j
-i
)*sizeof(struct ospf_lsa_header
)+
115 sizeof(struct ospf_dbdes_packet
);
116 op
->length
=htons(length
);
118 ospf_pkt_finalize(ifa
, op
);
119 DBG("%s: DB_DES (M) prepared for %I.\n", p
->name
, n
->ip
);
122 case NEIGHBOR_LOADING
:
127 length
=ntohs(op
->length
);
129 for(i
=0; i
<length
; i
++)
131 *(aa
+i
)=*(bb
+i
); /* Copy last sent packet again */
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
,
137 if(! n
->myimms
.bit
.ms
)
139 if((n
->myimms
.bit
.m
==0) && (n
->imms
.bit
.m
==0) &&
140 (n
->state
==NEIGHBOR_EXCHANGE
))
142 ospf_neigh_sm(n
, INM_EXDONE
);
147 default: /* Ignore it */
148 bug("Bug in dbdes sending");
154 ospf_dbdes_reqladd(struct ospf_dbdes_packet
*ps
, struct proto
*p
,
155 struct ospf_neighbor
*n
)
157 struct ospf_lsa_header
*plsa
,lsa
;
158 struct top_hash_entry
*he
,*sn
;
159 struct top_graph
*gr
;
160 struct ospf_packet
*op
;
164 op
=(struct ospf_packet
*)ps
;
168 j
=(ntohs(op
->length
)-sizeof(struct ospf_dbdes_packet
))/
169 sizeof( struct ospf_lsa_header
);
173 ntohlsah(plsa
+i
, &lsa
);
174 if(((he
=ospf_hash_find(gr
,lsa
.id
,lsa
.rt
,lsa
.type
))==NULL
)||
175 (lsa_comp(&lsa
, &(he
->lsa
))==1))
177 /* Is this condition necessary? */
178 if(ospf_hash_find(n
->lsrqh
,lsa
.id
,lsa
.rt
,lsa
.type
)==NULL
)
180 sn
=ospf_hash_get(n
->lsrqh
,lsa
.id
,lsa
.rt
,lsa
.type
);
181 ntohlsah(plsa
+i
, &(sn
->lsa
));
182 s_add_tail(&(n
->lsrql
), SNODE sn
);
189 ospf_dbdes_rx(struct ospf_dbdes_packet
*ps
, struct proto
*p
,
190 struct ospf_iface
*ifa
, u16 size
)
193 struct ospf_neighbor
*n
;
195 nrid
=ntohl(((struct ospf_packet
*)ps
)->routerid
);
197 myrid
=p
->cf
->global
->router_id
;
199 if((n
=find_neigh(ifa
, nrid
))==NULL
)
201 OSPF_TRACE(D_PACKETS
, "Received dbdes from unknown neigbor! %I.",
206 if(ifa
->iface
->mtu
<size
)
208 OSPF_TRACE(D_PACKETS
, "Received dbdes larger than MTU from %I!", n
->ip
);
212 OSPF_TRACE(D_PACKETS
, "Received dbdes from %I via %s.", n
->ip
,
214 ospf_neigh_sm(n
, INM_HELLOREC
);
219 case NEIGHBOR_ATTEMPT
:
224 ospf_neigh_sm(n
, INM_2WAYREC
);
225 if(n
->state
!=NEIGHBOR_EXSTART
) return;
226 case NEIGHBOR_EXSTART
:
227 if((ps
->imms
.bit
.m
&& ps
->imms
.bit
.ms
&& ps
->imms
.bit
.i
)
228 && (n
->rid
> myrid
) &&
229 (size
== sizeof(struct ospf_dbdes_packet
)))
232 n
->dds
=ntohl(ps
->ddseq
);
233 n
->ddr
=ntohl(ps
->ddseq
);
234 n
->options
=ps
->options
;
236 n
->imms
.byte
=ps
->imms
.byte
;
237 OSPF_TRACE(D_PACKETS
, "I'm slave to %I.", n
->ip
);
238 ospf_neigh_sm(n
, INM_NEGDONE
);
244 if(((ps
->imms
.bit
.i
==0) && (ps
->imms
.bit
.ms
==0)) &&
245 (n
->rid
< myrid
) && (n
->dds
== ntohl(ps
->ddseq
)))
248 n
->options
=ps
->options
;
249 n
->ddr
=ntohl(ps
->ddseq
)-1;
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
);
256 DBG("%s: Nothing happend to %I (imms=%u)\n", p
->name
, n
->ip
,
261 if(ps
->imms
.bit
.i
) break;
262 case NEIGHBOR_EXCHANGE
:
263 if((ps
->imms
.byte
==n
->imms
.byte
) && (ps
->options
==n
->options
) &&
264 (ntohl(ps
->ddseq
)==n
->ddr
))
266 /* Duplicate packet */
267 OSPF_TRACE(D_PACKETS
, "Received duplicate dbdes from %I.", n
->ip
);
268 if(n
->imms
.bit
.ms
==0)
275 n
->ddr
=ntohl(ps
->ddseq
);
277 if(ps
->imms
.bit
.ms
!=n
->imms
.bit
.ms
) /* M/S bit differs */
279 log("SEQMIS-BIT-MS\n");
280 ospf_neigh_sm(n
, INM_SEQMIS
);
284 if(ps
->imms
.bit
.i
) /* I bit is set */
286 log("SEQMIS-BIT-I\n");
287 ospf_neigh_sm(n
, INM_SEQMIS
);
291 n
->imms
.byte
=ps
->imms
.byte
;
293 if(ps
->options
!=n
->options
) /* Options differs */
296 ospf_neigh_sm(n
, INM_SEQMIS
);
302 if(ntohl(ps
->ddseq
)!=n
->dds
) /* MASTER */
304 log("SEQMIS-MASTER\n");
305 ospf_neigh_sm(n
, INM_SEQMIS
);
309 DBG("Incrementing dds\n");
310 ospf_dbdes_reqladd(ps
,p
,n
);
311 if((n
->myimms
.bit
.m
==0) && (ps
->imms
.bit
.m
==0))
313 ospf_neigh_sm(n
, INM_EXDONE
);
323 if(ntohl(ps
->ddseq
)!=(n
->dds
+1)) /* SLAVE */
325 log("SEQMIS-SLAVE\n");
326 ospf_neigh_sm(n
, INM_SEQMIS
);
329 n
->ddr
=ntohl(ps
->ddseq
);
330 n
->dds
=ntohl(ps
->ddseq
);
331 ospf_dbdes_reqladd(ps
,p
,n
);
336 case NEIGHBOR_LOADING
:
338 if((ps
->imms
.byte
==n
->imms
.byte
) && (ps
->options
==n
->options
) &&
339 (ntohl(ps
->ddseq
)==n
->ddr
)) /* Only duplicate are accepted */
341 OSPF_TRACE(D_PACKETS
, "Received duplicate dbdes from %I.",n
->ip
);
346 log("SEQMIS-FULL\n");
347 ospf_neigh_sm(n
, INM_SEQMIS
);
351 bug("%s: Received dbdes from %I in undefined state.", p
->name
, n
->ip
);