net: Set net_buf alloc timeout for IPv4 ARP and IPv6 ND

Instead of having K_FOREVER when allocating a packet in IPv4 ARP
and IPv6 ND, set a timeout so that we do not have a case where we
would wait net_buf forever.

Fixes #5484

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2018-02-14 18:43:34 +02:00
parent e84d1a4f31
commit 023628f3d7
2 changed files with 72 additions and 33 deletions

View file

@ -36,6 +36,11 @@
#include "rpl.h"
#include "net_stats.h"
/* Timeout value to be used when allocating net buffer during various
* neighbor discovery procedures.
*/
#define ND_NET_BUF_TIMEOUT MSEC(100)
/* IPv6 wildcard and loopback address defined by RFC2553 */
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
@ -461,6 +466,7 @@ struct net_nbr *net_ipv6_nbr_add(struct net_if *iface,
enum net_ipv6_nbr_state state)
{
struct net_nbr *nbr;
int ret;
#if defined(CONFIG_NET_MGMT_EVENT_INFO)
struct net_event_ipv6_nbr info;
#endif
@ -500,7 +506,10 @@ struct net_nbr *net_ipv6_nbr_add(struct net_if *iface,
/* Send NS so that we can verify that the neighbor is
* reachable.
*/
net_ipv6_send_ns(iface, NULL, NULL, NULL, addr, false);
ret = net_ipv6_send_ns(iface, NULL, NULL, NULL, addr, false);
if (ret < 0) {
NET_DBG("Cannot send NS (%d)", ret);
}
}
NET_DBG("[%d] nbr %p state %d router %d IPv6 %s ll %s iface %p",
@ -961,6 +970,7 @@ struct net_pkt *net_ipv6_prepare_for_send(struct net_pkt *pkt)
struct in6_addr *nexthop = NULL;
struct net_if *iface = NULL;
struct net_nbr *nbr;
int ret;
NET_ASSERT(pkt && pkt->frags);
@ -972,8 +982,6 @@ struct net_pkt *net_ipv6_prepare_for_send(struct net_pkt *pkt)
size_t pkt_len = net_pkt_get_len(pkt);
if (pkt_len > NET_IPV6_MTU) {
int ret;
ret = net_ipv6_send_fragmented_pkt(net_pkt_iface(pkt),
pkt, pkt_len);
if (ret < 0) {
@ -1125,20 +1133,21 @@ try_send:
#if defined(CONFIG_NET_IPV6_ND)
/* We need to send NS and wait for NA before sending the packet. */
if (net_ipv6_send_ns(net_pkt_iface(pkt),
pkt,
&NET_IPV6_HDR(pkt)->src,
NULL,
nexthop,
false) < 0) {
ret = net_ipv6_send_ns(net_pkt_iface(pkt), pkt,
&NET_IPV6_HDR(pkt)->src, NULL,
nexthop, false);
if (ret < 0) {
/* In case of an error, the NS send function will unref
* the pkt.
*/
NET_DBG("Cannot send NS (%d)", ret);
return NULL;
}
NET_DBG("pkt %p (frag %p) will be sent later", pkt, pkt->frags);
#else
ARG_UNUSED(ret);
NET_DBG("pkt %p (frag %p) cannot be sent, dropping it.", pkt,
pkt->frags);
@ -1270,13 +1279,16 @@ int net_ipv6_send_na(struct net_if *iface, const struct in6_addr *src,
u8_t llao_len;
pkt = net_pkt_get_reserve_tx(net_if_get_ll_reserve(iface, dst),
K_FOREVER);
ND_NET_BUF_TIMEOUT);
if (!pkt) {
return -ENOMEM;
}
NET_ASSERT_INFO(pkt, "Out of TX packets");
frag = net_pkt_get_frag(pkt, K_FOREVER);
NET_ASSERT_INFO(frag, "Out of DATA buffers");
frag = net_pkt_get_frag(pkt, ND_NET_BUF_TIMEOUT);
if (!frag) {
net_pkt_unref(pkt);
return -ENOMEM;
}
net_pkt_frag_add(pkt, frag);
@ -1590,6 +1602,7 @@ send_na:
tgt,
flags);
if (!ret) {
NET_DBG("Cannot send NA (%d)", ret);
net_pkt_unref(pkt);
return NET_OK;
}
@ -1611,6 +1624,7 @@ static void nd_reachable_timeout(struct k_work *work)
reachable);
struct net_nbr *nbr = get_nbr_from_data(data);
int ret;
if (!data || !nbr) {
NET_DBG("ND reachable timeout but no nbr data "
@ -1641,8 +1655,11 @@ static void nd_reachable_timeout(struct k_work *work)
NET_DBG("nbr %p incomplete count %u", nbr,
data->ns_count);
net_ipv6_send_ns(nbr->iface, NULL, NULL, NULL,
&data->addr, false);
ret = net_ipv6_send_ns(nbr->iface, NULL, NULL, NULL,
&data->addr, false);
if (ret < 0) {
NET_DBG("Cannot send NS (%d)", ret);
}
}
break;
@ -1688,8 +1705,11 @@ static void nd_reachable_timeout(struct k_work *work)
NET_DBG("nbr %p probe count %u", nbr,
data->ns_count);
net_ipv6_send_ns(nbr->iface, NULL, NULL, NULL,
&data->addr, false);
ret = net_ipv6_send_ns(nbr->iface, NULL, NULL, NULL,
&data->addr, false);
if (ret < 0) {
NET_DBG("Cannot send NS (%d)", ret);
}
k_delayed_work_submit(
&net_ipv6_nbr_data(nbr)->reachable,
@ -2011,13 +2031,16 @@ int net_ipv6_send_ns(struct net_if *iface,
u8_t llao_len;
pkt = net_pkt_get_reserve_tx(net_if_get_ll_reserve(iface, dst),
K_FOREVER);
ND_NET_BUF_TIMEOUT);
if (!pkt) {
return -ENOMEM;
}
NET_ASSERT_INFO(pkt, "Out of TX packets");
frag = net_pkt_get_frag(pkt, K_FOREVER);
NET_ASSERT_INFO(frag, "Out of DATA buffers");
frag = net_pkt_get_frag(pkt, ND_NET_BUF_TIMEOUT);
if (!frag) {
net_pkt_unref(pkt);
return -ENOMEM;
}
net_pkt_frag_add(pkt, frag);
@ -2146,9 +2169,16 @@ int net_ipv6_send_rs(struct net_if *iface)
u8_t llao_len = 0;
pkt = net_pkt_get_reserve_tx(net_if_get_ll_reserve(iface, NULL),
K_FOREVER);
ND_NET_BUF_TIMEOUT);
if (!pkt) {
return -ENOMEM;
}
frag = net_pkt_get_frag(pkt, K_FOREVER);
frag = net_pkt_get_frag(pkt, ND_NET_BUF_TIMEOUT);
if (!frag) {
net_pkt_unref(pkt);
return -ENOMEM;
}
net_pkt_frag_add(pkt, frag);

View file

@ -21,6 +21,8 @@
#include <net/arp.h>
#include "net_private.h"
#define NET_BUF_TIMEOUT MSEC(100)
static struct arp_entry arp_table[CONFIG_NET_ARP_TABLE_SIZE];
static inline struct arp_entry *find_entry(struct net_if *iface,
@ -100,12 +102,13 @@ static inline struct net_pkt *prepare_arp(struct net_if *iface,
struct net_eth_hdr *eth;
struct in_addr *my_addr;
pkt = net_pkt_get_reserve_tx(sizeof(struct net_eth_hdr), K_FOREVER);
pkt = net_pkt_get_reserve_tx(sizeof(struct net_eth_hdr),
NET_BUF_TIMEOUT);
if (!pkt) {
return NULL;
}
frag = net_pkt_get_frag(pkt, K_FOREVER);
frag = net_pkt_get_frag(pkt, NET_BUF_TIMEOUT);
if (!frag) {
net_pkt_unref(pkt);
return NULL;
@ -187,9 +190,12 @@ struct net_pkt *net_arp_prepare(struct net_pkt *pkt)
/* Add the ethernet header if it is missing. */
struct net_buf *header;
net_pkt_set_ll_reserve(pkt, sizeof(struct net_eth_hdr));
header = net_pkt_get_frag(pkt, NET_BUF_TIMEOUT);
if (!header) {
return NULL;
}
header = net_pkt_get_frag(pkt, K_FOREVER);
net_pkt_set_ll_reserve(pkt, sizeof(struct net_eth_hdr));
hdr = (struct net_eth_hdr *)(header->data -
net_pkt_ll_reserve(pkt));
@ -358,12 +364,13 @@ static inline struct net_pkt *prepare_arp_reply(struct net_if *iface,
struct net_arp_hdr *hdr, *query;
struct net_eth_hdr *eth, *eth_query;
pkt = net_pkt_get_reserve_tx(sizeof(struct net_eth_hdr), K_FOREVER);
pkt = net_pkt_get_reserve_tx(sizeof(struct net_eth_hdr),
NET_BUF_TIMEOUT);
if (!pkt) {
goto fail;
}
frag = net_pkt_get_frag(pkt, K_FOREVER);
frag = net_pkt_get_frag(pkt, NET_BUF_TIMEOUT);
if (!frag) {
goto fail;
}
@ -455,6 +462,8 @@ enum net_verdict net_arp_input(struct net_pkt *pkt)
reply = prepare_arp_reply(net_pkt_iface(pkt), pkt);
if (reply) {
net_if_queue_tx(net_pkt_iface(reply), reply);
} else {
NET_DBG("Cannot send ARP reply");
}
break;