* [RFC 1/2] net: Add support to configure SR-IOV VF minimum and maximum Tx rate through ip tool.
2014-03-05 7:33 [RFC 0/2]: Add minimum bandwidth support in IP tool Sucheta Chakraborty
@ 2014-03-05 7:33 ` Sucheta Chakraborty
2014-03-05 9:33 ` Michal Kubecek
2014-03-09 17:23 ` Ben Hutchings
2014-03-05 7:33 ` [RFC 2/2] qlcnic: " Sucheta Chakraborty
1 sibling, 2 replies; 7+ messages in thread
From: Sucheta Chakraborty @ 2014-03-05 7:33 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept-HSGLinuxNICDev
o A new handler set_vf_rate for attr IFLA_VF_RATE has been introduced
which takes 4 arguments:
netdev, VF number, min_tx_rate, max_tx_rate
o min_tx_rate puts lower limit on the VF bandwidth. VF is guaranteed
to have a bandwidth of at least this value.
max_tx_rate puts cap on the VF bandwidth. VF can have a bandwidth
of up to this value.
o Idea is to deprecate IFLA_VF_TX_RATE and ndo_set_vf_tx_rate in future.
And to have consistent display of rate values to user.
o Usage example: -
./ip link set p4p1 vf 0 rate 900
WARN: "rate" option will be deprecated. Use "min_tx_rate" and
"max_tx_rate" instead.
./ip link show p4p1
32: p4p1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode
DEFAULT qlen 1000
link/ether 00:0e:1e:08:b0:f0 brd ff:ff:ff:ff:ff:ff
vf 0 MAC 3e:a0:ca:bd:ae:5a, tx rate 900 (Mbps)
vf 1 MAC f6:c6:7c:3f:3d:6c
vf 2 MAC 56:32:43:98:d7:71
vf 3 MAC d6:be:c3:b5:85:ff
vf 4 MAC ee:a9:9a:1e:19:14
vf 5 MAC 4a:d0:4c:07:52:18
vf 6 MAC 3a:76:44:93:62:f9
vf 7 MAC 82:e9:e7:e3:15:1a
./ip link set p4p1 vf 0 max_tx_rate 300 min_tx_rate 200
./ip link show p4p1
32: p4p1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode
DEFAULT qlen 1000
link/ether 00:0e:1e:08:b0:f0 brd ff:ff:ff:ff:ff:ff
vf 0 MAC 3e:a0:ca:bd:ae:5a, max tx rate 300 (Mbps), min tx rate
200 (Mbps)
vf 1 MAC f6:c6:7c:3f:3d:6c
vf 2 MAC 56:32:43:98:d7:71
vf 3 MAC d6:be:c3:b5:85:ff
vf 4 MAC ee:a9:9a:1e:19:14
vf 5 MAC 4a:d0:4c:07:52:18
vf 6 MAC 3a:76:44:93:62:f9
vf 7 MAC 82:e9:e7:e3:15:1a
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
---
include/linux/if_link.h | 2 ++
include/linux/netdevice.h | 5 +++++
include/uapi/linux/if_link.h | 9 ++++++++-
net/core/rtnetlink.c | 30 ++++++++++++++++++++++++++++++
4 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index a86784d..3fad5db 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -13,5 +13,7 @@ struct ifla_vf_info {
__u32 tx_rate;
__u32 spoofchk;
__u32 linkstate;
+ __u32 min_tx_rate;
+ __u32 max_tx_rate;
};
#endif /* _LINUX_IF_LINK_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 1a86948..d2bbcfc 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -854,6 +854,8 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
* int (*ndo_set_vf_mac)(struct net_device *dev, int vf, u8* mac);
* int (*ndo_set_vf_vlan)(struct net_device *dev, int vf, u16 vlan, u8 qos);
* int (*ndo_set_vf_tx_rate)(struct net_device *dev, int vf, int rate);
+ * int (*ndo_set_vf_rate)(struct net_device *dev, int vf, int min_tx_rate,
+ * int max_tx_rate);
* int (*ndo_set_vf_spoofchk)(struct net_device *dev, int vf, bool setting);
* int (*ndo_get_vf_config)(struct net_device *dev,
* int vf, struct ifla_vf_info *ivf);
@@ -1050,6 +1052,9 @@ struct net_device_ops {
int queue, u16 vlan, u8 qos);
int (*ndo_set_vf_tx_rate)(struct net_device *dev,
int vf, int rate);
+ int (*ndo_set_vf_rate)(struct net_device *dev,
+ int vf, int min_tx_rate,
+ int max_tx_rate);
int (*ndo_set_vf_spoofchk)(struct net_device *dev,
int vf, bool setting);
int (*ndo_get_vf_config)(struct net_device *dev,
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 16410b6..fce6437 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -398,7 +398,8 @@ enum {
IFLA_VF_UNSPEC,
IFLA_VF_MAC, /* Hardware queue specific attributes */
IFLA_VF_VLAN,
- IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */
+ IFLA_VF_TX_RATE, /* Max TX Bandwidth Allocation */
+ IFLA_VF_RATE, /* Min and Max TX Bandwidth Allocation */
IFLA_VF_SPOOFCHK, /* Spoof Checking on/off switch */
IFLA_VF_LINK_STATE, /* link state enable/disable/auto switch */
__IFLA_VF_MAX,
@@ -422,6 +423,12 @@ struct ifla_vf_tx_rate {
__u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */
};
+struct ifla_vf_rate {
+ __u32 vf;
+ __u32 min_tx_rate; /* Min Bandwidth in Mbps */
+ __u32 max_tx_rate; /* Max Bandwidth in Mbps */
+};
+
struct ifla_vf_spoofchk {
__u32 vf;
__u32 setting;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index fc122fd..220d9c3 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1027,6 +1027,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
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;
@@ -1047,6 +1048,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
break;
vf_mac.vf =
vf_vlan.vf =
+ vf_rate.vf =
vf_tx_rate.vf =
vf_spoofchk.vf =
vf_linkstate.vf = ivi.vf;
@@ -1055,6 +1057,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
vf_vlan.vlan = ivi.vlan;
vf_vlan.qos = ivi.qos;
vf_tx_rate.rate = ivi.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 = nla_nest_start(skb, IFLA_VF_INFO);
@@ -1064,6 +1068,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
}
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),
@@ -1328,6 +1334,30 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
ivt->rate);
break;
}
+ case IFLA_VF_RATE: {
+ struct ifla_vf_rate *ivt;
+ struct ifla_vf_info ivf;
+ ivt = nla_data(vf);
+ err = -EOPNOTSUPP;
+ if ((!ivt->min_tx_rate || !ivt->max_tx_rate) &&
+ ops->ndo_get_vf_config)
+ err = ops->ndo_get_vf_config(dev, ivt->vf,
+ &ivf);
+ else
+ err = 0;
+ if (err)
+ break;
+ if (!ivt->min_tx_rate)
+ ivt->min_tx_rate = ivf.min_tx_rate;
+ if (!ivt->max_tx_rate)
+ ivt->max_tx_rate = ivf.max_tx_rate;
+ err = -EOPNOTSUPP;
+ if (ops->ndo_set_vf_rate)
+ err = ops->ndo_set_vf_rate(dev, ivt->vf,
+ ivt->min_tx_rate,
+ ivt->max_tx_rate);
+ break;
+ }
case IFLA_VF_SPOOFCHK: {
struct ifla_vf_spoofchk *ivs;
ivs = nla_data(vf);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* [RFC 2/2] qlcnic: Add support to configure SR-IOV VF minimum and maximum Tx rate through ip tool.
2014-03-05 7:33 [RFC 0/2]: Add minimum bandwidth support in IP tool Sucheta Chakraborty
2014-03-05 7:33 ` [RFC 1/2] net: Add support to configure SR-IOV VF minimum and maximum Tx rate through ip tool Sucheta Chakraborty
@ 2014-03-05 7:33 ` Sucheta Chakraborty
1 sibling, 0 replies; 7+ messages in thread
From: Sucheta Chakraborty @ 2014-03-05 7:33 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept-HSGLinuxNICDev
o ip command can be used to configure minimum and maximum Tx rate.
o "min_tx_rate" option has been added for minimum Tx rate. Hence, for
consistent naming, "max_tx_rate" option has been introduced for maximum
Tx rate. And plan is to deprecate "rate" option of ip tool.
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 1 +
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h | 1 +
.../net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | 102 +++++++++++++++++++--
3 files changed, 94 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index a335472..58cc49f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -485,6 +485,7 @@ static const struct net_device_ops qlcnic_netdev_ops = {
#ifdef CONFIG_QLCNIC_SRIOV
.ndo_set_vf_mac = qlcnic_sriov_set_vf_mac,
.ndo_set_vf_tx_rate = qlcnic_sriov_set_vf_tx_rate,
+ .ndo_set_vf_rate = qlcnic_sriov_set_vf_rate,
.ndo_get_vf_config = qlcnic_sriov_get_vf_config,
.ndo_set_vf_vlan = qlcnic_sriov_set_vf_vlan,
.ndo_set_vf_spoofchk = qlcnic_sriov_set_vf_spoofchk,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
index 396bd1f..7d53caa 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
@@ -232,6 +232,7 @@ void qlcnic_sriov_pf_reset(struct qlcnic_adapter *);
int qlcnic_sriov_pf_reinit(struct qlcnic_adapter *);
int qlcnic_sriov_set_vf_mac(struct net_device *, int, u8 *);
int qlcnic_sriov_set_vf_tx_rate(struct net_device *, int, int);
+int qlcnic_sriov_set_vf_rate(struct net_device *, int, int, int);
int qlcnic_sriov_get_vf_config(struct net_device *, int ,
struct ifla_vf_info *);
int qlcnic_sriov_set_vf_vlan(struct net_device *, int, u16, u8);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
index a28460c..69bf0b2 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
@@ -1821,28 +1821,32 @@ int qlcnic_sriov_set_vf_tx_rate(struct net_device *netdev, int vf, int tx_rate)
struct qlcnic_vf_info *vf_info;
struct qlcnic_info nic_info;
struct qlcnic_vport *vp;
- u16 vpid;
+ u16 vpid, min_tx_rate;
- if (!qlcnic_sriov_pf_check(adapter))
+ if (!qlcnic_sriov_pf_check(adapter) || qlcnic_84xx_check(adapter))
return -EOPNOTSUPP;
if (vf >= sriov->num_vfs)
return -EINVAL;
- if (tx_rate >= 10000 || tx_rate < 100) {
+ vf_info = &sriov->vf_info[vf];
+ vp = vf_info->vp;
+ vpid = vp->handle;
+
+ min_tx_rate = vp->min_tx_bw * 100;
+ if (!min_tx_rate)
+ min_tx_rate = QLC_VF_MIN_TX_RATE;
+
+ if (tx_rate >= 10000 || tx_rate < min_tx_rate) {
netdev_err(netdev,
"Invalid Tx rate, allowed range is [%d - %d]",
- QLC_VF_MIN_TX_RATE, QLC_VF_MAX_TX_RATE);
+ min_tx_rate, QLC_VF_MAX_TX_RATE);
return -EINVAL;
}
if (tx_rate == 0)
tx_rate = 10000;
- vf_info = &sriov->vf_info[vf];
- vp = vf_info->vp;
- vpid = vp->handle;
-
if (test_bit(QLC_BC_VF_STATE, &vf_info->state)) {
if (qlcnic_sriov_get_vf_vport_info(adapter, &nic_info, vpid))
return -EIO;
@@ -1952,13 +1956,24 @@ int qlcnic_sriov_get_vf_config(struct net_device *netdev,
vp = sriov->vf_info[vf].vp;
memcpy(&ivi->mac, vp->mac, ETH_ALEN);
+ ivi->tx_rate = 0;
ivi->vlan = qlcnic_sriov_get_vf_vlan(adapter, vp, vf);
ivi->qos = vp->qos;
ivi->spoofchk = vp->spoofchk;
if (vp->max_tx_bw == MAX_BW)
- ivi->tx_rate = 0;
+ ivi->max_tx_rate = 0;
else
- ivi->tx_rate = vp->max_tx_bw * 100;
+ ivi->max_tx_rate = vp->max_tx_bw * 100;
+
+ if (vp->min_tx_bw * 100 == QLC_VF_MIN_TX_RATE)
+ ivi->min_tx_rate = 0;
+ else
+ ivi->min_tx_rate = vp->min_tx_bw * 100;
+
+ if (!qlcnic_84xx_check(adapter) && !ivi->min_tx_rate) {
+ ivi->tx_rate = ivi->max_tx_rate;
+ ivi->max_tx_rate = 0;
+ }
ivi->vf = vf;
return 0;
@@ -1989,3 +2004,70 @@ int qlcnic_sriov_set_vf_spoofchk(struct net_device *netdev, int vf, bool chk)
vp->spoofchk = chk;
return 0;
}
+
+int qlcnic_sriov_set_vf_rate(struct net_device *netdev, int vf,
+ int min_tx_rate, int max_tx_rate)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ struct qlcnic_sriov *sriov = adapter->ahw->sriov;
+ struct qlcnic_vf_info *vf_info;
+ struct qlcnic_info nic_info;
+ struct qlcnic_vport *vp;
+ u16 vpid;
+
+ if (!qlcnic_sriov_pf_check(adapter))
+ return -EOPNOTSUPP;
+
+ if (vf >= sriov->num_vfs)
+ return -EINVAL;
+
+ vf_info = &sriov->vf_info[vf];
+ vp = vf_info->vp;
+ vpid = vp->handle;
+
+ if (!min_tx_rate)
+ min_tx_rate = QLC_VF_MIN_TX_RATE;
+
+ if (max_tx_rate &&
+ (max_tx_rate >= 10000 || max_tx_rate < min_tx_rate)) {
+ netdev_err(netdev,
+ "Invalid max Tx rate, allowed range is [%d - %d]",
+ min_tx_rate, QLC_VF_MAX_TX_RATE);
+ return -EINVAL;
+ }
+
+ if (!max_tx_rate)
+ max_tx_rate = 10000;
+
+ if (min_tx_rate &&
+ (min_tx_rate > max_tx_rate || min_tx_rate < QLC_VF_MIN_TX_RATE)) {
+ netdev_err(netdev,
+ "Invalid min Tx rate, allowed range is [%d - %d]",
+ QLC_VF_MIN_TX_RATE, max_tx_rate);
+ return -EINVAL;
+ }
+
+ if (test_bit(QLC_BC_VF_STATE, &vf_info->state)) {
+ if (qlcnic_sriov_get_vf_vport_info(adapter, &nic_info, vpid))
+ return -EIO;
+
+ nic_info.max_tx_bw = max_tx_rate / 100;
+ nic_info.min_tx_bw = min_tx_rate / 100;
+ nic_info.bit_offsets = BIT_0;
+
+ if (qlcnic_sriov_pf_set_vport_info(adapter, &nic_info, vpid))
+ return -EIO;
+ }
+
+ vp->max_tx_bw = max_tx_rate / 100;
+ netdev_info(netdev,
+ "Setting Max Tx rate %d (Mbps), %d %% of PF bandwidth, for VF %d\n",
+ max_tx_rate, vp->max_tx_bw, vf);
+
+ vp->min_tx_bw = min_tx_rate / 100;
+ netdev_info(netdev,
+ "%s: Setting Min Tx rate %d (Mbps), %d %% of PF bandwidth, for VF %d\n",
+ __func__, min_tx_rate, vp->min_tx_bw, vf);
+
+ return 0;
+}
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread