aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r--net/ipv4/udp.c139
1 files changed, 108 insertions, 31 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 0a073a263720..0ae038a4c7a8 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -902,9 +902,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
902 ipc.addr = inet->inet_saddr; 902 ipc.addr = inet->inet_saddr;
903 903
904 ipc.oif = sk->sk_bound_dev_if; 904 ipc.oif = sk->sk_bound_dev_if;
905 err = sock_tx_timestamp(sk, &ipc.tx_flags); 905
906 if (err) 906 sock_tx_timestamp(sk, &ipc.tx_flags);
907 return err; 907
908 if (msg->msg_controllen) { 908 if (msg->msg_controllen) {
909 err = ip_cmsg_send(sock_net(sk), msg, &ipc); 909 err = ip_cmsg_send(sock_net(sk), msg, &ipc);
910 if (err) 910 if (err)
@@ -1131,6 +1131,8 @@ static unsigned int first_packet_length(struct sock *sk)
1131 spin_lock_bh(&rcvq->lock); 1131 spin_lock_bh(&rcvq->lock);
1132 while ((skb = skb_peek(rcvq)) != NULL && 1132 while ((skb = skb_peek(rcvq)) != NULL &&
1133 udp_lib_checksum_complete(skb)) { 1133 udp_lib_checksum_complete(skb)) {
1134 UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS,
1135 IS_UDPLITE(sk));
1134 UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, 1136 UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS,
1135 IS_UDPLITE(sk)); 1137 IS_UDPLITE(sk));
1136 atomic_inc(&sk->sk_drops); 1138 atomic_inc(&sk->sk_drops);
@@ -1286,8 +1288,10 @@ out:
1286 1288
1287csum_copy_err: 1289csum_copy_err:
1288 slow = lock_sock_fast(sk); 1290 slow = lock_sock_fast(sk);
1289 if (!skb_kill_datagram(sk, skb, flags)) 1291 if (!skb_kill_datagram(sk, skb, flags)) {
1292 UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
1290 UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); 1293 UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
1294 }
1291 unlock_sock_fast(sk, slow); 1295 unlock_sock_fast(sk, slow);
1292 1296
1293 if (noblock) 1297 if (noblock)
@@ -1513,7 +1517,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
1513 1517
1514 if (rcu_access_pointer(sk->sk_filter) && 1518 if (rcu_access_pointer(sk->sk_filter) &&
1515 udp_lib_checksum_complete(skb)) 1519 udp_lib_checksum_complete(skb))
1516 goto drop; 1520 goto csum_error;
1517 1521
1518 1522
1519 if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) 1523 if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf))
@@ -1533,6 +1537,8 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
1533 1537
1534 return rc; 1538 return rc;
1535 1539
1540csum_error:
1541 UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
1536drop: 1542drop:
1537 UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); 1543 UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
1538 atomic_inc(&sk->sk_drops); 1544 atomic_inc(&sk->sk_drops);
@@ -1749,6 +1755,7 @@ csum_error:
1749 proto == IPPROTO_UDPLITE ? "Lite" : "", 1755 proto == IPPROTO_UDPLITE ? "Lite" : "",
1750 &saddr, ntohs(uh->source), &daddr, ntohs(uh->dest), 1756 &saddr, ntohs(uh->source), &daddr, ntohs(uh->dest),
1751 ulen); 1757 ulen);
1758 UDP_INC_STATS_BH(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE);
1752drop: 1759drop:
1753 UDP_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); 1760 UDP_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE);
1754 kfree_skb(skb); 1761 kfree_skb(skb);
@@ -2093,7 +2100,7 @@ static void udp_seq_stop(struct seq_file *seq, void *v)
2093 2100
2094int udp_seq_open(struct inode *inode, struct file *file) 2101int udp_seq_open(struct inode *inode, struct file *file)
2095{ 2102{
2096 struct udp_seq_afinfo *afinfo = PDE(inode)->data; 2103 struct udp_seq_afinfo *afinfo = PDE_DATA(inode);
2097 struct udp_iter_state *s; 2104 struct udp_iter_state *s;
2098 int err; 2105 int err;
2099 2106
@@ -2279,31 +2286,93 @@ void __init udp_init(void)
2279 2286
2280int udp4_ufo_send_check(struct sk_buff *skb) 2287int udp4_ufo_send_check(struct sk_buff *skb)
2281{ 2288{
2282 const struct iphdr *iph; 2289 if (!pskb_may_pull(skb, sizeof(struct udphdr)))
2283 struct udphdr *uh;
2284
2285 if (!pskb_may_pull(skb, sizeof(*uh)))
2286 return -EINVAL; 2290 return -EINVAL;
2287 2291
2288 iph = ip_hdr(skb); 2292 if (likely(!skb->encapsulation)) {
2289 uh = udp_hdr(skb); 2293 const struct iphdr *iph;
2294 struct udphdr *uh;
2295
2296 iph = ip_hdr(skb);
2297 uh = udp_hdr(skb);
2290 2298
2291 uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len, 2299 uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len,
2292 IPPROTO_UDP, 0); 2300 IPPROTO_UDP, 0);
2293 skb->csum_start = skb_transport_header(skb) - skb->head; 2301 skb->csum_start = skb_transport_header(skb) - skb->head;
2294 skb->csum_offset = offsetof(struct udphdr, check); 2302 skb->csum_offset = offsetof(struct udphdr, check);
2295 skb->ip_summed = CHECKSUM_PARTIAL; 2303 skb->ip_summed = CHECKSUM_PARTIAL;
2304 }
2296 return 0; 2305 return 0;
2297} 2306}
2298 2307
2308static struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
2309 netdev_features_t features)
2310{
2311 struct sk_buff *segs = ERR_PTR(-EINVAL);
2312 int mac_len = skb->mac_len;
2313 int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
2314 struct ethhdr *inner_eth = (struct ethhdr *)skb_inner_mac_header(skb);
2315 __be16 protocol = skb->protocol;
2316 netdev_features_t enc_features;
2317 int outer_hlen;
2318
2319 if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
2320 goto out;
2321
2322 skb->encapsulation = 0;
2323 __skb_pull(skb, tnl_hlen);
2324 skb_reset_mac_header(skb);
2325 skb_set_network_header(skb, skb_inner_network_offset(skb));
2326 skb->mac_len = skb_inner_network_offset(skb);
2327 inner_eth = (struct ethhdr *)skb_mac_header(skb);
2328 skb->protocol = inner_eth->h_proto;
2329
2330 /* segment inner packet. */
2331 enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
2332 segs = skb_mac_gso_segment(skb, enc_features);
2333 if (!segs || IS_ERR(segs))
2334 goto out;
2335
2336 outer_hlen = skb_tnl_header_len(skb);
2337 skb = segs;
2338 do {
2339 struct udphdr *uh;
2340 int udp_offset = outer_hlen - tnl_hlen;
2341
2342 skb->mac_len = mac_len;
2343
2344 skb_push(skb, outer_hlen);
2345 skb_reset_mac_header(skb);
2346 skb_set_network_header(skb, mac_len);
2347 skb_set_transport_header(skb, udp_offset);
2348 uh = udp_hdr(skb);
2349 uh->len = htons(skb->len - udp_offset);
2350
2351 /* csum segment if tunnel sets skb with csum. */
2352 if (unlikely(uh->check)) {
2353 struct iphdr *iph = ip_hdr(skb);
2354
2355 uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
2356 skb->len - udp_offset,
2357 IPPROTO_UDP, 0);
2358 uh->check = csum_fold(skb_checksum(skb, udp_offset,
2359 skb->len - udp_offset, 0));
2360 if (uh->check == 0)
2361 uh->check = CSUM_MANGLED_0;
2362
2363 }
2364 skb->ip_summed = CHECKSUM_NONE;
2365 skb->protocol = protocol;
2366 } while ((skb = skb->next));
2367out:
2368 return segs;
2369}
2370
2299struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, 2371struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
2300 netdev_features_t features) 2372 netdev_features_t features)
2301{ 2373{
2302 struct sk_buff *segs = ERR_PTR(-EINVAL); 2374 struct sk_buff *segs = ERR_PTR(-EINVAL);
2303 unsigned int mss; 2375 unsigned int mss;
2304 int offset;
2305 __wsum csum;
2306
2307 mss = skb_shinfo(skb)->gso_size; 2376 mss = skb_shinfo(skb)->gso_size;
2308 if (unlikely(skb->len <= mss)) 2377 if (unlikely(skb->len <= mss))
2309 goto out; 2378 goto out;
@@ -2313,6 +2382,7 @@ struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
2313 int type = skb_shinfo(skb)->gso_type; 2382 int type = skb_shinfo(skb)->gso_type;
2314 2383
2315 if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY | 2384 if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY |
2385 SKB_GSO_UDP_TUNNEL |
2316 SKB_GSO_GRE) || 2386 SKB_GSO_GRE) ||
2317 !(type & (SKB_GSO_UDP)))) 2387 !(type & (SKB_GSO_UDP))))
2318 goto out; 2388 goto out;
@@ -2323,20 +2393,27 @@ struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
2323 goto out; 2393 goto out;
2324 } 2394 }
2325 2395
2326 /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
2327 * do checksum of UDP packets sent as multiple IP fragments.
2328 */
2329 offset = skb_checksum_start_offset(skb);
2330 csum = skb_checksum(skb, offset, skb->len - offset, 0);
2331 offset += skb->csum_offset;
2332 *(__sum16 *)(skb->data + offset) = csum_fold(csum);
2333 skb->ip_summed = CHECKSUM_NONE;
2334
2335 /* Fragment the skb. IP headers of the fragments are updated in 2396 /* Fragment the skb. IP headers of the fragments are updated in
2336 * inet_gso_segment() 2397 * inet_gso_segment()
2337 */ 2398 */
2338 segs = skb_segment(skb, features); 2399 if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL)
2400 segs = skb_udp_tunnel_segment(skb, features);
2401 else {
2402 int offset;
2403 __wsum csum;
2404
2405 /* Do software UFO. Complete and fill in the UDP checksum as
2406 * HW cannot do checksum of UDP packets sent as multiple
2407 * IP fragments.
2408 */
2409 offset = skb_checksum_start_offset(skb);
2410 csum = skb_checksum(skb, offset, skb->len - offset, 0);
2411 offset += skb->csum_offset;
2412 *(__sum16 *)(skb->data + offset) = csum_fold(csum);
2413 skb->ip_summed = CHECKSUM_NONE;
2414
2415 segs = skb_segment(skb, features);
2416 }
2339out: 2417out:
2340 return segs; 2418 return segs;
2341} 2419}
2342