|
@@ -1045,15 +1045,156 @@ static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device *dev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static noinline_for_stack int rtnl_fill_stats(struct sk_buff *skb,
|
|
|
+ struct net_device *dev)
|
|
|
+{
|
|
|
+ const struct rtnl_link_stats64 *stats;
|
|
|
+ struct rtnl_link_stats64 temp;
|
|
|
+ struct nlattr *attr;
|
|
|
+
|
|
|
+ stats = dev_get_stats(dev, &temp);
|
|
|
+
|
|
|
+ attr = nla_reserve(skb, IFLA_STATS,
|
|
|
+ sizeof(struct rtnl_link_stats));
|
|
|
+ if (!attr)
|
|
|
+ return -EMSGSIZE;
|
|
|
+
|
|
|
+ copy_rtnl_link_stats(nla_data(attr), stats);
|
|
|
+
|
|
|
+ attr = nla_reserve(skb, IFLA_STATS64,
|
|
|
+ sizeof(struct rtnl_link_stats64));
|
|
|
+ if (!attr)
|
|
|
+ return -EMSGSIZE;
|
|
|
+
|
|
|
+ copy_rtnl_link_stats64(nla_data(attr), stats);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
|
|
|
+ struct net_device *dev,
|
|
|
+ int vfs_num,
|
|
|
+ struct nlattr *vfinfo)
|
|
|
+{
|
|
|
+ struct ifla_vf_rss_query_en vf_rss_query_en;
|
|
|
+ struct ifla_vf_link_state vf_linkstate;
|
|
|
+ struct ifla_vf_spoofchk vf_spoofchk;
|
|
|
+ struct ifla_vf_tx_rate vf_tx_rate;
|
|
|
+ struct ifla_vf_stats vf_stats;
|
|
|
+ struct ifla_vf_trust vf_trust;
|
|
|
+ struct ifla_vf_vlan vf_vlan;
|
|
|
+ struct ifla_vf_rate vf_rate;
|
|
|
+ struct nlattr *vf, *vfstats;
|
|
|
+ struct ifla_vf_mac vf_mac;
|
|
|
+ struct ifla_vf_info ivi;
|
|
|
+
|
|
|
+ /* Not all SR-IOV capable drivers support the
|
|
|
+ * spoofcheck and "RSS query enable" query. Preset to
|
|
|
+ * -1 so the user space tool can detect that the driver
|
|
|
+ * didn't report anything.
|
|
|
+ */
|
|
|
+ ivi.spoofchk = -1;
|
|
|
+ ivi.rss_query_en = -1;
|
|
|
+ ivi.trusted = -1;
|
|
|
+ memset(ivi.mac, 0, sizeof(ivi.mac));
|
|
|
+ /* The default value for VF link state is "auto"
|
|
|
+ * IFLA_VF_LINK_STATE_AUTO which equals zero
|
|
|
+ */
|
|
|
+ ivi.linkstate = 0;
|
|
|
+ if (dev->netdev_ops->ndo_get_vf_config(dev, vfs_num, &ivi))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ vf_mac.vf =
|
|
|
+ vf_vlan.vf =
|
|
|
+ vf_rate.vf =
|
|
|
+ vf_tx_rate.vf =
|
|
|
+ vf_spoofchk.vf =
|
|
|
+ vf_linkstate.vf =
|
|
|
+ vf_rss_query_en.vf =
|
|
|
+ vf_trust.vf = ivi.vf;
|
|
|
+
|
|
|
+ memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
|
|
|
+ vf_vlan.vlan = ivi.vlan;
|
|
|
+ vf_vlan.qos = ivi.qos;
|
|
|
+ vf_tx_rate.rate = ivi.max_tx_rate;
|
|
|
+ vf_rate.min_tx_rate = ivi.min_tx_rate;
|
|
|
+ vf_rate.max_tx_rate = ivi.max_tx_rate;
|
|
|
+ vf_spoofchk.setting = ivi.spoofchk;
|
|
|
+ vf_linkstate.link_state = ivi.linkstate;
|
|
|
+ vf_rss_query_en.setting = ivi.rss_query_en;
|
|
|
+ vf_trust.setting = ivi.trusted;
|
|
|
+ vf = nla_nest_start(skb, IFLA_VF_INFO);
|
|
|
+ if (!vf) {
|
|
|
+ nla_nest_cancel(skb, vfinfo);
|
|
|
+ return -EMSGSIZE;
|
|
|
+ }
|
|
|
+ if (nla_put(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac) ||
|
|
|
+ nla_put(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan) ||
|
|
|
+ nla_put(skb, IFLA_VF_RATE, sizeof(vf_rate),
|
|
|
+ &vf_rate) ||
|
|
|
+ nla_put(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate),
|
|
|
+ &vf_tx_rate) ||
|
|
|
+ nla_put(skb, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk),
|
|
|
+ &vf_spoofchk) ||
|
|
|
+ nla_put(skb, IFLA_VF_LINK_STATE, sizeof(vf_linkstate),
|
|
|
+ &vf_linkstate) ||
|
|
|
+ nla_put(skb, IFLA_VF_RSS_QUERY_EN,
|
|
|
+ sizeof(vf_rss_query_en),
|
|
|
+ &vf_rss_query_en) ||
|
|
|
+ nla_put(skb, IFLA_VF_TRUST,
|
|
|
+ sizeof(vf_trust), &vf_trust))
|
|
|
+ return -EMSGSIZE;
|
|
|
+ memset(&vf_stats, 0, sizeof(vf_stats));
|
|
|
+ if (dev->netdev_ops->ndo_get_vf_stats)
|
|
|
+ dev->netdev_ops->ndo_get_vf_stats(dev, vfs_num,
|
|
|
+ &vf_stats);
|
|
|
+ vfstats = nla_nest_start(skb, IFLA_VF_STATS);
|
|
|
+ if (!vfstats) {
|
|
|
+ nla_nest_cancel(skb, vf);
|
|
|
+ nla_nest_cancel(skb, vfinfo);
|
|
|
+ return -EMSGSIZE;
|
|
|
+ }
|
|
|
+ if (nla_put_u64(skb, IFLA_VF_STATS_RX_PACKETS,
|
|
|
+ vf_stats.rx_packets) ||
|
|
|
+ nla_put_u64(skb, IFLA_VF_STATS_TX_PACKETS,
|
|
|
+ vf_stats.tx_packets) ||
|
|
|
+ nla_put_u64(skb, IFLA_VF_STATS_RX_BYTES,
|
|
|
+ vf_stats.rx_bytes) ||
|
|
|
+ nla_put_u64(skb, IFLA_VF_STATS_TX_BYTES,
|
|
|
+ vf_stats.tx_bytes) ||
|
|
|
+ nla_put_u64(skb, IFLA_VF_STATS_BROADCAST,
|
|
|
+ vf_stats.broadcast) ||
|
|
|
+ nla_put_u64(skb, IFLA_VF_STATS_MULTICAST,
|
|
|
+ vf_stats.multicast))
|
|
|
+ return -EMSGSIZE;
|
|
|
+ nla_nest_end(skb, vfstats);
|
|
|
+ nla_nest_end(skb, vf);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev)
|
|
|
+{
|
|
|
+ struct rtnl_link_ifmap map = {
|
|
|
+ .mem_start = dev->mem_start,
|
|
|
+ .mem_end = dev->mem_end,
|
|
|
+ .base_addr = dev->base_addr,
|
|
|
+ .irq = dev->irq,
|
|
|
+ .dma = dev->dma,
|
|
|
+ .port = dev->if_port,
|
|
|
+ };
|
|
|
+ if (nla_put(skb, IFLA_MAP, sizeof(map), &map))
|
|
|
+ return -EMSGSIZE;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
|
|
|
int type, u32 pid, u32 seq, u32 change,
|
|
|
unsigned int flags, u32 ext_filter_mask)
|
|
|
{
|
|
|
struct ifinfomsg *ifm;
|
|
|
struct nlmsghdr *nlh;
|
|
|
- struct rtnl_link_stats64 temp;
|
|
|
- const struct rtnl_link_stats64 *stats;
|
|
|
- struct nlattr *attr, *af_spec;
|
|
|
+ struct nlattr *af_spec;
|
|
|
struct rtnl_af_ops *af_ops;
|
|
|
struct net_device *upper_dev = netdev_master_upper_dev_get(dev);
|
|
|
|
|
@@ -1096,18 +1237,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
|
|
|
nla_put_u8(skb, IFLA_PROTO_DOWN, dev->proto_down))
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
- if (1) {
|
|
|
- struct rtnl_link_ifmap map = {
|
|
|
- .mem_start = dev->mem_start,
|
|
|
- .mem_end = dev->mem_end,
|
|
|
- .base_addr = dev->base_addr,
|
|
|
- .irq = dev->irq,
|
|
|
- .dma = dev->dma,
|
|
|
- .port = dev->if_port,
|
|
|
- };
|
|
|
- if (nla_put(skb, IFLA_MAP, sizeof(map), &map))
|
|
|
- goto nla_put_failure;
|
|
|
- }
|
|
|
+ if (rtnl_fill_link_ifmap(skb, dev))
|
|
|
+ goto nla_put_failure;
|
|
|
|
|
|
if (dev->addr_len) {
|
|
|
if (nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr) ||
|
|
@@ -1124,128 +1255,27 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
|
|
|
if (rtnl_phys_switch_id_fill(skb, dev))
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
- attr = nla_reserve(skb, IFLA_STATS,
|
|
|
- sizeof(struct rtnl_link_stats));
|
|
|
- if (attr == NULL)
|
|
|
- goto nla_put_failure;
|
|
|
-
|
|
|
- stats = dev_get_stats(dev, &temp);
|
|
|
- copy_rtnl_link_stats(nla_data(attr), stats);
|
|
|
-
|
|
|
- attr = nla_reserve(skb, IFLA_STATS64,
|
|
|
- sizeof(struct rtnl_link_stats64));
|
|
|
- if (attr == NULL)
|
|
|
+ if (rtnl_fill_stats(skb, dev))
|
|
|
goto nla_put_failure;
|
|
|
- copy_rtnl_link_stats64(nla_data(attr), stats);
|
|
|
|
|
|
if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF) &&
|
|
|
nla_put_u32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)))
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
- if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent
|
|
|
- && (ext_filter_mask & RTEXT_FILTER_VF)) {
|
|
|
+ if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent &&
|
|
|
+ ext_filter_mask & RTEXT_FILTER_VF) {
|
|
|
int i;
|
|
|
-
|
|
|
- struct nlattr *vfinfo, *vf, *vfstats;
|
|
|
+ struct nlattr *vfinfo;
|
|
|
int num_vfs = dev_num_vf(dev->dev.parent);
|
|
|
|
|
|
vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST);
|
|
|
if (!vfinfo)
|
|
|
goto nla_put_failure;
|
|
|
for (i = 0; i < num_vfs; i++) {
|
|
|
- struct ifla_vf_info ivi;
|
|
|
- struct ifla_vf_mac vf_mac;
|
|
|
- struct ifla_vf_vlan vf_vlan;
|
|
|
- struct ifla_vf_rate vf_rate;
|
|
|
- struct ifla_vf_tx_rate vf_tx_rate;
|
|
|
- struct ifla_vf_spoofchk vf_spoofchk;
|
|
|
- struct ifla_vf_link_state vf_linkstate;
|
|
|
- struct ifla_vf_rss_query_en vf_rss_query_en;
|
|
|
- struct ifla_vf_stats vf_stats;
|
|
|
- struct ifla_vf_trust vf_trust;
|
|
|
-
|
|
|
- /*
|
|
|
- * Not all SR-IOV capable drivers support the
|
|
|
- * spoofcheck and "RSS query enable" query. Preset to
|
|
|
- * -1 so the user space tool can detect that the driver
|
|
|
- * didn't report anything.
|
|
|
- */
|
|
|
- ivi.spoofchk = -1;
|
|
|
- ivi.rss_query_en = -1;
|
|
|
- ivi.trusted = -1;
|
|
|
- memset(ivi.mac, 0, sizeof(ivi.mac));
|
|
|
- /* The default value for VF link state is "auto"
|
|
|
- * IFLA_VF_LINK_STATE_AUTO which equals zero
|
|
|
- */
|
|
|
- ivi.linkstate = 0;
|
|
|
- if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi))
|
|
|
- break;
|
|
|
- vf_mac.vf =
|
|
|
- vf_vlan.vf =
|
|
|
- vf_rate.vf =
|
|
|
- vf_tx_rate.vf =
|
|
|
- vf_spoofchk.vf =
|
|
|
- vf_linkstate.vf =
|
|
|
- vf_rss_query_en.vf =
|
|
|
- vf_trust.vf = ivi.vf;
|
|
|
-
|
|
|
- memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
|
|
|
- vf_vlan.vlan = ivi.vlan;
|
|
|
- vf_vlan.qos = ivi.qos;
|
|
|
- vf_tx_rate.rate = ivi.max_tx_rate;
|
|
|
- vf_rate.min_tx_rate = ivi.min_tx_rate;
|
|
|
- vf_rate.max_tx_rate = ivi.max_tx_rate;
|
|
|
- vf_spoofchk.setting = ivi.spoofchk;
|
|
|
- vf_linkstate.link_state = ivi.linkstate;
|
|
|
- vf_rss_query_en.setting = ivi.rss_query_en;
|
|
|
- vf_trust.setting = ivi.trusted;
|
|
|
- vf = nla_nest_start(skb, IFLA_VF_INFO);
|
|
|
- if (!vf) {
|
|
|
- nla_nest_cancel(skb, vfinfo);
|
|
|
- goto nla_put_failure;
|
|
|
- }
|
|
|
- if (nla_put(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac) ||
|
|
|
- nla_put(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan) ||
|
|
|
- nla_put(skb, IFLA_VF_RATE, sizeof(vf_rate),
|
|
|
- &vf_rate) ||
|
|
|
- nla_put(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate),
|
|
|
- &vf_tx_rate) ||
|
|
|
- nla_put(skb, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk),
|
|
|
- &vf_spoofchk) ||
|
|
|
- nla_put(skb, IFLA_VF_LINK_STATE, sizeof(vf_linkstate),
|
|
|
- &vf_linkstate) ||
|
|
|
- nla_put(skb, IFLA_VF_RSS_QUERY_EN,
|
|
|
- sizeof(vf_rss_query_en),
|
|
|
- &vf_rss_query_en) ||
|
|
|
- nla_put(skb, IFLA_VF_TRUST,
|
|
|
- sizeof(vf_trust), &vf_trust))
|
|
|
+ if (rtnl_fill_vfinfo(skb, dev, i, vfinfo))
|
|
|
goto nla_put_failure;
|
|
|
- memset(&vf_stats, 0, sizeof(vf_stats));
|
|
|
- if (dev->netdev_ops->ndo_get_vf_stats)
|
|
|
- dev->netdev_ops->ndo_get_vf_stats(dev, i,
|
|
|
- &vf_stats);
|
|
|
- vfstats = nla_nest_start(skb, IFLA_VF_STATS);
|
|
|
- if (!vfstats) {
|
|
|
- nla_nest_cancel(skb, vf);
|
|
|
- nla_nest_cancel(skb, vfinfo);
|
|
|
- goto nla_put_failure;
|
|
|
- }
|
|
|
- if (nla_put_u64(skb, IFLA_VF_STATS_RX_PACKETS,
|
|
|
- vf_stats.rx_packets) ||
|
|
|
- nla_put_u64(skb, IFLA_VF_STATS_TX_PACKETS,
|
|
|
- vf_stats.tx_packets) ||
|
|
|
- nla_put_u64(skb, IFLA_VF_STATS_RX_BYTES,
|
|
|
- vf_stats.rx_bytes) ||
|
|
|
- nla_put_u64(skb, IFLA_VF_STATS_TX_BYTES,
|
|
|
- vf_stats.tx_bytes) ||
|
|
|
- nla_put_u64(skb, IFLA_VF_STATS_BROADCAST,
|
|
|
- vf_stats.broadcast) ||
|
|
|
- nla_put_u64(skb, IFLA_VF_STATS_MULTICAST,
|
|
|
- vf_stats.multicast))
|
|
|
- goto nla_put_failure;
|
|
|
- nla_nest_end(skb, vfstats);
|
|
|
- nla_nest_end(skb, vf);
|
|
|
}
|
|
|
+
|
|
|
nla_nest_end(skb, vfinfo);
|
|
|
}
|
|
|
|