Skip to content

Commit d283130

Browse files
JordanYateskartben
authored andcommitted
net: l2: ethernet: arp: explicit error codes
Update `net_arp_prepare` to return a return code instead of a pointer, so that the various results of the function can be differentiated. Signed-off-by: Jordan Yates <jordan@embeint.com>
1 parent 4e0386a commit d283130

File tree

5 files changed

+82
-40
lines changed

5 files changed

+82
-40
lines changed

subsys/net/ip/ipv4_acd.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ static struct net_pkt *ipv4_acd_prepare_arp(struct net_if *iface,
7474
struct in_addr *sender_ip,
7575
struct in_addr *target_ip)
7676
{
77-
struct net_pkt *pkt;
77+
struct net_pkt *pkt, *arp;
78+
int ret;
7879

7980
/* We provide AF_UNSPEC to the allocator: this packet does not
8081
* need space for any IPv4 header.
@@ -88,7 +89,13 @@ static struct net_pkt *ipv4_acd_prepare_arp(struct net_if *iface,
8889
net_pkt_set_family(pkt, AF_INET);
8990
net_pkt_set_ipv4_acd(pkt, true);
9091

91-
return net_arp_prepare(pkt, target_ip, sender_ip);
92+
ret = net_arp_prepare(pkt, target_ip, sender_ip, &arp);
93+
if (ret == NET_ARP_PKT_REPLACED) {
94+
pkt = arp;
95+
} else if (ret < 0) {
96+
pkt = NULL;
97+
}
98+
return pkt;
9299
}
93100

94101
static void ipv4_acd_send_probe(struct net_if_addr *ifaddr)

subsys/net/l2/ethernet/arp.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -352,21 +352,23 @@ static inline struct net_pkt *arp_prepare(struct net_if *iface,
352352
return pkt;
353353
}
354354

355-
struct net_pkt *net_arp_prepare(struct net_pkt *pkt,
356-
struct in_addr *request_ip,
357-
struct in_addr *current_ip)
355+
int net_arp_prepare(struct net_pkt *pkt,
356+
struct in_addr *request_ip,
357+
struct in_addr *current_ip,
358+
struct net_pkt **arp_pkt)
358359
{
359360
bool is_ipv4_ll_used = false;
360361
struct arp_entry *entry;
361362
struct in_addr *addr;
362363

363364
if (!pkt || !pkt->buffer) {
364-
return NULL;
365+
return -EINVAL;
365366
}
366367

367368
if (net_pkt_ipv4_acd(pkt)) {
368-
return arp_prepare(net_pkt_iface(pkt), request_ip, NULL,
369-
pkt, current_ip);
369+
*arp_pkt = arp_prepare(net_pkt_iface(pkt), request_ip, NULL,
370+
pkt, current_ip);
371+
return *arp_pkt ? NET_ARP_PKT_REPLACED : -ENOMEM;
370372
}
371373

372374
if (IS_ENABLED(CONFIG_NET_IPV4_AUTO)) {
@@ -391,7 +393,7 @@ struct net_pkt *net_arp_prepare(struct net_pkt *pkt,
391393
net_if_get_by_iface(net_pkt_iface(pkt)),
392394
net_sprint_ipv4_addr(request_ip));
393395

394-
return NULL;
396+
return -EINVAL;
395397
}
396398
} else {
397399
addr = request_ip;
@@ -427,7 +429,7 @@ struct net_pkt *net_arp_prepare(struct net_pkt *pkt,
427429
NET_DBG("Pending ARP request for %s, queuing pkt %p",
428430
net_sprint_ipv4_addr(addr), pkt);
429431
k_mutex_unlock(&arp_mutex);
430-
return NULL;
432+
return NET_ARP_PKT_QUEUED;
431433
}
432434

433435
entry = NULL;
@@ -452,7 +454,8 @@ struct net_pkt *net_arp_prepare(struct net_pkt *pkt,
452454
}
453455

454456
k_mutex_unlock(&arp_mutex);
455-
return req;
457+
*arp_pkt = req;
458+
return req ? NET_ARP_PKT_REPLACED : -ENOMEM;
456459
}
457460

458461
k_mutex_unlock(&arp_mutex);
@@ -469,7 +472,7 @@ struct net_pkt *net_arp_prepare(struct net_pkt *pkt,
469472
sizeof(struct net_eth_addr)),
470473
net_sprint_ipv4_addr(NET_IPV4_HDR(pkt)->dst));
471474

472-
return pkt;
475+
return NET_ARP_COMPLETE;
473476
}
474477

475478
static void arp_gratuitous(struct net_if *iface,

subsys/net/l2/ethernet/arp.h

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
#ifndef __ARP_H
88
#define __ARP_H
99

10-
#if defined(CONFIG_NET_ARP) && defined(CONFIG_NET_NATIVE)
11-
1210
#include <zephyr/sys/slist.h>
1311
#include <zephyr/net/ethernet.h>
1412

@@ -23,6 +21,15 @@ extern "C" {
2321
* @{
2422
*/
2523

24+
/** @brief Address resolution complete, destination link address injected */
25+
#define NET_ARP_COMPLETE 0
26+
/** @brief Destination link address unknown, ARP request to be sent instead */
27+
#define NET_ARP_PKT_REPLACED 1
28+
/** @brief Destination link address unknown, ARP request pending, packet queued */
29+
#define NET_ARP_PKT_QUEUED 2
30+
31+
#if defined(CONFIG_NET_ARP) && defined(CONFIG_NET_NATIVE)
32+
2633
#define NET_ARP_HDR(pkt) ((struct net_arp_hdr *)net_pkt_data(pkt))
2734

2835
struct net_arp_hdr {
@@ -43,9 +50,23 @@ struct net_arp_hdr {
4350
#define NET_ARP_REQUEST 1
4451
#define NET_ARP_REPLY 2
4552

46-
struct net_pkt *net_arp_prepare(struct net_pkt *pkt,
47-
struct in_addr *request_ip,
48-
struct in_addr *current_ip);
53+
/**
54+
* @brief Prepare an ARP request, if required
55+
*
56+
* @param pkt Packet that wants to be sent
57+
* @param request_ip Destination address of the packet
58+
* @param current_ip Sending IP (Can be NULL)
59+
* @param arp_pkt ARP packet that should be sent in place of @a pkt, if not NULL
60+
*
61+
* @retval NET_ARP_COMPLETE ARP information populated in @a pkt
62+
* @retval NET_ARP_PKT_REPLACED ARP request to be sent existing in @a arp_pkt
63+
* @retval NET_ARP_PKT_QUEUED @a pkt was queued for transmission on ARP resolution
64+
* @retval <0 on failure
65+
*/
66+
int net_arp_prepare(struct net_pkt *pkt,
67+
struct in_addr *request_ip,
68+
struct in_addr *current_ip,
69+
struct net_pkt **arp_pkt);
4970
enum net_verdict net_arp_input(struct net_pkt *pkt,
5071
struct net_eth_addr *src,
5172
struct net_eth_addr *dst);
@@ -72,16 +93,9 @@ void net_arp_update(struct net_if *iface, struct in_addr *src,
7293
struct net_eth_addr *hwaddr, bool gratuitous,
7394
bool force);
7495

75-
/**
76-
* @}
77-
*/
78-
79-
#ifdef __cplusplus
80-
}
81-
#endif
8296

8397
#else /* CONFIG_NET_ARP */
84-
#define net_arp_prepare(_kt, _u1, _u2) _kt
98+
#define net_arp_prepare(_kt, _u1, _u2, _arp) NET_ARP_COMPLETE
8599
#define net_arp_input(...) NET_OK
86100
#define net_arp_clear_cache(...)
87101
#define net_arp_foreach(...) 0
@@ -91,4 +105,12 @@ void net_arp_update(struct net_if *iface, struct in_addr *src,
91105

92106
#endif /* CONFIG_NET_ARP */
93107

108+
/**
109+
* @}
110+
*/
111+
112+
#ifdef __cplusplus
113+
}
114+
#endif
115+
94116
#endif /* __ARP_H */

subsys/net/l2/ethernet/ethernet.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -508,21 +508,23 @@ static struct net_pkt *ethernet_ll_prepare_on_ipv4(struct net_if *iface,
508508

509509
if (IS_ENABLED(CONFIG_NET_ARP)) {
510510
struct net_pkt *arp_pkt;
511+
int ret;
511512

512-
arp_pkt = net_arp_prepare(pkt, (struct in_addr *)NET_IPV4_HDR(pkt)->dst, NULL);
513-
if (!arp_pkt) {
514-
return NULL;
515-
}
516-
517-
if (pkt != arp_pkt) {
513+
ret = net_arp_prepare(pkt, (struct in_addr *)NET_IPV4_HDR(pkt)->dst, NULL, &arp_pkt);
514+
if (ret == NET_ARP_COMPLETE) {
515+
NET_DBG("Found ARP entry, sending pkt %p to iface %d (%p)",
516+
pkt, net_if_get_by_iface(iface), iface);
517+
} else if (ret == NET_ARP_PKT_REPLACED) {
518518
NET_DBG("Sending arp pkt %p (orig %p) to iface %d (%p)",
519519
arp_pkt, pkt, net_if_get_by_iface(iface), iface);
520-
net_pkt_unref(pkt);
521520
return arp_pkt;
521+
} else if (ret == NET_ARP_PKT_QUEUED) {
522+
NET_DBG("Pending ARP request, pkt %p queued", pkt);
523+
return NULL;
524+
} else {
525+
NET_WARN("ARP failure (%d)", ret);
526+
return NULL;
522527
}
523-
524-
NET_DBG("Found ARP entry, sending pkt %p to iface %d (%p)",
525-
pkt, net_if_get_by_iface(iface), iface);
526528
}
527529

528530
return pkt;

tests/net/arp/src/main.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ ZTEST(arp_fn_tests, test_arp)
320320
struct net_if_addr *ifaddr;
321321
struct net_arp_hdr *arp_hdr;
322322
struct net_ipv4_hdr *ipv4;
323-
int len;
323+
int len, ret;
324324

325325
struct in_addr dst = { { { 192, 0, 2, 2 } } };
326326
struct in_addr dst_far = { { { 10, 11, 12, 13 } } };
@@ -367,7 +367,9 @@ ZTEST(arp_fn_tests, test_arp)
367367

368368
memcpy(net_buf_add(pkt->buffer, len), app_data, len);
369369

370-
pkt2 = net_arp_prepare(pkt, &dst, NULL);
370+
ret = net_arp_prepare(pkt, &dst, NULL, &pkt2);
371+
372+
zassert_equal(NET_ARP_PKT_REPLACED, ret);
371373

372374
/* pkt2 is the ARP packet and pkt is the IPv4 packet and it was
373375
* stored in ARP table.
@@ -453,7 +455,9 @@ ZTEST(arp_fn_tests, test_arp)
453455
/* Then a case where target is not in the same subnet */
454456
net_ipv4_addr_copy_raw(ipv4->dst, (uint8_t *)&dst_far);
455457

456-
pkt2 = net_arp_prepare(pkt, &dst_far, NULL);
458+
ret = net_arp_prepare(pkt, &dst_far, NULL, &pkt2);
459+
460+
zassert_equal(NET_ARP_PKT_REPLACED, ret);
457461

458462
zassert_not_equal((void *)(pkt2), (void *)(pkt),
459463
"ARP cache should not find anything");
@@ -484,7 +488,9 @@ ZTEST(arp_fn_tests, test_arp)
484488
*/
485489
net_pkt_ref(pkt);
486490

487-
pkt2 = net_arp_prepare(pkt, &dst_far, NULL);
491+
ret = net_arp_prepare(pkt, &dst_far, NULL, &pkt2);
492+
493+
zassert_equal(NET_ARP_PKT_REPLACED, ret);
488494

489495
zassert_not_null(pkt2,
490496
"ARP cache is not sending the request again");
@@ -501,7 +507,9 @@ ZTEST(arp_fn_tests, test_arp)
501507
*/
502508
net_pkt_ref(pkt);
503509

504-
pkt2 = net_arp_prepare(pkt, &dst_far2, NULL);
510+
ret = net_arp_prepare(pkt, &dst_far2, NULL, &pkt2);
511+
512+
zassert_equal(NET_ARP_PKT_REPLACED, ret);
505513

506514
zassert_not_null(pkt2,
507515
"ARP cache did not send a req");

0 commit comments

Comments
 (0)