diff options
author | Williams, Mitch A <mitch.a.williams@intel.com> | 2010-02-09 20:44:05 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-12 19:56:08 -0500 |
commit | ebc08a6f47ee76ecad8e9f26c26e6ec9b46ca659 (patch) | |
tree | 08c46bdb0ae7ad752876a5cfdfd2350e0c53196d /net/core | |
parent | 95c26df829ba4a25f40595cadb4c9433883cbe28 (diff) |
rtnetlink: Add VF config code to rtnetlink
Add code to allow rtnetlink clients to query and set VF information through
the PF driver.
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/rtnetlink.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 62f3878a6010..42da96a4eeee 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/security.h> | 35 | #include <linux/security.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/if_addr.h> | 37 | #include <linux/if_addr.h> |
38 | #include <linux/pci.h> | ||
38 | 39 | ||
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
40 | #include <asm/system.h> | 41 | #include <asm/system.h> |
@@ -580,6 +581,15 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | |||
580 | a->tx_compressed = b->tx_compressed; | 581 | a->tx_compressed = b->tx_compressed; |
581 | }; | 582 | }; |
582 | 583 | ||
584 | static inline int rtnl_vfinfo_size(const struct net_device *dev) | ||
585 | { | ||
586 | if (dev->dev.parent && dev_is_pci(dev->dev.parent)) | ||
587 | return dev_num_vf(dev->dev.parent) * | ||
588 | sizeof(struct ifla_vf_info); | ||
589 | else | ||
590 | return 0; | ||
591 | } | ||
592 | |||
583 | static inline size_t if_nlmsg_size(const struct net_device *dev) | 593 | static inline size_t if_nlmsg_size(const struct net_device *dev) |
584 | { | 594 | { |
585 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) | 595 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) |
@@ -597,6 +607,8 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) | |||
597 | + nla_total_size(4) /* IFLA_MASTER */ | 607 | + nla_total_size(4) /* IFLA_MASTER */ |
598 | + nla_total_size(1) /* IFLA_OPERSTATE */ | 608 | + nla_total_size(1) /* IFLA_OPERSTATE */ |
599 | + nla_total_size(1) /* IFLA_LINKMODE */ | 609 | + nla_total_size(1) /* IFLA_LINKMODE */ |
610 | + nla_total_size(4) /* IFLA_NUM_VF */ | ||
611 | + nla_total_size(rtnl_vfinfo_size(dev)) /* IFLA_VFINFO */ | ||
600 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ | 612 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ |
601 | } | 613 | } |
602 | 614 | ||
@@ -665,6 +677,17 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
665 | stats = dev_get_stats(dev); | 677 | stats = dev_get_stats(dev); |
666 | copy_rtnl_link_stats(nla_data(attr), stats); | 678 | copy_rtnl_link_stats(nla_data(attr), stats); |
667 | 679 | ||
680 | if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { | ||
681 | int i; | ||
682 | struct ifla_vf_info ivi; | ||
683 | |||
684 | NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)); | ||
685 | for (i = 0; i < dev_num_vf(dev->dev.parent); i++) { | ||
686 | if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) | ||
687 | break; | ||
688 | NLA_PUT(skb, IFLA_VFINFO, sizeof(ivi), &ivi); | ||
689 | } | ||
690 | } | ||
668 | if (dev->rtnl_link_ops) { | 691 | if (dev->rtnl_link_ops) { |
669 | if (rtnl_link_fill(skb, dev) < 0) | 692 | if (rtnl_link_fill(skb, dev) < 0) |
670 | goto nla_put_failure; | 693 | goto nla_put_failure; |
@@ -725,6 +748,12 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
725 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, | 748 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, |
726 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, | 749 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, |
727 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, | 750 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, |
751 | [IFLA_VF_MAC] = { .type = NLA_BINARY, | ||
752 | .len = sizeof(struct ifla_vf_mac) }, | ||
753 | [IFLA_VF_VLAN] = { .type = NLA_BINARY, | ||
754 | .len = sizeof(struct ifla_vf_vlan) }, | ||
755 | [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, | ||
756 | .len = sizeof(struct ifla_vf_tx_rate) }, | ||
728 | }; | 757 | }; |
729 | EXPORT_SYMBOL(ifla_policy); | 758 | EXPORT_SYMBOL(ifla_policy); |
730 | 759 | ||
@@ -898,6 +927,44 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
898 | write_unlock_bh(&dev_base_lock); | 927 | write_unlock_bh(&dev_base_lock); |
899 | } | 928 | } |
900 | 929 | ||
930 | if (tb[IFLA_VF_MAC]) { | ||
931 | struct ifla_vf_mac *ivm; | ||
932 | ivm = nla_data(tb[IFLA_VF_MAC]); | ||
933 | write_lock_bh(&dev_base_lock); | ||
934 | if (ops->ndo_set_vf_mac) | ||
935 | err = ops->ndo_set_vf_mac(dev, ivm->vf, ivm->mac); | ||
936 | write_unlock_bh(&dev_base_lock); | ||
937 | if (err < 0) | ||
938 | goto errout; | ||
939 | modified = 1; | ||
940 | } | ||
941 | |||
942 | if (tb[IFLA_VF_VLAN]) { | ||
943 | struct ifla_vf_vlan *ivv; | ||
944 | ivv = nla_data(tb[IFLA_VF_VLAN]); | ||
945 | write_lock_bh(&dev_base_lock); | ||
946 | if (ops->ndo_set_vf_vlan) | ||
947 | err = ops->ndo_set_vf_vlan(dev, ivv->vf, | ||
948 | (u16)ivv->vlan, | ||
949 | (u8)ivv->qos); | ||
950 | write_unlock_bh(&dev_base_lock); | ||
951 | if (err < 0) | ||
952 | goto errout; | ||
953 | modified = 1; | ||
954 | } | ||
955 | err = 0; | ||
956 | |||
957 | if (tb[IFLA_VF_TX_RATE]) { | ||
958 | struct ifla_vf_tx_rate *ivt; | ||
959 | ivt = nla_data(tb[IFLA_VF_TX_RATE]); | ||
960 | write_lock_bh(&dev_base_lock); | ||
961 | if (ops->ndo_set_vf_tx_rate) | ||
962 | err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, ivt->rate); | ||
963 | write_unlock_bh(&dev_base_lock); | ||
964 | if (err < 0) | ||
965 | goto errout; | ||
966 | modified = 1; | ||
967 | } | ||
901 | err = 0; | 968 | err = 0; |
902 | 969 | ||
903 | errout: | 970 | errout: |