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
2525 FOU_CMD_UNSPEC,
2626 FOU_CMD_ADD,
2727 FOU_CMD_DEL,
28+ FOU_CMD_GET,
2829
2930 __FOU_CMD_MAX,
3031 };
net/ipv4/fou.c+185−45
@@ -16,14 +16,12 @@ · 15 unmodified lines
1616 #include <uapi/linux/fou.h>
1717 #include <uapi/linux/genetlink.h>
1818
19−static DEFINE_SPINLOCK(fou_lock);
20−static LIST_HEAD(fou_list);
21−
2219 struct fou {
2320 struct socket *sock;
2421 u8 protocol;
2522 u8 flags;
26− u16 port;
23+ __be16 port;
24+ u16 type;
2725 struct udp_offload udp_offloads;
2826 struct list_head list;
2927 };
@@ -37,6 +35,13 @@ struct fou_cfg { · 7 unmodified lines
3735 struct udp_port_cfg udp_config;
3836 };
3937
38+static unsigned int fou_net_id;
39+
40+struct fou_net {
41+ struct list_head fou_list;
42+ struct mutex fou_lock;
43+};
44+
4045 static inline struct fou *fou_from_sock(struct sock *sk)
4146 {
4247 return sk->sk_user_data;
@@ -387,20 +392,21 @@ out_unlock: · 344 unmodified lines
387392 return err;
388393 }
389394
390−static int fou_add_to_port_list(struct fou *fou)
395+static int fou_add_to_port_list(struct net *net, struct fou *fou)
391396 {
397+ struct fou_net *fn = net_generic(net, fou_net_id);
392398 struct fou *fout;
393399
394− spin_lock(&fou_lock);
395− list_for_each_entry(fout, &fou_list, list) {
400+ mutex_lock(&fn->fou_lock);
401+ list_for_each_entry(fout, &fn->fou_list, list) {
396402 if (fou->port == fout->port) {
397− spin_unlock(&fou_lock);
403+ mutex_unlock(&fn->fou_lock);
398404 return -EALREADY;
399405 }
400406 }
401407
402− list_add(&fou->list, &fou_list);
403− spin_unlock(&fou_lock);
408+ list_add(&fou->list, &fn->fou_list);
409+ mutex_unlock(&fn->fou_lock);
404410
405411 return 0;
406412 }
@@ -410,14 +416,10 @@ static void fou_release(struct fou *fou) · 3 unmodified lines
410416 struct socket *sock = fou->sock;
411417 struct sock *sk = sock->sk;
412418
413− udp_del_offload(&fou->udp_offloads);
414−
419+ if (sk->sk_family == AF_INET)
420+ udp_del_offload(&fou->udp_offloads);
415421 list_del(&fou->list);
416−
417− /* Remove hooks into tunnel socket */
418− sk->sk_user_data = NULL;
419−
420− sock_release(sock);
422+ udp_tunnel_sock_release(sock);
421423
422424 kfree(fou);
423425 }
@@ -447,10 +449,10 @@ static int gue_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg) · 23 unmodified lines
447449 static int fou_create(struct net *net, struct fou_cfg *cfg,
448450 struct socket **sockp)
449451 {
450− struct fou *fou = NULL;
451− int err;
452452 struct socket *sock = NULL;
453+ struct fou *fou = NULL;
453454 struct sock *sk;
455+ int err;
454456
455457 /* Open UDP socket */
456458 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
486488 goto error;
487489 }
488490
491+ fou->type = cfg->type;
492+
489493 udp_sk(sk)->encap_type = 1;
490494 udp_encap_enable();
491495
@@ -502,7 +506,7 @@ static int fou_create(struct net *net, struct fou_cfg *cfg, · 10 unmodified lines
502506 goto error;
503507 }
504508
505− err = fou_add_to_port_list(fou);
509+ err = fou_add_to_port_list(net, fou);
506510 if (err)
507511 goto error;
508512
@@ -514,27 +518,27 @@ static int fou_create(struct net *net, struct fou_cfg *cfg, · 5 unmodified lines
514518 error:
515519 kfree(fou);
516520 if (sock)
517− sock_release(sock);
521+ udp_tunnel_sock_release(sock);
518522
519523 return err;
520524 }
521525
522526 static int fou_destroy(struct net *net, struct fou_cfg *cfg)
523527 {
524− struct fou *fou;
525− u16 port = cfg->udp_config.local_udp_port;
528+ struct fou_net *fn = net_generic(net, fou_net_id);
529+ __be16 port = cfg->udp_config.local_udp_port;
526530 int err = -EINVAL;
531+ struct fou *fou;
527532
528− spin_lock(&fou_lock);
529− list_for_each_entry(fou, &fou_list, list) {
533+ mutex_lock(&fn->fou_lock);
534+ list_for_each_entry(fou, &fn->fou_list, list) {
530535 if (fou->port == port) {
531− udp_del_offload(&fou->udp_offloads);
532536 fou_release(fou);
533537 err = 0;
534538 break;
535539 }
536540 }
537− spin_unlock(&fou_lock);
541+ mutex_unlock(&fn->fou_lock);
538542
539543 return err;
540544 }
@@ -573,7 +577,7 @@ static int parse_nl_config(struct genl_info *info, · 32 unmodified lines
573577 }
574578
575579 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]);
577581
578582 cfg->udp_config.local_udp_port = port;
579583 }
@@ -592,6 +596,7 @@ static int parse_nl_config(struct genl_info *info, · 12 unmodified lines
592596
593597 static int fou_nl_cmd_add_port(struct sk_buff *skb, struct genl_info *info)
594598 {
599+ struct net *net = genl_info_net(info);
595600 struct fou_cfg cfg;
596601 int err;
597602
@@ -599,16 +604,120 @@ static int fou_nl_cmd_add_port(struct sk_buff *skb, struct genl_info *info) · 1 unmodified line
599604 if (err)
600605 return err;
601606
602− return fou_create(&init_net, &cfg, NULL);
607+ return fou_create(net, &cfg, NULL);
603608 }
604609
605610 static int fou_nl_cmd_rm_port(struct sk_buff *skb, struct genl_info *info)
606611 {
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+
623+static 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+
637+static 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+
652+nla_put_failure:
653+ genlmsg_cancel(skb, hdr);
654+ return -EMSGSIZE;
655+}
656+
657+static 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;
607662 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;
608691
609− parse_nl_config(info, &cfg);
692+ return genlmsg_reply(msg, info);
610693
611− return fou_destroy(&init_net, &cfg);
694+out_free:
695+ nlmsg_free(msg);
696+ return ret;
697+}
698+
699+static 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+
718+done:
719+ cb->args[0] = idx;
720+ return skb->len;
612721 }
613722
614723 static const struct genl_ops fou_nl_ops[] = {
@@ -624,6 +733,12 @@ static const struct genl_ops fou_nl_ops[] = { · 9 unmodified lines
624733 .policy = fou_nl_policy,
625734 .flags = GENL_ADMIN_PERM,
626735 },
736+ {
737+ .cmd = FOU_CMD_GET,
738+ .doit = fou_nl_cmd_get_port,
739+ .dumpit = fou_nl_dump,
740+ .policy = fou_nl_policy,
741+ },
627742 };
628743
629744 size_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
820935
821936 #endif
822937
938+static __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+
947+static __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+
959+static 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+
823966 static int __init fou_init(void)
824967 {
825968 int ret;
826969
970+ ret = register_pernet_device(&fou_net_ops);
971+ if (ret)
972+ goto exit;
973+
827974 ret = genl_register_family_with_ops(&fou_nl_family,
828975 fou_nl_ops);
829−
830976 if (ret < 0)
831− goto exit;
977+ goto unregister;
832978
833979 ret = ip_tunnel_encap_add_fou_ops();
834− if (ret < 0)
835− genl_unregister_family(&fou_nl_family);
980+ if (ret == 0)
981+ return 0;
836982
983+ genl_unregister_family(&fou_nl_family);
984+unregister:
985+ unregister_pernet_device(&fou_net_ops);
837986 exit:
838987 return ret;
839988 }
840989
841990 static void __exit fou_fini(void)
842991 {
843− struct fou *fou, *next;
844−
845992 ip_tunnel_encap_del_fou_ops();
846−
847993 genl_unregister_family(&fou_nl_family);
848−
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);
994+ unregister_pernet_device(&fou_net_ops);
855995 }
856996
857997 module_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