1212#include <net/udp.h>
1313#include <net/protocol.h>
1414#include <net/inet_common.h>
15- #include <net/udp_tunnel.h>
16-
17- #if IS_ENABLED (CONFIG_NET_UDP_TUNNEL )
18-
19- /*
20- * Dummy GRO tunnel callback, exists mainly to avoid dangling/NULL
21- * values for the udp tunnel static call.
22- */
23- static struct sk_buff * dummy_gro_rcv (struct sock * sk ,
24- struct list_head * head ,
25- struct sk_buff * skb )
26- {
27- NAPI_GRO_CB (skb )-> flush = 1 ;
28- return NULL ;
29- }
30-
31- typedef struct sk_buff * (* udp_tunnel_gro_rcv_t )(struct sock * sk ,
32- struct list_head * head ,
33- struct sk_buff * skb );
34-
35- struct udp_tunnel_type_entry {
36- udp_tunnel_gro_rcv_t gro_receive ;
37- refcount_t count ;
38- };
39-
40- #define UDP_MAX_TUNNEL_TYPES (IS_ENABLED(CONFIG_GENEVE) + \
41- IS_ENABLED(CONFIG_VXLAN) * 2 + \
42- IS_ENABLED(CONFIG_NET_FOU) * 2)
43-
44- DEFINE_STATIC_CALL (udp_tunnel_gro_rcv , dummy_gro_rcv );
45- static DEFINE_STATIC_KEY_FALSE (udp_tunnel_static_call );
46- static struct mutex udp_tunnel_gro_type_lock ;
47- static struct udp_tunnel_type_entry udp_tunnel_gro_types [UDP_MAX_TUNNEL_TYPES ];
48- static unsigned int udp_tunnel_gro_type_nr ;
49- static DEFINE_SPINLOCK (udp_tunnel_gro_lock );
50-
51- void udp_tunnel_update_gro_lookup (struct net * net , struct sock * sk , bool add )
52- {
53- bool is_ipv6 = sk -> sk_family == AF_INET6 ;
54- struct udp_sock * tup , * up = udp_sk (sk );
55- struct udp_tunnel_gro * udp_tunnel_gro ;
56-
57- spin_lock (& udp_tunnel_gro_lock );
58- udp_tunnel_gro = & net -> ipv4 .udp_tunnel_gro [is_ipv6 ];
59- if (add )
60- hlist_add_head (& up -> tunnel_list , & udp_tunnel_gro -> list );
61- else
62- hlist_del_init (& up -> tunnel_list );
63-
64- if (udp_tunnel_gro -> list .first &&
65- !udp_tunnel_gro -> list .first -> next ) {
66- tup = hlist_entry (udp_tunnel_gro -> list .first , struct udp_sock ,
67- tunnel_list );
68-
69- rcu_assign_pointer (udp_tunnel_gro -> sk , (struct sock * )tup );
70- } else {
71- RCU_INIT_POINTER (udp_tunnel_gro -> sk , NULL );
72- }
73-
74- spin_unlock (& udp_tunnel_gro_lock );
75- }
76- EXPORT_SYMBOL_GPL (udp_tunnel_update_gro_lookup );
77-
78- void udp_tunnel_update_gro_rcv (struct sock * sk , bool add )
79- {
80- struct udp_tunnel_type_entry * cur = NULL ;
81- struct udp_sock * up = udp_sk (sk );
82- int i , old_gro_type_nr ;
83-
84- if (!up -> gro_receive )
85- return ;
86-
87- mutex_lock (& udp_tunnel_gro_type_lock );
88- for (i = 0 ; i < udp_tunnel_gro_type_nr ; i ++ )
89- if (udp_tunnel_gro_types [i ].gro_receive == up -> gro_receive )
90- cur = & udp_tunnel_gro_types [i ];
91-
92- old_gro_type_nr = udp_tunnel_gro_type_nr ;
93- if (add ) {
94- /*
95- * Update the matching entry, if found, or add a new one
96- * if needed
97- */
98- if (cur ) {
99- refcount_inc (& cur -> count );
100- goto out ;
101- }
102-
103- if (unlikely (udp_tunnel_gro_type_nr == UDP_MAX_TUNNEL_TYPES )) {
104- pr_err_once ("Too many UDP tunnel types, please increase UDP_MAX_TUNNEL_TYPES\n" );
105- /* Ensure static call will never be enabled */
106- udp_tunnel_gro_type_nr = UDP_MAX_TUNNEL_TYPES + 2 ;
107- goto out ;
108- }
109-
110- cur = & udp_tunnel_gro_types [udp_tunnel_gro_type_nr ++ ];
111- refcount_set (& cur -> count , 1 );
112- cur -> gro_receive = up -> gro_receive ;
113- } else {
114- /*
115- * The stack cleanups only successfully added tunnel, the
116- * lookup on removal should never fail.
117- */
118- if (WARN_ON_ONCE (!cur ))
119- goto out ;
120-
121- if (!refcount_dec_and_test (& cur -> count ))
122- goto out ;
123-
124- /* avoid gaps, so that the enable tunnel has always id 0 */
125- * cur = udp_tunnel_gro_types [-- udp_tunnel_gro_type_nr ];
126- }
127-
128- if (udp_tunnel_gro_type_nr == 1 ) {
129- static_call_update (udp_tunnel_gro_rcv ,
130- udp_tunnel_gro_types [0 ].gro_receive );
131- static_branch_enable (& udp_tunnel_static_call );
132- } else if (old_gro_type_nr == 1 ) {
133- static_branch_disable (& udp_tunnel_static_call );
134- static_call_update (udp_tunnel_gro_rcv , dummy_gro_rcv );
135- }
136-
137- out :
138- mutex_unlock (& udp_tunnel_gro_type_lock );
139- }
140- EXPORT_SYMBOL_GPL (udp_tunnel_update_gro_rcv );
141-
142- static void udp_tunnel_gro_init (void )
143- {
144- mutex_init (& udp_tunnel_gro_type_lock );
145- }
146-
147- static struct sk_buff * udp_tunnel_gro_rcv (struct sock * sk ,
148- struct list_head * head ,
149- struct sk_buff * skb )
150- {
151- if (static_branch_likely (& udp_tunnel_static_call )) {
152- if (unlikely (gro_recursion_inc_test (skb ))) {
153- NAPI_GRO_CB (skb )-> flush |= 1 ;
154- return NULL ;
155- }
156- return static_call (udp_tunnel_gro_rcv )(sk , head , skb );
157- }
158- return call_gro_receive_sk (udp_sk (sk )-> gro_receive , sk , head , skb );
159- }
160-
161- #else
162-
163- static void udp_tunnel_gro_init (void ) {}
164-
165- static struct sk_buff * udp_tunnel_gro_rcv (struct sock * sk ,
166- struct list_head * head ,
167- struct sk_buff * skb )
168- {
169- return call_gro_receive_sk (udp_sk (sk )-> gro_receive , sk , head , skb );
170- }
171-
172- #endif
17315
17416static struct sk_buff * __skb_udp_tunnel_segment (struct sk_buff * skb ,
17517 netdev_features_t features ,
@@ -780,7 +622,7 @@ struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb,
780622
781623 skb_gro_pull (skb , sizeof (struct udphdr )); /* pull encapsulating udp header */
782624 skb_gro_postpull_rcsum (skb , uh , sizeof (struct udphdr ));
783- pp = udp_tunnel_gro_rcv ( sk , head , skb );
625+ pp = call_gro_receive_sk ( udp_sk ( sk ) -> gro_receive , sk , head , skb );
784626
785627out :
786628 skb_gro_flush_final (skb , pp , flush );
@@ -793,13 +635,8 @@ static struct sock *udp4_gro_lookup_skb(struct sk_buff *skb, __be16 sport,
793635{
794636 const struct iphdr * iph = skb_gro_network_header (skb );
795637 struct net * net = dev_net_rcu (skb -> dev );
796- struct sock * sk ;
797638 int iif , sdif ;
798639
799- sk = udp_tunnel_sk (net , false);
800- if (sk && dport == htons (sk -> sk_num ))
801- return sk ;
802-
803640 inet_get_iif_sdif (skb , & iif , & sdif );
804641
805642 return __udp4_lib_lookup (net , iph -> saddr , sport ,
@@ -930,7 +767,5 @@ int __init udpv4_offload_init(void)
930767 .gro_complete = udp4_gro_complete ,
931768 },
932769 };
933-
934- udp_tunnel_gro_init ();
935770 return inet_add_offload (& net_hotdata .udpv4_offload , IPPROTO_UDP );
936771}
0 commit comments