[DCB_ATTR_CAP] = {.type = NLA_NESTED},
[DCB_ATTR_PFC_STATE] = {.type = NLA_U8},
[DCB_ATTR_BCN] = {.type = NLA_NESTED},
+ [DCB_ATTR_APP] = {.type = NLA_NESTED},
};
/* DCB priority flow control to User Priority nested attributes */
[DCB_BCN_ATTR_RP_6] = {.type = NLA_U8},
[DCB_BCN_ATTR_RP_7] = {.type = NLA_U8},
[DCB_BCN_ATTR_RP_ALL] = {.type = NLA_FLAG},
+ [DCB_BCN_ATTR_BCNA_0] = {.type = NLA_U32},
+ [DCB_BCN_ATTR_BCNA_1] = {.type = NLA_U32},
[DCB_BCN_ATTR_ALPHA] = {.type = NLA_U32},
[DCB_BCN_ATTR_BETA] = {.type = NLA_U32},
[DCB_BCN_ATTR_GD] = {.type = NLA_U32},
[DCB_BCN_ATTR_ALL] = {.type = NLA_FLAG},
};
+/* DCB APP nested attributes. */
+static struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = {
+ [DCB_APP_ATTR_IDTYPE] = {.type = NLA_U8},
+ [DCB_APP_ATTR_ID] = {.type = NLA_U16},
+ [DCB_APP_ATTR_PRIORITY] = {.type = NLA_U8},
+};
+
/* standard netlink reply call */
static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
u32 seq, u16 flags)
nlmsg_end(dcbnl_skb, nlh);
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret)
- goto err;
+ return -EINVAL;
return 0;
nlmsg_failure:
err:
- kfree(dcbnl_skb);
+ kfree_skb(dcbnl_skb);
return ret;
}
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret)
- goto err;
+ goto err_out;
return 0;
nlmsg_failure:
err:
- kfree(dcbnl_skb);
+ kfree_skb(dcbnl_skb);
err_out:
return -EINVAL;
}
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret)
- goto err;
+ goto err_out;
return 0;
nlmsg_failure:
-err:
- kfree(dcbnl_skb);
+ kfree_skb(dcbnl_skb);
err_out:
return -EINVAL;
}
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret)
- goto err;
+ goto err_out;
return 0;
nlmsg_failure:
err:
- kfree(dcbnl_skb);
+ kfree_skb(dcbnl_skb);
err_out:
return -EINVAL;
}
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret) {
ret = -EINVAL;
- goto err;
+ goto err_out;
}
return 0;
nlmsg_failure:
err:
- kfree(dcbnl_skb);
+ kfree_skb(dcbnl_skb);
err_out:
return ret;
}
return ret;
}
+static int dcbnl_getapp(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 *app_nest;
+ struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
+ u16 id;
+ u8 up, idtype;
+ int ret = -EINVAL;
+
+ if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->getapp)
+ goto out;
+
+ ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
+ dcbnl_app_nest);
+ if (ret)
+ goto out;
+
+ ret = -EINVAL;
+ /* all must be non-null */
+ if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
+ (!app_tb[DCB_APP_ATTR_ID]))
+ goto out;
+
+ /* either by eth type or by socket number */
+ idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
+ if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
+ (idtype != DCB_APP_IDTYPE_PORTNUM))
+ goto out;
+
+ id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
+ up = netdev->dcbnl_ops->getapp(netdev, idtype, id);
+
+ /* send this back */
+ dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!dcbnl_skb)
+ goto 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_GAPP;
+
+ app_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_APP);
+ ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype);
+ if (ret)
+ goto out_cancel;
+
+ ret = nla_put_u16(dcbnl_skb, DCB_APP_ATTR_ID, id);
+ if (ret)
+ goto out_cancel;
+
+ ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_PRIORITY, up);
+ if (ret)
+ goto out_cancel;
+
+ nla_nest_end(dcbnl_skb, app_nest);
+ nlmsg_end(dcbnl_skb, nlh);
+
+ ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
+ if (ret)
+ goto nlmsg_failure;
+
+ goto out;
+
+out_cancel:
+ nla_nest_cancel(dcbnl_skb, app_nest);
+nlmsg_failure:
+ kfree_skb(dcbnl_skb);
+out:
+ return ret;
+}
+
+static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb,
+ u32 pid, u32 seq, u16 flags)
+{
+ int ret = -EINVAL;
+ u16 id;
+ u8 up, idtype;
+ struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
+
+ if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->setapp)
+ goto out;
+
+ ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
+ dcbnl_app_nest);
+ if (ret)
+ goto out;
+
+ ret = -EINVAL;
+ /* all must be non-null */
+ if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
+ (!app_tb[DCB_APP_ATTR_ID]) ||
+ (!app_tb[DCB_APP_ATTR_PRIORITY]))
+ goto out;
+
+ /* either by eth type or by socket number */
+ idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
+ if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
+ (idtype != DCB_APP_IDTYPE_PORTNUM))
+ goto out;
+
+ id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
+ up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]);
+
+ ret = dcbnl_reply(netdev->dcbnl_ops->setapp(netdev, idtype, id, up),
+ RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP,
+ pid, seq, flags);
+out:
+ return ret;
+}
+
static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb,
u32 pid, u32 seq, u16 flags, int dir)
{
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret)
- goto err;
+ goto err_out;
return 0;
nla_nest_cancel(dcbnl_skb, pg_nest);
nlmsg_failure:
err:
- kfree(dcbnl_skb);
+ kfree_skb(dcbnl_skb);
err_out:
ret = -EINVAL;
return ret;
value = nla_get_u8(tb[DCB_ATTR_STATE]);
- netdev->dcbnl_ops->setstate(netdev, value);
-
- ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE,
+ ret = dcbnl_reply(netdev->dcbnl_ops->setstate(netdev, value),
+ RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE,
pid, seq, flags);
return ret;
goto err_bcn;
}
- for (i = DCB_BCN_ATTR_ALPHA; i <= DCB_BCN_ATTR_RI; i++) {
+ for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
if (!getall && !bcn_tb[i])
continue;
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret)
- goto err;
+ goto err_out;
return 0;
nla_nest_cancel(dcbnl_skb, bcn_nest);
nlmsg_failure:
err:
- kfree(dcbnl_skb);
+ kfree_skb(dcbnl_skb);
err_out:
ret = -EINVAL;
return ret;
u8 value_byte;
u32 value_int;
- if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg
- || !netdev->dcbnl_ops->setbcnrp)
+ if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg ||
+ !netdev->dcbnl_ops->setbcnrp)
return ret;
ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX,
data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte);
}
- for (i = DCB_BCN_ATTR_ALPHA; i <= DCB_BCN_ATTR_RI; i++) {
+ for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
if (data[i] == NULL)
continue;
value_int = nla_get_u32(data[i]);
u32 pid = skb ? NETLINK_CB(skb).pid : 0;
int ret = -EINVAL;
- if (net != &init_net)
+ if (!net_eq(net, &init_net))
return -EINVAL;
ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
nlh->nlmsg_flags);
goto out;
+ case DCB_CMD_GAPP:
+ ret = dcbnl_getapp(netdev, tb, pid, nlh->nlmsg_seq,
+ nlh->nlmsg_flags);
+ goto out;
+ case DCB_CMD_SAPP:
+ ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq,
+ nlh->nlmsg_flags);
+ goto out;
default:
goto errout;
}