Skip to content

Commit

Permalink
DCB: Add interface to query for the DCB capabilities of an device.
Browse files Browse the repository at this point in the history
Adds to the netlink interface for Data Center Bridging (DCB), allowing
the DCB capabilities supported by a device to be queried.

Signed-off-by: Alexander Duyck <[email protected]>
Signed-off-by: Jeff Kirsher <[email protected]>
Signed-off-by: Peter P Waskiewicz Jr <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Alexander Duyck authored and davem330 committed Nov 21, 2008
1 parent 2f90b86 commit 4613218
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 1 deletion.
42 changes: 41 additions & 1 deletion drivers/net/ixgbe/ixgbe_dcb_nl.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,45 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
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 = {
.getstate = ixgbe_dcbnl_get_state,
.setstate = ixgbe_dcbnl_set_state,
Expand All @@ -351,6 +390,7 @@ struct dcbnl_rtnl_ops dcbnl_ops = {
.getpgbwgcfgrx = ixgbe_dcbnl_get_pg_bwg_cfg_rx,
.setpfccfg = ixgbe_dcbnl_set_pfc_cfg,
.getpfccfg = ixgbe_dcbnl_get_pfc_cfg,
.setall = ixgbe_dcbnl_set_all
.setall = ixgbe_dcbnl_set_all,
.getcap = ixgbe_dcbnl_getcap
};

37 changes: 37 additions & 0 deletions include/linux/dcbnl.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ struct dcbmsg {
* @DCB_CMD_SET_ALL: apply all changes to the underlying device
* @DCB_CMD_GPERM_HWADDR: get the permanent MAC address of the underlying
* device. Only useful when using bonding.
* @DCB_CMD_GCAP: request the DCB capabilities of the device
*/
enum dcbnl_commands {
DCB_CMD_UNDEFINED,
Expand All @@ -60,6 +61,7 @@ enum dcbnl_commands {

DCB_CMD_SET_ALL,
DCB_CMD_GPERM_HWADDR,
DCB_CMD_GCAP,

__DCB_CMD_ENUM_MAX,
DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1,
Expand All @@ -78,6 +80,7 @@ enum dcbnl_commands {
* @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_PERM_HWADDR: MAC address of the physical device (NLA_NESTED)
* @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED)
*/
enum dcbnl_attrs {
DCB_ATTR_UNDEFINED,
Expand All @@ -90,6 +93,7 @@ enum dcbnl_attrs {
DCB_ATTR_PG_CFG,
DCB_ATTR_SET_ALL,
DCB_ATTR_PERM_HWADDR,
DCB_ATTR_CAP,

__DCB_ATTR_ENUM_MAX,
DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1,
Expand Down Expand Up @@ -216,6 +220,39 @@ enum dcbnl_tc_attrs {
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
*
Expand Down
1 change: 1 addition & 0 deletions include/net/dcbnl.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct dcbnl_rtnl_ops {
void (*setpfccfg)(struct net_device *, int, u8);
void (*getpfccfg)(struct net_device *, int, u8 *);
u8 (*setall)(struct net_device *);
u8 (*getcap)(struct net_device *, int, u8 *);
};

#endif /* __NET_DCBNL_H__ */
82 changes: 82 additions & 0 deletions net/dcb/dcbnl.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = {
[DCB_ATTR_PG_CFG] = {.type = NLA_NESTED},
[DCB_ATTR_SET_ALL] = {.type = NLA_U8},
[DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG},
[DCB_ATTR_CAP] = {.type = NLA_NESTED},
};

/* DCB priority flow control to User Priority nested attributes */
Expand Down Expand Up @@ -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 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 */
static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
Expand Down Expand Up @@ -269,6 +281,72 @@ static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb,
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,
u32 pid, u32 seq, u16 flags, int dir)
{
Expand Down Expand Up @@ -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,
nlh->nlmsg_flags);
goto out;
case DCB_CMD_GCAP:
ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq,
nlh->nlmsg_flags);
goto out;
default:
goto errout;
}
Expand Down

0 comments on commit 4613218

Please sign in to comment.