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

Commit 8b44fe68 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "net: rmnet_data: Add support for MAPv4 data format"

parents 854262df 6aad2753
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
 /*
 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -24,6 +24,7 @@
#define RMNET_EGRESS_FORMAT_AGGREGATION         (1<<2)
#define RMNET_EGRESS_FORMAT_MUXING              (1<<3)
#define RMNET_EGRESS_FORMAT_MAP_CKSUMV3         (1<<4)
#define RMNET_EGRESS_FORMAT_MAP_CKSUMV4         (1<<5)

#define RMNET_INGRESS_FIX_ETHERNET              (1<<0)
#define RMNET_INGRESS_FORMAT_MAP                (1<<1)
@@ -31,6 +32,7 @@
#define RMNET_INGRESS_FORMAT_DEMUXING           (1<<3)
#define RMNET_INGRESS_FORMAT_MAP_COMMANDS       (1<<4)
#define RMNET_INGRESS_FORMAT_MAP_CKSUMV3        (1<<5)
#define RMNET_INGRESS_FORMAT_MAP_CKSUMV4        (1<<6)

/* ***************** Netlink API ******************************************** */
#define RMNET_NETLINK_PROTO 31
+8 −4
Original line number Diff line number Diff line
@@ -364,7 +364,8 @@ static rx_handler_result_t _rmnet_map_ingress_handler(struct sk_buff *skb,
	if (config->ingress_data_format & RMNET_INGRESS_FORMAT_DEMUXING)
		skb->dev = ep->egress_dev;

	if (config->ingress_data_format & RMNET_INGRESS_FORMAT_MAP_CKSUMV3) {
	if ((config->ingress_data_format & RMNET_INGRESS_FORMAT_MAP_CKSUMV3) ||
	    (config->ingress_data_format & RMNET_INGRESS_FORMAT_MAP_CKSUMV4)) {
		ckresult = rmnet_map_checksum_downlink_packet(skb);
		trace_rmnet_map_checksum_downlink_packet(skb, ckresult);
		rmnet_stats_dl_checksum(ckresult);
@@ -453,7 +454,8 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
	additional_header_length = 0;

	required_headroom = sizeof(struct rmnet_map_header_s);
	if (config->egress_data_format & RMNET_EGRESS_FORMAT_MAP_CKSUMV3) {
	if ((config->egress_data_format & RMNET_EGRESS_FORMAT_MAP_CKSUMV3) ||
	    (config->egress_data_format & RMNET_EGRESS_FORMAT_MAP_CKSUMV4)) {
		required_headroom +=
			sizeof(struct rmnet_map_ul_checksum_header_s);
		additional_header_length +=
@@ -470,8 +472,10 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
		}
	}

	if (config->egress_data_format & RMNET_EGRESS_FORMAT_MAP_CKSUMV3) {
		ckresult = rmnet_map_checksum_uplink_packet(skb, orig_dev);
	if ((config->egress_data_format & RMNET_EGRESS_FORMAT_MAP_CKSUMV3) ||
	    (config->egress_data_format & RMNET_EGRESS_FORMAT_MAP_CKSUMV4)) {
		ckresult = rmnet_map_checksum_uplink_packet
				(skb, orig_dev, config->egress_data_format);
		trace_rmnet_map_checksum_uplink_packet(orig_dev, ckresult);
		rmnet_stats_ul_checksum(ckresult);
	}
+2 −2
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -141,6 +141,6 @@ void rmnet_map_aggregate(struct sk_buff *skb,

int rmnet_map_checksum_downlink_packet(struct sk_buff *skb);
int rmnet_map_checksum_uplink_packet(struct sk_buff *skb,
				      struct net_device *orig_dev);
	struct net_device *orig_dev, uint32_t egress_data_format);

#endif /* _RMNET_MAP_H_ */
+42 −2
Original line number Diff line number Diff line
@@ -132,7 +132,8 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,
	maph = (struct rmnet_map_header_s *) skb->data;
	packet_len = ntohs(maph->pkt_len) + sizeof(struct rmnet_map_header_s);

	if (config->ingress_data_format & RMNET_INGRESS_FORMAT_MAP_CKSUMV3)
	if ((config->ingress_data_format & RMNET_INGRESS_FORMAT_MAP_CKSUMV3) ||
	    (config->ingress_data_format & RMNET_INGRESS_FORMAT_MAP_CKSUMV4))
		packet_len += sizeof(struct rmnet_map_dl_checksum_trailer_s);

	if ((((int)skb->len) - ((int)packet_len)) < 0) {
@@ -645,6 +646,37 @@ static void rmnet_map_fill_ipv6_packet_ul_checksum_header(void *iphdr,
	skb->ip_summed = CHECKSUM_NONE;
}

static void rmnet_map_complement_ipv4_txporthdr_csum_field(void *iphdr)
{
	struct iphdr *ip4h = (struct iphdr *)iphdr;
	void *txporthdr;
	uint16_t *csum;

	txporthdr = iphdr + ip4h->ihl*4;

	if ((ip4h->protocol == IPPROTO_TCP) ||
	    (ip4h->protocol == IPPROTO_UDP)) {
		csum = (uint16_t *)rmnet_map_get_checksum_field(ip4h->protocol,
								txporthdr);
		*csum = ~(*csum);
	}
}

static void rmnet_map_complement_ipv6_txporthdr_csum_field(void *ip6hdr)
{
	struct ipv6hdr *ip6h = (struct ipv6hdr *)ip6hdr;
	void *txporthdr;
	uint16_t *csum;

	txporthdr = ip6hdr + sizeof(struct ipv6hdr);

	if ((ip6h->nexthdr == IPPROTO_TCP) || (ip6h->nexthdr == IPPROTO_UDP)) {
		csum = (uint16_t *)rmnet_map_get_checksum_field(ip6h->nexthdr,
								txporthdr);
		*csum = ~(*csum);
	}
}

/**
 * rmnet_map_checksum_uplink_packet() - Generates UL checksum
 * meta info header
@@ -659,7 +691,7 @@ static void rmnet_map_fill_ipv6_packet_ul_checksum_header(void *iphdr,
 *   - RMNET_MAP_CHECKSUM_SW: Unsupported packet for UL checksum offload.
 */
int rmnet_map_checksum_uplink_packet(struct sk_buff *skb,
	struct net_device *orig_dev)
	struct net_device *orig_dev, uint32_t egress_data_format)
{
	unsigned char ip_version;
	struct rmnet_map_ul_checksum_header_s *ul_header;
@@ -682,10 +714,18 @@ int rmnet_map_checksum_uplink_packet(struct sk_buff *skb,
		if (ip_version == 0x04) {
			rmnet_map_fill_ipv4_packet_ul_checksum_header(iphdr,
				ul_header, skb);
			if (egress_data_format &
			    RMNET_EGRESS_FORMAT_MAP_CKSUMV4)
				rmnet_map_complement_ipv4_txporthdr_csum_field(
					iphdr);
			return RMNET_MAP_CHECKSUM_OK;
		} else if (ip_version == 0x06) {
			rmnet_map_fill_ipv6_packet_ul_checksum_header(iphdr,
				ul_header, skb);
			if (egress_data_format &
			    RMNET_EGRESS_FORMAT_MAP_CKSUMV4)
				rmnet_map_complement_ipv6_txporthdr_csum_field(
					iphdr);
			return RMNET_MAP_CHECKSUM_OK;
		} else {
			ret = RMNET_MAP_CHECKSUM_ERR_UNKNOWN_IP_VERSION;