diff options
Diffstat (limited to 'net/dcb/dcbnl.c')
-rw-r--r-- | net/dcb/dcbnl.c | 1168 |
1 files changed, 398 insertions, 770 deletions
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 656c7c75b19..81f2bb62dea 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -28,8 +28,7 @@ #include <linux/module.h> #include <net/sock.h> -/** - * Data Center Bridging (DCB) is a collection of Ethernet enhancements +/* Data Center Bridging (DCB) is a collection of Ethernet enhancements * intended to allow network traffic with differing requirements * (highly reliable, no drops vs. best effort vs. low latency) to operate * and co-exist on Ethernet. Current DCB features are: @@ -196,92 +195,66 @@ static const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = { static LIST_HEAD(dcb_app_list); static DEFINE_SPINLOCK(dcb_lock); -/* standard netlink reply call */ -static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, - u32 seq, u16 flags) +static struct sk_buff *dcbnl_newmsg(int type, u8 cmd, u32 port, u32 seq, + u32 flags, struct nlmsghdr **nlhp) { - struct sk_buff *dcbnl_skb; + struct sk_buff *skb; struct dcbmsg *dcb; struct nlmsghdr *nlh; - int ret = -EINVAL; - dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!dcbnl_skb) - return ret; + skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!skb) + return NULL; - nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags); + nlh = nlmsg_put(skb, port, seq, type, sizeof(*dcb), flags); + BUG_ON(!nlh); - dcb = NLMSG_DATA(nlh); + dcb = nlmsg_data(nlh); dcb->dcb_family = AF_UNSPEC; dcb->cmd = cmd; dcb->dcb_pad = 0; - ret = nla_put_u8(dcbnl_skb, attr, value); - if (ret) - goto err; + if (nlhp) + *nlhp = nlh; - /* end the message, assign the nlmsg_len. */ - nlmsg_end(dcbnl_skb, nlh); - ret = rtnl_unicast(dcbnl_skb, &init_net, pid); - if (ret) - return -EINVAL; - - return 0; -nlmsg_failure: -err: - kfree_skb(dcbnl_skb); - return ret; + return skb; } -static int dcbnl_getstate(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_getstate(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - int ret = -EINVAL; - /* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */ if (!netdev->dcbnl_ops->getstate) - return ret; - - ret = dcbnl_reply(netdev->dcbnl_ops->getstate(netdev), RTM_GETDCB, - DCB_CMD_GSTATE, DCB_ATTR_STATE, pid, seq, flags); + return -EOPNOTSUPP; - return ret; + return nla_put_u8(skb, DCB_ATTR_STATE, + netdev->dcbnl_ops->getstate(netdev)); } -static int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_getpfccfg(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - struct sk_buff *dcbnl_skb; - struct nlmsghdr *nlh; - struct dcbmsg *dcb; struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest; u8 value; - int ret = -EINVAL; + int ret; int i; int getall = 0; - if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->getpfccfg) - return ret; + if (!tb[DCB_ATTR_PFC_CFG]) + return -EINVAL; + + if (!netdev->dcbnl_ops->getpfccfg) + return -EOPNOTSUPP; ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, tb[DCB_ATTR_PFC_CFG], dcbnl_pfc_up_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_PFC_GCFG; + return ret; - nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG); + nest = nla_nest_start(skb, DCB_ATTR_PFC_CFG); if (!nest) - goto err; + return -EMSGSIZE; if (data[DCB_PFC_UP_ATTR_ALL]) getall = 1; @@ -292,103 +265,53 @@ static int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb, netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value); - ret = nla_put_u8(dcbnl_skb, i, value); - + ret = nla_put_u8(skb, i, value); if (ret) { - nla_nest_cancel(dcbnl_skb, nest); - goto err; + nla_nest_cancel(skb, nest); + return ret; } } - nla_nest_end(dcbnl_skb, nest); - - nlmsg_end(dcbnl_skb, nlh); - - ret = rtnl_unicast(dcbnl_skb, &init_net, pid); - if (ret) - goto err_out; + nla_nest_end(skb, nest); return 0; -nlmsg_failure: -err: - kfree_skb(dcbnl_skb); -err_out: - return -EINVAL; } -static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - struct sk_buff *dcbnl_skb; - struct nlmsghdr *nlh; - struct dcbmsg *dcb; u8 perm_addr[MAX_ADDR_LEN]; - int ret = -EINVAL; if (!netdev->dcbnl_ops->getpermhwaddr) - return ret; - - 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_GPERM_HWADDR; + return -EOPNOTSUPP; netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr); - ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), - perm_addr); - - nlmsg_end(dcbnl_skb, nlh); - - ret = rtnl_unicast(dcbnl_skb, &init_net, pid); - if (ret) - goto err_out; - - return 0; - -nlmsg_failure: - kfree_skb(dcbnl_skb); -err_out: - return -EINVAL; + return nla_put(skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), perm_addr); } -static int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_getcap(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - 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 ret; int i; int getall = 0; - if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap) - return ret; + if (!tb[DCB_ATTR_CAP]) + return -EINVAL; + + if (!netdev->dcbnl_ops->getcap) + return -EOPNOTSUPP; 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; + return ret; - nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP); + nest = nla_nest_start(skb, DCB_ATTR_CAP); if (!nest) - goto err; + return -EMSGSIZE; if (data[DCB_CAP_ATTR_ALL]) getall = 1; @@ -398,69 +321,41 @@ static int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb, continue; if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) { - ret = nla_put_u8(dcbnl_skb, i, value); - + ret = nla_put_u8(skb, i, value); if (ret) { - nla_nest_cancel(dcbnl_skb, nest); - goto err; + nla_nest_cancel(skb, nest); + return ret; } } } - nla_nest_end(dcbnl_skb, nest); - - nlmsg_end(dcbnl_skb, nlh); - - ret = rtnl_unicast(dcbnl_skb, &init_net, pid); - if (ret) - goto err_out; + nla_nest_end(skb, nest); return 0; -nlmsg_failure: -err: - kfree_skb(dcbnl_skb); -err_out: - return -EINVAL; } -static int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_getnumtcs(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - struct sk_buff *dcbnl_skb; - struct nlmsghdr *nlh; - struct dcbmsg *dcb; struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest; u8 value; - int ret = -EINVAL; + int ret; int i; int getall = 0; - if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs) - return ret; + if (!tb[DCB_ATTR_NUMTCS]) + return -EINVAL; + + if (!netdev->dcbnl_ops->getnumtcs) + return -EOPNOTSUPP; ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], dcbnl_numtcs_nest); - if (ret) { - ret = -EINVAL; - goto err_out; - } - - dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!dcbnl_skb) { - ret = -EINVAL; - 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_GNUMTCS; + if (ret) + return ret; - nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS); - if (!nest) { - ret = -EINVAL; - goto err; - } + nest = nla_nest_start(skb, DCB_ATTR_NUMTCS); + if (!nest) + return -EMSGSIZE; if (data[DCB_NUMTCS_ATTR_ALL]) getall = 1; @@ -471,53 +366,37 @@ static int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb, ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value); if (!ret) { - ret = nla_put_u8(dcbnl_skb, i, value); - + ret = nla_put_u8(skb, i, value); if (ret) { - nla_nest_cancel(dcbnl_skb, nest); - ret = -EINVAL; - goto err; + nla_nest_cancel(skb, nest); + return ret; } - } else { - goto err; - } - } - nla_nest_end(dcbnl_skb, nest); - - nlmsg_end(dcbnl_skb, nlh); - - ret = rtnl_unicast(dcbnl_skb, &init_net, pid); - if (ret) { - ret = -EINVAL; - goto err_out; + } else + return -EINVAL; } + nla_nest_end(skb, nest); return 0; -nlmsg_failure: -err: - kfree_skb(dcbnl_skb); -err_out: - return ret; } -static int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_setnumtcs(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1]; - int ret = -EINVAL; + int ret; u8 value; int i; - if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setnumtcs) - return ret; + if (!tb[DCB_ATTR_NUMTCS]) + return -EINVAL; + + if (!netdev->dcbnl_ops->setnumtcs) + return -EOPNOTSUPP; ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], dcbnl_numtcs_nest); - - if (ret) { - ret = -EINVAL; - goto err; - } + if (ret) + return ret; for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { if (data[i] == NULL) @@ -526,84 +405,68 @@ static int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb, value = nla_get_u8(data[i]); ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value); - if (ret) - goto operr; + break; } -operr: - ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS, - DCB_ATTR_NUMTCS, pid, seq, flags); - -err: - return ret; + return nla_put_u8(skb, DCB_ATTR_NUMTCS, !!ret); } -static int dcbnl_getpfcstate(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_getpfcstate(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - int ret = -EINVAL; - if (!netdev->dcbnl_ops->getpfcstate) - return ret; - - ret = dcbnl_reply(netdev->dcbnl_ops->getpfcstate(netdev), RTM_GETDCB, - DCB_CMD_PFC_GSTATE, DCB_ATTR_PFC_STATE, - pid, seq, flags); + return -EOPNOTSUPP; - return ret; + return nla_put_u8(skb, DCB_ATTR_PFC_STATE, + netdev->dcbnl_ops->getpfcstate(netdev)); } -static int dcbnl_setpfcstate(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_setpfcstate(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - int ret = -EINVAL; u8 value; - if (!tb[DCB_ATTR_PFC_STATE] || !netdev->dcbnl_ops->setpfcstate) - return ret; + if (!tb[DCB_ATTR_PFC_STATE]) + return -EINVAL; + + if (!netdev->dcbnl_ops->setpfcstate) + return -EOPNOTSUPP; value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]); netdev->dcbnl_ops->setpfcstate(netdev, value); - ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SSTATE, DCB_ATTR_PFC_STATE, - pid, seq, flags); - - return ret; + return nla_put_u8(skb, DCB_ATTR_PFC_STATE, 0); } -static int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_getapp(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - 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; + int ret; if (!tb[DCB_ATTR_APP]) - goto out; + return -EINVAL; ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], dcbnl_app_nest); if (ret) - goto out; + return ret; - ret = -EINVAL; /* all must be non-null */ if ((!app_tb[DCB_APP_ATTR_IDTYPE]) || (!app_tb[DCB_APP_ATTR_ID])) - goto out; + return -EINVAL; /* 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; + return -EINVAL; id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); @@ -617,138 +480,106 @@ static int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb, up = dcb_getapp(netdev, &app); } - /* 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); + app_nest = nla_nest_start(skb, DCB_ATTR_APP); if (!app_nest) - goto out_cancel; + return -EMSGSIZE; - ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype); + ret = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE, idtype); if (ret) goto out_cancel; - ret = nla_put_u16(dcbnl_skb, DCB_APP_ATTR_ID, id); + ret = nla_put_u16(skb, DCB_APP_ATTR_ID, id); if (ret) goto out_cancel; - ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_PRIORITY, up); + ret = nla_put_u8(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; + nla_nest_end(skb, app_nest); - goto out; + return 0; out_cancel: - nla_nest_cancel(dcbnl_skb, app_nest); -nlmsg_failure: - kfree_skb(dcbnl_skb); -out: + nla_nest_cancel(skb, app_nest); return ret; } -static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_setapp(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - int err, ret = -EINVAL; + int ret; u16 id; u8 up, idtype; struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; if (!tb[DCB_ATTR_APP]) - goto out; + return -EINVAL; ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], dcbnl_app_nest); if (ret) - goto out; + return ret; - 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; + return -EINVAL; /* 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; + return -EINVAL; id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]); if (netdev->dcbnl_ops->setapp) { - err = netdev->dcbnl_ops->setapp(netdev, idtype, id, up); + ret = netdev->dcbnl_ops->setapp(netdev, idtype, id, up); } else { struct dcb_app app; app.selector = idtype; app.protocol = id; app.priority = up; - err = dcb_setapp(netdev, &app); + ret = dcb_setapp(netdev, &app); } - ret = dcbnl_reply(err, RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP, - pid, seq, flags); + ret = nla_put_u8(skb, DCB_ATTR_APP, ret); dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SAPP, seq, 0); -out: + return ret; } -static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags, int dir) +static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, + struct nlattr **tb, struct sk_buff *skb, int dir) { - struct sk_buff *dcbnl_skb; - struct nlmsghdr *nlh; - struct dcbmsg *dcb; struct nlattr *pg_nest, *param_nest, *data; struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; u8 prio, pgid, tc_pct, up_map; - int ret = -EINVAL; + int ret; int getall = 0; int i; - if (!tb[DCB_ATTR_PG_CFG] || - !netdev->dcbnl_ops->getpgtccfgtx || + if (!tb[DCB_ATTR_PG_CFG]) + return -EINVAL; + + if (!netdev->dcbnl_ops->getpgtccfgtx || !netdev->dcbnl_ops->getpgtccfgrx || !netdev->dcbnl_ops->getpgbwgcfgtx || !netdev->dcbnl_ops->getpgbwgcfgrx) - return ret; + return -EOPNOTSUPP; ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, tb[DCB_ATTR_PG_CFG], dcbnl_pg_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 = (dir) ? DCB_CMD_PGRX_GCFG : DCB_CMD_PGTX_GCFG; + return ret; - pg_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PG_CFG); + pg_nest = nla_nest_start(skb, DCB_ATTR_PG_CFG); if (!pg_nest) - goto err; + return -EMSGSIZE; if (pg_tb[DCB_PG_ATTR_TC_ALL]) getall = 1; @@ -766,7 +597,7 @@ static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, if (ret) goto err_pg; - param_nest = nla_nest_start(dcbnl_skb, i); + param_nest = nla_nest_start(skb, i); if (!param_nest) goto err_pg; @@ -789,33 +620,33 @@ static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, if (param_tb[DCB_TC_ATTR_PARAM_PGID] || param_tb[DCB_TC_ATTR_PARAM_ALL]) { - ret = nla_put_u8(dcbnl_skb, + ret = nla_put_u8(skb, DCB_TC_ATTR_PARAM_PGID, pgid); if (ret) goto err_param; } if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] || param_tb[DCB_TC_ATTR_PARAM_ALL]) { - ret = nla_put_u8(dcbnl_skb, + ret = nla_put_u8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map); if (ret) goto err_param; } if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] || param_tb[DCB_TC_ATTR_PARAM_ALL]) { - ret = nla_put_u8(dcbnl_skb, + ret = nla_put_u8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio); if (ret) goto err_param; } if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] || param_tb[DCB_TC_ATTR_PARAM_ALL]) { - ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_BW_PCT, + ret = nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct); if (ret) goto err_param; } - nla_nest_end(dcbnl_skb, param_nest); + nla_nest_end(skb, param_nest); } if (pg_tb[DCB_PG_ATTR_BW_ID_ALL]) @@ -838,80 +669,71 @@ static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, netdev->dcbnl_ops->getpgbwgcfgtx(netdev, i - DCB_PG_ATTR_BW_ID_0, &tc_pct); } - ret = nla_put_u8(dcbnl_skb, i, tc_pct); - + ret = nla_put_u8(skb, i, tc_pct); if (ret) goto err_pg; } - nla_nest_end(dcbnl_skb, pg_nest); - - nlmsg_end(dcbnl_skb, nlh); - - ret = rtnl_unicast(dcbnl_skb, &init_net, pid); - if (ret) - goto err_out; + nla_nest_end(skb, pg_nest); return 0; err_param: - nla_nest_cancel(dcbnl_skb, param_nest); + nla_nest_cancel(skb, param_nest); err_pg: - nla_nest_cancel(dcbnl_skb, pg_nest); -nlmsg_failure: -err: - kfree_skb(dcbnl_skb); -err_out: - ret = -EINVAL; - return ret; + nla_nest_cancel(skb, pg_nest); + + return -EMSGSIZE; } -static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 0); + return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 0); } -static int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 1); + return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 1); } -static int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_setstate(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - int ret = -EINVAL; u8 value; - if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate) - return ret; + if (!tb[DCB_ATTR_STATE]) + return -EINVAL; - value = nla_get_u8(tb[DCB_ATTR_STATE]); + if (!netdev->dcbnl_ops->setstate) + return -EOPNOTSUPP; - ret = dcbnl_reply(netdev->dcbnl_ops->setstate(netdev, value), - RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE, - pid, seq, flags); + value = nla_get_u8(tb[DCB_ATTR_STATE]); - return ret; + return nla_put_u8(skb, DCB_ATTR_STATE, + netdev->dcbnl_ops->setstate(netdev, value)); } -static int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_setpfccfg(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1]; int i; - int ret = -EINVAL; + int ret; u8 value; - if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->setpfccfg) - return ret; + if (!tb[DCB_ATTR_PFC_CFG]) + return -EINVAL; + + if (!netdev->dcbnl_ops->setpfccfg) + return -EOPNOTSUPP; ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, tb[DCB_ATTR_PFC_CFG], dcbnl_pfc_up_nest); if (ret) - goto err; + return ret; for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { if (data[i] == NULL) @@ -921,50 +743,53 @@ static int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb, data[i]->nla_type - DCB_PFC_UP_ATTR_0, value); } - ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SCFG, DCB_ATTR_PFC_CFG, - pid, seq, flags); -err: - return ret; + return nla_put_u8(skb, DCB_ATTR_PFC_CFG, 0); } -static int dcbnl_setall(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_setall(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - int ret = -EINVAL; + int ret; - if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall) - return ret; + if (!tb[DCB_ATTR_SET_ALL]) + return -EINVAL; + + if (!netdev->dcbnl_ops->setall) + return -EOPNOTSUPP; - ret = dcbnl_reply(netdev->dcbnl_ops->setall(netdev), RTM_SETDCB, - DCB_CMD_SET_ALL, DCB_ATTR_SET_ALL, pid, seq, flags); + ret = nla_put_u8(skb, DCB_ATTR_SET_ALL, + netdev->dcbnl_ops->setall(netdev)); dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SET_ALL, seq, 0); return ret; } -static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags, int dir) +static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb, + int dir) { struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; - int ret = -EINVAL; + int ret; int i; u8 pgid; u8 up_map; u8 prio; u8 tc_pct; - if (!tb[DCB_ATTR_PG_CFG] || - !netdev->dcbnl_ops->setpgtccfgtx || + if (!tb[DCB_ATTR_PG_CFG]) + return -EINVAL; + + if (!netdev->dcbnl_ops->setpgtccfgtx || !netdev->dcbnl_ops->setpgtccfgrx || !netdev->dcbnl_ops->setpgbwgcfgtx || !netdev->dcbnl_ops->setpgbwgcfgrx) - return ret; + return -EOPNOTSUPP; ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest); if (ret) - goto err; + return ret; for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { if (!pg_tb[i]) @@ -973,7 +798,7 @@ static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb, ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX, pg_tb[i], dcbnl_tc_param_nest); if (ret) - goto err; + return ret; pgid = DCB_ATTR_VALUE_UNDEFINED; prio = DCB_ATTR_VALUE_UNDEFINED; @@ -1026,63 +851,47 @@ static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb, } } - ret = dcbnl_reply(0, RTM_SETDCB, - (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG), - DCB_ATTR_PG_CFG, pid, seq, flags); - -err: - return ret; + return nla_put_u8(skb, DCB_ATTR_PG_CFG, 0); } -static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 0); + return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 0); } -static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1); + return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 1); } -static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { - struct sk_buff *dcbnl_skb; - struct nlmsghdr *nlh; - struct dcbmsg *dcb; struct nlattr *bcn_nest; struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1]; u8 value_byte; u32 value_integer; - int ret = -EINVAL; + int ret; bool getall = false; int i; - if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->getbcnrp || + if (!tb[DCB_ATTR_BCN]) + return -EINVAL; + + if (!netdev->dcbnl_ops->getbcnrp || !netdev->dcbnl_ops->getbcncfg) - return ret; + return -EOPNOTSUPP; ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX, tb[DCB_ATTR_BCN], dcbnl_bcn_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_BCN_GCFG; + return ret; - bcn_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_BCN); + bcn_nest = nla_nest_start(skb, DCB_ATTR_BCN); if (!bcn_nest) - goto err; + return -EMSGSIZE; if (bcn_tb[DCB_BCN_ATTR_ALL]) getall = true; @@ -1093,7 +902,7 @@ static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb, netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0, &value_byte); - ret = nla_put_u8(dcbnl_skb, i, value_byte); + ret = nla_put_u8(skb, i, value_byte); if (ret) goto err_bcn; } @@ -1104,49 +913,41 @@ static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb, netdev->dcbnl_ops->getbcncfg(netdev, i, &value_integer); - ret = nla_put_u32(dcbnl_skb, i, value_integer); + ret = nla_put_u32(skb, i, value_integer); if (ret) goto err_bcn; } - nla_nest_end(dcbnl_skb, bcn_nest); - - nlmsg_end(dcbnl_skb, nlh); - - ret = rtnl_unicast(dcbnl_skb, &init_net, pid); - if (ret) - goto err_out; + nla_nest_end(skb, bcn_nest); return 0; err_bcn: - nla_nest_cancel(dcbnl_skb, bcn_nest); -nlmsg_failure: -err: - kfree_skb(dcbnl_skb); -err_out: - ret = -EINVAL; + nla_nest_cancel(skb, bcn_nest); return ret; } -static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlattr **tb, - u32 pid, u32 seq, u16 flags) +static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) { struct nlattr *data[DCB_BCN_ATTR_MAX + 1]; int i; - int ret = -EINVAL; + int ret; u8 value_byte; u32 value_int; - if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg || + if (!tb[DCB_ATTR_BCN]) + return -EINVAL; + + if (!netdev->dcbnl_ops->setbcncfg || !netdev->dcbnl_ops->setbcnrp) - return ret; + return -EOPNOTSUPP; ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX, tb[DCB_ATTR_BCN], dcbnl_pfc_up_nest); if (ret) - goto err; + return ret; for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) { if (data[i] == NULL) @@ -1164,10 +965,7 @@ static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlattr **tb, i, value_int); } - ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_BCN_SCFG, DCB_ATTR_BCN, - pid, seq, flags); -err: - return ret; + return nla_put_u8(skb, DCB_ATTR_BCN, 0); } static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb, @@ -1233,20 +1031,21 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) struct dcb_app_type *itr; const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; int dcbx; - int err = -EMSGSIZE; + int err; if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name)) - goto nla_put_failure; + return -EMSGSIZE; + ieee = nla_nest_start(skb, DCB_ATTR_IEEE); if (!ieee) - goto nla_put_failure; + return -EMSGSIZE; if (ops->ieee_getets) { struct ieee_ets ets; err = ops->ieee_getets(netdev, &ets); if (!err && nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets)) - goto nla_put_failure; + return -EMSGSIZE; } if (ops->ieee_getmaxrate) { @@ -1256,7 +1055,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE, sizeof(maxrate), &maxrate); if (err) - goto nla_put_failure; + return -EMSGSIZE; } } @@ -1265,12 +1064,12 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) err = ops->ieee_getpfc(netdev, &pfc); if (!err && nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc)) - goto nla_put_failure; + return -EMSGSIZE; } app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE); if (!app) - goto nla_put_failure; + return -EMSGSIZE; spin_lock(&dcb_lock); list_for_each_entry(itr, &dcb_app_list, list) { @@ -1279,7 +1078,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) &itr->app); if (err) { spin_unlock(&dcb_lock); - goto nla_put_failure; + return -EMSGSIZE; } } } @@ -1298,7 +1097,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) err = ops->ieee_peer_getets(netdev, &ets); if (!err && nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets)) - goto nla_put_failure; + return -EMSGSIZE; } if (ops->ieee_peer_getpfc) { @@ -1306,7 +1105,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) err = ops->ieee_peer_getpfc(netdev, &pfc); if (!err && nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc)) - goto nla_put_failure; + return -EMSGSIZE; } if (ops->peer_getappinfo && ops->peer_getapptable) { @@ -1315,20 +1114,17 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) DCB_ATTR_IEEE_APP_UNSPEC, DCB_ATTR_IEEE_APP); if (err) - goto nla_put_failure; + return -EMSGSIZE; } nla_nest_end(skb, ieee); if (dcbx >= 0) { err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx); if (err) - goto nla_put_failure; + return -EMSGSIZE; } return 0; - -nla_put_failure: - return err; } static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev, @@ -1340,13 +1136,13 @@ static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev, struct nlattr *pg = nla_nest_start(skb, i); if (!pg) - goto nla_put_failure; + return -EMSGSIZE; for (i = DCB_PG_ATTR_TC_0; i <= D |