Loading drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c +45 −7 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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) { Loading @@ -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; Loading net/core/skbuff.c +4 −0 Original line number Diff line number Diff line Loading @@ -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 } Loading Loading
drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c +45 −7 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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) { Loading @@ -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; Loading
net/core/skbuff.c +4 −0 Original line number Diff line number Diff line Loading @@ -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 } Loading