Skip to content

Commit c5f9c6c

Browse files
committed
net: core: Dynamic priority and deferred processing
To enable quality-of-service (QoS) applications, allow to reschedule/defer the processing of a network packet based on its properties. This means, that processing can be offloaded to tc-queue-threads with different priorities. Signed-off-by: Cla Mattia Galliard <[email protected]>
1 parent 0630e2e commit c5f9c6c

File tree

3 files changed

+57
-24
lines changed

3 files changed

+57
-24
lines changed

subsys/net/ip/net_core.c

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ LOG_MODULE_REGISTER(net_core, CONFIG_NET_CORE_LOG_LEVEL);
6363

6464
#include "net_stats.h"
6565

66+
static void net_queue_rx(struct net_if *iface, struct net_pkt *pkt);
67+
6668
#if defined(CONFIG_NET_NATIVE)
6769
static inline enum net_verdict process_data(struct net_pkt *pkt)
6870
{
@@ -77,27 +79,25 @@ static inline enum net_verdict process_data(struct net_pkt *pkt)
7779
if (!pkt->frags) {
7880
NET_DBG("Corrupted packet (frags %p)", pkt->frags);
7981
net_stats_update_processing_error(net_pkt_iface(pkt));
80-
8182
return NET_DROP;
8283
}
8384

8485
if (!net_pkt_is_l2_processed(pkt)) {
85-
ret = net_if_recv_data(net_pkt_iface(pkt), pkt);
8686
net_pkt_set_l2_processed(pkt, true);
87+
ret = net_if_recv_data(net_pkt_iface(pkt), pkt);
8788
if (ret != NET_CONTINUE) {
8889
if (ret == NET_DROP) {
8990
NET_DBG("Packet %p discarded by L2", pkt);
9091
net_stats_update_processing_error(
9192
net_pkt_iface(pkt));
9293
}
93-
9494
return ret;
9595
}
96-
9796
/* L2 has modified the buffer starting point, it is easier
9897
* to re-initialize the cursor rather than updating it.
9998
*/
10099
net_pkt_cursor_init(pkt);
100+
return NET_CONTINUE;
101101
}
102102

103103
if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET_DGRAM) &&
@@ -128,7 +128,6 @@ static inline enum net_verdict process_data(struct net_pkt *pkt)
128128
} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && family == AF_CAN) {
129129
return net_canbus_socket_input(pkt);
130130
}
131-
132131
NET_DBG("Unknown protocol family packet (0x%x)", family);
133132
return NET_DROP;
134133
}
@@ -137,29 +136,47 @@ static inline enum net_verdict process_data(struct net_pkt *pkt)
137136

138137
}
139138

139+
static void update_priority(struct net_pkt *pkt)
140+
{
141+
/* This is just an example.
142+
* Similar infrastructure with custom application rules like
143+
* net_pkt_filter could be established
144+
*/
145+
if (net_pkt_is_l2_processed(pkt)) {
146+
if (net_pkt_ll_proto_type(pkt) == NET_ETH_PTYPE_PTP) {
147+
net_pkt_set_priority(pkt, NET_PRIORITY_IC);
148+
}
149+
}
150+
}
151+
152+
static bool being_processed_by_correct_thread(struct net_pkt *pkt)
153+
{
154+
uint8_t prio = net_pkt_priority(pkt);
155+
uint8_t tc = net_rx_priority2tc(prio);
156+
157+
return net_tc_rx_is_current_thread(tc);
158+
}
159+
140160
static void processing_data(struct net_pkt *pkt)
141161
{
142-
again:
143-
switch (process_data(pkt)) {
144-
case NET_CONTINUE:
145-
if (IS_ENABLED(CONFIG_NET_L2_VIRTUAL)) {
146-
/* If we have a tunneling packet, feed it back
147-
* to the stack in this case.
148-
*/
149-
goto again;
150-
} else {
151-
NET_DBG("Dropping pkt %p", pkt);
152-
net_pkt_unref(pkt);
162+
enum net_verdict verdict = NET_CONTINUE;
163+
164+
do {
165+
verdict = process_data(pkt);
166+
if (verdict != NET_CONTINUE) {
167+
break;
153168
}
154-
break;
155-
case NET_OK:
156-
NET_DBG("Consumed pkt %p", pkt);
157-
break;
158-
case NET_DROP:
159-
default:
160-
NET_DBG("Dropping pkt %p", pkt);
169+
170+
update_priority(pkt);
171+
172+
if (!being_processed_by_correct_thread(pkt)) {
173+
net_queue_rx(net_pkt_iface(pkt), pkt);
174+
}
175+
176+
} while (true);
177+
178+
if (verdict != NET_OK) {
161179
net_pkt_unref(pkt);
162-
break;
163180
}
164181
}
165182

subsys/net/ip/net_private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ static inline void net_tc_rx_init(void) { }
201201
#endif
202202
enum net_verdict net_tc_try_submit_to_tx_queue(uint8_t tc, struct net_pkt *pkt,
203203
k_timeout_t timeout);
204+
bool net_tc_rx_is_current_thread(uint8_t tc);
204205
extern enum net_verdict net_tc_submit_to_rx_queue(uint8_t tc, struct net_pkt *pkt);
205206
extern enum net_verdict net_promisc_mode_input(struct net_pkt *pkt);
206207

subsys/net/ip/net_tc.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,21 @@ static struct net_traffic_class tx_classes[NET_TC_TX_COUNT];
6565
static struct net_traffic_class rx_classes[NET_TC_RX_COUNT];
6666
#endif
6767

68+
bool net_tc_rx_is_current_thread(uint8_t tc)
69+
{
70+
uint8_t thread_priority;
71+
int priority;
72+
int desired_priority;
73+
74+
thread_priority = rx_tc2thread(tc);
75+
desired_priority = IS_ENABLED(CONFIG_NET_TC_THREAD_COOPERATIVE) ?
76+
K_PRIO_COOP(thread_priority) :
77+
K_PRIO_PREEMPT(thread_priority);
78+
priority = k_thread_priority_get(k_current_get());
79+
80+
return priority == desired_priority;
81+
}
82+
6883
enum net_verdict net_tc_try_submit_to_tx_queue(uint8_t tc, struct net_pkt *pkt,
6984
k_timeout_t timeout)
7085
{

0 commit comments

Comments
 (0)