Merge branch 'nfp-vf-rate-limit-support'

Simon Horman says:

====================
*nfp: VF rate limit support

this short series adds VF rate limiting to the NFP driver.

The first patch, as suggested by Jakub Kicinski, adds a helper
to check that ndo_set_vf_rate() rate parameters are sane.
It also provides a place for further parameter checking to live,
if needed in future.

The second patch adds VF rate limit support to the NFP driver.
It addresses several comments made on v1, including removing
the parameter check that is now provided by the helper added
in the first patch.
====================

Link: https://lore.kernel.org/r/20220511113932.92114-1-simon.horman@corigine.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Paolo Abeni 2022-05-12 13:03:12 +02:00
commit b33177f1d6
4 changed files with 74 additions and 12 deletions

View File

@ -1903,6 +1903,7 @@ const struct net_device_ops nfp_nfd3_netdev_ops = {
.ndo_vlan_rx_kill_vid = nfp_net_vlan_rx_kill_vid, .ndo_vlan_rx_kill_vid = nfp_net_vlan_rx_kill_vid,
.ndo_set_vf_mac = nfp_app_set_vf_mac, .ndo_set_vf_mac = nfp_app_set_vf_mac,
.ndo_set_vf_vlan = nfp_app_set_vf_vlan, .ndo_set_vf_vlan = nfp_app_set_vf_vlan,
.ndo_set_vf_rate = nfp_app_set_vf_rate,
.ndo_set_vf_spoofchk = nfp_app_set_vf_spoofchk, .ndo_set_vf_spoofchk = nfp_app_set_vf_spoofchk,
.ndo_set_vf_trust = nfp_app_set_vf_trust, .ndo_set_vf_trust = nfp_app_set_vf_trust,
.ndo_get_vf_config = nfp_app_get_vf_config, .ndo_get_vf_config = nfp_app_get_vf_config,

View File

@ -142,6 +142,37 @@ int nfp_app_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,
return nfp_net_sriov_update(app, vf, update, "vlan"); return nfp_net_sriov_update(app, vf, update, "vlan");
} }
int nfp_app_set_vf_rate(struct net_device *netdev, int vf,
int min_tx_rate, int max_tx_rate)
{
struct nfp_app *app = nfp_app_from_netdev(netdev);
u32 vf_offset, ratevalue;
int err;
err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_RATE, "rate");
if (err)
return err;
if (max_tx_rate >= NFP_NET_VF_RATE_MAX ||
min_tx_rate >= NFP_NET_VF_RATE_MAX) {
nfp_warn(app->cpp, "tx-rate exceeds %d.\n",
NFP_NET_VF_RATE_MAX);
return -EINVAL;
}
vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ;
ratevalue = FIELD_PREP(NFP_NET_VF_CFG_MAX_RATE,
max_tx_rate ? max_tx_rate :
NFP_NET_VF_RATE_MAX) |
FIELD_PREP(NFP_NET_VF_CFG_MIN_RATE, min_tx_rate);
writel(ratevalue,
app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_RATE);
return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_RATE,
"rate");
}
int nfp_app_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable) int nfp_app_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable)
{ {
struct nfp_app *app = nfp_app_from_netdev(netdev); struct nfp_app *app = nfp_app_from_netdev(netdev);
@ -228,9 +259,8 @@ int nfp_app_get_vf_config(struct net_device *netdev, int vf,
struct ifla_vf_info *ivi) struct ifla_vf_info *ivi)
{ {
struct nfp_app *app = nfp_app_from_netdev(netdev); struct nfp_app *app = nfp_app_from_netdev(netdev);
unsigned int vf_offset; u32 vf_offset, mac_hi, rate;
u32 vlan_tag; u32 vlan_tag;
u32 mac_hi;
u16 mac_lo; u16 mac_lo;
u8 flags; u8 flags;
int err; int err;
@ -261,5 +291,19 @@ int nfp_app_get_vf_config(struct net_device *netdev, int vf,
ivi->trusted = FIELD_GET(NFP_NET_VF_CFG_CTRL_TRUST, flags); ivi->trusted = FIELD_GET(NFP_NET_VF_CFG_CTRL_TRUST, flags);
ivi->linkstate = FIELD_GET(NFP_NET_VF_CFG_CTRL_LINK_STATE, flags); ivi->linkstate = FIELD_GET(NFP_NET_VF_CFG_CTRL_LINK_STATE, flags);
err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_RATE, "rate");
if (!err) {
rate = readl(app->pf->vfcfg_tbl2 + vf_offset +
NFP_NET_VF_CFG_RATE);
ivi->max_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MAX_RATE, rate);
ivi->min_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MIN_RATE, rate);
if (ivi->max_tx_rate == NFP_NET_VF_RATE_MAX)
ivi->max_tx_rate = 0;
if (ivi->min_tx_rate == NFP_NET_VF_RATE_MAX)
ivi->min_tx_rate = 0;
}
return 0; return 0;
} }

View File

@ -20,6 +20,7 @@
#define NFP_NET_VF_CFG_MB_CAP_LINK_STATE (0x1 << 3) #define NFP_NET_VF_CFG_MB_CAP_LINK_STATE (0x1 << 3)
#define NFP_NET_VF_CFG_MB_CAP_TRUST (0x1 << 4) #define NFP_NET_VF_CFG_MB_CAP_TRUST (0x1 << 4)
#define NFP_NET_VF_CFG_MB_CAP_VLAN_PROTO (0x1 << 5) #define NFP_NET_VF_CFG_MB_CAP_VLAN_PROTO (0x1 << 5)
#define NFP_NET_VF_CFG_MB_CAP_RATE (0x1 << 6)
#define NFP_NET_VF_CFG_MB_RET 0x2 #define NFP_NET_VF_CFG_MB_RET 0x2
#define NFP_NET_VF_CFG_MB_UPD 0x4 #define NFP_NET_VF_CFG_MB_UPD 0x4
#define NFP_NET_VF_CFG_MB_UPD_MAC (0x1 << 0) #define NFP_NET_VF_CFG_MB_UPD_MAC (0x1 << 0)
@ -28,6 +29,7 @@
#define NFP_NET_VF_CFG_MB_UPD_LINK_STATE (0x1 << 3) #define NFP_NET_VF_CFG_MB_UPD_LINK_STATE (0x1 << 3)
#define NFP_NET_VF_CFG_MB_UPD_TRUST (0x1 << 4) #define NFP_NET_VF_CFG_MB_UPD_TRUST (0x1 << 4)
#define NFP_NET_VF_CFG_MB_UPD_VLAN_PROTO (0x1 << 5) #define NFP_NET_VF_CFG_MB_UPD_VLAN_PROTO (0x1 << 5)
#define NFP_NET_VF_CFG_MB_UPD_RATE (0x1 << 6)
#define NFP_NET_VF_CFG_MB_VF_NUM 0x7 #define NFP_NET_VF_CFG_MB_VF_NUM 0x7
/* VF config entry /* VF config entry
@ -48,10 +50,17 @@
#define NFP_NET_VF_CFG_VLAN_PROT 0xffff0000 #define NFP_NET_VF_CFG_VLAN_PROT 0xffff0000
#define NFP_NET_VF_CFG_VLAN_QOS 0xe000 #define NFP_NET_VF_CFG_VLAN_QOS 0xe000
#define NFP_NET_VF_CFG_VLAN_VID 0x0fff #define NFP_NET_VF_CFG_VLAN_VID 0x0fff
#define NFP_NET_VF_CFG_RATE 0xc
#define NFP_NET_VF_CFG_MIN_RATE 0x0000ffff
#define NFP_NET_VF_CFG_MAX_RATE 0xffff0000
#define NFP_NET_VF_RATE_MAX 0xffff
int nfp_app_set_vf_mac(struct net_device *netdev, int vf, u8 *mac); int nfp_app_set_vf_mac(struct net_device *netdev, int vf, u8 *mac);
int nfp_app_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos, int nfp_app_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,
__be16 vlan_proto); __be16 vlan_proto);
int nfp_app_set_vf_rate(struct net_device *netdev, int vf, int min_tx_rate,
int max_tx_rate);
int nfp_app_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting); int nfp_app_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting);
int nfp_app_set_vf_trust(struct net_device *netdev, int vf, bool setting); int nfp_app_set_vf_trust(struct net_device *netdev, int vf, bool setting);
int nfp_app_set_vf_link_state(struct net_device *netdev, int vf, int nfp_app_set_vf_link_state(struct net_device *netdev, int vf,

View File

@ -2306,6 +2306,19 @@ static int rtnl_ensure_unique_netns(struct nlattr *tb[],
return -EINVAL; return -EINVAL;
} }
static int rtnl_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate,
int max_tx_rate)
{
const struct net_device_ops *ops = dev->netdev_ops;
if (!ops->ndo_set_vf_rate)
return -EOPNOTSUPP;
if (max_tx_rate && max_tx_rate < min_tx_rate)
return -EINVAL;
return ops->ndo_set_vf_rate(dev, vf, min_tx_rate, max_tx_rate);
}
static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[], static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[],
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
@ -2443,11 +2456,8 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)
if (err < 0) if (err < 0)
return err; return err;
err = -EOPNOTSUPP; err = rtnl_set_vf_rate(dev, ivt->vf,
if (ops->ndo_set_vf_rate) ivf.min_tx_rate, ivt->rate);
err = ops->ndo_set_vf_rate(dev, ivt->vf,
ivf.min_tx_rate,
ivt->rate);
if (err < 0) if (err < 0)
return err; return err;
} }
@ -2457,11 +2467,9 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)
if (ivt->vf >= INT_MAX) if (ivt->vf >= INT_MAX)
return -EINVAL; return -EINVAL;
err = -EOPNOTSUPP;
if (ops->ndo_set_vf_rate) err = rtnl_set_vf_rate(dev, ivt->vf,
err = ops->ndo_set_vf_rate(dev, ivt->vf, ivt->min_tx_rate, ivt->max_tx_rate);
ivt->min_tx_rate,
ivt->max_tx_rate);
if (err < 0) if (err < 0)
return err; return err;
} }