diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/rtnetlink.c | 159 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 34 | ||||
-rw-r--r-- | net/sctp/transport.c | 4 |
3 files changed, 138 insertions, 59 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 23a71cb21273..66db1201da9b 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -644,12 +644,19 @@ static void copy_rtnl_link_stats64(void *v, const struct net_device_stats *b) | |||
644 | memcpy(v, &a, sizeof(a)); | 644 | memcpy(v, &a, sizeof(a)); |
645 | } | 645 | } |
646 | 646 | ||
647 | /* All VF info */ | ||
647 | static inline int rtnl_vfinfo_size(const struct net_device *dev) | 648 | static inline int rtnl_vfinfo_size(const struct net_device *dev) |
648 | { | 649 | { |
649 | if (dev->dev.parent && dev_is_pci(dev->dev.parent)) | 650 | if (dev->dev.parent && dev_is_pci(dev->dev.parent)) { |
650 | return dev_num_vf(dev->dev.parent) * | 651 | |
651 | sizeof(struct ifla_vf_info); | 652 | int num_vfs = dev_num_vf(dev->dev.parent); |
652 | else | 653 | size_t size = nlmsg_total_size(sizeof(struct nlattr)); |
654 | size += nlmsg_total_size(num_vfs * sizeof(struct nlattr)); | ||
655 | size += num_vfs * (sizeof(struct ifla_vf_mac) + | ||
656 | sizeof(struct ifla_vf_vlan) + | ||
657 | sizeof(struct ifla_vf_tx_rate)); | ||
658 | return size; | ||
659 | } else | ||
653 | return 0; | 660 | return 0; |
654 | } | 661 | } |
655 | 662 | ||
@@ -672,7 +679,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) | |||
672 | + nla_total_size(1) /* IFLA_OPERSTATE */ | 679 | + nla_total_size(1) /* IFLA_OPERSTATE */ |
673 | + nla_total_size(1) /* IFLA_LINKMODE */ | 680 | + nla_total_size(1) /* IFLA_LINKMODE */ |
674 | + nla_total_size(4) /* IFLA_NUM_VF */ | 681 | + nla_total_size(4) /* IFLA_NUM_VF */ |
675 | + nla_total_size(rtnl_vfinfo_size(dev)) /* IFLA_VFINFO */ | 682 | + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */ |
676 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ | 683 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ |
677 | } | 684 | } |
678 | 685 | ||
@@ -749,14 +756,37 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
749 | 756 | ||
750 | if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { | 757 | if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { |
751 | int i; | 758 | int i; |
752 | struct ifla_vf_info ivi; | ||
753 | 759 | ||
754 | NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)); | 760 | struct nlattr *vfinfo, *vf; |
755 | for (i = 0; i < dev_num_vf(dev->dev.parent); i++) { | 761 | int num_vfs = dev_num_vf(dev->dev.parent); |
762 | |||
763 | NLA_PUT_U32(skb, IFLA_NUM_VF, num_vfs); | ||
764 | vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST); | ||
765 | if (!vfinfo) | ||
766 | goto nla_put_failure; | ||
767 | for (i = 0; i < num_vfs; i++) { | ||
768 | struct ifla_vf_info ivi; | ||
769 | struct ifla_vf_mac vf_mac; | ||
770 | struct ifla_vf_vlan vf_vlan; | ||
771 | struct ifla_vf_tx_rate vf_tx_rate; | ||
756 | if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) | 772 | if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) |
757 | break; | 773 | break; |
758 | NLA_PUT(skb, IFLA_VFINFO, sizeof(ivi), &ivi); | 774 | vf_mac.vf = vf_vlan.vf = vf_tx_rate.vf = ivi.vf; |
775 | memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); | ||
776 | vf_vlan.vlan = ivi.vlan; | ||
777 | vf_vlan.qos = ivi.qos; | ||
778 | vf_tx_rate.rate = ivi.tx_rate; | ||
779 | vf = nla_nest_start(skb, IFLA_VF_INFO); | ||
780 | if (!vf) { | ||
781 | nla_nest_cancel(skb, vfinfo); | ||
782 | goto nla_put_failure; | ||
783 | } | ||
784 | NLA_PUT(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac); | ||
785 | NLA_PUT(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan); | ||
786 | NLA_PUT(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), &vf_tx_rate); | ||
787 | nla_nest_end(skb, vf); | ||
759 | } | 788 | } |
789 | nla_nest_end(skb, vfinfo); | ||
760 | } | 790 | } |
761 | if (dev->rtnl_link_ops) { | 791 | if (dev->rtnl_link_ops) { |
762 | if (rtnl_link_fill(skb, dev) < 0) | 792 | if (rtnl_link_fill(skb, dev) < 0) |
@@ -818,12 +848,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
818 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, | 848 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, |
819 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, | 849 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, |
820 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, | 850 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, |
821 | [IFLA_VF_MAC] = { .type = NLA_BINARY, | 851 | [IFLA_VFINFO_LIST] = {. type = NLA_NESTED }, |
822 | .len = sizeof(struct ifla_vf_mac) }, | ||
823 | [IFLA_VF_VLAN] = { .type = NLA_BINARY, | ||
824 | .len = sizeof(struct ifla_vf_vlan) }, | ||
825 | [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, | ||
826 | .len = sizeof(struct ifla_vf_tx_rate) }, | ||
827 | }; | 852 | }; |
828 | EXPORT_SYMBOL(ifla_policy); | 853 | EXPORT_SYMBOL(ifla_policy); |
829 | 854 | ||
@@ -832,6 +857,19 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { | |||
832 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, | 857 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, |
833 | }; | 858 | }; |
834 | 859 | ||
860 | static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { | ||
861 | [IFLA_VF_INFO] = { .type = NLA_NESTED }, | ||
862 | }; | ||
863 | |||
864 | static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { | ||
865 | [IFLA_VF_MAC] = { .type = NLA_BINARY, | ||
866 | .len = sizeof(struct ifla_vf_mac) }, | ||
867 | [IFLA_VF_VLAN] = { .type = NLA_BINARY, | ||
868 | .len = sizeof(struct ifla_vf_vlan) }, | ||
869 | [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, | ||
870 | .len = sizeof(struct ifla_vf_tx_rate) }, | ||
871 | }; | ||
872 | |||
835 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) | 873 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) |
836 | { | 874 | { |
837 | struct net *net; | 875 | struct net *net; |
@@ -861,6 +899,52 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) | |||
861 | return 0; | 899 | return 0; |
862 | } | 900 | } |
863 | 901 | ||
902 | static int do_setvfinfo(struct net_device *dev, struct nlattr *attr) | ||
903 | { | ||
904 | int rem, err = -EINVAL; | ||
905 | struct nlattr *vf; | ||
906 | const struct net_device_ops *ops = dev->netdev_ops; | ||
907 | |||
908 | nla_for_each_nested(vf, attr, rem) { | ||
909 | switch (nla_type(vf)) { | ||
910 | case IFLA_VF_MAC: { | ||
911 | struct ifla_vf_mac *ivm; | ||
912 | ivm = nla_data(vf); | ||
913 | err = -EOPNOTSUPP; | ||
914 | if (ops->ndo_set_vf_mac) | ||
915 | err = ops->ndo_set_vf_mac(dev, ivm->vf, | ||
916 | ivm->mac); | ||
917 | break; | ||
918 | } | ||
919 | case IFLA_VF_VLAN: { | ||
920 | struct ifla_vf_vlan *ivv; | ||
921 | ivv = nla_data(vf); | ||
922 | err = -EOPNOTSUPP; | ||
923 | if (ops->ndo_set_vf_vlan) | ||
924 | err = ops->ndo_set_vf_vlan(dev, ivv->vf, | ||
925 | ivv->vlan, | ||
926 | ivv->qos); | ||
927 | break; | ||
928 | } | ||
929 | case IFLA_VF_TX_RATE: { | ||
930 | struct ifla_vf_tx_rate *ivt; | ||
931 | ivt = nla_data(vf); | ||
932 | err = -EOPNOTSUPP; | ||
933 | if (ops->ndo_set_vf_tx_rate) | ||
934 | err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, | ||
935 | ivt->rate); | ||
936 | break; | ||
937 | } | ||
938 | default: | ||
939 | err = -EINVAL; | ||
940 | break; | ||
941 | } | ||
942 | if (err) | ||
943 | break; | ||
944 | } | ||
945 | return err; | ||
946 | } | ||
947 | |||
864 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | 948 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, |
865 | struct nlattr **tb, char *ifname, int modified) | 949 | struct nlattr **tb, char *ifname, int modified) |
866 | { | 950 | { |
@@ -991,40 +1075,17 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
991 | write_unlock_bh(&dev_base_lock); | 1075 | write_unlock_bh(&dev_base_lock); |
992 | } | 1076 | } |
993 | 1077 | ||
994 | if (tb[IFLA_VF_MAC]) { | 1078 | if (tb[IFLA_VFINFO_LIST]) { |
995 | struct ifla_vf_mac *ivm; | 1079 | struct nlattr *attr; |
996 | ivm = nla_data(tb[IFLA_VF_MAC]); | 1080 | int rem; |
997 | err = -EOPNOTSUPP; | 1081 | nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) { |
998 | if (ops->ndo_set_vf_mac) | 1082 | if (nla_type(attr) != IFLA_VF_INFO) |
999 | err = ops->ndo_set_vf_mac(dev, ivm->vf, ivm->mac); | 1083 | goto errout; |
1000 | if (err < 0) | 1084 | err = do_setvfinfo(dev, attr); |
1001 | goto errout; | 1085 | if (err < 0) |
1002 | modified = 1; | 1086 | goto errout; |
1003 | } | 1087 | modified = 1; |
1004 | 1088 | } | |
1005 | if (tb[IFLA_VF_VLAN]) { | ||
1006 | struct ifla_vf_vlan *ivv; | ||
1007 | ivv = nla_data(tb[IFLA_VF_VLAN]); | ||
1008 | err = -EOPNOTSUPP; | ||
1009 | if (ops->ndo_set_vf_vlan) | ||
1010 | err = ops->ndo_set_vf_vlan(dev, ivv->vf, | ||
1011 | ivv->vlan, | ||
1012 | ivv->qos); | ||
1013 | if (err < 0) | ||
1014 | goto errout; | ||
1015 | modified = 1; | ||
1016 | } | ||
1017 | err = 0; | ||
1018 | |||
1019 | if (tb[IFLA_VF_TX_RATE]) { | ||
1020 | struct ifla_vf_tx_rate *ivt; | ||
1021 | ivt = nla_data(tb[IFLA_VF_TX_RATE]); | ||
1022 | err = -EOPNOTSUPP; | ||
1023 | if (ops->ndo_set_vf_tx_rate) | ||
1024 | err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, ivt->rate); | ||
1025 | if (err < 0) | ||
1026 | goto errout; | ||
1027 | modified = 1; | ||
1028 | } | 1089 | } |
1029 | err = 0; | 1090 | err = 0; |
1030 | 1091 | ||
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 8ce29747ad9b..3284393d09b4 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2840,7 +2840,6 @@ static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool * __percpu *pool) | |||
2840 | if (p->md5_desc.tfm) | 2840 | if (p->md5_desc.tfm) |
2841 | crypto_free_hash(p->md5_desc.tfm); | 2841 | crypto_free_hash(p->md5_desc.tfm); |
2842 | kfree(p); | 2842 | kfree(p); |
2843 | p = NULL; | ||
2844 | } | 2843 | } |
2845 | } | 2844 | } |
2846 | free_percpu(pool); | 2845 | free_percpu(pool); |
@@ -2938,25 +2937,40 @@ retry: | |||
2938 | 2937 | ||
2939 | EXPORT_SYMBOL(tcp_alloc_md5sig_pool); | 2938 | EXPORT_SYMBOL(tcp_alloc_md5sig_pool); |
2940 | 2939 | ||
2941 | struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu) | 2940 | |
2941 | /** | ||
2942 | * tcp_get_md5sig_pool - get md5sig_pool for this user | ||
2943 | * | ||
2944 | * We use percpu structure, so if we succeed, we exit with preemption | ||
2945 | * and BH disabled, to make sure another thread or softirq handling | ||
2946 | * wont try to get same context. | ||
2947 | */ | ||
2948 | struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) | ||
2942 | { | 2949 | { |
2943 | struct tcp_md5sig_pool * __percpu *p; | 2950 | struct tcp_md5sig_pool * __percpu *p; |
2944 | spin_lock_bh(&tcp_md5sig_pool_lock); | 2951 | |
2952 | local_bh_disable(); | ||
2953 | |||
2954 | spin_lock(&tcp_md5sig_pool_lock); | ||
2945 | p = tcp_md5sig_pool; | 2955 | p = tcp_md5sig_pool; |
2946 | if (p) | 2956 | if (p) |
2947 | tcp_md5sig_users++; | 2957 | tcp_md5sig_users++; |
2948 | spin_unlock_bh(&tcp_md5sig_pool_lock); | 2958 | spin_unlock(&tcp_md5sig_pool_lock); |
2949 | return (p ? *per_cpu_ptr(p, cpu) : NULL); | 2959 | |
2950 | } | 2960 | if (p) |
2961 | return *per_cpu_ptr(p, smp_processor_id()); | ||
2951 | 2962 | ||
2952 | EXPORT_SYMBOL(__tcp_get_md5sig_pool); | 2963 | local_bh_enable(); |
2964 | return NULL; | ||
2965 | } | ||
2966 | EXPORT_SYMBOL(tcp_get_md5sig_pool); | ||
2953 | 2967 | ||
2954 | void __tcp_put_md5sig_pool(void) | 2968 | void tcp_put_md5sig_pool(void) |
2955 | { | 2969 | { |
2970 | local_bh_enable(); | ||
2956 | tcp_free_md5sig_pool(); | 2971 | tcp_free_md5sig_pool(); |
2957 | } | 2972 | } |
2958 | 2973 | EXPORT_SYMBOL(tcp_put_md5sig_pool); | |
2959 | EXPORT_SYMBOL(__tcp_put_md5sig_pool); | ||
2960 | 2974 | ||
2961 | int tcp_md5_hash_header(struct tcp_md5sig_pool *hp, | 2975 | int tcp_md5_hash_header(struct tcp_md5sig_pool *hp, |
2962 | struct tcphdr *th) | 2976 | struct tcphdr *th) |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index d67501f92ca3..132046cb82fc 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -148,6 +148,10 @@ void sctp_transport_free(struct sctp_transport *transport) | |||
148 | del_timer(&transport->T3_rtx_timer)) | 148 | del_timer(&transport->T3_rtx_timer)) |
149 | sctp_transport_put(transport); | 149 | sctp_transport_put(transport); |
150 | 150 | ||
151 | /* Delete the ICMP proto unreachable timer if it's active. */ | ||
152 | if (timer_pending(&transport->proto_unreach_timer) && | ||
153 | del_timer(&transport->proto_unreach_timer)) | ||
154 | sctp_association_put(transport->asoc); | ||
151 | 155 | ||
152 | sctp_transport_put(transport); | 156 | sctp_transport_put(transport); |
153 | } | 157 | } |