Commit 46132188 authored by Alexander Duyck's avatar Alexander Duyck Committed by David S. Miller

DCB: Add interface to query for the DCB capabilities of an device.

Adds to the netlink interface for Data Center Bridging (DCB), allowing
the DCB capabilities supported by a device to be queried.
Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarPeter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2f90b865
...@@ -337,6 +337,45 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) ...@@ -337,6 +337,45 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
return ret; return ret;
} }
static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
u8 rval = 0;
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
switch (capid) {
case DCB_CAP_ATTR_PG:
*cap = true;
break;
case DCB_CAP_ATTR_PFC:
*cap = true;
break;
case DCB_CAP_ATTR_UP2TC:
*cap = false;
break;
case DCB_CAP_ATTR_PG_TCS:
*cap = 0x80;
break;
case DCB_CAP_ATTR_PFC_TCS:
*cap = 0x80;
break;
case DCB_CAP_ATTR_GSP:
*cap = true;
break;
case DCB_CAP_ATTR_BCN:
*cap = false;
break;
default:
rval = -EINVAL;
break;
}
} else {
rval = -EINVAL;
}
return rval;
}
struct dcbnl_rtnl_ops dcbnl_ops = { struct dcbnl_rtnl_ops dcbnl_ops = {
.getstate = ixgbe_dcbnl_get_state, .getstate = ixgbe_dcbnl_get_state,
.setstate = ixgbe_dcbnl_set_state, .setstate = ixgbe_dcbnl_set_state,
...@@ -351,6 +390,7 @@ struct dcbnl_rtnl_ops dcbnl_ops = { ...@@ -351,6 +390,7 @@ struct dcbnl_rtnl_ops dcbnl_ops = {
.getpgbwgcfgrx = ixgbe_dcbnl_get_pg_bwg_cfg_rx, .getpgbwgcfgrx = ixgbe_dcbnl_get_pg_bwg_cfg_rx,
.setpfccfg = ixgbe_dcbnl_set_pfc_cfg, .setpfccfg = ixgbe_dcbnl_set_pfc_cfg,
.getpfccfg = ixgbe_dcbnl_get_pfc_cfg, .getpfccfg = ixgbe_dcbnl_get_pfc_cfg,
.setall = ixgbe_dcbnl_set_all .setall = ixgbe_dcbnl_set_all,
.getcap = ixgbe_dcbnl_getcap
}; };
...@@ -43,6 +43,7 @@ struct dcbmsg { ...@@ -43,6 +43,7 @@ struct dcbmsg {
* @DCB_CMD_SET_ALL: apply all changes to the underlying device * @DCB_CMD_SET_ALL: apply all changes to the underlying device
* @DCB_CMD_GPERM_HWADDR: get the permanent MAC address of the underlying * @DCB_CMD_GPERM_HWADDR: get the permanent MAC address of the underlying
* device. Only useful when using bonding. * device. Only useful when using bonding.
* @DCB_CMD_GCAP: request the DCB capabilities of the device
*/ */
enum dcbnl_commands { enum dcbnl_commands {
DCB_CMD_UNDEFINED, DCB_CMD_UNDEFINED,
...@@ -60,6 +61,7 @@ enum dcbnl_commands { ...@@ -60,6 +61,7 @@ enum dcbnl_commands {
DCB_CMD_SET_ALL, DCB_CMD_SET_ALL,
DCB_CMD_GPERM_HWADDR, DCB_CMD_GPERM_HWADDR,
DCB_CMD_GCAP,
__DCB_CMD_ENUM_MAX, __DCB_CMD_ENUM_MAX,
DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1,
...@@ -78,6 +80,7 @@ enum dcbnl_commands { ...@@ -78,6 +80,7 @@ enum dcbnl_commands {
* @DCB_ATTR_PG_CFG: priority group configuration (NLA_NESTED) * @DCB_ATTR_PG_CFG: priority group configuration (NLA_NESTED)
* @DCB_ATTR_SET_ALL: bool to commit changes to hardware or not (NLA_U8) * @DCB_ATTR_SET_ALL: bool to commit changes to hardware or not (NLA_U8)
* @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED) * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED)
* @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED)
*/ */
enum dcbnl_attrs { enum dcbnl_attrs {
DCB_ATTR_UNDEFINED, DCB_ATTR_UNDEFINED,
...@@ -90,6 +93,7 @@ enum dcbnl_attrs { ...@@ -90,6 +93,7 @@ enum dcbnl_attrs {
DCB_ATTR_PG_CFG, DCB_ATTR_PG_CFG,
DCB_ATTR_SET_ALL, DCB_ATTR_SET_ALL,
DCB_ATTR_PERM_HWADDR, DCB_ATTR_PERM_HWADDR,
DCB_ATTR_CAP,
__DCB_ATTR_ENUM_MAX, __DCB_ATTR_ENUM_MAX,
DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1,
...@@ -216,6 +220,39 @@ enum dcbnl_tc_attrs { ...@@ -216,6 +220,39 @@ enum dcbnl_tc_attrs {
DCB_TC_ATTR_PARAM_MAX = __DCB_TC_ATTR_PARAM_ENUM_MAX - 1, DCB_TC_ATTR_PARAM_MAX = __DCB_TC_ATTR_PARAM_ENUM_MAX - 1,
}; };
/**
* enum dcbnl_cap_attrs - DCB Capability attributes
*
* @DCB_CAP_ATTR_UNDEFINED: unspecified attribute to catch errors
* @DCB_CAP_ATTR_ALL: (NLA_FLAG) all capability parameters
* @DCB_CAP_ATTR_PG: (NLA_U8) device supports Priority Groups
* @DCB_CAP_ATTR_PFC: (NLA_U8) device supports Priority Flow Control
* @DCB_CAP_ATTR_UP2TC: (NLA_U8) device supports user priority to
* traffic class mapping
* @DCB_CAP_ATTR_PG_TCS: (NLA_U8) bitmap where each bit represents a
* number of traffic classes the device
* can be configured to use for Priority Groups
* @DCB_CAP_ATTR_PFC_TCS: (NLA_U8) bitmap where each bit represents a
* number of traffic classes the device can be
* configured to use for Priority Flow Control
* @DCB_CAP_ATTR_GSP: (NLA_U8) device supports group strict priority
* @DCB_CAP_ATTR_BCN: (NLA_U8) device supports Backwards Congestion
* Notification
*/
enum dcbnl_cap_attrs {
DCB_CAP_ATTR_UNDEFINED,
DCB_CAP_ATTR_ALL,
DCB_CAP_ATTR_PG,
DCB_CAP_ATTR_PFC,
DCB_CAP_ATTR_UP2TC,
DCB_CAP_ATTR_PG_TCS,
DCB_CAP_ATTR_PFC_TCS,
DCB_CAP_ATTR_GSP,
DCB_CAP_ATTR_BCN,
__DCB_CAP_ATTR_ENUM_MAX,
DCB_CAP_ATTR_MAX = __DCB_CAP_ATTR_ENUM_MAX - 1,
};
/** /**
* enum dcb_general_attr_values - general DCB attribute values * enum dcb_general_attr_values - general DCB attribute values
* *
......
...@@ -39,6 +39,7 @@ struct dcbnl_rtnl_ops { ...@@ -39,6 +39,7 @@ struct dcbnl_rtnl_ops {
void (*setpfccfg)(struct net_device *, int, u8); void (*setpfccfg)(struct net_device *, int, u8);
void (*getpfccfg)(struct net_device *, int, u8 *); void (*getpfccfg)(struct net_device *, int, u8 *);
u8 (*setall)(struct net_device *); u8 (*setall)(struct net_device *);
u8 (*getcap)(struct net_device *, int, u8 *);
}; };
#endif /* __NET_DCBNL_H__ */ #endif /* __NET_DCBNL_H__ */
...@@ -61,6 +61,7 @@ static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { ...@@ -61,6 +61,7 @@ static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = {
[DCB_ATTR_PG_CFG] = {.type = NLA_NESTED}, [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED},
[DCB_ATTR_SET_ALL] = {.type = NLA_U8}, [DCB_ATTR_SET_ALL] = {.type = NLA_U8},
[DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG}, [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG},
[DCB_ATTR_CAP] = {.type = NLA_NESTED},
}; };
/* DCB priority flow control to User Priority nested attributes */ /* DCB priority flow control to User Priority nested attributes */
...@@ -107,6 +108,17 @@ static struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = { ...@@ -107,6 +108,17 @@ static struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = {
[DCB_TC_ATTR_PARAM_ALL] = {.type = NLA_FLAG}, [DCB_TC_ATTR_PARAM_ALL] = {.type = NLA_FLAG},
}; };
/* DCB capabilities nested attributes. */
static struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = {
[DCB_CAP_ATTR_ALL] = {.type = NLA_FLAG},
[DCB_CAP_ATTR_PG] = {.type = NLA_U8},
[DCB_CAP_ATTR_PFC] = {.type = NLA_U8},
[DCB_CAP_ATTR_UP2TC] = {.type = NLA_U8},
[DCB_CAP_ATTR_PG_TCS] = {.type = NLA_U8},
[DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8},
[DCB_CAP_ATTR_GSP] = {.type = NLA_U8},
[DCB_CAP_ATTR_BCN] = {.type = NLA_U8},
};
/* standard netlink reply call */ /* standard netlink reply call */
static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
...@@ -269,6 +281,72 @@ static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb, ...@@ -269,6 +281,72 @@ static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb,
return -EINVAL; return -EINVAL;
} }
static int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb,
u32 pid, u32 seq, u16 flags)
{
struct sk_buff *dcbnl_skb;
struct nlmsghdr *nlh;
struct dcbmsg *dcb;
struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest;
u8 value;
int ret = -EINVAL;
int i;
int getall = 0;
if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap)
return ret;
ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP],
dcbnl_cap_nest);
if (ret)
goto err_out;
dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!dcbnl_skb)
goto err_out;
nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
dcb = NLMSG_DATA(nlh);
dcb->dcb_family = AF_UNSPEC;
dcb->cmd = DCB_CMD_GCAP;
nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP);
if (!nest)
goto err;
if (data[DCB_CAP_ATTR_ALL])
getall = 1;
for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) {
if (!getall && !data[i])
continue;
if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) {
ret = nla_put_u8(dcbnl_skb, i, value);
if (ret) {
nla_nest_cancel(dcbnl_skb, nest);
goto err;
}
}
}
nla_nest_end(dcbnl_skb, nest);
nlmsg_end(dcbnl_skb, nlh);
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret)
goto err;
return 0;
nlmsg_failure:
err:
kfree(dcbnl_skb);
err_out:
return -EINVAL;
}
static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb,
u32 pid, u32 seq, u16 flags, int dir) u32 pid, u32 seq, u16 flags, int dir)
{ {
...@@ -675,6 +753,10 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -675,6 +753,10 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
nlh->nlmsg_flags); nlh->nlmsg_flags);
goto out; goto out;
case DCB_CMD_GCAP:
ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq,
nlh->nlmsg_flags);
goto out;
default: default:
goto errout; goto errout;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment