Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 207c3f6e authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "net: qualcomm: rmnet: Clone UDP and command packets"

parents e8da9526 3279acc1
Loading
Loading
Loading
Loading
+45 −7
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@

#define RMNET_MAP_DEAGGR_SPACING  64
#define RMNET_MAP_DEAGGR_HEADROOM (RMNET_MAP_DEAGGR_SPACING / 2)
#define RMNET_MAP_PKT_COPY_THRESHOLD 64

static __sum16 *rmnet_map_get_csum_field(unsigned char protocol,
					 const void *txporthdr)
@@ -307,11 +308,34 @@ struct rmnet_map_header *rmnet_map_add_map_header(struct sk_buff *skb,
}

/* Deaggregates a single packet
 * A whole new buffer is allocated for each portion of an aggregated frame.
 * A whole new buffer is allocated for each portion of an aggregated frame
 * except when a UDP or command packet is received.
 * Caller should keep calling deaggregate() on the source skb until 0 is
 * returned, indicating that there are no more packets to deaggregate. Caller
 * is responsible for freeing the original skb.
 */
static int rmnet_validate_clone(struct sk_buff *skb)
{
	if (RMNET_MAP_GET_CD_BIT(skb))
		return 0;

	if (skb->len < RMNET_MAP_PKT_COPY_THRESHOLD)
		return 1;

	switch (skb->data[4] & 0xF0) {
	case 0x40:
		if (((struct iphdr *)&skb->data[4])->protocol == IPPROTO_UDP)
			return 0;
		break;
	case 0x60:
		if (((struct ipv6hdr *)&skb->data[4])->nexthdr == IPPROTO_UDP)
			return 0;
		/* Fall through */
	}

	return 1;
}

struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,
				      struct rmnet_port *port)
{
@@ -335,13 +359,27 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,
	if (ntohs(maph->pkt_len) == 0)
		return NULL;

	skbn = alloc_skb(packet_len + RMNET_MAP_DEAGGR_SPACING, GFP_ATOMIC);

	if (rmnet_validate_clone(skb)) {
		skbn = alloc_skb(packet_len + RMNET_MAP_DEAGGR_SPACING,
				 GFP_ATOMIC);
		if (!skbn)
			return NULL;

		skb_reserve(skbn, RMNET_MAP_DEAGGR_HEADROOM);
		skb_put(skbn, packet_len);
		memcpy(skbn->data, skb->data, packet_len);

	} else {
		skbn = skb_clone(skb, GFP_ATOMIC);
		if (!skbn)
			return NULL;

		skb_trim(skbn, packet_len);
		skbn->truesize = SKB_TRUESIZE(packet_len);
		__skb_set_hash(skbn, 0, 0, 0);
	}

	skb_pull(skb, packet_len);

	return skbn;
+4 −0
Original line number Diff line number Diff line
@@ -870,6 +870,10 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
	atomic_inc(&(skb_shinfo(skb)->dataref));
	skb->cloned = 1;

#ifdef CONFIG_IPV6_NDISC_NODETYPE
	C(ndisc_nodetype);
#endif

	return n;
#undef C
}