Skip to content

Commit 394ca9b

Browse files
committed
net: Add timeout to various send functions
Timeout can be used to early drop some request for arp and icmp to avoid being slowed when in a flood situation. Signed-off-by: Cla Mattia Galliard <[email protected]>
1 parent a94acf3 commit 394ca9b

File tree

17 files changed

+86
-32
lines changed

17 files changed

+86
-32
lines changed

include/zephyr/net/net_core.h

+16-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ int net_recv_data(struct net_if *iface, struct net_pkt *pkt);
128128
*
129129
* @details Send data to network. This should not be used normally by
130130
* applications as it requires that the network packet is properly
131-
* constructed.
131+
* constructed. Equivalent to net_try_send_data with infinite timeout.
132132
*
133133
* @param pkt Network packet.
134134
*
@@ -137,6 +137,21 @@ int net_recv_data(struct net_if *iface, struct net_pkt *pkt);
137137
*/
138138
int net_send_data(struct net_pkt *pkt);
139139

140+
/**
141+
* @brief Try sending data to network.
142+
*
143+
* @details Send data to network. This should not be used normally by
144+
* applications as it requires that the network packet is properly
145+
* constructed.
146+
*
147+
* @param pkt Network packet.
148+
* @param timeout Timeout for send.
149+
*
150+
* @return 0 if ok, <0 if error. If <0 is returned, then the caller needs
151+
* to unref the pkt in order to avoid memory leak.
152+
*/
153+
int net_try_send_data(struct net_pkt *pkt, k_timeout timeout)
154+
140155
/** @cond INTERNAL_HIDDEN */
141156

142157
/* Some helper defines for traffic class support */

include/zephyr/net/net_if.h

+22-1
Original file line numberDiff line numberDiff line change
@@ -914,13 +914,25 @@ static inline enum net_if_oper_state net_if_oper_state(struct net_if *iface)
914914
/**
915915
* @brief Send a packet through a net iface
916916
*
917+
* This is equivalent to net_if_try_queue_tx with an infinite timeout
917918
* @param iface Pointer to a network interface structure
918919
* @param pkt Pointer to a net packet to send
919920
*
920-
* return verdict about the packet
921+
* @return verdict about the packet
921922
*/
922923
enum net_verdict net_if_send_data(struct net_if *iface, struct net_pkt *pkt);
923924

925+
/**
926+
* @brief Try sending a packet through a net iface
927+
*
928+
* @param iface Pointer to a network interface structure
929+
* @param pkt Pointer to a net packet to send
930+
* @param timeout timeout for attempting to send
931+
*
932+
* @return verdict about the packet
933+
*/
934+
enum net_verdict net_if_try_send_data(struct net_if *iface, struct net_pkt *pkt, k_timeout timeout);
935+
924936
/**
925937
* @brief Get a pointer to the interface L2
926938
*
@@ -982,11 +994,20 @@ static inline const struct device *net_if_get_device(struct net_if *iface)
982994
/**
983995
* @brief Queue a packet to the net interface TX queue
984996
*
997+
* This is equivalent to net_if_try_queue_tx with an infinite timeout
985998
* @param iface Pointer to a network interface structure
986999
* @param pkt Pointer to a net packet to queue
9871000
*/
9881001
void net_if_queue_tx(struct net_if *iface, struct net_pkt *pkt);
9891002

1003+
/**
1004+
* @brief Try enqueuing a packet to the net interface TX queue
1005+
*
1006+
* @param iface Pointer to a network interface structure
1007+
* @param pkt Pointer to a net packet to queue
1008+
*/
1009+
void net_if_try_queue_tx(struct net_if *iface, struct net_pkt *pkt, k_timeout timeout);
1010+
9901011
/**
9911012
* @brief Return the IP offload status
9921013
*

subsys/net/ip/icmp.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ static int send_icmpv4_echo_request(struct net_icmp_ctx *ctx,
207207
ctx->user_data = user_data;
208208
ctx->iface = iface;
209209

210-
if (net_send_data(pkt) >= 0) {
210+
if (net_try_send_data(pkt, K_NO_WAIT) >= 0) {
211211
net_stats_update_icmp_sent(iface);
212212
return 0;
213213
}
@@ -330,7 +330,7 @@ static int send_icmpv6_echo_request(struct net_icmp_ctx *ctx,
330330
ctx->user_data = user_data;
331331
ctx->iface = iface;
332332

333-
if (net_send_data(pkt) >= 0) {
333+
if (net_try_send_data(pkt, K_NO_WAIT) >= 0) {
334334
net_stats_update_icmp_sent(iface);
335335
return 0;
336336
}

subsys/net/ip/icmpv4.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ static int icmpv4_handle_echo_request(struct net_icmp_ctx *ctx,
493493
net_sprint_ipv4_addr(src),
494494
net_sprint_ipv4_addr(&ip_hdr->src));
495495

496-
if (net_send_data(reply) < 0) {
496+
if (net_try_send_data(reply, K_NO_WAIT) < 0) {
497497
goto drop;
498498
}
499499

@@ -588,7 +588,7 @@ int net_icmpv4_send_error(struct net_pkt *orig, uint8_t type, uint8_t code)
588588
net_sprint_ipv4_addr(&ip_hdr->dst),
589589
net_sprint_ipv4_addr(&ip_hdr->src));
590590

591-
if (net_send_data(pkt) >= 0) {
591+
if (net_try_send_data(pkt, K_NO_WAIT) >= 0) {
592592
net_stats_update_icmp_sent(net_pkt_iface(orig));
593593
return 0;
594594
}

subsys/net/ip/icmpv6.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ static int icmpv6_handle_echo_request(struct net_icmp_ctx *ctx,
169169
net_sprint_ipv6_addr(src),
170170
net_sprint_ipv6_addr(&ip_hdr->src));
171171

172-
if (net_send_data(reply) < 0) {
172+
if (net_try_send_data(reply, K_NO_WAIT) < 0) {
173173
goto drop;
174174
}
175175

@@ -319,7 +319,7 @@ int net_icmpv6_send_error(struct net_pkt *orig, uint8_t type, uint8_t code,
319319
net_sprint_ipv6_addr(src),
320320
net_sprint_ipv6_addr(&ip_hdr->src));
321321

322-
if (net_send_data(pkt) >= 0) {
322+
if (net_try_send_data(pkt, K_NO_WAIT) >= 0) {
323323
net_stats_update_icmp_sent(net_pkt_iface(pkt));
324324
return 0;
325325
}

subsys/net/ip/ipv4_acd.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ static void ipv4_acd_send_probe(struct net_if_addr *ifaddr)
103103
return;
104104
}
105105

106-
if (net_if_send_data(iface, pkt) == NET_DROP) {
106+
if (net_if_try_send_data(iface, pkt, K_FOREVER) == NET_DROP) {
107107
net_pkt_unref(pkt);
108108
}
109109
}
@@ -120,7 +120,7 @@ static void ipv4_acd_send_announcement(struct net_if_addr *ifaddr)
120120
return;
121121
}
122122

123-
if (net_if_send_data(iface, pkt) == NET_DROP) {
123+
if (net_if_try_send_data(iface, pkt, K_FOREVER) == NET_DROP) {
124124
net_pkt_unref(pkt);
125125
}
126126
}

subsys/net/ip/net_context.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2609,7 +2609,7 @@ static int context_sendto(struct net_context *context,
26092609
net_pkt_set_ll_proto_type(pkt,
26102610
ntohs(ll_dst_addr->sll_protocol));
26112611

2612-
net_if_queue_tx(net_pkt_iface(pkt), pkt);
2612+
net_if_try_queue_tx(net_pkt_iface(pkt), pkt, timeout);
26132613
}
26142614
} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && family == AF_CAN &&
26152615
net_context_get_proto(context) == CAN_RAW) {

subsys/net/ip/net_core.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,12 @@ static inline int check_ip(struct net_pkt *pkt)
363363
return ret;
364364
}
365365

366-
/* Called when data needs to be sent to network */
367366
int net_send_data(struct net_pkt *pkt)
367+
{
368+
return net_try_send_data(pkt, K_FOREVER);
369+
}
370+
371+
int net_try_send_data(struct net_pkt *pkt, k_timeout timeout)
368372
{
369373
int status;
370374
int ret;
@@ -407,7 +411,7 @@ int net_send_data(struct net_pkt *pkt)
407411
goto err;
408412
}
409413

410-
if (net_if_send_data(net_pkt_iface(pkt), pkt) == NET_DROP) {
414+
if (net_if_try_send_data(net_pkt_iface(pkt), pkt, timeout) == NET_DROP) {
411415
ret = -EIO;
412416
goto err;
413417
}

subsys/net/ip/net_if.c

+13-3
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,11 @@ void net_process_tx_packet(struct net_pkt *pkt)
343343
}
344344

345345
void net_if_queue_tx(struct net_if *iface, struct net_pkt *pkt)
346+
{
347+
net_if_try_queue_tx(iface, pkt, K_FOREVER);
348+
}
349+
350+
void net_if_try_queue_tx(struct net_if *iface, struct net_pkt *pkt, k_timeout timeout)
346351
{
347352
if (!net_pkt_filter_send_ok(pkt)) {
348353
/* silently drop the packet */
@@ -368,7 +373,7 @@ void net_if_queue_tx(struct net_if *iface, struct net_pkt *pkt)
368373

369374
net_if_tx(net_pkt_iface(pkt), pkt);
370375
} else {
371-
if (net_tc_submit_to_tx_queue(tc, pkt) != NET_OK) {
376+
if (net_tc_try_submit_to_tx_queue(tc, pkt, timeout) != NET_OK) {
372377
goto drop;
373378
}
374379
#if defined(CONFIG_NET_POWER_MANAGEMENT)
@@ -451,7 +456,12 @@ static inline void init_iface(struct net_if *iface)
451456
}
452457

453458
#if defined(CONFIG_NET_NATIVE)
454-
enum net_verdict net_if_send_data(struct net_if *iface, struct net_pkt *pkt)
459+
enum net_verdict net_if_send_data(struct net_if *iface, struct net_pkt *pkt, k_timeout timeout)
460+
{
461+
return net_if_try_send_data(iface, pkt, K_FOREVER);
462+
}
463+
464+
enum net_verdict net_if_try_send_data(struct net_if *iface, struct net_pkt *pkt, k_timeout timeout)
455465
{
456466
const struct net_l2 *l2;
457467
struct net_context *context = net_pkt_context(pkt);
@@ -550,7 +560,7 @@ enum net_verdict net_if_send_data(struct net_if *iface, struct net_pkt *pkt)
550560
}
551561
} else if (verdict == NET_OK) {
552562
/* Packet is ready to be sent by L2, let's queue */
553-
net_if_queue_tx(iface, pkt);
563+
net_if_try_queue_tx(iface, pkt, timeout);
554564
}
555565

556566
return verdict;

subsys/net/ip/net_private.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ static inline enum net_verdict net_ipv6_input(struct net_pkt *pkt,
203203
static inline void net_tc_tx_init(void) { }
204204
static inline void net_tc_rx_init(void) { }
205205
#endif
206-
extern enum net_verdict net_tc_submit_to_tx_queue(uint8_t tc, struct net_pkt *pkt);
206+
enum net_verdict net_tc_try_submit_to_tx_queue(uint8_t tc, struct net_pkt *pkt, k_timeout timeout);
207207
extern enum net_verdict net_tc_submit_to_rx_queue(uint8_t tc, struct net_pkt *pkt);
208208
extern enum net_verdict net_promisc_mode_input(struct net_pkt *pkt);
209209

subsys/net/ip/net_tc.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,13 @@ 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-
enum net_verdict net_tc_submit_to_tx_queue(uint8_t tc, struct net_pkt *pkt)
68+
enum net_verdict net_tc_try_submit_to_tx_queue(uint8_t tc, struct net_pkt *pkt, k_timeout timeout)
6969
{
7070
#if NET_TC_TX_COUNT > 0
7171
net_pkt_set_tx_stats_tick(pkt, k_cycle_get_32());
7272

7373
#if NET_TC_TX_EFFECTIVE_COUNT > 1
74-
if (k_sem_take(&tx_classes[tc].fifo_slot, K_FOREVER) != 0) {
74+
if (k_sem_take(&tx_classes[tc].fifo_slot, timeout) != 0) {
7575
return NET_DROP;
7676
}
7777
#endif

subsys/net/l2/ethernet/arp.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,9 @@ static void arp_gratuitous_send(struct net_if *iface,
531531

532532
NET_DBG("Sending gratuitous ARP pkt %p", pkt);
533533

534-
if (net_if_send_data(iface, pkt) == NET_DROP) {
534+
/* send without timeout, so we do not risk being blocked by tx when
535+
* being flooded */
536+
if (net_if_try_send_data(iface, pkt, K_NO_WAIT) == NET_DROP) {
535537
net_pkt_unref(pkt);
536538
}
537539
}
@@ -874,7 +876,7 @@ enum net_verdict net_arp_input(struct net_pkt *pkt,
874876
/* Send reply */
875877
reply = arp_prepare_reply(net_pkt_iface(pkt), pkt, dst_hw_addr);
876878
if (reply) {
877-
net_if_queue_tx(net_pkt_iface(reply), reply);
879+
net_if_try_queue_tx(net_pkt_iface(reply), reply, K_NO_WAIT);
878880
} else {
879881
NET_DBG("Cannot send ARP reply");
880882
}

subsys/net/l2/ethernet/bridge.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ static enum net_verdict bridge_iface_process(struct net_if *iface,
384384

385385
net_pkt_set_family(send_pkt, AF_UNSPEC);
386386
net_pkt_set_iface(send_pkt, ctx->eth_iface[i]);
387-
net_if_queue_tx(ctx->eth_iface[i], send_pkt);
387+
net_if_try_queue_tx(ctx->eth_iface[i], send_pkt, K_FOREVER);
388388

389389
NET_DBG("%s iface %d pkt %p (ref %d)",
390390
is_send ? "Send" : "Recv",

subsys/net/l2/ethernet/ethernet.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ static enum net_verdict ethernet_recv(struct net_if *iface,
281281
out_pkt, pkt, net_if_get_by_iface(bridge),
282282
net_if_get_by_iface(iface));
283283

284-
(void)net_if_queue_tx(bridge, out_pkt);
284+
(void)net_if_try_queue_tx(bridge, out_pkt, K_FOREVER);
285285
}
286286

287287
type = ntohs(hdr->type);
@@ -788,7 +788,7 @@ static int ethernet_send(struct net_if *iface, struct net_pkt *pkt)
788788
out_pkt, pkt, net_if_get_by_iface(bridge),
789789
net_if_get_by_iface(iface));
790790

791-
(void)net_if_queue_tx(bridge, out_pkt);
791+
(void)net_if_try_queue_tx(bridge, out_pkt, K_FOREVER);
792792
}
793793

794794
ret = net_l2_send(api->send, net_if_get_device(iface), iface, pkt);

subsys/net/l2/ethernet/gptp/gptp_messages.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,7 @@ void gptp_send_sync(int port, struct net_pkt *pkt)
826826

827827
NET_GPTP_INFO("SYNC", pkt);
828828

829-
net_if_queue_tx(net_pkt_iface(pkt), pkt);
829+
net_if_try_queue_tx(net_pkt_iface(pkt), pkt, K_FOREVER);
830830
}
831831

832832
void gptp_send_follow_up(int port, struct net_pkt *pkt)
@@ -835,7 +835,7 @@ void gptp_send_follow_up(int port, struct net_pkt *pkt)
835835

836836
NET_GPTP_INFO("FOLLOWUP", pkt);
837837

838-
net_if_queue_tx(net_pkt_iface(pkt), pkt);
838+
net_if_try_queue_tx(net_pkt_iface(pkt), pkt, K_FOREVER);
839839
}
840840

841841
void gptp_send_announce(int port, struct net_pkt *pkt)
@@ -844,7 +844,7 @@ void gptp_send_announce(int port, struct net_pkt *pkt)
844844

845845
NET_GPTP_INFO("ANNOUNCE", pkt);
846846

847-
net_if_queue_tx(net_pkt_iface(pkt), pkt);
847+
net_if_try_queue_tx(net_pkt_iface(pkt), pkt, K_FOREVER);
848848
}
849849

850850
void gptp_send_pdelay_req(int port)
@@ -871,7 +871,7 @@ void gptp_send_pdelay_req(int port)
871871

872872
NET_GPTP_INFO("PDELAY_REQ", pkt);
873873

874-
net_if_queue_tx(net_pkt_iface(pkt), pkt);
874+
net_if_try_queue_tx(net_pkt_iface(pkt), pkt, K_FOREVER);
875875
} else {
876876
NET_ERR("Failed to prepare %s", "PDELAY_REQ");
877877
}
@@ -897,7 +897,7 @@ void gptp_send_pdelay_resp(int port, struct net_pkt *pkt,
897897

898898
NET_GPTP_INFO("PDELAY_RESP", pkt);
899899

900-
net_if_queue_tx(net_pkt_iface(pkt), pkt);
900+
net_if_try_queue_tx(net_pkt_iface(pkt), pkt, K_FOREVER);
901901
}
902902

903903
void gptp_send_pdelay_follow_up(int port, struct net_pkt *pkt,
@@ -920,5 +920,5 @@ void gptp_send_pdelay_follow_up(int port, struct net_pkt *pkt,
920920

921921
NET_GPTP_INFO("PDELAY_FOLLOWUP", pkt);
922922

923-
net_if_queue_tx(net_pkt_iface(pkt), pkt);
923+
net_if_try_queue_tx(net_pkt_iface(pkt), pkt, K_FOREVER);
924924
}

subsys/net/l2/ethernet/lldp/lldp.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,9 @@ static int lldp_send(struct ethernet_lldp *lldp)
147147
net_pkt_lladdr_dst(pkt)->addr = (uint8_t *)lldp_multicast_eth_addr.addr;
148148
net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr);
149149

150-
if (net_if_send_data(lldp->iface, pkt) == NET_DROP) {
150+
/* send without timeout, so we do not risk being blocked by tx when
151+
* being flooded */
152+
if (net_if_try_send_data(lldp->iface, pkt, K_NO_WAIT) == NET_DROP) {
151153
net_pkt_unref(pkt);
152154
ret = -EIO;
153155
}

subsys/net/lib/capture/capture.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ static int capture_send(const struct device *dev, struct net_if *iface,
707707

708708
net_pkt_cursor_init(pkt);
709709

710-
verdict = net_if_send_data(ctx->tunnel_iface, pkt);
710+
verdict = net_if_try_send_data(ctx->tunnel_iface, pkt, K_FOREVER);
711711
if (verdict == NET_DROP) {
712712
ret = -EIO;
713713
}

0 commit comments

Comments
 (0)