Loading net/rmnet_data/rmnet_data_handlers.c +3 −0 Original line number Original line Diff line number Diff line Loading @@ -597,6 +597,9 @@ static int rmnet_map_egress_handler(struct sk_buff *skb, if ((config->egress_data_format & RMNET_EGRESS_FORMAT_AGGREGATION) && if ((config->egress_data_format & RMNET_EGRESS_FORMAT_AGGREGATION) && !non_linear_skb) { !non_linear_skb) { if (rmnet_ul_aggregation_skip(skb, required_headroom)) return RMNET_MAP_SUCCESS; rmnet_map_aggregate(skb, config); rmnet_map_aggregate(skb, config); return RMNET_MAP_CONSUMED; return RMNET_MAP_CONSUMED; } } Loading net/rmnet_data/rmnet_map.h +2 −2 Original line number Original line Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -146,5 +146,5 @@ int rmnet_map_checksum_downlink_packet(struct sk_buff *skb); int rmnet_map_checksum_uplink_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, u32 egress_data_format); u32 egress_data_format); int rmnet_ul_aggregation_skip(struct sk_buff *skb, int offset); #endif /* _RMNET_MAP_H_ */ #endif /* _RMNET_MAP_H_ */ net/rmnet_data/rmnet_map_data.c +30 −8 Original line number Original line Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -234,16 +234,9 @@ void rmnet_map_aggregate(struct sk_buff *skb, if (!skb || !config) if (!skb || !config) return; return; size = config->egress_agg_size - skb->len; if (size < 2000) { LOGL("Invalid length %d", size); return; } new_packet: new_packet: spin_lock_irqsave(&config->agg_lock, flags); spin_lock_irqsave(&config->agg_lock, flags); memcpy(&last, &config->agg_last, sizeof(struct timespec)); memcpy(&last, &config->agg_last, sizeof(struct timespec)); getnstimeofday(&config->agg_last); getnstimeofday(&config->agg_last); Loading @@ -265,6 +258,7 @@ void rmnet_map_aggregate(struct sk_buff *skb, return; return; } } size = config->egress_agg_size - skb->len; config->agg_skb = skb_copy_expand(skb, 0, size, GFP_ATOMIC); config->agg_skb = skb_copy_expand(skb, 0, size, GFP_ATOMIC); if (!config->agg_skb) { if (!config->agg_skb) { config->agg_skb = 0; config->agg_skb = 0; Loading Loading @@ -748,3 +742,31 @@ int rmnet_map_checksum_uplink_packet(struct sk_buff *skb, done: done: return ret; return ret; } } int rmnet_ul_aggregation_skip(struct sk_buff *skb, int offset) { unsigned char *packet_start = skb->data + offset; int is_icmp = 0; if ((skb->data[offset]) >> 4 == 0x04) { struct iphdr *ip4h = (struct iphdr *)(packet_start); if (ip4h->protocol == IPPROTO_ICMP) is_icmp = 1; } else { struct ipv6hdr *ip6h = (struct ipv6hdr *)(packet_start); if (ip6h->nexthdr == NEXTHDR_FRAGMENT) { struct frag_hdr *frag; frag = (struct frag_hdr *)(packet_start + sizeof(struct ipv6hdr)); if (frag->nexthdr == IPPROTO_ICMPV6) is_icmp = 1; } else if (ip6h->nexthdr == IPPROTO_ICMPV6) { is_icmp = 1; } } return is_icmp; } Loading
net/rmnet_data/rmnet_data_handlers.c +3 −0 Original line number Original line Diff line number Diff line Loading @@ -597,6 +597,9 @@ static int rmnet_map_egress_handler(struct sk_buff *skb, if ((config->egress_data_format & RMNET_EGRESS_FORMAT_AGGREGATION) && if ((config->egress_data_format & RMNET_EGRESS_FORMAT_AGGREGATION) && !non_linear_skb) { !non_linear_skb) { if (rmnet_ul_aggregation_skip(skb, required_headroom)) return RMNET_MAP_SUCCESS; rmnet_map_aggregate(skb, config); rmnet_map_aggregate(skb, config); return RMNET_MAP_CONSUMED; return RMNET_MAP_CONSUMED; } } Loading
net/rmnet_data/rmnet_map.h +2 −2 Original line number Original line Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -146,5 +146,5 @@ int rmnet_map_checksum_downlink_packet(struct sk_buff *skb); int rmnet_map_checksum_uplink_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, u32 egress_data_format); u32 egress_data_format); int rmnet_ul_aggregation_skip(struct sk_buff *skb, int offset); #endif /* _RMNET_MAP_H_ */ #endif /* _RMNET_MAP_H_ */
net/rmnet_data/rmnet_map_data.c +30 −8 Original line number Original line Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -234,16 +234,9 @@ void rmnet_map_aggregate(struct sk_buff *skb, if (!skb || !config) if (!skb || !config) return; return; size = config->egress_agg_size - skb->len; if (size < 2000) { LOGL("Invalid length %d", size); return; } new_packet: new_packet: spin_lock_irqsave(&config->agg_lock, flags); spin_lock_irqsave(&config->agg_lock, flags); memcpy(&last, &config->agg_last, sizeof(struct timespec)); memcpy(&last, &config->agg_last, sizeof(struct timespec)); getnstimeofday(&config->agg_last); getnstimeofday(&config->agg_last); Loading @@ -265,6 +258,7 @@ void rmnet_map_aggregate(struct sk_buff *skb, return; return; } } size = config->egress_agg_size - skb->len; config->agg_skb = skb_copy_expand(skb, 0, size, GFP_ATOMIC); config->agg_skb = skb_copy_expand(skb, 0, size, GFP_ATOMIC); if (!config->agg_skb) { if (!config->agg_skb) { config->agg_skb = 0; config->agg_skb = 0; Loading Loading @@ -748,3 +742,31 @@ int rmnet_map_checksum_uplink_packet(struct sk_buff *skb, done: done: return ret; return ret; } } int rmnet_ul_aggregation_skip(struct sk_buff *skb, int offset) { unsigned char *packet_start = skb->data + offset; int is_icmp = 0; if ((skb->data[offset]) >> 4 == 0x04) { struct iphdr *ip4h = (struct iphdr *)(packet_start); if (ip4h->protocol == IPPROTO_ICMP) is_icmp = 1; } else { struct ipv6hdr *ip6h = (struct ipv6hdr *)(packet_start); if (ip6h->nexthdr == NEXTHDR_FRAGMENT) { struct frag_hdr *frag; frag = (struct frag_hdr *)(packet_start + sizeof(struct ipv6hdr)); if (frag->nexthdr == IPPROTO_ICMPV6) is_icmp = 1; } else if (ip6h->nexthdr == IPPROTO_ICMPV6) { is_icmp = 1; } } return is_icmp; }