aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-05-17 01:26:58 -0400
committerDavid S. Miller <davem@davemloft.net>2010-05-17 01:26:58 -0400
commit6811d58fc148c393f80a9f5a9db49d7e75cdc546 (patch)
treec25d5b0e49ec848943d35f819e748d157ccb492e /net/core
parentc4949f074332a64baeb2ead6ab9319ca37642f96 (diff)
parentc02db8c6290bb992442fec1407643c94cc414375 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: include/linux/if_link.h
Diffstat (limited to 'net/core')
-rw-r--r--net/core/rtnetlink.c159
1 files changed, 110 insertions, 49 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 */
647static inline int rtnl_vfinfo_size(const struct net_device *dev) 648static 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};
828EXPORT_SYMBOL(ifla_policy); 853EXPORT_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
860static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = {
861 [IFLA_VF_INFO] = { .type = NLA_NESTED },
862};
863
864static 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
835struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) 873struct 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
902static 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
864static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, 948static 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