OSDN Git Service

udp: implement GRO for plain UDP sockets.
[uclinux-h8/linux.git] / net / ipv4 / udp.c
index ca3ed93..9fc08b0 100644 (file)
@@ -81,7 +81,7 @@
 
 #include <linux/uaccess.h>
 #include <asm/ioctls.h>
-#include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/highmem.h>
 #include <linux/swap.h>
 #include <linux/types.h>
 #include "udp_impl.h"
 #include <net/sock_reuseport.h>
 #include <net/addrconf.h>
+#include <net/udp_tunnel.h>
 
 struct udp_table udp_table __read_mostly;
 EXPORT_SYMBOL(udp_table);
@@ -371,6 +372,7 @@ static int compute_score(struct sock *sk, struct net *net,
 {
        int score;
        struct inet_sock *inet;
+       bool dev_match;
 
        if (!net_eq(sock_net(sk), net) ||
            udp_sk(sk)->udp_port_hash != hnum ||
@@ -398,15 +400,11 @@ static int compute_score(struct sock *sk, struct net *net,
                score += 4;
        }
 
-       if (sk->sk_bound_dev_if || exact_dif) {
-               bool dev_match = (sk->sk_bound_dev_if == dif ||
-                                 sk->sk_bound_dev_if == sdif);
-
-               if (!dev_match)
-                       return -1;
-               if (sk->sk_bound_dev_if)
-                       score += 4;
-       }
+       dev_match = udp_sk_bound_dev_eq(net, sk->sk_bound_dev_if,
+                                       dif, sdif);
+       if (!dev_match)
+               return -1;
+       score += 4;
 
        if (sk->sk_incoming_cpu == raw_smp_processor_id())
                score++;
@@ -2398,11 +2396,15 @@ void udp_destroy_sock(struct sock *sk)
        bool slow = lock_sock_fast(sk);
        udp_flush_pending_frames(sk);
        unlock_sock_fast(sk, slow);
-       if (static_branch_unlikely(&udp_encap_needed_key) && up->encap_type) {
-               void (*encap_destroy)(struct sock *sk);
-               encap_destroy = READ_ONCE(up->encap_destroy);
-               if (encap_destroy)
-                       encap_destroy(sk);
+       if (static_branch_unlikely(&udp_encap_needed_key)) {
+               if (up->encap_type) {
+                       void (*encap_destroy)(struct sock *sk);
+                       encap_destroy = READ_ONCE(up->encap_destroy);
+                       if (encap_destroy)
+                               encap_destroy(sk);
+               }
+               if (up->encap_enabled)
+                       static_branch_disable(&udp_encap_needed_key);
        }
 }
 
@@ -2447,7 +2449,9 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
                        /* FALLTHROUGH */
                case UDP_ENCAP_L2TPINUDP:
                        up->encap_type = val;
-                       udp_encap_enable();
+                       lock_sock(sk);
+                       udp_tunnel_encap_enable(sk->sk_socket);
+                       release_sock(sk);
                        break;
                default:
                        err = -ENOPROTOOPT;
@@ -2469,6 +2473,14 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
                up->gso_size = val;
                break;
 
+       case UDP_GRO:
+               lock_sock(sk);
+               if (valbool)
+                       udp_tunnel_encap_enable(sk->sk_socket);
+               up->gro_enabled = valbool;
+               release_sock(sk);
+               break;
+
        /*
         *      UDP-Lite's partial checksum coverage (RFC 3828).
         */