net: arp: Timeout too long ARP request
There was no proper support to timeout an ARP requests which meant that trying to resolve non-existent IP address left network packet pending on ARP cache. Fixes #8019 Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
f971aacaf3
commit
4ae875f9c1
|
@ -51,7 +51,7 @@ struct net_pkt *net_arp_prepare(struct net_pkt *pkt);
|
|||
enum net_verdict net_arp_input(struct net_pkt *pkt);
|
||||
|
||||
struct arp_entry {
|
||||
u32_t time; /* FIXME - implement timeout functionality */
|
||||
struct k_delayed_work arp_request_timer;
|
||||
struct net_if *iface;
|
||||
struct net_pkt *pending;
|
||||
struct in_addr ip;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "net_private.h"
|
||||
|
||||
#define NET_BUF_TIMEOUT K_MSEC(100)
|
||||
#define ARP_REQUEST_TIMEOUT K_SECONDS(2)
|
||||
|
||||
static struct arp_entry arp_table[CONFIG_NET_ARP_TABLE_SIZE];
|
||||
|
||||
|
@ -151,6 +152,9 @@ static inline struct net_pkt *prepare_arp(struct net_if *iface,
|
|||
entry->pending = net_pkt_ref(pending);
|
||||
entry->iface = net_pkt_iface(pkt);
|
||||
|
||||
k_delayed_work_submit(&entry->arp_request_timer,
|
||||
ARP_REQUEST_TIMEOUT);
|
||||
|
||||
net_ipaddr_copy(&entry->ip, next_addr);
|
||||
|
||||
memcpy(ð->src.addr,
|
||||
|
@ -194,6 +198,22 @@ static inline struct net_pkt *prepare_arp(struct net_if *iface,
|
|||
return pkt;
|
||||
}
|
||||
|
||||
static void arp_request_timeout(struct k_work *work)
|
||||
{
|
||||
/* This means that the ARP failed. */
|
||||
struct arp_entry *entry = CONTAINER_OF(work,
|
||||
struct arp_entry,
|
||||
arp_request_timer);
|
||||
|
||||
if (entry->pending) {
|
||||
NET_DBG("Releasing pending pkt %p (ref %d)", entry->pending,
|
||||
entry->pending->ref - 1);
|
||||
net_pkt_unref(entry->pending);
|
||||
entry->pending = NULL;
|
||||
entry->iface = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct net_pkt *net_arp_prepare(struct net_pkt *pkt)
|
||||
{
|
||||
struct arp_entry *entry, *free_entry = NULL, *non_pending = NULL;
|
||||
|
@ -332,6 +352,8 @@ static inline void arp_update(struct net_if *iface,
|
|||
/* We only update the ARP cache if we were
|
||||
* initiating a request.
|
||||
*/
|
||||
k_delayed_work_cancel(&arp_table[i].arp_request_timer);
|
||||
|
||||
memcpy(&arp_table[i].eth, hwaddr,
|
||||
sizeof(struct net_eth_addr));
|
||||
|
||||
|
@ -493,9 +515,14 @@ void net_arp_clear_cache(struct net_if *iface)
|
|||
|
||||
if (arp_table[i].pending) {
|
||||
net_pkt_unref(arp_table[i].pending);
|
||||
k_delayed_work_cancel(&arp_table[i].arp_request_timer);
|
||||
}
|
||||
|
||||
memset(&arp_table[i], 0, sizeof(struct arp_entry));
|
||||
arp_table[i].pending = NULL;
|
||||
arp_table[i].iface = NULL;
|
||||
|
||||
memset(&arp_table[i].ip, 0, sizeof(arp_table[i].ip));
|
||||
memset(&arp_table[i].eth, 0, sizeof(arp_table[i].eth));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -518,5 +545,12 @@ int net_arp_foreach(net_arp_cb_t cb, void *user_data)
|
|||
|
||||
void net_arp_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
net_arp_clear_cache(NULL);
|
||||
|
||||
for (i = 0; i < CONFIG_NET_ARP_TABLE_SIZE; i++) {
|
||||
k_delayed_work_init(&arp_table[i].arp_request_timer,
|
||||
arp_request_timeout);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue