Skip to content

Commit 84f6e7a

Browse files
clamattiakartben
authored andcommitted
net: tc: Limit the max amount of packets in the traffic-class-fifo
To avoid starvation of a traffic class by another, limit the maximum amount of packets, that can sit in a single traffic-class-fifo to a fraction of the maximum amount of available packets. In the tx-case also reserve packets for direct sending, in the case, where CONFIG_NET_TC_SKIP_FOR_HIGH_PRIO is enabled. Signed-off-by: Cla Mattia Galliard <[email protected]>
1 parent d0d68d6 commit 84f6e7a

File tree

5 files changed

+112
-33
lines changed

5 files changed

+112
-33
lines changed

include/zephyr/net/net_if.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,11 @@ struct net_traffic_class {
614614
/** Fifo for handling this Tx or Rx packet */
615615
struct k_fifo fifo;
616616

617+
#if NET_TC_COUNT > 1 || defined(CONFIG_NET_TC_SKIP_FOR_HIGH_PRIO)
618+
/** Semaphore for tracking the available slots in the fifo */
619+
struct k_sem fifo_slot;
620+
#endif
621+
617622
/** Traffic class handler thread */
618623
struct k_thread handler;
619624

subsys/net/ip/net_core.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,17 @@ static void net_queue_rx(struct net_if *iface, struct net_pkt *pkt)
483483
if (NET_TC_RX_COUNT == 0) {
484484
net_process_rx_packet(pkt);
485485
} else {
486-
net_tc_submit_to_rx_queue(tc, pkt);
486+
if (net_tc_submit_to_rx_queue(tc, pkt) != NET_OK) {
487+
goto drop;
488+
}
487489
}
490+
491+
return;
492+
493+
drop:
494+
net_pkt_unref(pkt);
495+
/* TODO add statistics */
496+
return;
488497
}
489498

490499
/* Called by driver when a packet has been received */

subsys/net/ip/net_if.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,10 @@ void net_if_queue_tx(struct net_if *iface, struct net_pkt *pkt)
357357
net_stats_update_tc_sent_bytes(iface, tc, net_pkt_get_len(pkt));
358358
net_stats_update_tc_sent_priority(iface, tc, prio);
359359

360+
#if NET_TC_TX_COUNT > 1
361+
NET_DBG("TC %d with prio %d pkt %p", tc, prio, pkt);
362+
#endif
363+
360364
/* For highest priority packet, skip the TX queue and push directly to
361365
* the driver. Also if there are no TX queue/thread, push the packet
362366
* directly to the driver.
@@ -366,23 +370,21 @@ void net_if_queue_tx(struct net_if *iface, struct net_pkt *pkt)
366370
net_pkt_set_tx_stats_tick(pkt, k_cycle_get_32());
367371

368372
net_if_tx(net_pkt_iface(pkt), pkt);
369-
return;
370-
}
371-
372-
#if NET_TC_TX_COUNT > 1
373-
NET_DBG("TC %d with prio %d pkt %p", tc, prio, pkt);
374-
#endif
375-
376-
#if defined(CONFIG_NET_POWER_MANAGEMENT)
377-
iface->tx_pending++;
378-
#endif
379-
380-
if (!net_tc_submit_to_tx_queue(tc, pkt)) {
373+
} else {
374+
if (net_tc_submit_to_tx_queue(tc, pkt) != NET_OK) {
375+
goto drop;
376+
}
381377
#if defined(CONFIG_NET_POWER_MANAGEMENT)
382-
iface->tx_pending--
378+
iface->tx_pending++;
383379
#endif
384-
;
385380
}
381+
382+
return;
383+
384+
drop:
385+
net_pkt_unref(pkt);
386+
/* TODO add statistics */
387+
return;
386388
}
387389
#endif /* CONFIG_NET_NATIVE */
388390

subsys/net/ip/net_private.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ static inline enum net_verdict net_ipv6_input(struct net_pkt *pkt,
184184
static inline void net_tc_tx_init(void) { }
185185
static inline void net_tc_rx_init(void) { }
186186
#endif
187-
extern bool net_tc_submit_to_tx_queue(uint8_t tc, struct net_pkt *pkt);
188-
extern void net_tc_submit_to_rx_queue(uint8_t tc, struct net_pkt *pkt);
187+
extern enum net_verdict net_tc_submit_to_tx_queue(uint8_t tc, struct net_pkt *pkt);
188+
extern enum net_verdict net_tc_submit_to_rx_queue(uint8_t tc, struct net_pkt *pkt);
189189
extern enum net_verdict net_promisc_mode_input(struct net_pkt *pkt);
190190

191191
char *net_sprint_addr(sa_family_t af, const void *addr);

subsys/net/ip/net_tc.c

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,25 @@ LOG_MODULE_REGISTER(net_tc, CONFIG_NET_TC_LOG_LEVEL);
1818
#include "net_stats.h"
1919
#include "net_tc_mapping.h"
2020

21+
#if NET_TC_RX_COUNT > 1
22+
#define NET_TC_RX_SLOTS (CONFIG_NET_PKT_RX_COUNT / NET_TC_RX_COUNT)
23+
BUILD_ASSERT(NET_TC_RX_SLOTS > 0,
24+
"Misconfiguration: There are more traffic classes then packets, "
25+
"either increase CONFIG_NET_PKT_RX_COUNT or decrease "
26+
"CONFIG_NET_TC_RX_COUNT");
27+
#endif
28+
29+
#define TC_TX_PSEUDO_QUEUE (COND_CODE_1(CONFIG_NET_TC_SKIP_FOR_HIGH_PRIO, (1), (0)))
30+
#define NET_TC_TX_EFFECTIVE_COUNT (NET_TC_TX_COUNT + TC_TX_PSEUDO_QUEUE)
31+
32+
#if NET_TC_TX_EFFECTIVE_COUNT > 1
33+
#define NET_TC_TX_SLOTS (CONFIG_NET_PKT_TX_COUNT / NET_TC_TX_EFFECTIVE_COUNT)
34+
BUILD_ASSERT(NET_TC_TX_SLOTS > 0,
35+
"Misconfiguration: There are more traffic classes then packets, "
36+
"either increase CONFIG_NET_PKT_TX_COUNT or decrease "
37+
"CONFIG_NET_TC_TX_COUNT or disable CONFIG_NET_TC_SKIP_FOR_HIGH_PRIO");
38+
#endif
39+
2140
/* Template for thread name. The "xx" is either "TX" denoting transmit thread,
2241
* or "RX" denoting receive thread. The "q[y]" denotes the traffic class queue
2342
* where y indicates the traffic class id. The value of y can be from 0 to 7.
@@ -40,35 +59,43 @@ static struct net_traffic_class tx_classes[NET_TC_TX_COUNT];
4059
static struct net_traffic_class rx_classes[NET_TC_RX_COUNT];
4160
#endif
4261

43-
#if NET_TC_RX_COUNT > 0 || NET_TC_TX_COUNT > 0
44-
static void submit_to_queue(struct k_fifo *queue, struct net_pkt *pkt)
45-
{
46-
k_fifo_put(queue, pkt);
47-
}
48-
#endif
49-
50-
bool net_tc_submit_to_tx_queue(uint8_t tc, struct net_pkt *pkt)
62+
enum net_verdict net_tc_submit_to_tx_queue(uint8_t tc, struct net_pkt *pkt)
5163
{
5264
#if NET_TC_TX_COUNT > 0
5365
net_pkt_set_tx_stats_tick(pkt, k_cycle_get_32());
5466

55-
submit_to_queue(&tx_classes[tc].fifo, pkt);
67+
#if NET_TC_TX_EFFECTIVE_COUNT > 1
68+
if (k_sem_take(&tx_classes[tc].fifo_slot, K_NO_WAIT) != 0) {
69+
return NET_DROP;
70+
}
71+
#endif
72+
73+
k_fifo_put(&tx_classes[tc].fifo, pkt);
74+
return NET_OK;
5675
#else
5776
ARG_UNUSED(tc);
5877
ARG_UNUSED(pkt);
78+
return NET_DROP;
5979
#endif
60-
return true;
6180
}
6281

63-
void net_tc_submit_to_rx_queue(uint8_t tc, struct net_pkt *pkt)
82+
enum net_verdict net_tc_submit_to_rx_queue(uint8_t tc, struct net_pkt *pkt)
6483
{
6584
#if NET_TC_RX_COUNT > 0
6685
net_pkt_set_rx_stats_tick(pkt, k_cycle_get_32());
6786

68-
submit_to_queue(&rx_classes[tc].fifo, pkt);
87+
#if NET_TC_RX_COUNT > 1
88+
if (k_sem_take(&rx_classes[tc].fifo_slot, K_NO_WAIT) != 0) {
89+
return NET_DROP;
90+
}
91+
#endif
92+
93+
k_fifo_put(&rx_classes[tc].fifo, pkt);
94+
return NET_OK;
6995
#else
7096
ARG_UNUSED(tc);
7197
ARG_UNUSED(pkt);
98+
return NET_DROP;
7299
#endif
73100
}
74101

@@ -242,10 +269,14 @@ static void net_tc_rx_stats_priority_setup(struct net_if *iface,
242269
#if NET_TC_RX_COUNT > 0
243270
static void tc_rx_handler(void *p1, void *p2, void *p3)
244271
{
245-
ARG_UNUSED(p2);
246272
ARG_UNUSED(p3);
247273

248274
struct k_fifo *fifo = p1;
275+
#if NET_TC_RX_COUNT > 1
276+
struct k_sem *fifo_slot = p2;
277+
#else
278+
ARG_UNUSED(p2);
279+
#endif
249280
struct net_pkt *pkt;
250281

251282
while (1) {
@@ -254,6 +285,10 @@ static void tc_rx_handler(void *p1, void *p2, void *p3)
254285
continue;
255286
}
256287

288+
#if NET_TC_RX_COUNT > 1
289+
k_sem_give(fifo_slot);
290+
#endif
291+
257292
net_process_rx_packet(pkt);
258293
}
259294
}
@@ -262,10 +297,14 @@ static void tc_rx_handler(void *p1, void *p2, void *p3)
262297
#if NET_TC_TX_COUNT > 0
263298
static void tc_tx_handler(void *p1, void *p2, void *p3)
264299
{
265-
ARG_UNUSED(p2);
266300
ARG_UNUSED(p3);
267301

268302
struct k_fifo *fifo = p1;
303+
#if NET_TC_TX_EFFECTIVE_COUNT > 1
304+
struct k_sem *fifo_slot = p2;
305+
#else
306+
ARG_UNUSED(p2);
307+
#endif
269308
struct net_pkt *pkt;
270309

271310
while (1) {
@@ -274,6 +313,10 @@ static void tc_tx_handler(void *p1, void *p2, void *p3)
274313
continue;
275314
}
276315

316+
#if NET_TC_TX_EFFECTIVE_COUNT > 1
317+
k_sem_give(fifo_slot);
318+
#endif
319+
277320
net_process_tx_packet(pkt);
278321
}
279322
}
@@ -318,10 +361,20 @@ void net_tc_tx_init(void)
318361

319362
k_fifo_init(&tx_classes[i].fifo);
320363

364+
#if NET_TC_TX_EFFECTIVE_COUNT > 1
365+
k_sem_init(&tx_classes[i].fifo_slot, NET_TC_TX_SLOTS, NET_TC_TX_SLOTS);
366+
#endif
367+
321368
tid = k_thread_create(&tx_classes[i].handler, tx_stack[i],
322369
K_KERNEL_STACK_SIZEOF(tx_stack[i]),
323370
tc_tx_handler,
324-
&tx_classes[i].fifo, NULL, NULL,
371+
&tx_classes[i].fifo,
372+
#if NET_TC_TX_EFFECTIVE_COUNT > 1
373+
&tx_classes[i].fifo_slot,
374+
#else
375+
NULL,
376+
#endif
377+
NULL,
325378
priority, 0, K_FOREVER);
326379
if (!tid) {
327380
NET_ERR("Cannot create TC handler thread %d", i);
@@ -376,10 +429,20 @@ void net_tc_rx_init(void)
376429

377430
k_fifo_init(&rx_classes[i].fifo);
378431

432+
#if NET_TC_RX_COUNT > 1
433+
k_sem_init(&rx_classes[i].fifo_slot, NET_TC_RX_SLOTS, NET_TC_RX_SLOTS);
434+
#endif
435+
379436
tid = k_thread_create(&rx_classes[i].handler, rx_stack[i],
380437
K_KERNEL_STACK_SIZEOF(rx_stack[i]),
381438
tc_rx_handler,
382-
&rx_classes[i].fifo, NULL, NULL,
439+
&rx_classes[i].fifo,
440+
#if NET_TC_RX_COUNT > 1
441+
&rx_classes[i].fifo_slot,
442+
#else
443+
NULL,
444+
#endif
445+
NULL,
383446
priority, 0, K_FOREVER);
384447
if (!tid) {
385448
NET_ERR("Cannot create TC handler thread %d", i);

0 commit comments

Comments
 (0)