Skip to content
Permalink
Browse files

net: ip: net_pkt: Implement net_pkt_shallow_clone

This commit implements net_pkt_shallow_clone. A shallow clone clones
the net_pkt but not the buffers. The buffers are only referenced and
therefor only freed when both copies of the net_pkt are freed.

Signed-off-by: Alexander Wachter <alexander.wachter@student.tugraz.at>
  • Loading branch information...
alexanderwachter authored and jukkar committed Jun 7, 2019
1 parent 7fe8517 commit 95863a73daa71e39f59073cd3360e22904f77817
Showing with 76 additions and 22 deletions.
  1. +10 −0 include/net/net_pkt.h
  2. +66 −22 subsys/net/ip/net_pkt.c
@@ -1553,6 +1553,16 @@ int net_pkt_copy(struct net_pkt *pkt_dst,
*/
struct net_pkt *net_pkt_clone(struct net_pkt *pkt, s32_t timeout);

/**
* @brief Clone pkt and increase the refcount of its buffer.
*
* @param pkt Original pkt to be shallow cloned
* @param timeout Timeout to wait for free packet
*
* @return NULL if error, cloned packet otherwise.
*/
struct net_pkt *net_pkt_shallow_clone(struct net_pkt *pkt, s32_t timeout);

/**
* @brief Read some data from a net_pkt
*
@@ -1672,6 +1672,32 @@ int net_pkt_copy(struct net_pkt *pkt_dst,
return 0;
}

static void clone_pkt_attributes(struct net_pkt *pkt, struct net_pkt *clone_pkt)
{
net_pkt_set_family(clone_pkt, net_pkt_family(pkt));
net_pkt_set_context(clone_pkt, net_pkt_context(pkt));
net_pkt_set_ip_hdr_len(clone_pkt, net_pkt_ip_hdr_len(pkt));
net_pkt_set_vlan_tag(clone_pkt, net_pkt_vlan_tag(pkt));
net_pkt_set_timestamp(clone_pkt, net_pkt_timestamp(pkt));
net_pkt_set_priority(clone_pkt, net_pkt_priority(pkt));
net_pkt_set_orig_iface(clone_pkt, net_pkt_orig_iface(pkt));

if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) {
net_pkt_set_ipv4_ttl(clone_pkt, net_pkt_ipv4_ttl(pkt));
} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
net_pkt_family(pkt) == AF_INET6) {
net_pkt_set_ipv6_hop_limit(clone_pkt,
net_pkt_ipv6_hop_limit(pkt));
net_pkt_set_ipv6_ext_len(clone_pkt, net_pkt_ipv6_ext_len(pkt));
net_pkt_set_ipv6_ext_opt_len(clone_pkt,
net_pkt_ipv6_ext_opt_len(pkt));
net_pkt_set_ipv6_hdr_prev(clone_pkt,
net_pkt_ipv6_hdr_prev(pkt));
net_pkt_set_ipv6_next_hdr(clone_pkt,
net_pkt_ipv6_next_hdr(pkt));
}
}

struct net_pkt *net_pkt_clone(struct net_pkt *pkt, s32_t timeout)
{
struct net_pkt *clone_pkt;
@@ -1701,28 +1727,7 @@ struct net_pkt *net_pkt_clone(struct net_pkt *pkt, s32_t timeout)
sizeof(clone_pkt->lladdr_dst));
}

net_pkt_set_family(clone_pkt, net_pkt_family(pkt));
net_pkt_set_context(clone_pkt, net_pkt_context(pkt));
net_pkt_set_ip_hdr_len(clone_pkt, net_pkt_ip_hdr_len(pkt));
net_pkt_set_vlan_tag(clone_pkt, net_pkt_vlan_tag(pkt));
net_pkt_set_timestamp(clone_pkt, net_pkt_timestamp(pkt));
net_pkt_set_priority(clone_pkt, net_pkt_priority(pkt));
net_pkt_set_orig_iface(clone_pkt, net_pkt_orig_iface(pkt));

if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) {
net_pkt_set_ipv4_ttl(clone_pkt, net_pkt_ipv4_ttl(pkt));
} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
net_pkt_family(pkt) == AF_INET6) {
net_pkt_set_ipv6_hop_limit(clone_pkt,
net_pkt_ipv6_hop_limit(pkt));
net_pkt_set_ipv6_ext_len(clone_pkt, net_pkt_ipv6_ext_len(pkt));
net_pkt_set_ipv6_ext_opt_len(clone_pkt,
net_pkt_ipv6_ext_opt_len(pkt));
net_pkt_set_ipv6_hdr_prev(clone_pkt,
net_pkt_ipv6_hdr_prev(pkt));
net_pkt_set_ipv6_next_hdr(clone_pkt,
net_pkt_ipv6_next_hdr(pkt));
}
clone_pkt_attributes(pkt, clone_pkt);

net_pkt_cursor_init(clone_pkt);

@@ -1731,6 +1736,45 @@ struct net_pkt *net_pkt_clone(struct net_pkt *pkt, s32_t timeout)
return clone_pkt;
}

struct net_pkt *net_pkt_shallow_clone(struct net_pkt *pkt, s32_t timeout)
{
struct net_pkt *clone_pkt;
struct net_buf *buf;

clone_pkt = net_pkt_alloc(timeout);
if (!clone_pkt) {
return NULL;
}

net_pkt_set_iface(clone_pkt, net_pkt_iface(pkt));
clone_pkt->buffer = pkt->buffer;
buf = pkt->buffer;

while (buf) {
net_pkt_frag_ref(buf);
buf = buf->frags;
}

if (pkt->buffer) {
/* The link header pointers are only usable if there is
* a buffer that we copied because those pointers point
* to start of the fragment which we do not have right now.
*/
memcpy(&clone_pkt->lladdr_src, &pkt->lladdr_src,
sizeof(clone_pkt->lladdr_src));
memcpy(&clone_pkt->lladdr_dst, &pkt->lladdr_dst,
sizeof(clone_pkt->lladdr_dst));
}

clone_pkt_attributes(pkt, clone_pkt);

net_pkt_cursor_restore(clone_pkt, &pkt->cursor);

NET_DBG("Shallow cloned %p to %p", pkt, clone_pkt);

return clone_pkt;
}

size_t net_pkt_remaining_data(struct net_pkt *pkt)
{
struct net_buf *buf;

0 comments on commit 95863a7

Please sign in to comment.
You can’t perform that action at this time.