]>
git.proxmox.com Git - mirror_frr.git/blob - babeld/resend.c
1 // SPDX-License-Identifier: MIT
3 Copyright (c) 2007, 2008 by Juliusz Chroboczek
18 #include "babel_main.h"
21 #include "neighbour.h"
24 #include "babel_interface.h"
26 struct timeval resend_time
= {0, 0};
27 struct resend
*to_resend
= NULL
;
30 resend_match(struct resend
*resend
,
31 int kind
, const unsigned char *prefix
, unsigned char plen
)
33 return (resend
->kind
== kind
&&
34 resend
->plen
== plen
&& memcmp(resend
->prefix
, prefix
, 16) == 0);
37 /* This is called by neigh.c when a neighbour is flushed */
40 flush_resends(struct neighbour
*neigh
)
45 static struct resend
*
46 find_resend(int kind
, const unsigned char *prefix
, unsigned char plen
,
47 struct resend
**previous_return
)
49 struct resend
*current
, *previous
;
54 if(resend_match(current
, kind
, prefix
, plen
)) {
56 *previous_return
= previous
;
60 current
= current
->next
;
67 find_request(const unsigned char *prefix
, unsigned char plen
,
68 struct resend
**previous_return
)
70 return find_resend(RESEND_REQUEST
, prefix
, plen
, previous_return
);
74 record_resend(int kind
, const unsigned char *prefix
, unsigned char plen
,
75 unsigned short seqno
, const unsigned char *id
,
76 struct interface
*ifp
, int delay
)
78 struct resend
*resend
;
79 unsigned int ifindex
= ifp
? ifp
->ifindex
: 0;
81 if((kind
== RESEND_REQUEST
&&
82 input_filter(NULL
, prefix
, plen
, NULL
, ifindex
) >= INFINITY
) ||
83 (kind
== RESEND_UPDATE
&&
84 output_filter(NULL
, prefix
, plen
, ifindex
) >= INFINITY
))
90 resend
= find_resend(kind
, prefix
, plen
, NULL
);
92 if(resend
->delay
&& delay
)
93 resend
->delay
= MIN(resend
->delay
, delay
);
95 resend
->delay
= delay
;
96 resend
->time
= babel_now
;
97 resend
->max
= RESEND_MAX
;
98 if(id
&& memcmp(resend
->id
, id
, 8) == 0 &&
99 seqno_compare(resend
->seqno
, seqno
) > 0) {
103 memcpy(resend
->id
, id
, 8);
105 memset(resend
->id
, 0, 8);
106 resend
->seqno
= seqno
;
107 if(resend
->ifp
!= ifp
)
110 resend
= malloc(sizeof(struct resend
));
114 resend
->max
= RESEND_MAX
;
115 resend
->delay
= delay
;
116 memcpy(resend
->prefix
, prefix
, 16);
118 resend
->seqno
= seqno
;
120 memcpy(resend
->id
, id
, 8);
122 memset(resend
->id
, 0, 8);
124 resend
->time
= babel_now
;
125 resend
->next
= to_resend
;
130 struct timeval timeout
;
131 timeval_add_msec(&timeout
, &resend
->time
, resend
->delay
);
132 timeval_min(&resend_time
, &timeout
);
138 resend_expired(struct resend
*resend
)
140 switch(resend
->kind
) {
142 return timeval_minus_msec(&babel_now
, &resend
->time
) >= REQUEST_TIMEOUT
;
144 return resend
->max
<= 0;
149 unsatisfied_request(const unsigned char *prefix
, unsigned char plen
,
150 unsigned short seqno
, const unsigned char *id
)
152 struct resend
*request
;
154 request
= find_request(prefix
, plen
, NULL
);
155 if(request
== NULL
|| resend_expired(request
))
158 if(memcmp(request
->id
, id
, 8) != 0 ||
159 seqno_compare(request
->seqno
, seqno
) <= 0)
165 /* Determine whether a given request should be forwarded. */
167 request_redundant(struct interface
*ifp
,
168 const unsigned char *prefix
, unsigned char plen
,
169 unsigned short seqno
, const unsigned char *id
)
171 struct resend
*request
;
173 request
= find_request(prefix
, plen
, NULL
);
174 if(request
== NULL
|| resend_expired(request
))
177 if(memcmp(request
->id
, id
, 8) == 0 &&
178 seqno_compare(request
->seqno
, seqno
) > 0)
181 if(request
->ifp
!= NULL
&& request
->ifp
!= ifp
)
185 /* Will be resent. */
188 if(timeval_minus_msec(&babel_now
, &request
->time
) <
189 (ifp
? MIN(babel_get_if_nfo(ifp
)->hello_interval
, 1000) : 1000))
197 satisfy_request(const unsigned char *prefix
, unsigned char plen
,
198 unsigned short seqno
, const unsigned char *id
,
199 struct interface
*ifp
)
201 struct resend
*request
, *previous
;
203 request
= find_request(prefix
, plen
, &previous
);
207 if(ifp
!= NULL
&& request
->ifp
!= ifp
)
210 if(memcmp(request
->id
, id
, 8) != 0 ||
211 seqno_compare(request
->seqno
, seqno
) <= 0) {
212 /* We cannot remove the request, as we may be walking the list right
213 now. Mark it as expired, so that expire_resend will remove it. */
215 request
->time
.tv_sec
= 0;
216 recompute_resend_time();
226 struct resend
*current
, *previous
;
232 if(resend_expired(current
)) {
233 if(previous
== NULL
) {
234 to_resend
= current
->next
;
238 previous
->next
= current
->next
;
240 current
= previous
->next
;
245 current
= current
->next
;
249 recompute_resend_time();
253 recompute_resend_time(void)
255 struct resend
*request
;
256 struct timeval resend
= {0, 0};
260 if(!resend_expired(request
) && request
->delay
> 0 && request
->max
> 0) {
261 struct timeval timeout
;
262 timeval_add_msec(&timeout
, &request
->time
, request
->delay
);
263 timeval_min(&resend
, &timeout
);
265 request
= request
->next
;
268 resend_time
= resend
;
274 struct resend
*resend
;
278 if(!resend_expired(resend
) && resend
->delay
> 0 && resend
->max
> 0) {
279 struct timeval timeout
;
280 timeval_add_msec(&timeout
, &resend
->time
, resend
->delay
);
281 if(timeval_compare(&babel_now
, &timeout
) >= 0) {
282 switch(resend
->kind
) {
284 send_multihop_request(resend
->ifp
,
285 resend
->prefix
, resend
->plen
,
286 resend
->seqno
, resend
->id
, 127);
289 send_update(resend
->ifp
, 1,
290 resend
->prefix
, resend
->plen
);
294 resend
->delay
= MIN(0xFFFF, resend
->delay
* 2);
298 resend
= resend
->next
;
300 recompute_resend_time();