Lines Matching +full:non +full:- +full:compliant
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
25 check = &(((struct tcphdr *)txporthdr)->check); in rmnet_map_get_csum_field()
29 check = &(((struct udphdr *)txporthdr)->check); in rmnet_map_get_csum_field()
51 ip4h = (struct iphdr *)(skb->data); in rmnet_map_ipv4_dl_csum_trailer()
52 if ((ntohs(ip4h->frag_off) & IP_MF) || in rmnet_map_ipv4_dl_csum_trailer()
53 ((ntohs(ip4h->frag_off) & IP_OFFSET) > 0)) { in rmnet_map_ipv4_dl_csum_trailer()
54 priv->stats.csum_fragmented_pkt++; in rmnet_map_ipv4_dl_csum_trailer()
55 return -EOPNOTSUPP; in rmnet_map_ipv4_dl_csum_trailer()
58 txporthdr = skb->data + ip4h->ihl * 4; in rmnet_map_ipv4_dl_csum_trailer()
60 csum_field = rmnet_map_get_csum_field(ip4h->protocol, txporthdr); in rmnet_map_ipv4_dl_csum_trailer()
63 priv->stats.csum_err_invalid_transport++; in rmnet_map_ipv4_dl_csum_trailer()
64 return -EPROTONOSUPPORT; in rmnet_map_ipv4_dl_csum_trailer()
67 /* RFC 768 - Skip IPv4 UDP packets where sender checksum field is 0 */ in rmnet_map_ipv4_dl_csum_trailer()
68 if (*csum_field == 0 && ip4h->protocol == IPPROTO_UDP) { in rmnet_map_ipv4_dl_csum_trailer()
69 priv->stats.csum_skipped++; in rmnet_map_ipv4_dl_csum_trailer()
73 csum_value = ~ntohs(csum_trailer->csum_value); in rmnet_map_ipv4_dl_csum_trailer()
74 hdr_csum = ~ip_fast_csum(ip4h, (int)ip4h->ihl); in rmnet_map_ipv4_dl_csum_trailer()
78 pseudo_csum = ~csum_tcpudp_magic(ip4h->saddr, ip4h->daddr, in rmnet_map_ipv4_dl_csum_trailer()
79 ntohs(ip4h->tot_len) - ip4h->ihl * 4, in rmnet_map_ipv4_dl_csum_trailer()
80 ip4h->protocol, 0); in rmnet_map_ipv4_dl_csum_trailer()
89 switch (ip4h->protocol) { in rmnet_map_ipv4_dl_csum_trailer()
91 /* RFC 768 - DL4 1's complement rule for UDP csum 0 */ in rmnet_map_ipv4_dl_csum_trailer()
96 /* DL4 Non-RFC compliant TCP checksum found */ in rmnet_map_ipv4_dl_csum_trailer()
104 priv->stats.csum_ok++; in rmnet_map_ipv4_dl_csum_trailer()
107 priv->stats.csum_validation_failed++; in rmnet_map_ipv4_dl_csum_trailer()
108 return -EINVAL; in rmnet_map_ipv4_dl_csum_trailer()
125 ip6h = (struct ipv6hdr *)(skb->data); in rmnet_map_ipv6_dl_csum_trailer()
127 txporthdr = skb->data + sizeof(struct ipv6hdr); in rmnet_map_ipv6_dl_csum_trailer()
128 csum_field = rmnet_map_get_csum_field(ip6h->nexthdr, txporthdr); in rmnet_map_ipv6_dl_csum_trailer()
131 priv->stats.csum_err_invalid_transport++; in rmnet_map_ipv6_dl_csum_trailer()
132 return -EPROTONOSUPPORT; in rmnet_map_ipv6_dl_csum_trailer()
135 csum_value = ~ntohs(csum_trailer->csum_value); in rmnet_map_ipv6_dl_csum_trailer()
138 (int)(txporthdr - (void *)(skb->data)))); in rmnet_map_ipv6_dl_csum_trailer()
142 length = (ip6h->nexthdr == IPPROTO_UDP) ? in rmnet_map_ipv6_dl_csum_trailer()
143 ntohs(((struct udphdr *)txporthdr)->len) : in rmnet_map_ipv6_dl_csum_trailer()
144 ntohs(ip6h->payload_len); in rmnet_map_ipv6_dl_csum_trailer()
145 pseudo_csum = ~(csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, in rmnet_map_ipv6_dl_csum_trailer()
146 length, ip6h->nexthdr, 0)); in rmnet_map_ipv6_dl_csum_trailer()
155 switch (ip6h->nexthdr) { in rmnet_map_ipv6_dl_csum_trailer()
164 /* DL6 Non-RFC compliant TCP checksum found */ in rmnet_map_ipv6_dl_csum_trailer()
172 priv->stats.csum_ok++; in rmnet_map_ipv6_dl_csum_trailer()
175 priv->stats.csum_validation_failed++; in rmnet_map_ipv6_dl_csum_trailer()
176 return -EINVAL; in rmnet_map_ipv6_dl_csum_trailer()
187 txphdr = iphdr + ip4h->ihl * 4; in rmnet_map_complement_ipv4_txporthdr_csum_field()
189 if (ip4h->protocol == IPPROTO_TCP || ip4h->protocol == IPPROTO_UDP) { in rmnet_map_complement_ipv4_txporthdr_csum_field()
190 csum = (u16 *)rmnet_map_get_csum_field(ip4h->protocol, txphdr); in rmnet_map_complement_ipv4_txporthdr_csum_field()
203 offset = htons((__force u16)(skb_transport_header(skb) - in rmnet_map_ipv4_ul_csum_header()
205 ul_header->csum_start_offset = offset; in rmnet_map_ipv4_ul_csum_header()
206 ul_header->csum_insert_offset = skb->csum_offset; in rmnet_map_ipv4_ul_csum_header()
207 ul_header->csum_enabled = 1; in rmnet_map_ipv4_ul_csum_header()
208 if (ip4h->protocol == IPPROTO_UDP) in rmnet_map_ipv4_ul_csum_header()
209 ul_header->udp_ind = 1; in rmnet_map_ipv4_ul_csum_header()
211 ul_header->udp_ind = 0; in rmnet_map_ipv4_ul_csum_header()
217 skb->ip_summed = CHECKSUM_NONE; in rmnet_map_ipv4_ul_csum_header()
231 if (ip6h->nexthdr == IPPROTO_TCP || ip6h->nexthdr == IPPROTO_UDP) { in rmnet_map_complement_ipv6_txporthdr_csum_field()
232 csum = (u16 *)rmnet_map_get_csum_field(ip6h->nexthdr, txphdr); in rmnet_map_complement_ipv6_txporthdr_csum_field()
245 offset = htons((__force u16)(skb_transport_header(skb) - in rmnet_map_ipv6_ul_csum_header()
247 ul_header->csum_start_offset = offset; in rmnet_map_ipv6_ul_csum_header()
248 ul_header->csum_insert_offset = skb->csum_offset; in rmnet_map_ipv6_ul_csum_header()
249 ul_header->csum_enabled = 1; in rmnet_map_ipv6_ul_csum_header()
251 if (ip6h->nexthdr == IPPROTO_UDP) in rmnet_map_ipv6_ul_csum_header()
252 ul_header->udp_ind = 1; in rmnet_map_ipv6_ul_csum_header()
254 ul_header->udp_ind = 0; in rmnet_map_ipv6_ul_csum_header()
260 skb->ip_summed = CHECKSUM_NONE; in rmnet_map_ipv6_ul_csum_header()
266 /* Adds MAP header to front of skb->data
277 map_datalen = skb->len - hdrlen; in rmnet_map_add_map_header()
283 map_header->pkt_len = htons(map_datalen); in rmnet_map_add_map_header()
287 padding = ALIGN(map_datalen, 4) - map_datalen; in rmnet_map_add_map_header()
299 map_header->pkt_len = htons(map_datalen + padding); in rmnet_map_add_map_header()
300 map_header->pad_len = padding & 0x3F; in rmnet_map_add_map_header()
318 if (skb->len == 0) in rmnet_map_deaggregate()
321 maph = (struct rmnet_map_header *)skb->data; in rmnet_map_deaggregate()
322 packet_len = ntohs(maph->pkt_len) + sizeof(struct rmnet_map_header); in rmnet_map_deaggregate()
324 if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4) in rmnet_map_deaggregate()
327 if (((int)skb->len - (int)packet_len) < 0) in rmnet_map_deaggregate()
331 if (ntohs(maph->pkt_len) == 0) in rmnet_map_deaggregate()
340 memcpy(skbn->data, skb->data, packet_len); in rmnet_map_deaggregate()
354 struct rmnet_priv *priv = netdev_priv(skb->dev); in rmnet_map_checksum_downlink_packet()
357 if (unlikely(!(skb->dev->features & NETIF_F_RXCSUM))) { in rmnet_map_checksum_downlink_packet()
358 priv->stats.csum_sw++; in rmnet_map_checksum_downlink_packet()
359 return -EOPNOTSUPP; in rmnet_map_checksum_downlink_packet()
362 csum_trailer = (struct rmnet_map_dl_csum_trailer *)(skb->data + len); in rmnet_map_checksum_downlink_packet()
364 if (!csum_trailer->valid) { in rmnet_map_checksum_downlink_packet()
365 priv->stats.csum_valid_unset++; in rmnet_map_checksum_downlink_packet()
366 return -EINVAL; in rmnet_map_checksum_downlink_packet()
369 if (skb->protocol == htons(ETH_P_IP)) { in rmnet_map_checksum_downlink_packet()
371 } else if (skb->protocol == htons(ETH_P_IPV6)) { in rmnet_map_checksum_downlink_packet()
375 priv->stats.csum_err_invalid_ip_version++; in rmnet_map_checksum_downlink_packet()
376 return -EPROTONOSUPPORT; in rmnet_map_checksum_downlink_packet()
379 priv->stats.csum_err_invalid_ip_version++; in rmnet_map_checksum_downlink_packet()
380 return -EPROTONOSUPPORT; in rmnet_map_checksum_downlink_packet()
399 if (unlikely(!(orig_dev->features & in rmnet_map_checksum_uplink_packet()
403 if (skb->ip_summed == CHECKSUM_PARTIAL) { in rmnet_map_checksum_uplink_packet()
407 if (skb->protocol == htons(ETH_P_IP)) { in rmnet_map_checksum_uplink_packet()
410 } else if (skb->protocol == htons(ETH_P_IPV6)) { in rmnet_map_checksum_uplink_packet()
415 priv->stats.csum_err_invalid_ip_version++; in rmnet_map_checksum_uplink_packet()
419 priv->stats.csum_err_invalid_ip_version++; in rmnet_map_checksum_uplink_packet()
424 ul_header->csum_start_offset = 0; in rmnet_map_checksum_uplink_packet()
425 ul_header->csum_insert_offset = 0; in rmnet_map_checksum_uplink_packet()
426 ul_header->csum_enabled = 0; in rmnet_map_checksum_uplink_packet()
427 ul_header->udp_ind = 0; in rmnet_map_checksum_uplink_packet()
429 priv->stats.csum_sw++; in rmnet_map_checksum_uplink_packet()