aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-04-12 21:25:14 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-12 21:25:14 -0400
commit1ceb0b8ca5be40d32b0fcf57b117cfb595c9bbfa (patch)
tree3593ce71a5a16427c35823a073072292a0d2a704
parentd72da6aa00497ed86836a1d41fc55e2809a8ca18 (diff)
parent7a6c8c34e5b71ac50e39588e20b39494a9e1d8e5 (diff)
Merge branch 'fou-next'
Cong Wang says: ==================== fou: some fixes and updates Patch 1~3 fix some minor bugs in net/ipv4/fou.c, the only thing I am not sure is if it's too late to change the byte order of FOU_ATTR_PORT, if so we have to fix iproute2 instead of kernel. Patch 4~5 add some new features to make it complete. v2: make fou->port be16 too ==================== Acked-by: Tom Herbert <tom@herbertland.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/uapi/linux/fou.h1
-rw-r--r--net/ipv4/fou.c230
2 files changed, 186 insertions, 45 deletions
diff --git a/include/uapi/linux/fou.h b/include/uapi/linux/fou.h
index c303588bb767..d2947c52dc67 100644
--- a/include/uapi/linux/fou.h
+++ b/include/uapi/linux/fou.h
@@ -25,6 +25,7 @@ enum {
25 FOU_CMD_UNSPEC, 25 FOU_CMD_UNSPEC,
26 FOU_CMD_ADD, 26 FOU_CMD_ADD,
27 FOU_CMD_DEL, 27 FOU_CMD_DEL,
28 FOU_CMD_GET,
28 29
29 __FOU_CMD_MAX, 30 __FOU_CMD_MAX,
30}; 31};
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index ff069f6597ac..263710259774 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -16,14 +16,12 @@
16#include <uapi/linux/fou.h> 16#include <uapi/linux/fou.h>
17#include <uapi/linux/genetlink.h> 17#include <uapi/linux/genetlink.h>
18 18
19static DEFINE_SPINLOCK(fou_lock);
20static LIST_HEAD(fou_list);
21
22struct fou { 19struct fou {
23 struct socket *sock; 20 struct socket *sock;
24 u8 protocol; 21 u8 protocol;
25 u8 flags; 22 u8 flags;
26 u16 port; 23 __be16 port;
24 u16 type;
27 struct udp_offload udp_offloads; 25 struct udp_offload udp_offloads;
28 struct list_head list; 26 struct list_head list;
29}; 27};
@@ -37,6 +35,13 @@ struct fou_cfg {
37 struct udp_port_cfg udp_config; 35 struct udp_port_cfg udp_config;
38}; 36};
39 37
38static unsigned int fou_net_id;
39
40struct fou_net {
41 struct list_head fou_list;
42 struct mutex fou_lock;
43};
44
40static inline struct fou *fou_from_sock(struct sock *sk) 45static inline struct fou *fou_from_sock(struct sock *sk)
41{ 46{
42 return sk->sk_user_data; 47 return sk->sk_user_data;
@@ -387,20 +392,21 @@ out_unlock:
387 return err; 392 return err;
388} 393}
389 394
390static int fou_add_to_port_list(struct fou *fou) 395static int fou_add_to_port_list(struct net *net, struct fou *fou)
391{ 396{
397 struct fou_net *fn = net_generic(net, fou_net_id);
392 struct fou *fout; 398 struct fou *fout;
393 399
394 spin_lock(&fou_lock); 400 mutex_lock(&fn->fou_lock);
395 list_for_each_entry(fout, &fou_list, list) { 401 list_for_each_entry(fout, &fn->fou_list, list) {
396 if (fou->port == fout->port) { 402 if (fou->port == fout->port) {
397 spin_unlock(&fou_lock); 403 mutex_unlock(&fn->fou_lock);
398 return -EALREADY; 404 return -EALREADY;
399 } 405 }
400 } 406 }
401 407
402 list_add(&fou->list, &fou_list); 408 list_add(&fou->list, &fn->fou_list);
403 spin_unlock(&fou_lock); 409 mutex_unlock(&fn->fou_lock);
404 410
405 return 0; 411 return 0;
406} 412}
@@ -410,14 +416,10 @@ static void fou_release(struct fou *fou)
410 struct socket *sock = fou->sock; 416 struct socket *sock = fou->sock;
411 struct sock *sk = sock->sk; 417 struct sock *sk = sock->sk;
412 418
413 udp_del_offload(&fou->udp_offloads); 419 if (sk->sk_family == AF_INET)
414 420 udp_del_offload(&fou->udp_offloads);
415 list_del(&fou->list); 421 list_del(&fou->list);
416 422 udp_tunnel_sock_release(sock);
417 /* Remove hooks into tunnel socket */
418 sk->sk_user_data = NULL;
419
420 sock_release(sock);
421 423
422 kfree(fou); 424 kfree(fou);
423} 425}
@@ -447,10 +449,10 @@ static int gue_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg)
447static int fou_create(struct net *net, struct fou_cfg *cfg, 449static int fou_create(struct net *net, struct fou_cfg *cfg,
448 struct socket **sockp) 450 struct socket **sockp)
449{ 451{
450 struct fou *fou = NULL;
451 int err;
452 struct socket *sock = NULL; 452 struct socket *sock = NULL;
453 struct fou *fou = NULL;
453 struct sock *sk; 454 struct sock *sk;
455 int err;
454 456
455 /* Open UDP socket */ 457 /* Open UDP socket */
456 err = udp_sock_create(net, &cfg->udp_config, &sock); 458 err = udp_sock_create(net, &cfg->udp_config, &sock);
@@ -486,6 +488,8 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
486 goto error; 488 goto error;
487 } 489 }
488 490
491 fou->type = cfg->type;
492
489 udp_sk(sk)->encap_type = 1; 493 udp_sk(sk)->encap_type = 1;
490 udp_encap_enable(); 494 udp_encap_enable();
491 495
@@ -502,7 +506,7 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
502 goto error; 506 goto error;
503 } 507 }
504 508
505 err = fou_add_to_port_list(fou); 509 err = fou_add_to_port_list(net, fou);
506 if (err) 510 if (err)
507 goto error; 511 goto error;
508 512
@@ -514,27 +518,27 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
514error: 518error:
515 kfree(fou); 519 kfree(fou);
516 if (sock) 520 if (sock)
517 sock_release(sock); 521 udp_tunnel_sock_release(sock);
518 522
519 return err; 523 return err;
520} 524}
521 525
522static int fou_destroy(struct net *net, struct fou_cfg *cfg) 526static int fou_destroy(struct net *net, struct fou_cfg *cfg)
523{ 527{
524 struct fou *fou; 528 struct fou_net *fn = net_generic(net, fou_net_id);
525 u16 port = cfg->udp_config.local_udp_port; 529 __be16 port = cfg->udp_config.local_udp_port;
526 int err = -EINVAL; 530 int err = -EINVAL;
531 struct fou *fou;
527 532
528 spin_lock(&fou_lock); 533 mutex_lock(&fn->fou_lock);
529 list_for_each_entry(fou, &fou_list, list) { 534 list_for_each_entry(fou, &fn->fou_list, list) {
530 if (fou->port == port) { 535 if (fou->port == port) {
531 udp_del_offload(&fou->udp_offloads);
532 fou_release(fou); 536 fou_release(fou);
533 err = 0; 537 err = 0;
534 break; 538 break;
535 } 539 }
536 } 540 }
537 spin_unlock(&fou_lock); 541 mutex_unlock(&fn->fou_lock);
538 542
539 return err; 543 return err;
540} 544}
@@ -573,7 +577,7 @@ static int parse_nl_config(struct genl_info *info,
573 } 577 }
574 578
575 if (info->attrs[FOU_ATTR_PORT]) { 579 if (info->attrs[FOU_ATTR_PORT]) {
576 u16 port = nla_get_u16(info->attrs[FOU_ATTR_PORT]); 580 __be16 port = nla_get_be16(info->attrs[FOU_ATTR_PORT]);
577 581
578 cfg->udp_config.local_udp_port = port; 582 cfg->udp_config.local_udp_port = port;
579 } 583 }
@@ -592,6 +596,7 @@ static int parse_nl_config(struct genl_info *info,
592 596
593static int fou_nl_cmd_add_port(struct sk_buff *skb, struct genl_info *info) 597static int fou_nl_cmd_add_port(struct sk_buff *skb, struct genl_info *info)
594{ 598{
599 struct net *net = genl_info_net(info);
595 struct fou_cfg cfg; 600 struct fou_cfg cfg;
596 int err; 601 int err;