History

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 ====================

David S. Miller committed 11 years ago

Commit 1ceb0b82 parents d72da6a 7a6c8c32 files · +186 −45Browse files

Unified · Split

2 files
  1. include/uapi/linux/fou.h +1 −0
  2. net/ipv4/fou.c +185 −45
include/uapi/linux/fou.h+1−0
@@ -25,6 +25,7 @@ enum { · 24 unmodified lines
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};
net/ipv4/fou.c+185−45
@@ -16,14 +16,12 @@ · 15 unmodified lines
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 { · 7 unmodified lines
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: · 344 unmodified lines
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) · 3 unmodified lines
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) · 23 unmodified lines
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, · 29 unmodified lines
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, · 10 unmodified lines
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, · 5 unmodified lines
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, · 32 unmodified lines
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, · 12 unmodified lines
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) · 1 unmodified line
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[] = { · 9 unmodified lines
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) · 190 unmodified lines
820 935
821#endif936#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);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t