3 static spinlock_t conn_credits_lock
;
5 /* credit_lock must be held while calling this */
6 int refresh_credits_state(struct neighbor
*nb
)
8 long jiffies_tmp
= jiffies
;
10 __s64 creditrate
= 1000 * ((__s64
)(nb
->creditrate_initial
+
11 nb
->creditrate_earning
- nb
->creditrate_spending
));
13 __s64 crediterrorrate
= 1000 * ((__s64
)(nb
->creditrate_spending
-
14 nb
->creditrate_spending_expected
)) -
16 * tolerance is 50% of creditsrate_initial + 2.5% of
17 * both spending+earning
19 500 * ((__s64
)(nb
->creditrate_initial
)) -
20 25 * ((__s64
)(nb
->creditrate_spending_expected
)) -
21 25 * ((__s64
)(nb
->creditrate_earning
));
23 __s64 debitrate
= 1000 * ((__s64
)(nb
->debitrate_initial
+
24 nb
->debitrate_initial_adj
+ nb
->debitrate_earning
-
25 nb
->debitrate_spending
));
28 __s64 credits_adj
= (jiffies_tmp
- nb
->jiffies_credit_update
) *
29 creditrate
+ nb
->credits_fract
;
31 __s64 creditsd_adj
= (jiffies_tmp
- nb
->jiffies_credit_update
) *
32 crediterrorrate
+ nb
->credits_diff_fract
;
34 __s64 debits_adj
= (jiffies_tmp
- nb
->jiffies_credit_update
) *
35 debitrate
+ nb
->debits_fract
;
38 nb
->jiffies_credit_update
= jiffies_tmp
;
41 if (unlikely(credits_adj
< 0 && (nb
->credits
< -(credits_adj
/HZ
)))) {
43 nb
->credits_fract
= 0;
45 nb
->credits
+= credits_adj
/ HZ
;
46 nb
->credits_fract
= credits_adj
% HZ
;
49 if (unlikely(creditsd_adj
< 0 && (nb
->credits_diff
<
50 -(creditsd_adj
/HZ
)))) {
52 nb
->credits_diff_fract
= 0;
54 nb
->credits_diff
+= creditsd_adj
/ HZ
;
55 nb
->credits_diff_fract
= creditsd_adj
% HZ
;
58 if (unlikely(debits_adj
< 0 && (nb
->debits
< -(debits_adj
/HZ
)))) {
64 nb
->debits
+= debits_adj
/ HZ
;
65 nb
->debits_fract
= debits_adj
% HZ
;
71 void check_credit_state(struct neighbor
*nb
)
76 struct list_head
*currlh
;
79 spin_lock_irqsave( &(nb
->credits_lock
), iflags
);
80 refresh_credits_state(nb
);
81 resetconns
= (nb
->debits
== 0 && ((
82 (__s64
) nb
->debitrate_initial_adj
+
83 (__s64
) nb
->debitrate_earning
-
84 (__s64
) nb
->debitrate_spending
) < 0));
85 spin_unlock_irqrestore( &(nb
->credits_lock
), iflags
);
87 if (likely(resetconns
== 0)) {
88 if (unlikely(sendcredits
))
95 mutex_lock(&(nb
->conn_list_lock
));
96 BUG_ON(list_empty(&(nb
->snd_conn_list
)) && nb
->num_send_conns
!= 0);
97 currlh
= nb
->snd_conn_list
.next
;
99 while (currlh
!= &(nb
->snd_conn_list
)) {
101 struct conn
*sconn
= container_of(currlh
, struct conn
,
103 struct conn
*rconn
= sconn
->reversedir
;
105 mutex_lock(&(rconn
->rcv_lock
));
106 BUG_ON(sconn
->targettype
!= TARGET_OUT
);
107 BUG_ON(rconn
->sourcetype
!= SOURCE_IN
);
109 spin_lock_irqsave(&conn_credits_lock
, iflags
);
110 if (rconn
->targettype
== TARGET_UNCONNECTED
||
111 (rconn
->targettype
== TARGET_SOCK
&&
112 rconn
->target
.sock
.credituser
!= 0))
115 ispaying
= (sconn
->recp_crate
> rconn
->sender_crate
);
116 spin_unlock_irqrestore(&conn_credits_lock
, iflags
);
118 mutex_unlock(&(rconn
->rcv_lock
));
122 * reset_conn must not be called with conn_list_lock
125 mutex_unlock(&(nb
->conn_list_lock
));
129 currlh
= currlh
->next
;
135 int debit_adj_needed(struct neighbor
*nb
)
138 unsigned long iflags
;
140 spin_lock_irqsave( &(nb
->credits_lock
), iflags
);
142 refresh_credits_state(nb
);
144 expected_adj
= nb
->creditrate_initial
- nb
->credits_diff
/10000;
145 if (unlikely((expected_adj
< 0 || nb
->debitrate_initial_adj
< 0) &&
146 ( (expected_adj
* 2 < nb
->debitrate_initial_adj
) ||
147 (expected_adj
> nb
->debitrate_initial_adj
* 2) ))) {
148 nb
->debitrate_initial_adj
= (nb
->debitrate_initial_adj
* 15 +
153 spin_unlock_irqrestore( &(nb
->credits_lock
), iflags
);
158 void set_credits(struct neighbor
*nb
, __u64 credits
, __s32 creditrate_initial
,
159 __u32 creditrate_earning
, __u32 creditrate_spending
)
161 unsigned long iflags
;
163 spin_lock_irqsave( &(nb
->credits_lock
), iflags
);
165 refresh_credits_state(nb
);
167 if (nb
->credits_diff
+ nb
->credits
< credits
)
168 nb
->credits_diff
= 0;
170 nb
->credits_diff
+= nb
->credits
- credits
;
171 nb
->credits
= credits
;
172 nb
->creditrate_initial
= creditrate_initial
;
173 nb
->creditrate_earning
= creditrate_earning
;
174 nb
->creditrate_spending
= creditrate_spending
;
176 spin_unlock_irqrestore( &(nb
->credits_lock
), iflags
);
179 void set_debitrate_initial(struct neighbor
*nb
, __u32 debitrate
)
181 unsigned long iflags
;
183 spin_lock_irqsave( &(nb
->credits_lock
), iflags
);
185 refresh_credits_state(nb
);
186 nb
->debitrate_initial
= debitrate
;
188 spin_unlock_irqrestore( &(nb
->credits_lock
), iflags
);
193 static __u32
credit_exchange_in(struct neighbor
*nb
, __u32 crate_in_raw
)
195 unsigned long iflags
;
197 spin_lock_irqsave( &(nb
->credits_lock
), iflags
);
198 if (unlikely(nb
->debits
== 0))
201 ret
= multiply_div(nb
->credits
, crate_in_raw
, nb
->debits
);
202 spin_unlock_irqrestore( &(nb
->credits_lock
), iflags
);
204 if ((ret
>> 32) != 0)
209 static void refresh_conn_crates(struct conn
*conn
)
211 if (conn
->sourcetype
== SOURCE_NONE
) {
212 conn
->sender_crate
= conn
->reversedir
->recp_crate
;
213 } else if (conn
->sourcetype
== SOURCE_IN
) {
214 conn
->sender_crate
= credit_exchange_in(conn
->source
.in
.nb
,
215 conn
->source
.in
.crate_in_raw
);
216 } else if (conn
->sourcetype
== SOURCE_SOCK
) {
217 BUG_ON(conn
->reversedir
->target
.sock
.credituser
== 1 &&
218 conn
->targettype
== TARGET_SOCK
&&
219 conn
->reversedir
->recp_crate
!= 0);
222 if ((conn
->source
.sock
.crate
+ conn
->reversedir
->recp_crate
) <
223 conn
->reversedir
->recp_crate
|| (
224 conn
->reversedir
->recp_crate
+
225 conn
->source
.sock
.crate
) > MAX_CREDITRATE_SOCK
)
226 conn
->sender_crate
= MAX_CREDITRATE_SOCK
;
228 conn
->sender_crate
= conn
->reversedir
->recp_crate
+
229 conn
->source
.sock
.crate
;
234 if (conn
->targettype
== TARGET_UNCONNECTED
) {
235 conn
->recp_crate
= conn
->sender_crate
;
236 conn
->reversedir
->sender_crate
= conn
->recp_crate
;
237 } else if ((conn
->targettype
== TARGET_SOCK
&&
238 conn
->target
.sock
.credituser
== 0)) {
239 conn
->recp_crate
= conn
->sender_crate
;
240 conn
->reversedir
->sender_crate
= conn
->recp_crate
+
241 conn
->reversedir
->source
.sock
.crate
;
245 static void _refresh_conn_credits(struct conn
*conn
)
247 long jiffies_tmp
= jiffies
;
249 __u32 scrate
= conn
->sender_crate
;
250 __u32 rcrate
= conn
->recp_crate
;
254 refresh_conn_crates(conn
);
256 refresh_conn_crates(conn
);
258 /* 500 and not 1000 here: 1000 * (*_crate + *rate)/2 = 500 * ... */
259 diff
= 500 * ((__s64
) conn
->sender_crate
+ (__s64
) scrate
-
260 (__s64
) conn
->recp_crate
- (__s64
) rcrate
) * (
261 jiffies_tmp
- conn
->jiffies_credit_update
) +
264 conn
->credits
+= diff
/ HZ
;
265 conn
->credits_fract
= diff
% HZ
;
267 conn
->jiffies_credit_update
= jiffies_tmp
;
271 * locked for access to credits + source.* + target.*
272 * lock both sides, if either source or target is not out/in
274 static __u32
credits_lock_conn(struct conn
*conn
)
277 mutex_lock(&(conn
->rcv_lock
));
278 if (conn
->sourcetype
!= SOURCE_IN
) {
279 mutex_unlock(&(conn
->rcv_lock
));
281 mutex_lock(&(conn
->reversedir
->rcv_lock
));
282 mutex_lock(&(conn
->rcv_lock
));
285 } else if (conn
->targettype
!= TARGET_OUT
) {
286 mutex_lock(&(conn
->reversedir
->rcv_lock
));
293 static void credits_unlock_conn(struct conn
*conn
, __u32 hints
)
295 if ((hints
& 1) != 0)
296 mutex_unlock(&(conn
->rcv_lock
));
297 if ((hints
& 2) != 0)
298 mutex_unlock(&(conn
->reversedir
->rcv_lock
));
299 if ((hints
& 4) != 0)
300 mutex_unlock(&(conn
->rcv_lock
));
303 void refresh_conn_credits(struct conn
*conn
)
305 unsigned long iflags
;
306 __u32 unlockhints
= credits_lock_conn(conn
);
308 if (unlikely(conn
->targettype
== TARGET_SOCK
&&
309 conn
->reversedir
->targettype
== TARGET_SOCK
&&
310 conn
->target
.sock
.credituser
== 0 &&
311 conn
->reversedir
->target
.sock
.credituser
== 0))
313 spin_lock_irqsave(&conn_credits_lock
, iflags
);
315 _refresh_conn_credits(conn
);
316 refresh_conn_crates(conn
);
318 spin_unlock_irqrestore(&conn_credits_lock
, iflags
);
320 credits_unlock_conn(conn
, unlockhints
);
323 void set_conn_in_crate(struct conn
*rconn
, __u32 crate_in
)
325 unsigned long iflags
;
327 __u32 unlockhints
= credits_lock_conn(rconn
);
328 spin_lock_irqsave(&conn_credits_lock
, iflags
);
330 BUG_ON(rconn
->sourcetype
!= SOURCE_IN
);
331 _refresh_conn_credits(rconn
);
332 rconn
->source
.in
.crate_in_raw
= crate_in
;
333 refresh_conn_crates(rconn
);
335 spin_unlock_irqrestore(&conn_credits_lock
, iflags
);
336 credits_unlock_conn(rconn
, unlockhints
);
339 int __init
cor_credits_init(void)
341 spin_lock_init(&conn_credits_lock
);