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;
597 602
@@ -599,16 +604,120 @@ static int fou_nl_cmd_add_port(struct sk_buff *skb, struct genl_info *info)
599 if (err) 604 if (err)
600 return err; 605 return err;
601 606
602 return fou_create(&init_net, &cfg, NULL); 607 return fou_create(net, &cfg, NULL);
603} 608}
604 609
605static int fou_nl_cmd_rm_port(struct sk_buff *skb, struct genl_info *info) 610static int fou_nl_cmd_rm_port(struct sk_buff *skb, struct genl_info *info)
606{ 611{
612 struct net *net = genl_info_net(info);
613 struct fou_cfg cfg;
614 int err;
615
616 err = parse_nl_config(info, &cfg);
617 if (err)
618 return err;
619
620 return fou_destroy(net, &cfg);
621}
622
623static int fou_fill_info(struct fou *fou, struct sk_buff *msg)
624{
625 if (nla_put_u8(msg, FOU_ATTR_AF, fou->sock->sk->sk_family) ||
626 nla_put_be16(msg, FOU_ATTR_PORT, fou->port) ||
627 nla_put_u8(msg, FOU_ATTR_IPPROTO, fou->protocol) ||
628 nla_put_u8(msg, FOU_ATTR_TYPE, fou->type))
629 return -1;
630
631 if (fou->flags & FOU_F_REMCSUM_NOPARTIAL)
632 if (nla_put_flag(msg, FOU_ATTR_REMCSUM_NOPARTIAL))
633 return -1;
634 return 0;
635}
636
637static int fou_dump_info(struct fou *fou, u32 portid, u32 seq,
638 u32 flags, struct sk_buff *skb, u8 cmd)
639{
640 void *hdr;
641
642 hdr = genlmsg_put(skb, portid, seq, &fou_nl_family, flags, cmd);
643 if (!hdr)
644 return -ENOMEM;
645
646 if (fou_fill_info(fou, skb) < 0)
647 goto nla_put_failure;
648
649 genlmsg_end(skb, hdr);
650 return 0;
651
652nla_put_failure:
653 genlmsg_cancel(skb, hdr);
654 return -EMSGSIZE;
655}
656
657static int fou_nl_cmd_get_port(struct sk_buff *skb, struct genl_info *info)
658{
659 struct net *net = genl_info_net(info);
660 struct fou_net *fn = net_generic(net, fou_net_id);
661 struct sk_buff *msg;
607 struct fou_cfg cfg; 662 struct fou_cfg cfg;
663 struct fou *fout;
664 __be16 port;
665 int ret;
666
667 ret = parse_nl_config(info, &cfg);
668 if (ret)
669 return ret;
670 port = cfg.udp_config.local_udp_port;
671 if (port == 0)
672 return -EINVAL;
673
674 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
675 if (!msg)
676 return -ENOMEM;
677
678 ret = -ESRCH;
679 mutex_lock(&fn->fou_lock);
680 list_for_each_entry(fout, &fn->fou_list, list) {
681 if (port == fout->port) {
682 ret = fou_dump_info(fout, info->snd_portid,
683 info->snd_seq, 0, msg,
684 info->genlhdr->cmd);
685 break;
686 }
687 }
688 mutex_unlock(&fn->fou_lock);
689 if (ret < 0)
690 goto out_free;
608 691
609 parse_nl_config(info, &cfg); 692 return genlmsg_reply(msg, info);
610 693
611 return fou_destroy(&init_net, &cfg); 694out_free:
695 nlmsg_free(msg);
696 return ret;
697}
698
699static int fou_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
700{
701 struct net *net = sock_net(skb->sk);
702 struct fou_net *fn = net_generic(net, fou_net_id);
703 struct fou *fout;
704 int idx = 0, ret;
705
706 mutex_lock(&fn->fou_lock);
707 list_for_each_entry(fout, &fn->fou_list, list) {
708 if (idx++ < cb->args[0])
709 continue;
710 ret = fou_dump_info(fout, NETLINK_CB(cb->skb).portid,
711 cb->nlh->nlmsg_seq, NLM_F_MULTI,
712 skb, FOU_CMD_GET);
713 if (ret)
714 goto done;
715 }
716 mutex_unlock(&fn->fou_lock);
717
718done:
719 cb->args[0] = idx;
720 return skb->len;
612} 721}
613 722
614static const struct genl_ops fou_nl_ops[] = { 723static const struct genl_ops fou_nl_ops[] = {
@@ -624,6 +733,12 @@ static const struct genl_ops fou_nl_ops[] = {
624 .policy = fou_nl_policy, 733 .policy = fou_nl_policy,
625 .flags = GENL_ADMIN_PERM, 734 .flags = GENL_ADMIN_PERM,
626 }, 735 },
736 {
737 .cmd = FOU_CMD_GET,
738 .doit = fou_nl_cmd_get_port,
739 .dumpit = fou_nl_dump,
740 .policy = fou_nl_policy,
741 },
627}; 742};
628 743
629size_t fou_encap_hlen(struct ip_tunnel_encap *e) 744size_t fou_encap_hlen(struct ip_tunnel_encap *e)
@@ -820,38 +935,63 @@ static void ip_tunnel_encap_del_fou_ops(void)
820 935
821#endif 936#endif
822 937
938static __net_init int fou_init_net(struct net *net)
939{
940 struct fou_net *fn = net_generic(net, fou_net_id);
941
942 INIT_LIST_HEAD(&fn->fou_list);
943 mutex_init(&fn->fou_lock);
944 return 0;
945}
946
947static __net_exit void fou_exit_net(struct net *net)
948{
949 struct fou_net *fn = net_generic(net, fou_net_id);
950 struct fou *fou, *next;
951
952 /* Close all the FOU sockets */
953 mutex_lock(&fn->fou_lock);
954 list_for_each_entry_safe(fou, next, &fn->fou_list, list)
955 fou_release(fou);
956 mutex_unlock(&fn->fou_lock);
957}
958
959static struct pernet_operations fou_net_ops = {
960 .init = fou_init_net,
961 .exit = fou_exit_net,
962 .id = &fou_net_id,
963 .size = sizeof(struct fou_net),
964};
965
823static int __init fou_init(void) 966static int __init fou_init(void)
824{ 967{
825 int ret; 968 int ret;
826 969
970 ret = register_pernet_device(&fou_net_ops);
971 if (ret)
972 goto exit;
973
827 ret = genl_register_family_with_ops(&fou_nl_family, 974 ret = genl_register_family_with_ops(&fou_nl_family,
828 fou_nl_ops); 975 fou_nl_ops);
829
830 if (ret < 0) 976 if (ret < 0)
831 goto exit; 977 goto unregister;
832 978
833 ret = ip_tunnel_encap_add_fou_ops(); 979 ret = ip_tunnel_encap_add_fou_ops();
834 if (ret < 0) 980 if (ret == 0)
835 genl_unregister_family(&fou_nl_family); 981 return 0;
836 982
983 genl_unregister_family(&fou_nl_family);
984unregister:
985 unregister_pernet_device(&fou_net_ops);
837exit: 986exit:
838 return ret; 987 return ret;
839} 988}
840 989
841static void __exit fou_fini(void) 990static void __exit fou_fini(void)
842{ 991{
843 struct fou *fou, *next;
844
845 ip_tunnel_encap_del_fou_ops(); 992 ip_tunnel_encap_del_fou_ops();
846
847 genl_unregister_family(&fou_nl_family); 993 genl_unregister_family(&fou_nl_family);
848 994 unregister_pernet_device(&fou_net_ops);
849 /* Close all the FOU sockets */
850
851 spin_lock(&fou_lock);
852 list_for_each_entry_safe(fou, next, &fou_list, list)
853 fou_release(fou);
854 spin_unlock(&fou_lock);
855} 995}
856 996
857module_init(fou_init); 997module_init(fou_init);