dcbnl: add support for retrieving peer configuration - cee

This patch adds the support for retrieving the remote or peer DCBX
configuration via dcbnl for embedded DCBX stacks supporting the CEE DCBX
standard.

Signed-off-by: Shmulik Ravid <shmulikr@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Shmulik Ravid
2011-02-27 05:04:38 +00:00
committed by David S. Miller
parent eed84713bc
commit dc6ed1df5a
3 changed files with 155 additions and 4 deletions

View File

@ -1224,7 +1224,9 @@ err:
return err;
}
static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb)
static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
int app_nested_type, int app_info_type,
int app_entry_type)
{
struct dcb_peer_app_info info;
struct dcb_app *table = NULL;
@ -1256,12 +1258,15 @@ static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb)
*/
err = -EMSGSIZE;
app = nla_nest_start(skb, DCB_ATTR_IEEE_PEER_APP);
app = nla_nest_start(skb, app_nested_type);
if (!app)
goto nla_put_failure;
if (app_info_type)
NLA_PUT(skb, app_info_type, sizeof(info), &info);
for (i = 0; i < app_count; i++)
NLA_PUT(skb, DCB_ATTR_IEEE_APP, sizeof(struct dcb_app),
NLA_PUT(skb, app_entry_type, sizeof(struct dcb_app),
&table[i]);
nla_nest_end(skb, app);
@ -1352,7 +1357,10 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
}
if (ops->peer_getappinfo && ops->peer_getapptable) {
err = dcbnl_build_peer_app(netdev, skb);
err = dcbnl_build_peer_app(netdev, skb,
DCB_ATTR_IEEE_PEER_APP,
DCB_ATTR_IEEE_APP_UNSPEC,
DCB_ATTR_IEEE_APP);
if (err)
goto nla_put_failure;
}
@ -1510,6 +1518,71 @@ err:
return ret;
}
/* Handle CEE DCBX GET commands. */
static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
u32 pid, u32 seq, u16 flags)
{
struct sk_buff *skb;
struct nlmsghdr *nlh;
struct dcbmsg *dcb;
struct nlattr *cee;
const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
int err;
if (!ops)
return -EOPNOTSUPP;
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!skb)
return -ENOBUFS;
nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
dcb = NLMSG_DATA(nlh);
dcb->dcb_family = AF_UNSPEC;
dcb->cmd = DCB_CMD_CEE_GET;
NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
cee = nla_nest_start(skb, DCB_ATTR_CEE);
if (!cee)
goto nla_put_failure;
/* get peer info if available */
if (ops->cee_peer_getpg) {
struct cee_pg pg;
err = ops->cee_peer_getpg(netdev, &pg);
if (!err)
NLA_PUT(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg);
}
if (ops->cee_peer_getpfc) {
struct cee_pfc pfc;
err = ops->cee_peer_getpfc(netdev, &pfc);
if (!err)
NLA_PUT(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc);
}
if (ops->peer_getappinfo && ops->peer_getapptable) {
err = dcbnl_build_peer_app(netdev, skb,
DCB_ATTR_CEE_PEER_APP_TABLE,
DCB_ATTR_CEE_PEER_APP_INFO,
DCB_ATTR_CEE_PEER_APP);
if (err)
goto nla_put_failure;
}
nla_nest_end(skb, cee);
nlmsg_end(skb, nlh);
return rtnl_unicast(skb, &init_net, pid);
nla_put_failure:
nlmsg_cancel(skb, nlh);
nlmsg_failure:
kfree_skb(skb);
return -1;
}
static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
struct net *net = sock_net(skb->sk);
@ -1639,6 +1712,10 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
ret = dcbnl_setfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
nlh->nlmsg_flags);
goto out;
case DCB_CMD_CEE_GET:
ret = dcbnl_cee_get(netdev, tb, pid, nlh->nlmsg_seq,
nlh->nlmsg_flags);
goto out;
default:
goto errout;
}