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

Commit 3279acc1 authored by Subash Abhinov Kasiviswanathan's avatar Subash Abhinov Kasiviswanathan
Browse files

net: qualcomm: rmnet: Clone UDP and command packets



This allows for more efficient processing of UDP and command
packets in the network stack. TCP packets cannot be cloned
since they need to be processed with GRO.

Also reset the hash to prevent RPS from having an invalid input.

CRs-Fixed: 2233026
Change-Id: If34fb8caa23c31a851c7b595adfec9af84707336
Signed-off-by: default avatarSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>
parent e1ba8be6
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;