2 * Connection oriented routing
3 * Copyright (C) 2007-2023 Michael Blizek
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
19 static void _cor_neigh_waitingsconns_resume_accountbusytime(
20 struct cor_conn
*trgt_out_l
, __u32 priority
, __u32 burstprio
,
21 unsigned long jiffies_nb_lastduration
)
23 unsigned long jiffies_tmp
= jiffies
;
24 __u64 jiffies_nb_lastduration_shifted
= (jiffies_nb_lastduration
<<
25 JIFFIES_LAST_IDLE_SHIFT
);
28 if (trgt_out_l
->is_highlatency
!= 0) {
31 BUG_ON(burstprio
< priority
);
32 burstfactor
= div_u64(1024LL * (__u64
) burstprio
, priority
) * 2 -
34 BUG_ON(burstfactor
< 1024);
37 trgt_out_l
->trgt
.out
.jiffies_idle_since
+=
38 (jiffies_nb_lastduration_shifted
* burstfactor
) / 1024;
40 if (time_before(jiffies_tmp
<< JIFFIES_LAST_IDLE_SHIFT
,
41 trgt_out_l
->trgt
.out
.jiffies_idle_since
))
42 trgt_out_l
->trgt
.out
.jiffies_idle_since
=
43 jiffies_tmp
<< JIFFIES_LAST_IDLE_SHIFT
;
46 static int _cor_neigh_waitingsconns_resume_nbnotactive(struct cor_neighbor
*nb
)
48 struct cor_dev
*cd
= nb
->cd
;
51 spin_lock(&cd
->send_queue
.qlock
);
53 if (unlikely(cor_get_neigh_state(nb
) == NEIGHBOR_STATE_ACTIVE
)) {
54 spin_unlock(&cd
->send_queue
.qlock
);
58 if (likely(nb
->rb
.in_queue
== RB_INQUEUE_TRUE
)) {
60 cor_nb_kref_put_bug(nb
, "qos_queue_nb");
61 nb
->rb
.in_queue
= RB_INQUEUE_NBNOTACTIVE
;
62 BUG_ON(cd
->send_queue
.numconns
< nb
->conns_waiting
.cnt
);
63 cd
->send_queue
.numconns
-= nb
->conns_waiting
.cnt
;
64 BUG_ON(nb
->conns_waiting
.priority_sum
>
65 cd
->send_queue
.priority_sum
);
66 cd
->send_queue
.priority_sum
-= nb
->conns_waiting
.priority_sum
;
68 if (list_empty(&cd
->send_queue
.neighbors_waiting
) &&
69 list_empty(&cd
->send_queue
.neighbors_waiting_nextpass
)) {
70 BUG_ON(cd
->send_queue
.numconns
!= 0);
71 BUG_ON(cd
->send_queue
.priority_sum
!= 0);
76 cor_dev_queue_set_congstatus(cd
);
79 spin_unlock(&cd
->send_queue
.qlock
);
82 kref_put(&cd
->ref
, cor_dev_free
);
87 static __u32
_cor_neigh_waitingsconns_resume_burstprio(
88 struct cor_conn
*trgt_out_l
, __u32 priority
)
90 unsigned long idletime_hz_shifted
= cor_get_conn_idletime(trgt_out_l
);
91 __u32 idletime_msecs
= jiffies_to_msecs(idletime_hz_shifted
>>
92 JIFFIES_LAST_IDLE_SHIFT
);
95 if (trgt_out_l
->is_highlatency
!= 0) {
97 * negative burst for high latency conns:
104 BUG_ON(idletime_msecs
>
105 BURSTPRIO_MAXIDLETIME_HIGHLATENCY_SECS
* 1000);
106 BUG_ON(BURSTPRIO_MAXIDLETIME_HIGHLATENCY_SECS
* 1000LL >
109 burstfactor
= 768 - (768 * idletime_msecs
) /
110 (BURSTPRIO_MAXIDLETIME_HIGHLATENCY_SECS
* 1000);
112 newprio
= (((__u64
) priority
) * (512 + burstfactor
)) /
117 BUG_ON(idletime_msecs
>
118 BURSTPRIO_MAXIDLETIME_LOWLATENCY_SECS
* 1000);
119 BUG_ON(BURSTPRIO_MAXIDLETIME_LOWLATENCY_SECS
* 1000LL >
122 burstfactor
= (1024 * idletime_msecs
) /
123 (BURSTPRIO_MAXIDLETIME_LOWLATENCY_SECS
* 1000);
125 newprio
= (((__u64
) priority
) * (1024 + burstfactor
* 2)) /
129 BUG_ON(newprio
> U32_MAX
);
130 return (__u32
) newprio
;
133 static __u32
_cor_neigh_waitingsconns_resume_maxsend(
134 struct cor_conn
*trgt_out_l
, __u32 newpriority
,
135 int *maxsend_forcedelay
)
137 unsigned long iflags
;
139 struct cor_neighbor
*nb
= trgt_out_l
->trgt
.out
.nb
;
140 struct cor_dev
*cd
= nb
->cd
;
143 __u64 bytes_per_round
;
146 spin_lock_irqsave(&nb
->conns_waiting
.lock
, iflags
);
147 spin_lock(&cd
->send_queue
.qlock
);
149 if (unlikely(unlikely(trgt_out_l
->trgt
.out
.rb
.in_queue
!=
151 unlikely(nb
->rb
.in_queue
!= RB_INQUEUE_TRUE
))) {
152 spin_unlock(&cd
->send_queue
.qlock
);
153 spin_unlock_irqrestore(&nb
->conns_waiting
.lock
, iflags
);
158 BUG_ON(nb
->conns_waiting
.priority_sum
<
159 trgt_out_l
->trgt
.out
.rb_priority
);
160 BUG_ON(cd
->send_queue
.priority_sum
< trgt_out_l
->trgt
.out
.rb_priority
);
161 nb
->conns_waiting
.priority_sum
-= trgt_out_l
->trgt
.out
.rb_priority
;
162 cd
->send_queue
.priority_sum
-= trgt_out_l
->trgt
.out
.rb_priority
;
164 #warning todo remove priority_sum
165 BUG_ON(nb
->conns_waiting
.priority_sum
+ newpriority
<
166 nb
->conns_waiting
.priority_sum
);
167 BUG_ON(cd
->send_queue
.priority_sum
+ newpriority
< cd
->send_queue
.priority_sum
);
168 nb
->conns_waiting
.priority_sum
+= newpriority
;
169 cd
->send_queue
.priority_sum
+= newpriority
;
170 trgt_out_l
->trgt
.out
.rb_priority
= newpriority
;
172 priority_sum
= cd
->send_queue
.priority_sum
;
173 numconns
= cd
->send_queue
.numconns
;
175 spin_unlock(&cd
->send_queue
.qlock
);
176 spin_unlock_irqrestore(&nb
->conns_waiting
.lock
, iflags
);
179 *maxsend_forcedelay
= 1;
180 bytes_per_round
= 2048;
182 *maxsend_forcedelay
= 0;
183 bytes_per_round
= 1024;
186 ret
= div_u64(bytes_per_round
* ((__u64
) newpriority
) *
187 ((__u64
) numconns
), priority_sum
);
188 if (unlikely(ret
> U32_MAX
))
193 static int _cor_neigh_waitingsconns_resume_nextpass(
194 struct cor_neighbor
*nb_waitingconnslocked
)
196 BUG_ON(list_empty(&nb_waitingconnslocked
->conns_waiting
.lh
) == 0);
198 if (list_empty(&nb_waitingconnslocked
->conns_waiting
.lh_nextpass
)) {
199 BUG_ON(nb_waitingconnslocked
->conns_waiting
.cnt
!= 0);
203 BUG_ON(nb_waitingconnslocked
->conns_waiting
.cnt
== 0);
205 cor_swap_list_items(&nb_waitingconnslocked
->conns_waiting
.lh
,
206 &nb_waitingconnslocked
->conns_waiting
.lh_nextpass
);
211 int cor_neigh_waitingsconns_resume(struct cor_dev
*cd
, struct cor_neighbor
*nb
,
212 unsigned long jiffies_nb_lastduration
, int *progress
)
214 unsigned long iflags
;
220 int maxsend_forcedelay
= 0;
225 struct cor_conn
*cn
= 0;
227 spin_lock_irqsave(&nb
->conns_waiting
.lock
, iflags
);
228 if (list_empty(&nb
->conns_waiting
.lh
) != 0) {
229 int done
= _cor_neigh_waitingsconns_resume_nextpass(nb
);
231 spin_unlock_irqrestore(&nb
->conns_waiting
.lock
, iflags
);
232 return done
? QOS_RESUME_DONE
: QOS_RESUME_NEXTNEIGHBOR
;
234 BUG_ON(nb
->conns_waiting
.cnt
== 0);
236 cn
= container_of(nb
->conns_waiting
.lh
.next
, struct cor_conn
,
238 BUG_ON(cn
->targettype
!= TARGET_OUT
);
239 BUG_ON(cn
->trgt
.out
.rb
.lh
.prev
!= &nb
->conns_waiting
.lh
);
240 BUG_ON((cn
->trgt
.out
.rb
.lh
.next
== &nb
->conns_waiting
.lh
) &&
241 (nb
->conns_waiting
.lh
.prev
!=
242 &cn
->trgt
.out
.rb
.lh
));
243 list_del(&cn
->trgt
.out
.rb
.lh
);
244 list_add_tail(&cn
->trgt
.out
.rb
.lh
,
245 &nb
->conns_waiting
.lh_nextpass
);
246 cor_conn_kref_get(cn
, "stack");
247 spin_unlock_irqrestore(&nb
->conns_waiting
.lock
, iflags
);
250 priority
= cor_conn_refresh_priority(cn
, 0);
252 spin_lock_bh(&cn
->rcv_lock
);
254 if (unlikely(cn
->targettype
!= TARGET_OUT
)) {
255 spin_unlock_bh(&cn
->rcv_lock
);
259 burstprio
= _cor_neigh_waitingsconns_resume_burstprio(cn
,
262 maxsend
= _cor_neigh_waitingsconns_resume_maxsend(cn
, burstprio
,
263 &maxsend_forcedelay
);
264 if (cn
->trgt
.out
.maxsend_extra
>= maxsend
)
265 maxsend_forcedelay
= 0;
266 maxsend
+= cn
->trgt
.out
.maxsend_extra
;
267 if (unlikely(maxsend
> U32_MAX
))
269 if (unlikely(maxsend
>= 65536))
270 maxsend_forcedelay
= 0;
273 rc2
= _cor_flush_out(cn
, maxsend
, &sent2
, 1,
276 if (rc2
== RC_FLUSH_CONN_OUT_OK
) {
277 cn
->trgt
.out
.maxsend_extra
= 0;
278 cor_neigh_waitingconns_remove_conn(cn
);
279 } else if (unlikely(rc2
== RC_FLUSH_CONN_OUT_NBNOTACTIVE
)) {
280 if (_cor_neigh_waitingsconns_resume_nbnotactive(nb
) != 0)
282 } else if (sent2
== 0 && (rc2
== RC_FLUSH_CONN_OUT_CONG
||
283 unlikely(rc2
== RC_FLUSH_CONN_OUT_OOM
))) {
284 spin_lock_irqsave(&nb
->conns_waiting
.lock
, iflags
);
285 if (likely(cn
->trgt
.out
.rb
.in_queue
!=
287 list_del(&cn
->trgt
.out
.rb
.lh
);
288 list_add(&cn
->trgt
.out
.rb
.lh
,
289 &nb
->conns_waiting
.lh
);
291 spin_unlock_irqrestore(&nb
->conns_waiting
.lock
, iflags
);
292 } else if (rc2
== RC_FLUSH_CONN_OUT_CONG
||
293 unlikely(rc2
== RC_FLUSH_CONN_OUT_OOM
)) {
294 cn
->trgt
.out
.maxsend_extra
= 0;
295 } else if (likely(rc2
== RC_FLUSH_CONN_OUT_MAXSENT
)) {
296 if (unlikely(maxsend
- sent2
> 65535))
297 cn
->trgt
.out
.maxsend_extra
= 65535;
299 cn
->trgt
.out
.maxsend_extra
= maxsend
- sent2
;
303 _cor_neigh_waitingsconns_resume_accountbusytime(cn
,
305 jiffies_nb_lastduration
);
307 spin_unlock_bh(&cn
->rcv_lock
);
314 cor_conn_kref_put(cn
, "stack");
316 if (rc2
== RC_FLUSH_CONN_OUT_CONG
||
317 unlikely(rc2
== RC_FLUSH_CONN_OUT_OOM
)) {
318 return QOS_RESUME_CONG
;
319 } else if (unlikely(rc2
== RC_FLUSH_CONN_OUT_NBNOTACTIVE
)) {
320 return QOS_RESUME_NEXTNEIGHBOR
;
325 void cor_neigh_waitingconns_remove_conn(struct cor_conn
*trgt_out_lx
)
327 unsigned long iflags
;
328 struct cor_neighbor
*nb
= trgt_out_lx
->trgt
.out
.nb
;
329 struct cor_dev
*cd
= nb
->cd
;
333 BUG_ON(trgt_out_lx
->targettype
!= TARGET_OUT
);
336 spin_lock_irqsave(&nb
->conns_waiting
.lock
, iflags
);
337 if (trgt_out_lx
->trgt
.out
.rb
.in_queue
== RB_INQUEUE_FALSE
) {
338 spin_unlock_irqrestore(&nb
->conns_waiting
.lock
, iflags
);
341 spin_lock(&cd
->send_queue
.qlock
);
343 trgt_out_lx
->trgt
.out
.rb
.in_queue
= RB_INQUEUE_FALSE
;
344 list_del(&trgt_out_lx
->trgt
.out
.rb
.lh
);
345 BUG_ON(nb
->conns_waiting
.cnt
== 0);
346 nb
->conns_waiting
.cnt
--;
347 if (nb
->rb
.in_queue
== RB_INQUEUE_TRUE
) {
348 BUG_ON(cd
->send_queue
.numconns
== 0);
349 cd
->send_queue
.numconns
--;
352 BUG_ON(nb
->conns_waiting
.priority_sum
<
353 trgt_out_lx
->trgt
.out
.rb_priority
);
354 BUG_ON(cd
->send_queue
.priority_sum
< trgt_out_lx
->trgt
.out
.rb_priority
);
355 nb
->conns_waiting
.priority_sum
-=
356 trgt_out_lx
->trgt
.out
.rb_priority
;
357 cd
->send_queue
.priority_sum
-= trgt_out_lx
->trgt
.out
.rb_priority
;
358 trgt_out_lx
->trgt
.out
.rb_priority
= 0;
360 if (list_empty(&nb
->conns_waiting
.lh
) &&
361 list_empty(&nb
->conns_waiting
.lh_nextpass
)) {
362 BUG_ON(nb
->conns_waiting
.priority_sum
!= 0);
363 BUG_ON(nb
->conns_waiting
.cnt
!= 0);
365 BUG_ON(nb
->conns_waiting
.cnt
== 0);
368 if (list_empty(&nb
->conns_waiting
.lh
) &&
369 list_empty(&nb
->conns_waiting
.lh_nextpass
) &&
370 nb
->rb
.in_queue
== RB_INQUEUE_TRUE
) {
371 BUG_ON(nb
->conns_waiting
.priority_sum
!= 0);
373 nb
->rb
.in_queue
= RB_INQUEUE_FALSE
;
374 list_del(&nb
->rb
.lh
);
375 if (atomic_read(&nb
->cmsg_delay_conndata
) != 0) {
376 atomic_set(&nb
->cmsg_delay_conndata
, 0);
381 if (list_empty(&cd
->send_queue
.neighbors_waiting
) &&
382 list_empty(&cd
->send_queue
.neighbors_waiting_nextpass
)) {
383 BUG_ON(cd
->send_queue
.numconns
!= 0);
384 BUG_ON(cd
->send_queue
.priority_sum
!= 0);
387 cor_dev_queue_set_congstatus(cd
);
390 spin_unlock(&cd
->send_queue
.qlock
);
391 spin_unlock_irqrestore(&nb
->conns_waiting
.lock
, iflags
);
394 spin_lock_bh(&nb
->cmsg_lock
);
395 cor_schedule_controlmsg_timer(nb
);
396 spin_unlock_bh(&nb
->cmsg_lock
);
399 cor_conn_kref_put_bug(trgt_out_lx
, "qos_queue");
402 cor_nb_kref_put(nb
, "qos_queue_nb");
405 void cor_neigh_waitingconns_enqueue_conn(struct cor_conn
*trgt_out_lx
)
407 unsigned long iflags
;
408 struct cor_neighbor
*nb
= trgt_out_lx
->trgt
.out
.nb
;
411 BUG_ON(trgt_out_lx
->data_buf
.read_remaining
== 0);
413 spin_lock_irqsave(&nb
->conns_waiting
.lock
, iflags
);
415 if (trgt_out_lx
->trgt
.out
.rb
.in_queue
!= RB_INQUEUE_FALSE
)
418 BUG_ON(trgt_out_lx
->trgt
.out
.rb_priority
!= 0);
420 trgt_out_lx
->trgt
.out
.rb
.in_queue
= RB_INQUEUE_TRUE
;
421 list_add_tail(&trgt_out_lx
->trgt
.out
.rb
.lh
,
422 &nb
->conns_waiting
.lh
);
423 cor_conn_kref_get(trgt_out_lx
, "qos_queue");
424 nb
->conns_waiting
.cnt
++;
426 cd
= trgt_out_lx
->trgt
.out
.nb
->cd
;
427 spin_lock(&cd
->send_queue
.qlock
);
428 if (nb
->rb
.in_queue
== RB_INQUEUE_TRUE
) {
429 cd
->send_queue
.numconns
++;
431 _cor_dev_queue_enqueue(cd
, &nb
->rb
, 0, ns_to_ktime(0),
432 QOS_CALLER_NEIGHBOR
, 0, 0);
434 spin_unlock(&cd
->send_queue
.qlock
);
437 spin_unlock_irqrestore(&nb
->conns_waiting
.lock
, iflags
);