aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-09-05 23:03:35 -0400
committerDavid S. Miller <davem@davemloft.net>2017-09-05 23:03:35 -0400
commit18fb0b46d555dc42f52f69428dcd52f133877078 (patch)
tree7696741f50fb1a373aee3601074e30f6e366e425
parent39cebdb77d55a193492a42170bf1c3d11e41e740 (diff)
parent6d9c153a0b84392406bc77600aa7d3ea365de041 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
-rw-r--r--drivers/net/dsa/dsa_loop.c2
-rw-r--r--include/net/inet_frag.h35
-rw-r--r--include/net/route.h7
-rw-r--r--net/ieee802154/6lowpan/reassembly.c11
-rw-r--r--net/ipv4/inet_fragment.c4
-rw-r--r--net/ipv4/ip_fragment.c12
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c12
-rw-r--r--net/ipv6/reassembly.c12
-rw-r--r--net/l2tp/l2tp_core.c41
-rw-r--r--net/l2tp/l2tp_core.h8
-rw-r--r--net/l2tp/l2tp_eth.c11
-rw-r--r--net/l2tp/l2tp_netlink.c8
-rw-r--r--net/l2tp/l2tp_ppp.c19
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}
358module_exit(dsa_loop_exit); 358module_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
6struct netns_frags { 4struct 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 {
108int inet_frags_init(struct inet_frags *); 103int inet_frags_init(struct inet_frags *);
109void inet_frags_fini(struct inet_frags *); 104void inet_frags_fini(struct inet_frags *);
110 105
111static inline int inet_frags_init_net(struct netns_frags *nf) 106static inline void inet_frags_init_net(struct netns_frags *nf)
112{
113 return percpu_counter_init(&nf->mem, 0, GFP_KERNEL);
114}
115static 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
120void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f); 110void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f);
121 111
122void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f); 112void 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 */
148static unsigned int frag_percpu_counter_batch = 130000;
149
150static inline int frag_mem_limit(struct netns_frags *nf) 133static 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
155static inline void sub_frag_mem_limit(struct netns_frags *nf, int i) 138static 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
160static inline void add_frag_mem_limit(struct netns_frags *nf, int i) 143static 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
165static inline unsigned int sum_frag_mem_limit(struct netns_frags *nf) 148static 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
598static void __net_exit lowpan_frags_exit_net(struct net *net) 593static 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}
242EXPORT_SYMBOL(inet_frags_exit_net); 240EXPORT_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
845static int __net_init ipv4_frags_init_net(struct net *net) 845static 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
883static void __net_exit ipv4_frags_exit_net(struct net *net) 877static 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
623static int nf_ct_net_init(struct net *net) 623static 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
639static void nf_ct_net_exit(struct net *net) 633static 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
715static int __net_init ipv6_frags_init_net(struct net *net) 715static 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
732static void __net_exit ipv6_frags_exit_net(struct net *net) 726static 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
359exist_glob: 376err_tlock_pnlock:
360 spin_unlock_bh(&pn->l2tp_session_hlist_lock); 377 spin_unlock_bh(&pn->l2tp_session_hlist_lock);
361exist: 378err_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++) {
1289again: 1308again:
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
199struct l2tp_nl_cmd_ops { 203struct 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
265static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) 265static 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 */ 792static int pppol2tp_session_create(struct net *net, struct l2tp_tunnel *tunnel,
793static 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)