]>
git.proxmox.com Git - mirror_frr.git/blob - babeld/resend.c
2 * This file is free software: you may copy, redistribute and/or modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation, either version 2 of the License, or (at your
5 * option) any later version.
7 * This file is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 * This file incorporates work covered by the following copyright and
18 Copyright (c) 2007, 2008 by Juliusz Chroboczek
20 Permission is hereby granted, free of charge, to any person obtaining a copy
21 of this software and associated documentation files (the "Software"), to deal
22 in the Software without restriction, including without limitation the rights
23 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24 copies of the Software, and to permit persons to whom the Software is
25 furnished to do so, subject to the following conditions:
27 The above copyright notice and this permission notice shall be included in
28 all copies or substantial portions of the Software.
30 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47 #include "babel_main.h"
50 #include "neighbour.h"
53 #include "babel_interface.h"
55 struct timeval resend_time
= {0, 0};
56 struct resend
*to_resend
= NULL
;
59 resend_match(struct resend
*resend
,
60 int kind
, const unsigned char *prefix
, unsigned char plen
)
62 return (resend
->kind
== kind
&&
63 resend
->plen
== plen
&& memcmp(resend
->prefix
, prefix
, 16) == 0);
66 /* This is called by neigh.c when a neighbour is flushed */
69 flush_resends(struct neighbour
*neigh
)
74 static struct resend
*
75 find_resend(int kind
, const unsigned char *prefix
, unsigned char plen
,
76 struct resend
**previous_return
)
78 struct resend
*current
, *previous
;
83 if(resend_match(current
, kind
, prefix
, plen
)) {
85 *previous_return
= previous
;
89 current
= current
->next
;
96 find_request(const unsigned char *prefix
, unsigned char plen
,
97 struct resend
**previous_return
)
99 return find_resend(RESEND_REQUEST
, prefix
, plen
, previous_return
);
103 record_resend(int kind
, const unsigned char *prefix
, unsigned char plen
,
104 unsigned short seqno
, const unsigned char *id
,
105 struct interface
*ifp
, int delay
)
107 struct resend
*resend
;
108 unsigned int ifindex
= ifp
? ifp
->ifindex
: 0;
110 if((kind
== RESEND_REQUEST
&&
111 input_filter(NULL
, prefix
, plen
, NULL
, ifindex
) >= INFINITY
) ||
112 (kind
== RESEND_UPDATE
&&
113 output_filter(NULL
, prefix
, plen
, ifindex
) >= INFINITY
))
119 resend
= find_resend(kind
, prefix
, plen
, NULL
);
121 if(resend
->delay
&& delay
)
122 resend
->delay
= MIN(resend
->delay
, delay
);
124 resend
->delay
= delay
;
125 resend
->time
= babel_now
;
126 resend
->max
= RESEND_MAX
;
127 if(id
&& memcmp(resend
->id
, id
, 8) == 0 &&
128 seqno_compare(resend
->seqno
, seqno
) > 0) {
132 memcpy(resend
->id
, id
, 8);
134 memset(resend
->id
, 0, 8);
135 resend
->seqno
= seqno
;
136 if(resend
->ifp
!= ifp
)
139 resend
= malloc(sizeof(struct resend
));
143 resend
->max
= RESEND_MAX
;
144 resend
->delay
= delay
;
145 memcpy(resend
->prefix
, prefix
, 16);
147 resend
->seqno
= seqno
;
149 memcpy(resend
->id
, id
, 8);
151 memset(resend
->id
, 0, 8);
153 resend
->time
= babel_now
;
154 resend
->next
= to_resend
;
159 struct timeval timeout
;
160 timeval_add_msec(&timeout
, &resend
->time
, resend
->delay
);
161 timeval_min(&resend_time
, &timeout
);
167 resend_expired(struct resend
*resend
)
169 switch(resend
->kind
) {
171 return timeval_minus_msec(&babel_now
, &resend
->time
) >= REQUEST_TIMEOUT
;
173 return resend
->max
<= 0;
178 unsatisfied_request(const unsigned char *prefix
, unsigned char plen
,
179 unsigned short seqno
, const unsigned char *id
)
181 struct resend
*request
;
183 request
= find_request(prefix
, plen
, NULL
);
184 if(request
== NULL
|| resend_expired(request
))
187 if(memcmp(request
->id
, id
, 8) != 0 ||
188 seqno_compare(request
->seqno
, seqno
) <= 0)
194 /* Determine whether a given request should be forwarded. */
196 request_redundant(struct interface
*ifp
,
197 const unsigned char *prefix
, unsigned char plen
,
198 unsigned short seqno
, const unsigned char *id
)
200 struct resend
*request
;
202 request
= find_request(prefix
, plen
, NULL
);
203 if(request
== NULL
|| resend_expired(request
))
206 if(memcmp(request
->id
, id
, 8) == 0 &&
207 seqno_compare(request
->seqno
, seqno
) > 0)
210 if(request
->ifp
!= NULL
&& request
->ifp
!= ifp
)
214 /* Will be resent. */
217 if(timeval_minus_msec(&babel_now
, &request
->time
) <
218 (ifp
? MIN(babel_get_if_nfo(ifp
)->hello_interval
, 1000) : 1000))
226 satisfy_request(const unsigned char *prefix
, unsigned char plen
,
227 unsigned short seqno
, const unsigned char *id
,
228 struct interface
*ifp
)
230 struct resend
*request
, *previous
;
232 request
= find_request(prefix
, plen
, &previous
);
236 if(ifp
!= NULL
&& request
->ifp
!= ifp
)
239 if(memcmp(request
->id
, id
, 8) != 0 ||
240 seqno_compare(request
->seqno
, seqno
) <= 0) {
241 /* We cannot remove the request, as we may be walking the list right
242 now. Mark it as expired, so that expire_resend will remove it. */
244 request
->time
.tv_sec
= 0;
245 recompute_resend_time();
255 struct resend
*current
, *previous
;
261 if(resend_expired(current
)) {
262 if(previous
== NULL
) {
263 to_resend
= current
->next
;
267 previous
->next
= current
->next
;
269 current
= previous
->next
;
274 current
= current
->next
;
278 recompute_resend_time();
282 recompute_resend_time()
284 struct resend
*request
;
285 struct timeval resend
= {0, 0};
289 if(!resend_expired(request
) && request
->delay
> 0 && request
->max
> 0) {
290 struct timeval timeout
;
291 timeval_add_msec(&timeout
, &request
->time
, request
->delay
);
292 timeval_min(&resend
, &timeout
);
294 request
= request
->next
;
297 resend_time
= resend
;
303 struct resend
*resend
;
307 if(!resend_expired(resend
) && resend
->delay
> 0 && resend
->max
> 0) {
308 struct timeval timeout
;
309 timeval_add_msec(&timeout
, &resend
->time
, resend
->delay
);
310 if(timeval_compare(&babel_now
, &timeout
) >= 0) {
311 switch(resend
->kind
) {
313 send_multihop_request(resend
->ifp
,
314 resend
->prefix
, resend
->plen
,
315 resend
->seqno
, resend
->id
, 127);
318 send_update(resend
->ifp
, 1,
319 resend
->prefix
, resend
->plen
);
323 resend
->delay
= MIN(0xFFFF, resend
->delay
* 2);
327 resend
= resend
->next
;
329 recompute_resend_time();