diff options
author | David S. Miller <davem@davemloft.net> | 2017-09-05 23:03:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-09-05 23:03:35 -0400 |
commit | 18fb0b46d555dc42f52f69428dcd52f133877078 (patch) | |
tree | 7696741f50fb1a373aee3601074e30f6e366e425 | |
parent | 39cebdb77d55a193492a42170bf1c3d11e41e740 (diff) | |
parent | 6d9c153a0b84392406bc77600aa7d3ea365de041 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
-rw-r--r-- | drivers/net/dsa/dsa_loop.c | 2 | ||||
-rw-r--r-- | include/net/inet_frag.h | 35 | ||||
-rw-r--r-- | include/net/route.h | 7 | ||||
-rw-r--r-- | net/ieee802154/6lowpan/reassembly.c | 11 | ||||
-rw-r--r-- | net/ipv4/inet_fragment.c | 4 | ||||
-rw-r--r-- | net/ipv4/ip_fragment.c | 12 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 12 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 12 | ||||
-rw-r--r-- | net/l2tp/l2tp_core.c | 41 | ||||
-rw-r--r-- | net/l2tp/l2tp_core.h | 8 | ||||
-rw-r--r-- | net/l2tp/l2tp_eth.c | 11 | ||||
-rw-r--r-- | net/l2tp/l2tp_netlink.c | 8 | ||||
-rw-r--r-- | net/l2tp/l2tp_ppp.c | 19 |
13 files changed, 76 insertions, 106 deletions
diff --git a/drivers/net/dsa/dsa_loop.c b/drivers/net/dsa/dsa_loop.c index 7819a9fe8321..d55051abf4ed 100644 --- a/drivers/net/dsa/dsa_loop.c +++ b/drivers/net/dsa/dsa_loop.c | |||
@@ -352,7 +352,7 @@ static void __exit dsa_loop_exit(void) | |||
352 | 352 | ||
353 | mdio_driver_unregister(&dsa_loop_drv); | 353 | mdio_driver_unregister(&dsa_loop_drv); |
354 | for (i = 0; i < NUM_FIXED_PHYS; i++) | 354 | for (i = 0; i < NUM_FIXED_PHYS; i++) |
355 | if (phydevs[i]) | 355 | if (!IS_ERR(phydevs[i])) |
356 | fixed_phy_unregister(phydevs[i]); | 356 | fixed_phy_unregister(phydevs[i]); |
357 | } | 357 | } |
358 | module_exit(dsa_loop_exit); | 358 | module_exit(dsa_loop_exit); |
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h index 6fdcd2427776..fc59e0775e00 100644 --- a/include/net/inet_frag.h +++ b/include/net/inet_frag.h | |||
@@ -1,14 +1,9 @@ | |||
1 | #ifndef __NET_FRAG_H__ | 1 | #ifndef __NET_FRAG_H__ |
2 | #define __NET_FRAG_H__ | 2 | #define __NET_FRAG_H__ |
3 | 3 | ||
4 | #include <linux/percpu_counter.h> | ||
5 | |||
6 | struct netns_frags { | 4 | struct netns_frags { |
7 | /* The percpu_counter "mem" need to be cacheline aligned. | 5 | /* Keep atomic mem on separate cachelines in structs that include it */ |
8 | * mem.count must not share cacheline with other writers | 6 | atomic_t mem ____cacheline_aligned_in_smp; |
9 | */ | ||
10 | struct percpu_counter mem ____cacheline_aligned_in_smp; | ||
11 | |||
12 | /* sysctls */ | 7 | /* sysctls */ |
13 | int timeout; | 8 | int timeout; |
14 | int high_thresh; | 9 | int high_thresh; |
@@ -108,15 +103,10 @@ struct inet_frags { | |||
108 | int inet_frags_init(struct inet_frags *); | 103 | int inet_frags_init(struct inet_frags *); |
109 | void inet_frags_fini(struct inet_frags *); | 104 | void inet_frags_fini(struct inet_frags *); |
110 | 105 | ||
111 | static inline int inet_frags_init_net(struct netns_frags *nf) | 106 | static inline void inet_frags_init_net(struct netns_frags *nf) |
112 | { | ||
113 | return percpu_counter_init(&nf->mem, 0, GFP_KERNEL); | ||
114 | } | ||
115 | static inline void inet_frags_uninit_net(struct netns_frags *nf) | ||
116 | { | 107 | { |
117 | percpu_counter_destroy(&nf->mem); | 108 | atomic_set(&nf->mem, 0); |
118 | } | 109 | } |
119 | |||
120 | void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f); | 110 | void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f); |
121 | 111 | ||
122 | void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f); | 112 | void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f); |
@@ -140,31 +130,24 @@ static inline bool inet_frag_evicting(struct inet_frag_queue *q) | |||
140 | 130 | ||
141 | /* Memory Tracking Functions. */ | 131 | /* Memory Tracking Functions. */ |
142 | 132 | ||
143 | /* The default percpu_counter batch size is not big enough to scale to | ||
144 | * fragmentation mem acct sizes. | ||
145 | * The mem size of a 64K fragment is approx: | ||
146 | * (44 fragments * 2944 truesize) + frag_queue struct(200) = 129736 bytes | ||
147 | */ | ||
148 | static unsigned int frag_percpu_counter_batch = 130000; | ||
149 | |||
150 | static inline int frag_mem_limit(struct netns_frags *nf) | 133 | static inline int frag_mem_limit(struct netns_frags *nf) |
151 | { | 134 | { |
152 | return percpu_counter_read(&nf->mem); | 135 | return atomic_read(&nf->mem); |
153 | } | 136 | } |
154 | 137 | ||
155 | static inline void sub_frag_mem_limit(struct netns_frags *nf, int i) | 138 | static inline void sub_frag_mem_limit(struct netns_frags *nf, int i) |
156 | { | 139 | { |
157 | percpu_counter_add_batch(&nf->mem, -i, frag_percpu_counter_batch); | 140 | atomic_sub(i, &nf->mem); |
158 | } | 141 | } |
159 | 142 | ||
160 | static inline void add_frag_mem_limit(struct netns_frags *nf, int i) | 143 | static inline void add_frag_mem_limit(struct netns_frags *nf, int i) |
161 | { | 144 | { |
162 | percpu_counter_add_batch(&nf->mem, i, frag_percpu_counter_batch); | 145 | atomic_add(i, &nf->mem); |
163 | } | 146 | } |
164 | 147 | ||
165 | static inline unsigned int sum_frag_mem_limit(struct netns_frags *nf) | 148 | static inline int sum_frag_mem_limit(struct netns_frags *nf) |
166 | { | 149 | { |
167 | return percpu_counter_sum_positive(&nf->mem); | 150 | return atomic_read(&nf->mem); |
168 | } | 151 | } |
169 | 152 | ||
170 | /* RFC 3168 support : | 153 | /* RFC 3168 support : |
diff --git a/include/net/route.h b/include/net/route.h index cb0a76d9dde1..1b09a9368c68 100644 --- a/include/net/route.h +++ b/include/net/route.h | |||
@@ -189,10 +189,11 @@ static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src, | |||
189 | 189 | ||
190 | rcu_read_lock(); | 190 | rcu_read_lock(); |
191 | err = ip_route_input_noref(skb, dst, src, tos, devin); | 191 | err = ip_route_input_noref(skb, dst, src, tos, devin); |
192 | if (!err) | 192 | if (!err) { |
193 | skb_dst_force_safe(skb); | 193 | skb_dst_force_safe(skb); |
194 | if (!skb_dst(skb)) | 194 | if (!skb_dst(skb)) |
195 | err = -EINVAL; | 195 | err = -EINVAL; |
196 | } | ||
196 | rcu_read_unlock(); | 197 | rcu_read_unlock(); |
197 | 198 | ||
198 | return err; | 199 | return err; |
diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c index 30d875dff6b5..f85b08baff16 100644 --- a/net/ieee802154/6lowpan/reassembly.c +++ b/net/ieee802154/6lowpan/reassembly.c | |||
@@ -580,19 +580,14 @@ static int __net_init lowpan_frags_init_net(struct net *net) | |||
580 | { | 580 | { |
581 | struct netns_ieee802154_lowpan *ieee802154_lowpan = | 581 | struct netns_ieee802154_lowpan *ieee802154_lowpan = |
582 | net_ieee802154_lowpan(net); | 582 | net_ieee802154_lowpan(net); |
583 | int res; | ||
584 | 583 | ||
585 | ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH; | 584 | ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH; |
586 | ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH; | 585 | ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH; |
587 | ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT; | 586 | ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT; |
588 | 587 | ||
589 | res = inet_frags_init_net(&ieee802154_lowpan->frags); | 588 | inet_frags_init_net(&ieee802154_lowpan->frags); |
590 | if (res) | 589 | |
591 | return res; | 590 | return lowpan_frags_ns_sysctl_register(net); |
592 | res = lowpan_frags_ns_sysctl_register(net); | ||
593 | if (res) | ||
594 | inet_frags_uninit_net(&ieee802154_lowpan->frags); | ||
595 | return res; | ||
596 | } | 591 | } |
597 | 592 | ||
598 | static void __net_exit lowpan_frags_exit_net(struct net *net) | 593 | static void __net_exit lowpan_frags_exit_net(struct net *net) |
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 96e95e83cc61..af74d0433453 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
@@ -234,10 +234,8 @@ evict_again: | |||
234 | cond_resched(); | 234 | cond_resched(); |
235 | 235 | ||
236 | if (read_seqretry(&f->rnd_seqlock, seq) || | 236 | if (read_seqretry(&f->rnd_seqlock, seq) || |
237 | percpu_counter_sum(&nf->mem)) | 237 | sum_frag_mem_limit(nf)) |
238 | goto evict_again; | 238 | goto evict_again; |
239 | |||
240 | percpu_counter_destroy(&nf->mem); | ||
241 | } | 239 | } |
242 | EXPORT_SYMBOL(inet_frags_exit_net); | 240 | EXPORT_SYMBOL(inet_frags_exit_net); |
243 | 241 | ||
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 9a8cfac503dc..46408c220d9d 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -844,8 +844,6 @@ static void __init ip4_frags_ctl_register(void) | |||
844 | 844 | ||
845 | static int __net_init ipv4_frags_init_net(struct net *net) | 845 | static int __net_init ipv4_frags_init_net(struct net *net) |
846 | { | 846 | { |
847 | int res; | ||
848 | |||
849 | /* Fragment cache limits. | 847 | /* Fragment cache limits. |
850 | * | 848 | * |
851 | * The fragment memory accounting code, (tries to) account for | 849 | * The fragment memory accounting code, (tries to) account for |
@@ -871,13 +869,9 @@ static int __net_init ipv4_frags_init_net(struct net *net) | |||
871 | 869 | ||
872 | net->ipv4.frags.max_dist = 64; | 870 | net->ipv4.frags.max_dist = 64; |
873 | 871 | ||
874 | res = inet_frags_init_net(&net->ipv4.frags); | 872 | inet_frags_init_net(&net->ipv4.frags); |
875 | if (res) | 873 | |
876 | return res; | 874 | return ip4_frags_ns_ctl_register(net); |
877 | res = ip4_frags_ns_ctl_register(net); | ||
878 | if (res) | ||
879 | inet_frags_uninit_net(&net->ipv4.frags); | ||
880 | return res; | ||
881 | } | 875 | } |
882 | 876 | ||
883 | static void __net_exit ipv4_frags_exit_net(struct net *net) | 877 | static void __net_exit ipv4_frags_exit_net(struct net *net) |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 986d4ca38832..b263bf3a19f7 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -622,18 +622,12 @@ EXPORT_SYMBOL_GPL(nf_ct_frag6_gather); | |||
622 | 622 | ||
623 | static int nf_ct_net_init(struct net *net) | 623 | static int nf_ct_net_init(struct net *net) |
624 | { | 624 | { |
625 | int res; | ||
626 | |||
627 | net->nf_frag.frags.high_thresh = IPV6_FRAG_HIGH_THRESH; | 625 | net->nf_frag.frags.high_thresh = IPV6_FRAG_HIGH_THRESH; |
628 | net->nf_frag.frags.low_thresh = IPV6_FRAG_LOW_THRESH; | 626 | net->nf_frag.frags.low_thresh = IPV6_FRAG_LOW_THRESH; |
629 | net->nf_frag.frags.timeout = IPV6_FRAG_TIMEOUT; | 627 | net->nf_frag.frags.timeout = IPV6_FRAG_TIMEOUT; |
630 | res = inet_frags_init_net(&net->nf_frag.frags); | 628 | inet_frags_init_net(&net->nf_frag.frags); |
631 | if (res) | 629 | |
632 | return res; | 630 | return nf_ct_frag6_sysctl_register(net); |
633 | res = nf_ct_frag6_sysctl_register(net); | ||
634 | if (res) | ||
635 | inet_frags_uninit_net(&net->nf_frag.frags); | ||
636 | return res; | ||
637 | } | 631 | } |
638 | 632 | ||
639 | static void nf_ct_net_exit(struct net *net) | 633 | static void nf_ct_net_exit(struct net *net) |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index e1da5b888cc4..846012eae526 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -714,19 +714,13 @@ static void ip6_frags_sysctl_unregister(void) | |||
714 | 714 | ||
715 | static int __net_init ipv6_frags_init_net(struct net *net) | 715 | static int __net_init ipv6_frags_init_net(struct net *net) |
716 | { | 716 | { |
717 | int res; | ||
718 | |||
719 | net->ipv6.frags.high_thresh = IPV6_FRAG_HIGH_THRESH; | 717 | net->ipv6.frags.high_thresh = IPV6_FRAG_HIGH_THRESH; |
720 | net->ipv6.frags.low_thresh = IPV6_FRAG_LOW_THRESH; | 718 | net->ipv6.frags.low_thresh = IPV6_FRAG_LOW_THRESH; |
721 | net->ipv6.frags.timeout = IPV6_FRAG_TIMEOUT; | 719 | net->ipv6.frags.timeout = IPV6_FRAG_TIMEOUT; |
722 | 720 | ||
723 | res = inet_frags_init_net(&net->ipv6.frags); | 721 | inet_frags_init_net(&net->ipv6.frags); |
724 | if (res) | 722 | |
725 | return res; | 723 | return ip6_frags_ns_sysctl_register(net); |
726 | res = ip6_frags_ns_sysctl_register(net); | ||
727 | if (res) | ||
728 | inet_frags_uninit_net(&net->ipv6.frags); | ||
729 | return res; | ||
730 | } | 724 | } |
731 | 725 | ||
732 | static void __net_exit ipv6_frags_exit_net(struct net *net) | 726 | static void __net_exit ipv6_frags_exit_net(struct net *net) |
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 90165a6874bc..ee485df73ccd 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
@@ -329,13 +329,21 @@ static int l2tp_session_add_to_tunnel(struct l2tp_tunnel *tunnel, | |||
329 | struct hlist_head *g_head; | 329 | struct hlist_head *g_head; |
330 | struct hlist_head *head; | 330 | struct hlist_head *head; |
331 | struct l2tp_net *pn; | 331 | struct l2tp_net *pn; |
332 | int err; | ||
332 | 333 | ||
333 | head = l2tp_session_id_hash(tunnel, session->session_id); | 334 | head = l2tp_session_id_hash(tunnel, session->session_id); |
334 | 335 | ||
335 | write_lock_bh(&tunnel->hlist_lock); | 336 | write_lock_bh(&tunnel->hlist_lock); |
337 | if (!tunnel->acpt_newsess) { | ||
338 | err = -ENODEV; | ||
339 | goto err_tlock; | ||
340 | } | ||
341 | |||
336 | hlist_for_each_entry(session_walk, head, hlist) | 342 | hlist_for_each_entry(session_walk, head, hlist) |
337 | if (session_walk->session_id == session->session_id) | 343 | if (session_walk->session_id == session->session_id) { |
338 | goto exist; | 344 | err = -EEXIST; |
345 | goto err_tlock; | ||
346 | } | ||
339 | 347 | ||
340 | if (tunnel->version == L2TP_HDR_VER_3) { | 348 | if (tunnel->version == L2TP_HDR_VER_3) { |
341 | pn = l2tp_pernet(tunnel->l2tp_net); | 349 | pn = l2tp_pernet(tunnel->l2tp_net); |
@@ -343,12 +351,21 @@ static int l2tp_session_add_to_tunnel(struct l2tp_tunnel *tunnel, | |||
343 | session->session_id); | 351 | session->session_id); |
344 | 352 | ||
345 | spin_lock_bh(&pn->l2tp_session_hlist_lock); | 353 | spin_lock_bh(&pn->l2tp_session_hlist_lock); |
354 | |||
346 | hlist_for_each_entry(session_walk, g_head, global_hlist) | 355 | hlist_for_each_entry(session_walk, g_head, global_hlist) |
347 | if (session_walk->session_id == session->session_id) | 356 | if (session_walk->session_id == session->session_id) { |
348 | goto exist_glob; | 357 | err = -EEXIST; |
358 | goto err_tlock_pnlock; | ||
359 | } | ||
349 | 360 | ||
361 | l2tp_tunnel_inc_refcount(tunnel); | ||
362 | sock_hold(tunnel->sock); | ||
350 | hlist_add_head_rcu(&session->global_hlist, g_head); | 363 | hlist_add_head_rcu(&session->global_hlist, g_head); |
364 | |||
351 | spin_unlock_bh(&pn->l2tp_session_hlist_lock); | 365 | spin_unlock_bh(&pn->l2tp_session_hlist_lock); |
366 | } else { | ||
367 | l2tp_tunnel_inc_refcount(tunnel); | ||
368 | sock_hold(tunnel->sock); | ||
352 | } | 369 | } |
353 | 370 | ||
354 | hlist_add_head(&session->hlist, head); | 371 | hlist_add_head(&session->hlist, head); |
@@ -356,12 +373,12 @@ static int l2tp_session_add_to_tunnel(struct l2tp_tunnel *tunnel, | |||
356 | 373 | ||
357 | return 0; | 374 | return 0; |
358 | 375 | ||
359 | exist_glob: | 376 | err_tlock_pnlock: |
360 | spin_unlock_bh(&pn->l2tp_session_hlist_lock); | 377 | spin_unlock_bh(&pn->l2tp_session_hlist_lock); |
361 | exist: | 378 | err_tlock: |
362 | write_unlock_bh(&tunnel->hlist_lock); | 379 | write_unlock_bh(&tunnel->hlist_lock); |
363 | 380 | ||
364 | return -EEXIST; | 381 | return err; |
365 | } | 382 | } |
366 | 383 | ||
367 | /* Lookup a tunnel by id | 384 | /* Lookup a tunnel by id |
@@ -1251,7 +1268,6 @@ static void l2tp_tunnel_destruct(struct sock *sk) | |||
1251 | /* Remove hooks into tunnel socket */ | 1268 | /* Remove hooks into tunnel socket */ |
1252 | sk->sk_destruct = tunnel->old_sk_destruct; | 1269 | sk->sk_destruct = tunnel->old_sk_destruct; |
1253 | sk->sk_user_data = NULL; | 1270 | sk->sk_user_data = NULL; |
1254 | tunnel->sock = NULL; | ||
1255 | 1271 | ||
1256 | /* Remove the tunnel struct from the tunnel list */ | 1272 | /* Remove the tunnel struct from the tunnel list */ |
1257 | pn = l2tp_pernet(tunnel->l2tp_net); | 1273 | pn = l2tp_pernet(tunnel->l2tp_net); |
@@ -1261,6 +1277,8 @@ static void l2tp_tunnel_destruct(struct sock *sk) | |||
1261 | atomic_dec(&l2tp_tunnel_count); | 1277 | atomic_dec(&l2tp_tunnel_count); |
1262 | 1278 | ||
1263 | l2tp_tunnel_closeall(tunnel); | 1279 | l2tp_tunnel_closeall(tunnel); |
1280 | |||
1281 | tunnel->sock = NULL; | ||
1264 | l2tp_tunnel_dec_refcount(tunnel); | 1282 | l2tp_tunnel_dec_refcount(tunnel); |
1265 | 1283 | ||
1266 | /* Call the original destructor */ | 1284 | /* Call the original destructor */ |
@@ -1285,6 +1303,7 @@ void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel) | |||
1285 | tunnel->name); | 1303 | tunnel->name); |
1286 | 1304 | ||
1287 | write_lock_bh(&tunnel->hlist_lock); | 1305 | write_lock_bh(&tunnel->hlist_lock); |
1306 | tunnel->acpt_newsess = false; | ||
1288 | for (hash = 0; hash < L2TP_HASH_SIZE; hash++) { | 1307 | for (hash = 0; hash < L2TP_HASH_SIZE; hash++) { |
1289 | again: | 1308 | again: |
1290 | hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) { | 1309 | hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) { |
@@ -1581,6 +1600,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 | |||
1581 | tunnel->magic = L2TP_TUNNEL_MAGIC; | 1600 | tunnel->magic = L2TP_TUNNEL_MAGIC; |
1582 | sprintf(&tunnel->name[0], "tunl %u", tunnel_id); | 1601 | sprintf(&tunnel->name[0], "tunl %u", tunnel_id); |
1583 | rwlock_init(&tunnel->hlist_lock); | 1602 | rwlock_init(&tunnel->hlist_lock); |
1603 | tunnel->acpt_newsess = true; | ||
1584 | 1604 | ||
1585 | /* The net we belong to */ | 1605 | /* The net we belong to */ |
1586 | tunnel->l2tp_net = net; | 1606 | tunnel->l2tp_net = net; |
@@ -1829,11 +1849,6 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn | |||
1829 | return ERR_PTR(err); | 1849 | return ERR_PTR(err); |
1830 | } | 1850 | } |
1831 | 1851 | ||
1832 | l2tp_tunnel_inc_refcount(tunnel); | ||
1833 | |||
1834 | /* Ensure tunnel socket isn't deleted */ | ||
1835 | sock_hold(tunnel->sock); | ||
1836 | |||
1837 | /* Ignore management session in session count value */ | 1852 | /* Ignore management session in session count value */ |
1838 | if (session->session_id != 0) | 1853 | if (session->session_id != 0) |
1839 | atomic_inc(&l2tp_session_count); | 1854 | atomic_inc(&l2tp_session_count); |
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 9101297f27ad..a305e0c5925a 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h | |||
@@ -162,6 +162,10 @@ struct l2tp_tunnel { | |||
162 | int magic; /* Should be L2TP_TUNNEL_MAGIC */ | 162 | int magic; /* Should be L2TP_TUNNEL_MAGIC */ |
163 | struct rcu_head rcu; | 163 | struct rcu_head rcu; |
164 | rwlock_t hlist_lock; /* protect session_hlist */ | 164 | rwlock_t hlist_lock; /* protect session_hlist */ |
165 | bool acpt_newsess; /* Indicates whether this | ||
166 | * tunnel accepts new sessions. | ||
167 | * Protected by hlist_lock. | ||
168 | */ | ||
165 | struct hlist_head session_hlist[L2TP_HASH_SIZE]; | 169 | struct hlist_head session_hlist[L2TP_HASH_SIZE]; |
166 | /* hashed list of sessions, | 170 | /* hashed list of sessions, |
167 | * hashed by id */ | 171 | * hashed by id */ |
@@ -197,7 +201,9 @@ struct l2tp_tunnel { | |||
197 | }; | 201 | }; |
198 | 202 | ||
199 | struct l2tp_nl_cmd_ops { | 203 | struct l2tp_nl_cmd_ops { |
200 | int (*session_create)(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg); | 204 | int (*session_create)(struct net *net, struct l2tp_tunnel *tunnel, |
205 | u32 session_id, u32 peer_session_id, | ||
206 | struct l2tp_session_cfg *cfg); | ||
201 | int (*session_delete)(struct l2tp_session *session); | 207 | int (*session_delete)(struct l2tp_session *session); |
202 | }; | 208 | }; |
203 | 209 | ||
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 4de2ec94b08c..87da9ef61860 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c | |||
@@ -262,24 +262,19 @@ static void l2tp_eth_adjust_mtu(struct l2tp_tunnel *tunnel, | |||
262 | dev->needed_headroom += session->hdr_len; | 262 | dev->needed_headroom += session->hdr_len; |
263 | } | 263 | } |
264 | 264 | ||
265 | static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) | 265 | static int l2tp_eth_create(struct net *net, struct l2tp_tunnel *tunnel, |
266 | u32 session_id, u32 peer_session_id, | ||
267 | struct l2tp_session_cfg *cfg) | ||
266 | { | 268 | { |
267 | unsigned char name_assign_type; | 269 | unsigned char name_assign_type; |
268 | struct net_device *dev; | 270 | struct net_device *dev; |
269 | char name[IFNAMSIZ]; | 271 | char name[IFNAMSIZ]; |
270 | struct l2tp_tunnel *tunnel; | ||
271 | struct l2tp_session *session; | 272 | struct l2tp_session *session; |
272 | struct l2tp_eth *priv; | 273 | struct l2tp_eth *priv; |
273 | struct l2tp_eth_sess *spriv; | 274 | struct l2tp_eth_sess *spriv; |
274 | int rc; | 275 | int rc; |
275 | struct l2tp_eth_net *pn; | 276 | struct l2tp_eth_net *pn; |
276 | 277 | ||
277 | tunnel = l2tp_tunnel_find(net, tunnel_id); | ||
278 | if (!tunnel) { | ||
279 | rc = -ENODEV; | ||
280 | goto out; | ||
281 | } | ||
282 | |||
283 | if (cfg->ifname) { | 278 | if (cfg->ifname) { |
284 | strlcpy(name, cfg->ifname, IFNAMSIZ); | 279 | strlcpy(name, cfg->ifname, IFNAMSIZ); |
285 | name_assign_type = NET_NAME_USER; | 280 | name_assign_type = NET_NAME_USER; |
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 57427d430f10..7135f4645d3a 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c | |||
@@ -643,10 +643,10 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf | |||
643 | break; | 643 | break; |
644 | } | 644 | } |
645 | 645 | ||
646 | ret = -EPROTONOSUPPORT; | 646 | ret = l2tp_nl_cmd_ops[cfg.pw_type]->session_create(net, tunnel, |
647 | if (l2tp_nl_cmd_ops[cfg.pw_type]->session_create) | 647 | session_id, |
648 | ret = (*l2tp_nl_cmd_ops[cfg.pw_type]->session_create)(net, tunnel_id, | 648 | peer_session_id, |
649 | session_id, peer_session_id, &cfg); | 649 | &cfg); |
650 | 650 | ||
651 | if (ret >= 0) { | 651 | if (ret >= 0) { |
652 | session = l2tp_session_get(net, tunnel, session_id, false); | 652 | session = l2tp_session_get(net, tunnel, session_id, false); |
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index f0edb7209079..50e3ee9a9d61 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c | |||
@@ -788,25 +788,20 @@ end: | |||
788 | 788 | ||
789 | #ifdef CONFIG_L2TP_V3 | 789 | #ifdef CONFIG_L2TP_V3 |
790 | 790 | ||
791 | /* Called when creating sessions via the netlink interface. | 791 | /* Called when creating sessions via the netlink interface. */ |
792 | */ | 792 | static int pppol2tp_session_create(struct net *net, struct l2tp_tunnel *tunnel, |
793 | static int pppol2tp_session_create(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) | 793 | u32 session_id, u32 peer_session_id, |
794 | struct l2tp_session_cfg *cfg) | ||
794 | { | 795 | { |
795 | int error; | 796 | int error; |
796 | struct l2tp_tunnel *tunnel; | ||
797 | struct l2tp_session *session; | 797 | struct l2tp_session *session; |
798 | struct pppol2tp_session *ps; | 798 | struct pppol2tp_session *ps; |
799 | 799 | ||
800 | tunnel = l2tp_tunnel_find(net, tunnel_id); | ||
801 | |||
802 | /* Error if we can't find the tunnel */ | ||
803 | error = -ENOENT; | ||
804 | if (tunnel == NULL) | ||
805 | goto out; | ||
806 | |||
807 | /* Error if tunnel socket is not prepped */ | 800 | /* Error if tunnel socket is not prepped */ |
808 | if (tunnel->sock == NULL) | 801 | if (!tunnel->sock) { |
802 | error = -ENOENT; | ||
809 | goto out; | 803 | goto out; |
804 | } | ||
810 | 805 | ||
811 | /* Default MTU values. */ | 806 | /* Default MTU values. */ |
812 | if (cfg->mtu == 0) | 807 | if (cfg->mtu == 0) |