net/ethernet: Make ethernet allocating its own frag for the header
This is currently unoptimized, as all frags are allocated with relevant
ll reserve for such header space. However, this is the first step
towards getting rid of that ll reserve concept everywhere.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
diff --git a/include/net/ethernet.h b/include/net/ethernet.h
index 8e40f12..584c212 100644
--- a/include/net/ethernet.h
+++ b/include/net/ethernet.h
@@ -544,13 +544,14 @@
* @param src Source ethernet address
* @param dst Destination ethernet address
*
- * @return Pointer to ethernet header struct inside net_buf.
+ * @return Pointer to newly inserted net_buf where header is found,
+ * NULL otherwise.
*/
-struct net_eth_hdr *net_eth_fill_header(struct ethernet_context *ctx,
- struct net_pkt *pkt,
- u32_t ptype,
- u8_t *src,
- u8_t *dst);
+struct net_buf *net_eth_fill_header(struct ethernet_context *ctx,
+ struct net_pkt *pkt,
+ u32_t ptype,
+ u8_t *src,
+ u8_t *dst);
/**
* @brief Inform ethernet L2 driver that ethernet carrier is detected.
diff --git a/subsys/net/l2/ethernet/arp.c b/subsys/net/l2/ethernet/arp.c
index 31235b4..f3114be 100644
--- a/subsys/net/l2/ethernet/arp.c
+++ b/subsys/net/l2/ethernet/arp.c
@@ -237,7 +237,6 @@
struct ethernet_context *ctx = net_if_l2_data(iface);
int eth_hdr_len = sizeof(struct net_eth_hdr);
struct net_pkt *pkt;
- struct net_buf *frag;
struct net_arp_hdr *hdr;
struct net_eth_hdr *eth;
struct in_addr *my_addr;
@@ -252,33 +251,28 @@
* things setup so no need to allocate new net_pkt
*/
pkt = pending;
-
- net_buf_add(pkt->frags, sizeof(struct net_arp_hdr));
} else {
pkt = net_pkt_get_reserve_tx(eth_hdr_len, NET_BUF_TIMEOUT);
if (!pkt) {
return NULL;
}
- frag = net_pkt_get_frag(pkt, NET_BUF_TIMEOUT);
- if (!frag) {
- net_pkt_unref(pkt);
- return NULL;
- }
-
- net_pkt_frag_add(pkt, frag);
net_pkt_set_iface(pkt, iface);
net_pkt_set_family(pkt, AF_INET);
-
- net_buf_add(frag, sizeof(struct net_arp_hdr));
}
- hdr = NET_ARP_HDR(pkt);
-
net_pkt_set_vlan_tag(pkt, net_eth_get_vlan_tag(iface));
- eth = net_eth_fill_header(ctx, pkt, htons(NET_ETH_PTYPE_ARP),
- NULL, NULL);
+ if(!net_eth_fill_header(ctx, pkt, htons(NET_ETH_PTYPE_ARP),
+ NULL, NULL)) {
+ net_pkt_unref(pkt);
+ return NULL;
+ }
+
+ net_buf_add(pkt->frags, sizeof(struct net_arp_hdr));
+
+ eth = NET_ETH_HDR(pkt);
+ hdr = NET_ARP_HDR(pkt);
/* If entry is not set, then we are just about to send
* an ARP request using the data in pending net_pkt.
@@ -339,7 +333,6 @@
struct ethernet_context *ctx;
struct arp_entry *entry;
struct net_linkaddr *ll;
- struct net_eth_hdr *hdr;
struct in_addr *addr;
if (!pkt || !pkt->frags) {
@@ -348,24 +341,6 @@
ctx = net_if_l2_data(net_pkt_iface(pkt));
- if (net_pkt_ll_reserve(pkt) != sizeof(struct net_eth_hdr) &&
- (IS_ENABLED(CONFIG_NET_VLAN) &&
- net_pkt_ll_reserve(pkt) != sizeof(struct net_eth_vlan_hdr))) {
- /* Add the ethernet header if it is missing. */
- struct net_buf *header;
-
- header = net_pkt_get_frag(pkt, NET_BUF_TIMEOUT);
- if (!header) {
- return NULL;
- }
-
- net_pkt_frag_insert(pkt, header);
-
- net_pkt_compact(pkt);
- }
-
- hdr = (struct net_eth_hdr *)net_pkt_ll(pkt);
-
/* Is the destination in the local network, if not route via
* the gateway address.
*/
@@ -429,10 +404,13 @@
sizeof(struct net_eth_addr))),
log_strdup(net_sprint_ipv4_addr(&NET_IPV4_HDR(pkt)->src)));
- net_eth_fill_header(ctx, pkt,
- current_ip == NULL ? htons(NET_ETH_PTYPE_IP) :
- htons(NET_ETH_PTYPE_ARP),
- ll->addr, entry->eth.addr);
+ if (!net_eth_fill_header(ctx, pkt,
+ current_ip == NULL ?
+ htons(NET_ETH_PTYPE_IP) :
+ htons(NET_ETH_PTYPE_ARP),
+ ll->addr, entry->eth.addr)) {
+ return NULL;
+ }
return pkt;
}
@@ -519,26 +497,25 @@
goto fail;
}
- frag = net_pkt_get_frag(pkt, NET_BUF_TIMEOUT);
+ net_pkt_set_iface(pkt, iface);
+ net_pkt_set_family(pkt, AF_INET);
+
+ eth_query = NET_ETH_HDR(req);
+
+ frag = net_eth_fill_header(ctx, pkt, htons(NET_ETH_PTYPE_ARP),
+ net_if_get_link_addr(iface)->addr,
+ eth_query->src.addr);
if (!frag) {
goto fail;
}
- net_pkt_frag_add(pkt, frag);
- net_pkt_set_iface(pkt, iface);
- net_pkt_set_family(pkt, AF_INET);
hdr = NET_ARP_HDR(pkt);
eth = NET_ETH_HDR(pkt);
query = NET_ARP_HDR(req);
- eth_query = NET_ETH_HDR(req);
net_pkt_set_vlan_tag(pkt, net_pkt_vlan_tag(req));
- net_eth_fill_header(ctx, pkt, htons(NET_ETH_PTYPE_ARP),
- net_if_get_link_addr(iface)->addr,
- eth_query->src.addr);
-
hdr->hwtype = htons(NET_ARP_HTYPE_ETH);
hdr->protocol = htons(NET_ETH_PTYPE_IP);
hdr->hwlen = sizeof(struct net_eth_addr);
diff --git a/subsys/net/l2/ethernet/ethernet.c b/subsys/net/l2/ethernet/ethernet.c
index 8aaf65c..e02633e 100644
--- a/subsys/net/l2/ethernet/ethernet.c
+++ b/subsys/net/l2/ethernet/ethernet.c
@@ -21,6 +21,8 @@
#include "ipv6.h"
#include "ipv4_autoconf_internal.h"
+#define NET_BUF_TIMEOUT K_MSEC(100)
+
#if defined(CONFIG_NET_IPV6)
static const struct net_eth_addr multicast_eth_addr = {
{ 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 } };
@@ -338,23 +340,28 @@
#define set_vlan_priority(...)
#endif /* CONFIG_NET_VLAN */
-struct net_eth_hdr *net_eth_fill_header(struct ethernet_context *ctx,
- struct net_pkt *pkt,
- u32_t ptype,
- u8_t *src,
- u8_t *dst)
+struct net_buf *net_eth_fill_header(struct ethernet_context *ctx,
+ struct net_pkt *pkt,
+ u32_t ptype,
+ u8_t *src,
+ u8_t *dst)
{
+ struct net_buf *hdr_frag;
struct net_eth_hdr *hdr;
- struct net_buf *frag = pkt->frags;
+
+ hdr_frag = net_pkt_get_frag(pkt, NET_BUF_TIMEOUT);
+ if (!hdr_frag) {
+ return NULL;
+ }
if (IS_ENABLED(CONFIG_NET_VLAN) &&
net_eth_is_vlan_enabled(ctx, net_pkt_iface(pkt))) {
struct net_eth_vlan_hdr *hdr_vlan;
- NET_ASSERT(net_buf_headroom(frag) >=
+ NET_ASSERT(net_buf_headroom(hdr_frag) >=
sizeof(struct net_eth_vlan_hdr));
- hdr_vlan = (struct net_eth_vlan_hdr *)(frag->data -
+ hdr_vlan = (struct net_eth_vlan_hdr *)(hdr_frag->data -
net_pkt_ll_reserve(pkt));
if (dst && ((u8_t *)&hdr_vlan->dst != dst)) {
@@ -373,29 +380,32 @@
print_vlan_ll_addrs(pkt, ntohs(hdr_vlan->type),
net_pkt_vlan_tci(pkt),
- frag->len,
+ hdr_frag->len,
&hdr_vlan->src, &hdr_vlan->dst);
+ } else {
+ NET_ASSERT(net_buf_headroom(hdr_frag) >=
+ sizeof(struct net_eth_hdr));
- return (struct net_eth_hdr *)hdr_vlan;
+ hdr = (struct net_eth_hdr *)(hdr_frag->data -
+ net_pkt_ll_reserve(pkt));
+
+ if (dst && ((u8_t *)&hdr->dst != dst)) {
+ memcpy(&hdr->dst, dst, sizeof(struct net_eth_addr));
+ }
+
+ if (src && ((u8_t *)&hdr->src != src)) {
+ memcpy(&hdr->src, src, sizeof(struct net_eth_addr));
+ }
+
+ hdr->type = ptype;
+
+ print_ll_addrs(pkt, ntohs(hdr->type),
+ hdr_frag->len, &hdr->src, &hdr->dst);
}
- NET_ASSERT(net_buf_headroom(frag) >= sizeof(struct net_eth_hdr));
+ net_pkt_frag_insert(pkt, hdr_frag);
- hdr = (struct net_eth_hdr *)(frag->data - net_pkt_ll_reserve(pkt));
-
- if (dst && ((u8_t *)&hdr->dst != dst)) {
- memcpy(&hdr->dst, dst, sizeof(struct net_eth_addr));
- }
-
- if (src && ((u8_t *)&hdr->src != src)) {
- memcpy(&hdr->src, src, sizeof(struct net_eth_addr));
- }
-
- hdr->type = ptype;
-
- print_ll_addrs(pkt, ntohs(hdr->type), frag->len, &hdr->src, &hdr->dst);
-
- return hdr;
+ return hdr_frag;
}
#if defined(CONFIG_NET_IPV4_AUTO)
@@ -549,9 +559,11 @@
* has already prepared the message to be sent.
*/
if (ptype != htons(NET_ETH_PTYPE_ARP)) {
- net_eth_fill_header(ctx, pkt, ptype,
- net_pkt_lladdr_src(pkt)->addr,
- net_pkt_lladdr_dst(pkt)->addr);
+ if (!net_eth_fill_header(ctx, pkt, ptype,
+ net_pkt_lladdr_src(pkt)->addr,
+ net_pkt_lladdr_dst(pkt)->addr)) {
+ return NET_DROP;
+ }
}
net_if_queue_tx(iface, pkt);