From 3e29027af43728c2a91fe3f735ab2822edaf54a8 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Thu, 30 Dec 2010 09:25:46 +0000 Subject: dcbnl: add support for ieee8021Qaz attributes The IEEE8021Qaz is the IEEE standard version of CEE. The standard has had enough significant changes from the CEE version that many of the CEE attributes have no meaning in the new spec or do not easily map to IEEE standards. Rather then attempt to create a complicated mapping between CEE and IEEE standards this patch adds a nested IEEE attribute to the list of DCB attributes. The policy is, [DCB_ATTR_IFNAME] [DCB_ATTR_STATE] ... [DCB_ATTR_IEEE] [DCB_ATTR_IEEE_ETS] [DCB_ATTR_IEEE_PFC] [DCB_ATTR_IEEE_APP_TABLE] [DCB_ATTR_IEEE_APP] ... The following dcbnl_rtnl_ops routines were added to handle the IEEE standard, int (*ieee_getets) (struct net_device *, struct ieee_ets *); int (*ieee_setets) (struct net_device *, struct ieee_ets *); int (*ieee_getpfc) (struct net_device *, struct ieee_pfc *); int (*ieee_setpfc) (struct net_device *, struct ieee_pfc *); int (*ieee_getapp) (struct net_device *, struct dcb_app *); int (*ieee_setapp) (struct net_device *, struct dcb_app *); Signed-off-by: John Fastabend Signed-off-by: David S. Miller --- net/dcb/dcbnl.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) (limited to 'net/dcb/dcbnl.c') diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 19ac2b985485..2ff908498924 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -66,6 +66,7 @@ static const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { [DCB_ATTR_PFC_STATE] = {.type = NLA_U8}, [DCB_ATTR_BCN] = {.type = NLA_NESTED}, [DCB_ATTR_APP] = {.type = NLA_NESTED}, + [DCB_ATTR_IEEE] = {.type = NLA_NESTED}, }; /* DCB priority flow control to User Priority nested attributes */ @@ -167,6 +168,17 @@ static const struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = { [DCB_APP_ATTR_PRIORITY] = {.type = NLA_U8}, }; +/* IEEE 802.1Qaz nested attributes. */ +static const struct nla_policy dcbnl_ieee_policy[DCB_ATTR_IEEE_MAX + 1] = { + [DCB_ATTR_IEEE_ETS] = {.len = sizeof(struct ieee_ets)}, + [DCB_ATTR_IEEE_PFC] = {.len = sizeof(struct ieee_pfc)}, + [DCB_ATTR_IEEE_APP_TABLE] = {.type = NLA_NESTED}, +}; + +static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = { + [DCB_ATTR_IEEE_APP] = {.len = sizeof(struct dcb_app)}, +}; + /* standard netlink reply call */ static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, u32 seq, u16 flags) @@ -1118,6 +1130,117 @@ err: return ret; } +/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not + * be completed the entire msg is aborted and error value is returned. + * No attempt is made to reconcile the case where only part of the + * cmd can be completed. + */ +static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) +{ + const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; + struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1]; + int err = -EOPNOTSUPP; + + if (!ops) + goto err; + + err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX, + tb[DCB_ATTR_IEEE], dcbnl_ieee_policy); + if (err) + goto err; + + if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) { + struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]); + err = ops->ieee_setets(netdev, ets); + if (err) + goto err; + } + + if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setets) { + struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]); + err = ops->ieee_setpfc(netdev, pfc); + if (err) + goto err; + } + + if (ieee[DCB_ATTR_IEEE_APP_TABLE] && ops->ieee_setapp) { + struct nlattr *attr; + int rem; + + nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) { + struct dcb_app *app_data; + if (nla_type(attr) != DCB_ATTR_IEEE_APP) + continue; + app_data = nla_data(attr); + err = ops->ieee_setapp(netdev, app_data); + if (err) + goto err; + } + } + +err: + dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE, + pid, seq, flags); + return err; +} + + +/* Handle IEEE 802.1Qaz GET commands. */ +static int dcbnl_ieee_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 *ieee; + 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_IEEE_GET; + + NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name); + + ieee = nla_nest_start(skb, DCB_ATTR_IEEE); + if (!ieee) + goto nla_put_failure; + + 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); + } + + if (ops->ieee_getpfc) { + struct ieee_pfc pfc; + err = ops->ieee_getpfc(netdev, &pfc); + if (!err) + NLA_PUT(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc); + } + + nla_nest_end(skb, ieee); + 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); @@ -1223,6 +1346,14 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq, nlh->nlmsg_flags); goto out; + case DCB_CMD_IEEE_SET: + ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_IEEE_GET: + ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; default: goto errout; } -- cgit v1.2.3 From 9ab933ab2cc80f04690d6aa385b1110075c5e507 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Thu, 30 Dec 2010 09:26:31 +0000 Subject: dcbnl: add appliction tlv handlers This patch adds application tlv handlers. Networking stacks may use the application priority to set the skb priority of their stack using the negoatiated dcbx priority. This patch provides the dcb_{get|set}app() routines for the stack to query these parameters. Notice lower layer drivers can use the dcbnl_ops routines if additional handling is needed. Perhaps in the firmware case for example Signed-off-by: John Fastabend Signed-off-by: Shmulik Ravid Signed-off-by: David S. Miller --- include/linux/dcbnl.h | 4 +- include/net/dcbnl.h | 9 ++++ net/dcb/dcbnl.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 135 insertions(+), 11 deletions(-) (limited to 'net/dcb/dcbnl.c') diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h index 287b5618e296..775bdb4465bf 100644 --- a/include/linux/dcbnl.h +++ b/include/linux/dcbnl.h @@ -82,7 +82,9 @@ struct ieee_pfc { __u64 indications[IEEE_8021QAZ_MAX_TCS]; }; -/* This structure contains the IEEE 802.1Qaz APP managed object +/* This structure contains the IEEE 802.1Qaz APP managed object. This + * object is also used for the CEE std as well. There is no difference + * between the objects. * * @selector: protocol identifier type * @protocol: protocol of type indicated diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h index e2d841e963b3..ab7d623a2793 100644 --- a/include/net/dcbnl.h +++ b/include/net/dcbnl.h @@ -22,6 +22,15 @@ #include +struct dcb_app_type { + char name[IFNAMSIZ]; + struct dcb_app app; + struct list_head list; +}; + +u8 dcb_setapp(struct net_device *, struct dcb_app *); +u8 dcb_getapp(struct net_device *, struct dcb_app *); + /* * Ops struct for the netlink callbacks. Used by DCB-enabled drivers through * the netdevice struct. diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 2ff908498924..cfd731faf6c6 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -179,6 +179,9 @@ static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = { [DCB_ATTR_IEEE_APP] = {.len = sizeof(struct dcb_app)}, }; +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) @@ -634,12 +637,12 @@ out: static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb, u32 pid, u32 seq, u16 flags) { - int ret = -EINVAL; + int err, 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) + if (!tb[DCB_ATTR_APP]) goto out; ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], @@ -663,9 +666,18 @@ static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb, 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); + if (netdev->dcbnl_ops->setapp) { + err = 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 = dcbnl_reply(err, RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP, + pid, seq, flags); out: return ret; } @@ -1164,7 +1176,7 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb, goto err; } - if (ieee[DCB_ATTR_IEEE_APP_TABLE] && ops->ieee_setapp) { + if (ieee[DCB_ATTR_IEEE_APP_TABLE]) { struct nlattr *attr; int rem; @@ -1173,7 +1185,10 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb, if (nla_type(attr) != DCB_ATTR_IEEE_APP) continue; app_data = nla_data(attr); - err = ops->ieee_setapp(netdev, app_data); + if (ops->ieee_setapp) + err = ops->ieee_setapp(netdev, app_data); + else + err = dcb_setapp(netdev, app_data); if (err) goto err; } @@ -1193,7 +1208,8 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, struct sk_buff *skb; struct nlmsghdr *nlh; struct dcbmsg *dcb; - struct nlattr *ieee; + struct nlattr *ieee, *app; + struct dcb_app_type *itr; const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; int err; @@ -1230,6 +1246,19 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, NLA_PUT(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc); } + app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE); + if (!app) + goto nla_put_failure; + + spin_lock(&dcb_lock); + list_for_each_entry(itr, &dcb_app_list, list) { + if (strncmp(itr->name, netdev->name, IFNAMSIZ) == 0) + NLA_PUT(skb, DCB_ATTR_IEEE_APP, + sizeof(itr->app), &itr->app); + } + spin_unlock(&dcb_lock); + nla_nest_end(skb, app); + nla_nest_end(skb, ieee); nlmsg_end(skb, nlh); @@ -1364,8 +1393,93 @@ out: return ret; } +/** + * dcb_getapp - retrieve the DCBX application user priority + * + * On success returns a non-zero 802.1p user priority bitmap + * otherwise returns 0 as the invalid user priority bitmap to + * indicate an error. + */ +u8 dcb_getapp(struct net_device *dev, struct dcb_app *app) +{ + struct dcb_app_type *itr; + u8 prio = 0; + + spin_lock(&dcb_lock); + list_for_each_entry(itr, &dcb_app_list, list) { + if (itr->app.selector == app->selector && + itr->app.protocol == app->protocol && + (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) { + prio = itr->app.priority; + break; + } + } + spin_unlock(&dcb_lock); + + return prio; +} +EXPORT_SYMBOL(dcb_getapp); + +/** + * ixgbe_dcbnl_setapp - add dcb application data to app list + * + * Priority 0 is the default priority this removes applications + * from the app list if the priority is set to zero. + */ +u8 dcb_setapp(struct net_device *dev, struct dcb_app *new) +{ + struct dcb_app_type *itr; + + spin_lock(&dcb_lock); + /* Search for existing match and replace */ + list_for_each_entry(itr, &dcb_app_list, list) { + if (itr->app.selector == new->selector && + itr->app.protocol == new->protocol && + (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) { + if (new->priority) + itr->app.priority = new->priority; + else { + list_del(&itr->list); + kfree(itr); + } + goto out; + } + } + /* App type does not exist add new application type */ + if (new->priority) { + struct dcb_app_type *entry; + entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC); + if (!entry) { + spin_unlock(&dcb_lock); + return -ENOMEM; + } + + memcpy(&entry->app, new, sizeof(*new)); + strncpy(entry->name, dev->name, IFNAMSIZ); + list_add(&entry->list, &dcb_app_list); + } +out: + spin_unlock(&dcb_lock); + return 0; +} +EXPORT_SYMBOL(dcb_setapp); + +void dcb_flushapp(void) +{ + struct dcb_app_type *app; + + spin_lock(&dcb_lock); + list_for_each_entry(app, &dcb_app_list, list) { + list_del(&app->list); + kfree(app); + } + spin_unlock(&dcb_lock); +} + static int __init dcbnl_init(void) { + INIT_LIST_HEAD(&dcb_app_list); + rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL); rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL); @@ -1377,7 +1491,6 @@ static void __exit dcbnl_exit(void) { rtnl_unregister(PF_UNSPEC, RTM_GETDCB); rtnl_unregister(PF_UNSPEC, RTM_SETDCB); + dcb_flushapp(); } module_exit(dcbnl_exit); - - -- cgit v1.2.3 From 96b99684e365f28d49bdb1221ca022b75cb91a98 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Thu, 30 Dec 2010 09:26:37 +0000 Subject: net_dcb: add application notifiers DCBx applications priorities can be changed dynamically. If application stacks are expected to keep the skb priority consistent with the dcbx priority the stack will need to be notified when these changes occur. This patch adds application notifiers for the stack to register with. Signed-off-by: John Fastabend Signed-off-by: David S. Miller --- include/net/dcbevent.h | 31 +++++++++++++++++++++++++++++++ net/dcb/Makefile | 2 +- net/dcb/dcbevent.c | 40 ++++++++++++++++++++++++++++++++++++++++ net/dcb/dcbnl.c | 2 ++ 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 include/net/dcbevent.h create mode 100644 net/dcb/dcbevent.c (limited to 'net/dcb/dcbnl.c') diff --git a/include/net/dcbevent.h b/include/net/dcbevent.h new file mode 100644 index 000000000000..bc1e7ef40171 --- /dev/null +++ b/include/net/dcbevent.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Author: John Fastabend + */ + +#ifndef _DCB_EVENT_H +#define _DCB_EVENT_H + +enum dcbevent_notif_type { + DCB_APP_EVENT = 1, +}; + +extern int register_dcbevent_notifier(struct notifier_block *nb); +extern int unregister_dcbevent_notifier(struct notifier_block *nb); +extern int call_dcbevent_notifiers(unsigned long val, void *v); + +#endif diff --git a/net/dcb/Makefile b/net/dcb/Makefile index 9930f4cde818..c1282c9e64fa 100644 --- a/net/dcb/Makefile +++ b/net/dcb/Makefile @@ -1 +1 @@ -obj-$(CONFIG_DCB) += dcbnl.o +obj-$(CONFIG_DCB) += dcbnl.o dcbevent.o diff --git a/net/dcb/dcbevent.c b/net/dcb/dcbevent.c new file mode 100644 index 000000000000..665a8802105a --- /dev/null +++ b/net/dcb/dcbevent.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Author: John Fastabend + */ + +#include +#include + +static ATOMIC_NOTIFIER_HEAD(dcbevent_notif_chain); + +int register_dcbevent_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&dcbevent_notif_chain, nb); +} +EXPORT_SYMBOL(register_dcbevent_notifier); + +int unregister_dcbevent_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&dcbevent_notif_chain, nb); +} +EXPORT_SYMBOL(unregister_dcbevent_notifier); + +int call_dcbevent_notifiers(unsigned long val, void *v) +{ + return atomic_notifier_call_chain(&dcbevent_notif_chain, val, v); +} diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index cfd731faf6c6..69144125fc4f 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -1460,6 +1461,7 @@ u8 dcb_setapp(struct net_device *dev, struct dcb_app *new) } out: spin_unlock(&dcb_lock); + call_dcbevent_notifiers(DCB_APP_EVENT, new); return 0; } EXPORT_SYMBOL(dcb_setapp); -- cgit v1.2.3 From 6241b6259b16aa390ff4bf50f520685b3801200b Mon Sep 17 00:00:00 2001 From: Shmulik Ravid Date: Thu, 30 Dec 2010 06:26:48 +0000 Subject: dcbnl: adding DCBX engine capability Adding an optional DCBX capability and a pair for get-set routines for setting the device DCBX mode. The DCBX capability is a bit field of supported attributes. The user is expected to set the DCBX mode with a subset of the advertised attributes. This patch is dependent on the following patches: [net-next-2.6 PATCH 1/3] dcbnl: add support for ieee8021Qaz attributes [net-next-2.6 PATCH 2/3] dcbnl: add appliction tlv handlers [net-next-2.6 PATCH 3/3] net_dcb: add application notifiers Signed-off-by: Shmulik Ravid Acked-by: John Fastabend Signed-off-by: David S. Miller --- include/linux/dcbnl.h | 43 +++++++++++++++++++++++++++++++++++++++++++ include/net/dcbnl.h | 5 +++++ net/dcb/dcbnl.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) (limited to 'net/dcb/dcbnl.c') diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h index 775bdb4465bf..16eea36d8934 100644 --- a/include/linux/dcbnl.h +++ b/include/linux/dcbnl.h @@ -135,6 +135,8 @@ struct dcbmsg { * @DCB_CMD_SAPP: set application protocol configuration * @DCB_CMD_IEEE_SET: set IEEE 802.1Qaz configuration * @DCB_CMD_IEEE_GET: get IEEE 802.1Qaz configuration + * @DCB_CMD_GDCBX: get DCBX engine configuration + * @DCB_CMD_SDCBX: set DCBX engine configuration */ enum dcbnl_commands { DCB_CMD_UNDEFINED, @@ -171,6 +173,9 @@ enum dcbnl_commands { DCB_CMD_IEEE_SET, DCB_CMD_IEEE_GET, + DCB_CMD_GDCBX, + DCB_CMD_SDCBX, + __DCB_CMD_ENUM_MAX, DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, }; @@ -191,6 +196,7 @@ enum dcbnl_commands { * @DCB_ATTR_NUMTCS: number of traffic classes supported (NLA_NESTED) * @DCB_ATTR_BCN: backward congestion notification configuration (NLA_NESTED) * @DCB_ATTR_IEEE: IEEE 802.1Qaz supported attributes (NLA_NESTED) + * @DCB_ATTR_DCBX: DCBX engine configuration in the device (NLA_U8) */ enum dcbnl_attrs { DCB_ATTR_UNDEFINED, @@ -211,6 +217,8 @@ enum dcbnl_attrs { /* IEEE std attributes */ DCB_ATTR_IEEE, + DCB_ATTR_DCBX, + __DCB_ATTR_ENUM_MAX, DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, }; @@ -370,6 +378,8 @@ enum dcbnl_tc_attrs { * @DCB_CAP_ATTR_GSP: (NLA_U8) device supports group strict priority * @DCB_CAP_ATTR_BCN: (NLA_U8) device supports Backwards Congestion * Notification + * @DCB_CAP_ATTR_DCBX: (NLA_U8) device supports DCBX engine + * */ enum dcbnl_cap_attrs { DCB_CAP_ATTR_UNDEFINED, @@ -381,11 +391,44 @@ enum dcbnl_cap_attrs { DCB_CAP_ATTR_PFC_TCS, DCB_CAP_ATTR_GSP, DCB_CAP_ATTR_BCN, + DCB_CAP_ATTR_DCBX, __DCB_CAP_ATTR_ENUM_MAX, DCB_CAP_ATTR_MAX = __DCB_CAP_ATTR_ENUM_MAX - 1, }; +/** + * DCBX capability flags + * + * @DCB_CAP_DCBX_HOST: DCBX negotiation is performed by the host LLDP agent. + * 'set' routines are used to configure the device with + * the negotiated parameters + * + * @DCB_CAP_DCBX_LLD_MANAGED: DCBX negotiation is not performed in the host but + * by another entity + * 'get' routines are used to retrieve the + * negotiated parameters + * 'set' routines can be used to set the initial + * negotiation configuration + * + * @DCB_CAP_DCBX_VER_CEE: for a non-host DCBX engine, indicates the engine + * supports the CEE protocol flavor + * + * @DCB_CAP_DCBX_VER_IEEE: for a non-host DCBX engine, indicates the engine + * supports the IEEE protocol flavor + * + * @DCB_CAP_DCBX_STATIC: for a non-host DCBX engine, indicates the engine + * supports static configuration (i.e no actual + * negotiation is performed negotiated parameters equal + * the initial configuration) + * + */ +#define DCB_CAP_DCBX_HOST 0x01 +#define DCB_CAP_DCBX_LLD_MANAGED 0x02 +#define DCB_CAP_DCBX_VER_CEE 0x04 +#define DCB_CAP_DCBX_VER_IEEE 0x08 +#define DCB_CAP_DCBX_STATIC 0x10 + /** * enum dcbnl_numtcs_attrs - number of traffic classes * diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h index ab7d623a2793..c65347b3cbbf 100644 --- a/include/net/dcbnl.h +++ b/include/net/dcbnl.h @@ -70,6 +70,11 @@ struct dcbnl_rtnl_ops { void (*setbcnrp)(struct net_device *, int, u8); u8 (*setapp)(struct net_device *, u8, u16, u8); u8 (*getapp)(struct net_device *, u8, u16); + + /* DCBX configuration */ + u8 (*getdcbx)(struct net_device *); + u8 (*setdcbx)(struct net_device *, u8); + }; #endif /* __NET_DCBNL_H__ */ diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 69144125fc4f..8f83ad859d9b 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -68,6 +68,7 @@ static const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { [DCB_ATTR_BCN] = {.type = NLA_NESTED}, [DCB_ATTR_APP] = {.type = NLA_NESTED}, [DCB_ATTR_IEEE] = {.type = NLA_NESTED}, + [DCB_ATTR_DCBX] = {.type = NLA_U8}, }; /* DCB priority flow control to User Priority nested attributes */ @@ -124,6 +125,7 @@ static const struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = { [DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8}, [DCB_CAP_ATTR_GSP] = {.type = NLA_U8}, [DCB_CAP_ATTR_BCN] = {.type = NLA_U8}, + [DCB_CAP_ATTR_DCBX] = {.type = NLA_U8}, }; /* DCB capabilities nested attributes. */ @@ -1271,6 +1273,39 @@ nlmsg_failure: return -1; } +/* DCBX configuration */ +static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) +{ + int ret = -EINVAL; + + if (!netdev->dcbnl_ops->getdcbx) + return ret; + + ret = dcbnl_reply(netdev->dcbnl_ops->getdcbx(netdev), RTM_GETDCB, + DCB_CMD_GDCBX, DCB_ATTR_DCBX, pid, seq, flags); + + return ret; +} + +static int dcbnl_setdcbx(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) +{ + int ret = -EINVAL; + u8 value; + + if (!tb[DCB_ATTR_DCBX] || !netdev->dcbnl_ops->setdcbx) + return ret; + + value = nla_get_u8(tb[DCB_ATTR_DCBX]); + + ret = dcbnl_reply(netdev->dcbnl_ops->setdcbx(netdev, value), + RTM_SETDCB, DCB_CMD_SDCBX, DCB_ATTR_DCBX, + pid, seq, flags); + + return ret; +} + static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { struct net *net = sock_net(skb->sk); @@ -1384,6 +1419,14 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq, nlh->nlmsg_flags); goto out; + case DCB_CMD_GDCBX: + ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_SDCBX: + ret = dcbnl_setdcbx(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; default: goto errout; } -- cgit v1.2.3 From ea45fe4e176a42d2396878f530cfdc8265bef37b Mon Sep 17 00:00:00 2001 From: Shmulik Ravid Date: Thu, 30 Dec 2010 06:26:55 +0000 Subject: dcbnl: adding DCBX feature flags get-set Adding a pair of set-get routines to dcbnl for setting the negotiation flags of the various DCB features. Conforms to the CEE flavor of DCBX The user sets these flags (enable, advertise, willing) for each feature to be used by the DCBX engine. The 'get' routine returns which of the features is enabled after the negotiation. This patch is dependent on the following patches: [net-next-2.6 PATCH 1/3] dcbnl: add support for ieee8021Qaz attributes [net-next-2.6 PATCH 2/3] dcbnl: add appliction tlv handlers [net-next-2.6 PATCH 3/3] net_dcb: add application notifiers Signed-off-by: Shmulik Ravid Signed-off-by: David S. Miller --- include/linux/dcbnl.h | 33 +++++++++++++ include/net/dcbnl.h | 3 ++ net/dcb/dcbnl.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+) (limited to 'net/dcb/dcbnl.c') diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h index 16eea36d8934..68cd248f6d3e 100644 --- a/include/linux/dcbnl.h +++ b/include/linux/dcbnl.h @@ -137,6 +137,8 @@ struct dcbmsg { * @DCB_CMD_IEEE_GET: get IEEE 802.1Qaz configuration * @DCB_CMD_GDCBX: get DCBX engine configuration * @DCB_CMD_SDCBX: set DCBX engine configuration + * @DCB_CMD_GFEATCFG: get DCBX features flags + * @DCB_CMD_SFEATCFG: set DCBX features negotiation flags */ enum dcbnl_commands { DCB_CMD_UNDEFINED, @@ -176,6 +178,9 @@ enum dcbnl_commands { DCB_CMD_GDCBX, DCB_CMD_SDCBX, + DCB_CMD_GFEATCFG, + DCB_CMD_SFEATCFG, + __DCB_CMD_ENUM_MAX, DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, }; @@ -197,6 +202,7 @@ enum dcbnl_commands { * @DCB_ATTR_BCN: backward congestion notification configuration (NLA_NESTED) * @DCB_ATTR_IEEE: IEEE 802.1Qaz supported attributes (NLA_NESTED) * @DCB_ATTR_DCBX: DCBX engine configuration in the device (NLA_U8) + * @DCB_ATTR_FEATCFG: DCBX features flags (NLA_NESTED) */ enum dcbnl_attrs { DCB_ATTR_UNDEFINED, @@ -218,6 +224,7 @@ enum dcbnl_attrs { DCB_ATTR_IEEE, DCB_ATTR_DCBX, + DCB_ATTR_FEATCFG, __DCB_ATTR_ENUM_MAX, DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, @@ -506,4 +513,30 @@ enum dcbnl_app_attrs { DCB_APP_ATTR_MAX = __DCB_APP_ATTR_ENUM_MAX - 1, }; +/** + * enum dcbnl_featcfg_attrs - features conifiguration flags + * + * @DCB_FEATCFG_ATTR_UNDEFINED: unspecified attribute to catch errors + * @DCB_FEATCFG_ATTR_ALL: (NLA_FLAG) all features configuration attributes + * @DCB_FEATCFG_ATTR_PG: (NLA_U8) configuration flags for priority groups + * @DCB_FEATCFG_ATTR_PFC: (NLA_U8) configuration flags for priority + * flow control + * @DCB_FEATCFG_ATTR_APP: (NLA_U8) configuration flags for application TLV + * + */ +#define DCB_FEATCFG_ERROR 0x01 /* error in feature resolution */ +#define DCB_FEATCFG_ENABLE 0x02 /* enable feature */ +#define DCB_FEATCFG_WILLING 0x04 /* feature is willing */ +#define DCB_FEATCFG_ADVERTISE 0x08 /* advertise feature */ +enum dcbnl_featcfg_attrs { + DCB_FEATCFG_ATTR_UNDEFINED, + DCB_FEATCFG_ATTR_ALL, + DCB_FEATCFG_ATTR_PG, + DCB_FEATCFG_ATTR_PFC, + DCB_FEATCFG_ATTR_APP, + + __DCB_FEATCFG_ATTR_ENUM_MAX, + DCB_FEATCFG_ATTR_MAX = __DCB_FEATCFG_ATTR_ENUM_MAX - 1, +}; + #endif /* __LINUX_DCBNL_H__ */ diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h index c65347b3cbbf..a8e7852b10ab 100644 --- a/include/net/dcbnl.h +++ b/include/net/dcbnl.h @@ -70,11 +70,14 @@ struct dcbnl_rtnl_ops { void (*setbcnrp)(struct net_device *, int, u8); u8 (*setapp)(struct net_device *, u8, u16, u8); u8 (*getapp)(struct net_device *, u8, u16); + u8 (*getfeatcfg)(struct net_device *, int, u8 *); + u8 (*setfeatcfg)(struct net_device *, int, u8); /* DCBX configuration */ u8 (*getdcbx)(struct net_device *); u8 (*setdcbx)(struct net_device *, u8); + }; #endif /* __NET_DCBNL_H__ */ diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 8f83ad859d9b..075af0a08d84 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -69,6 +69,7 @@ static const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { [DCB_ATTR_APP] = {.type = NLA_NESTED}, [DCB_ATTR_IEEE] = {.type = NLA_NESTED}, [DCB_ATTR_DCBX] = {.type = NLA_U8}, + [DCB_ATTR_FEATCFG] = {.type = NLA_NESTED}, }; /* DCB priority flow control to User Priority nested attributes */ @@ -182,6 +183,14 @@ static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = { [DCB_ATTR_IEEE_APP] = {.len = sizeof(struct dcb_app)}, }; +/* DCB number of traffic classes nested attributes. */ +static const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = { + [DCB_FEATCFG_ATTR_ALL] = {.type = NLA_FLAG}, + [DCB_FEATCFG_ATTR_PG] = {.type = NLA_U8}, + [DCB_FEATCFG_ATTR_PFC] = {.type = NLA_U8}, + [DCB_FEATCFG_ATTR_APP] = {.type = NLA_U8}, +}; + static LIST_HEAD(dcb_app_list); static DEFINE_SPINLOCK(dcb_lock); @@ -1306,6 +1315,122 @@ static int dcbnl_setdcbx(struct net_device *netdev, struct nlattr **tb, return ret; } +static int dcbnl_getfeatcfg(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_FEATCFG_ATTR_MAX + 1], *nest; + u8 value; + int ret = -EINVAL; + int i; + int getall = 0; + + if (!tb[DCB_ATTR_FEATCFG] || !netdev->dcbnl_ops->getfeatcfg) + return ret; + + ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG], + dcbnl_featcfg_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_GFEATCFG; + + nest = nla_nest_start(dcbnl_skb, DCB_ATTR_FEATCFG); + if (!nest) { + ret = -EINVAL; + goto err; + } + + if (data[DCB_FEATCFG_ATTR_ALL]) + getall = 1; + + for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) { + if (!getall && !data[i]) + continue; + + ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value); + if (!ret) { + ret = nla_put_u8(dcbnl_skb, i, value); + + if (ret) { + nla_nest_cancel(dcbnl_skb, nest); + ret = -EINVAL; + goto err; + } + } 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; + } + + return 0; +nlmsg_failure: +err: + kfree_skb(dcbnl_skb); +err_out: + return ret; +} + +static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) +{ + struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1]; + int ret = -EINVAL; + u8 value; + int i; + + if (!tb[DCB_ATTR_FEATCFG] || !netdev->dcbnl_ops->setfeatcfg) + return ret; + + ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG], + dcbnl_featcfg_nest); + + if (ret) { + ret = -EINVAL; + goto err; + } + + for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) { + if (data[i] == NULL) + continue; + + value = nla_get_u8(data[i]); + + ret = netdev->dcbnl_ops->setfeatcfg(netdev, i, value); + + if (ret) + goto operr; + } + +operr: + ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SFEATCFG, + DCB_ATTR_FEATCFG, pid, seq, flags); + +err: + return ret; +} + static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { struct net *net = sock_net(skb->sk); @@ -1427,6 +1552,14 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ret = dcbnl_setdcbx(netdev, tb, pid, nlh->nlmsg_seq, nlh->nlmsg_flags); goto out; + case DCB_CMD_GFEATCFG: + ret = dcbnl_getfeatcfg(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_SFEATCFG: + ret = dcbnl_setfeatcfg(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; default: goto errout; } -- cgit v1.2.3 From 7c14c3f10e6dcd7f70e49f77b6e1ae605c4861e6 Mon Sep 17 00:00:00 2001 From: Shmulik Ravid Date: Thu, 30 Dec 2010 06:27:10 +0000 Subject: dcbnl: cleanup A couple of small cleanups for patches: [net-next-2.6 PATCH 1/3] dcbnl: add support for ieee8021Qaz attributes [net-next-2.6 PATCH 2/3] dcbnl: add appliction tlv handlers [net-next-2.6 PATCH 3/3] net_dcb: add application notifiers Signed-off-by: Shmulik Ravid Signed-off-by: David S. Miller --- net/dcb/dcbnl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/dcb/dcbnl.c') diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 075af0a08d84..ff3c12d2cd72 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -1642,7 +1642,7 @@ out: } EXPORT_SYMBOL(dcb_setapp); -void dcb_flushapp(void) +static void dcb_flushapp(void) { struct dcb_app_type *app; -- cgit v1.2.3 From 7f891cf1fc0d5d5c5b359caec77e5383e1d55986 Mon Sep 17 00:00:00 2001 From: Shmulik Ravid Date: Mon, 3 Jan 2011 08:04:59 +0000 Subject: dcbnl: more informed return values for new dcbnl routines More accurate return values for the following (new) dcbnl routines: dcbnl_getdcbx() dcbnl_setdcbx() dcbnl_getfeatcfg() dcbnl_setfeatcfg() Signed-off-by: Shmulik Ravid Signed-off-by: David S. Miller --- net/dcb/dcbnl.c | 81 ++++++++++++++++++++++++++------------------------------- 1 file changed, 37 insertions(+), 44 deletions(-) (limited to 'net/dcb/dcbnl.c') diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index ff3c12d2cd72..9399af565715 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -1286,10 +1286,10 @@ nlmsg_failure: static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb, u32 pid, u32 seq, u16 flags) { - int ret = -EINVAL; + int ret; if (!netdev->dcbnl_ops->getdcbx) - return ret; + return -EOPNOTSUPP; ret = dcbnl_reply(netdev->dcbnl_ops->getdcbx(netdev), RTM_GETDCB, DCB_CMD_GDCBX, DCB_ATTR_DCBX, pid, seq, flags); @@ -1300,11 +1300,14 @@ static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb, static int dcbnl_setdcbx(struct net_device *netdev, struct nlattr **tb, u32 pid, u32 seq, u16 flags) { - int ret = -EINVAL; + int ret; u8 value; - if (!tb[DCB_ATTR_DCBX] || !netdev->dcbnl_ops->setdcbx) - return ret; + if (!netdev->dcbnl_ops->setdcbx) + return -EOPNOTSUPP; + + if (!tb[DCB_ATTR_DCBX]) + return -EINVAL; value = nla_get_u8(tb[DCB_ATTR_DCBX]); @@ -1323,23 +1326,23 @@ static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb, struct dcbmsg *dcb; struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest; u8 value; - int ret = -EINVAL; - int i; + int ret, i; int getall = 0; - if (!tb[DCB_ATTR_FEATCFG] || !netdev->dcbnl_ops->getfeatcfg) - return ret; + if (!netdev->dcbnl_ops->getfeatcfg) + return -EOPNOTSUPP; + + if (!tb[DCB_ATTR_FEATCFG]) + return -EINVAL; ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG], dcbnl_featcfg_nest); - if (ret) { - ret = -EINVAL; + if (ret) goto err_out; - } dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!dcbnl_skb) { - ret = -EINVAL; + ret = -ENOBUFS; goto err_out; } @@ -1351,8 +1354,8 @@ static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb, nest = nla_nest_start(dcbnl_skb, DCB_ATTR_FEATCFG); if (!nest) { - ret = -EINVAL; - goto err; + ret = -EMSGSIZE; + goto nla_put_failure; } if (data[DCB_FEATCFG_ATTR_ALL]) @@ -1363,30 +1366,22 @@ static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb, continue; ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value); - if (!ret) { + if (!ret) ret = nla_put_u8(dcbnl_skb, i, value); - if (ret) { - nla_nest_cancel(dcbnl_skb, nest); - ret = -EINVAL; - goto err; - } - } else - goto err; + if (ret) { + nla_nest_cancel(dcbnl_skb, nest); + goto nla_put_failure; + } } 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; - } - - return 0; + return rtnl_unicast(dcbnl_skb, &init_net, pid); +nla_put_failure: + nlmsg_cancel(dcbnl_skb, nlh); nlmsg_failure: -err: kfree_skb(dcbnl_skb); err_out: return ret; @@ -1396,20 +1391,20 @@ static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlattr **tb, u32 pid, u32 seq, u16 flags) { struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1]; - int ret = -EINVAL; + int ret, i; u8 value; - int i; - if (!tb[DCB_ATTR_FEATCFG] || !netdev->dcbnl_ops->setfeatcfg) - return ret; + if (!netdev->dcbnl_ops->setfeatcfg) + return -ENOTSUPP; + + if (!tb[DCB_ATTR_FEATCFG]) + return -EINVAL; ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG], dcbnl_featcfg_nest); - if (ret) { - ret = -EINVAL; + if (ret) goto err; - } for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) { if (data[i] == NULL) @@ -1420,14 +1415,12 @@ static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlattr **tb, ret = netdev->dcbnl_ops->setfeatcfg(netdev, i, value); if (ret) - goto operr; + goto err; } - -operr: - ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SFEATCFG, - DCB_ATTR_FEATCFG, pid, seq, flags); - err: + dcbnl_reply(ret, RTM_SETDCB, DCB_CMD_SFEATCFG, DCB_ATTR_FEATCFG, + pid, seq, flags); + return ret; } -- cgit v1.2.3 From 70bfa2d2e1bfd90ef26758b5e2749f043a940037 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 4 Jan 2011 21:03:12 +0000 Subject: dcb: unlock on error in dcbnl_ieee_get() There is a "goto nla_put_failure" hidden inside the NLA_PUT() macro, but we're holding the dcb_lock so we need to unlock first. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- net/dcb/dcbnl.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'net/dcb/dcbnl.c') diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 9399af565715..4323bd441f0f 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -1264,9 +1264,14 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, spin_lock(&dcb_lock); list_for_each_entry(itr, &dcb_app_list, list) { - if (strncmp(itr->name, netdev->name, IFNAMSIZ) == 0) - NLA_PUT(skb, DCB_ATTR_IEEE_APP, - sizeof(itr->app), &itr->app); + if (strncmp(itr->name, netdev->name, IFNAMSIZ) == 0) { + err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app), + &itr->app); + if (err) { + spin_unlock(&dcb_lock); + goto nla_put_failure; + } + } } spin_unlock(&dcb_lock); nla_nest_end(skb, app); -- cgit v1.2.3 From 2a8fe003741aa90b6b9453e90af4bbb7bc42918c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 4 Jan 2011 21:03:44 +0000 Subject: dcb: use after free in dcb_flushapp() The original code has a use after free bug because it's not using the _safe() version of the list_for_each_entry() macro. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- net/dcb/dcbnl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net/dcb/dcbnl.c') diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 4323bd441f0f..d900ab99814a 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -1643,9 +1643,10 @@ EXPORT_SYMBOL(dcb_setapp); static void dcb_flushapp(void) { struct dcb_app_type *app; + struct dcb_app_type *tmp; spin_lock(&dcb_lock); - list_for_each_entry(app, &dcb_app_list, list) { + list_for_each_entry_safe(app, tmp, &dcb_app_list, list) { list_del(&app->list); kfree(app); } -- cgit v1.2.3