net/ethernet: Remove inserted L2 header buffer
The packet can be referenced somewhere else and letting the newly added L2 header will generate corrupt packet. If the same packet is being resent, ethernet will add again its L2 header. Thus the need to remove such L2 header every time a packet has been sent, successfully or not. Fixes #12560 Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
parent
3610ec71f5
commit
499ffd6573
5 changed files with 22 additions and 20 deletions
|
@ -493,6 +493,18 @@ static void ethernet_update_tx_stats(struct net_if *iface, struct net_pkt *pkt)
|
|||
}
|
||||
#endif /* CONFIG_NET_STATISTICS_ETHERNET */
|
||||
|
||||
static void ethernet_remove_l2_header(struct net_pkt *pkt)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
|
||||
/* Remove the buffer added in ethernet_fill_header() */
|
||||
buf = pkt->buffer;
|
||||
pkt->buffer = buf->frags;
|
||||
buf->frags = NULL;
|
||||
|
||||
net_pkt_frag_unref(buf);
|
||||
}
|
||||
|
||||
static int ethernet_send(struct net_if *iface, struct net_pkt *pkt)
|
||||
{
|
||||
const struct ethernet_api *api = net_if_get_device(iface)->driver_api;
|
||||
|
@ -570,12 +582,14 @@ send:
|
|||
ret = api->send(net_if_get_device(iface), pkt);
|
||||
if (ret != 0) {
|
||||
eth_stats_update_errors_tx(iface);
|
||||
ethernet_remove_l2_header(pkt);
|
||||
goto error;
|
||||
}
|
||||
#if defined(CONFIG_NET_STATISTICS_ETHERNET)
|
||||
ethernet_update_tx_stats(iface, pkt);
|
||||
#endif
|
||||
ret = net_pkt_get_len(pkt);
|
||||
ethernet_remove_l2_header(pkt);
|
||||
|
||||
net_pkt_unref(pkt);
|
||||
error:
|
||||
|
|
|
@ -190,11 +190,9 @@ static int eth_tx_offloading_disabled(struct device *dev, struct net_pkt *pkt)
|
|||
memcpy(((struct net_eth_hdr *)net_pkt_data(pkt))->dst.addr,
|
||||
lladdr, sizeof(lladdr));
|
||||
|
||||
net_pkt_ref(pkt);
|
||||
|
||||
if (net_recv_data(net_pkt_iface(pkt), pkt) < 0) {
|
||||
if (net_recv_data(net_pkt_iface(pkt),
|
||||
net_pkt_clone(pkt, K_NO_WAIT)) < 0) {
|
||||
test_failed = true;
|
||||
net_pkt_unref(pkt);
|
||||
zassert_true(false, "Packet %p receive failed\n", pkt);
|
||||
}
|
||||
|
||||
|
|
|
@ -1026,16 +1026,12 @@ static int tester_send(struct device *dev, struct net_pkt *pkt)
|
|||
udp_hdr->dst_port = port;
|
||||
net_udp_set_hdr(pkt, udp_hdr);
|
||||
|
||||
if (net_recv_data(net_pkt_iface(pkt), pkt) < 0) {
|
||||
if (net_recv_data(net_pkt_iface(pkt),
|
||||
net_pkt_clone(pkt, K_NO_WAIT)) < 0) {
|
||||
TC_ERROR("Data receive failed.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* L2 or net_if will unref the pkt, but we are pushing it
|
||||
* to rx path, so let's reference it or it will be freed.
|
||||
*/
|
||||
net_pkt_ref(pkt);
|
||||
|
||||
timeout_token = 0;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -247,16 +247,12 @@ static int tester_send(struct device *dev, struct net_pkt *pkt)
|
|||
}
|
||||
|
||||
/* Feed this data back to us */
|
||||
if (net_recv_data(net_pkt_iface(pkt), pkt) < 0) {
|
||||
if (net_recv_data(net_pkt_iface(pkt),
|
||||
net_pkt_clone(pkt, K_NO_WAIT)) < 0) {
|
||||
TC_ERROR("Data receive failed.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* L2 will unref pkt, so since it got to rx path we need to ref it again
|
||||
* or it will be freed.
|
||||
*/
|
||||
net_pkt_ref(pkt);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
|
|
|
@ -183,11 +183,9 @@ static int eth_tx(struct device *dev, struct net_pkt *pkt)
|
|||
udp_hdr->src_port = udp_hdr->dst_port;
|
||||
udp_hdr->dst_port = port;
|
||||
|
||||
net_pkt_ref(pkt);
|
||||
|
||||
if (net_recv_data(net_pkt_iface(pkt), pkt) < 0) {
|
||||
if (net_recv_data(net_pkt_iface(pkt),
|
||||
net_pkt_clone(pkt, K_NO_WAIT)) < 0) {
|
||||
test_failed = true;
|
||||
net_pkt_unref(pkt);
|
||||
zassert_true(false, "Packet %p receive failed\n", pkt);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue