Netdev List
 help / color / mirror / Atom feed
* Re: net/netfilter/nf_conntrack_proto_tcp.c:1606:9: error: ‘struct nf_proto_net’ has no member named ‘user’
From: Pablo Neira Ayuso @ 2012-06-13 11:38 UTC (permalink / raw)
  To: Gao feng; +Cc: David Miller, wfg, netdev
In-Reply-To: <4FD85477.4050206@cn.fujitsu.com>

On Wed, Jun 13, 2012 at 04:51:03PM +0800, Gao feng wrote:
> 于 2012年06月13日 00:03, Pablo Neira Ayuso 写道:
> > Still, we have that pn->users thing:
> > 
> >         if (!pn->users++) {
> >                 for (i = 0; i < TCP_CONNTRACK_TIMEOUT_MAX; i++)
> >                         tn->timeouts[i] = tcp_timeouts[i];
> > 
> >                 tn->tcp_loose = nf_ct_tcp_loose;
> >                 tn->tcp_be_liberal = nf_ct_tcp_be_liberal;
> >                 tn->tcp_max_retrans = nf_ct_tcp_max_retrans;
> >         }
> > 
> > Define some pn->initialized boolean. Set it to true at the end of
> > the new tcp_init_net.
> 
> It should not be boolean,because We don't know what's the right time to set it false.
> Just like nf_conntrack_l4proto_tcp(4,6), they both use nf_tcp_net,we can set it false
> only when tcp4 and tcp6 are unregistered, so we need a referenct count here to point
> out if one proto has initialied the nf_tcp_net, or if there are no protos use nf_tcp_net.
>
> Though it maybe confusing,we can regard it as the reference count of nf_proto_net(how
> many protos are using nf_proto_net), and this reference count is increased when
> l4proto being registered success(no matter sysctl is enabled or disabled).

Yes, it makes sense indeed to regard pn->users as the refcount for the
per-net nf_proto_net. But in that case, I think we have to clean up
the code to increment pn->users everytime nf_conntrack_l[3|4]proto_register
is called, and decrement it for nf_conntrack_l[3|4]_unregister case.
Currently, by looking at the code, it seems that pn->users is some
sysctl specific refcount.

^ permalink raw reply

* Re: [net-next patch 8/12] bnx2x: Allow up to 63 RSS queues default 8 queues
From: Merav Sicron @ 2012-06-13 15:14 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: eilong, davem, netdev
In-Reply-To: <1339581175.22704.342.camel@edumazet-glaptop>

Hi Eric,

On Wed, 2012-06-13 at 11:52 +0200, Eric Dumazet wrote:
> On Wed, 2012-06-13 at 15:44 +0300, Merav Sicron wrote:
> > This patch removed the limitation in the code for 16 RSS queues. The default
> > (without other instruction from the user) number of queues is determined
> > according to the number of MSI-X vectors supported for that function, the number
> > of CPUs in the system, and a maximum of 8 queues.
> 
> Thats a very confusing changelog
> 
> You meant : " a minimum of 8 queues" ?
> 
No, I meant maximum...for example in a system with 16 CPUs we will
allocate 8 RSS queues. We saw that in most scenarios we tested there was
no need for more than 8 queues to get the maximal throughput, and by
limiting to 8 by default we reduce the allocated memory. We do provide
ethtool -L support so that the user could request more RSS queues if
desired.

> You should give more explanations, because its a sensible area for
> performances.
> 
Thanks,
Merav

^ permalink raw reply

* Re: [RFC] net/sched/em_canid: Ematch rule to match CAN frames according to their CAN IDs
From: Thomas Graf @ 2012-06-13 12:18 UTC (permalink / raw)
  To: Michal Sojka
  Cc: Oliver Hartkopp, Rostislav Lisovy, Eric Dumazet, netdev,
	linux-can, lartc, pisa
In-Reply-To: <878vfr7d4l.fsf@steelpick.2x.cz>

On Wed, Jun 13, 2012 at 11:52:10AM +0200, Michal Sojka wrote:
> The performance of ematch might be slightly lower than of standalone
> classifier. Rosta will compare the performance soon. 

I think it doesn't make a difference, there is no additional locking
involved. Numbers definitely welcome though.

> > E.g. is it still possible to add additional ematches like checking for
> > patterns inside can_frame.data[] (which is located in skb->data) with
> > ematch_u32 or e.g. ematch_text ??
> 
> AFAIK, this should be possible and it will be a big advantage over
> implementation as a standalone classifier.

Definitely and the real advantage is that you can combine these
using logic operators.

^ permalink raw reply

* am3359 (cpsw): unable to get gigabit link working (PHY: ICPlus IP1001)
From: Yegor Yefremov @ 2012-06-13 12:28 UTC (permalink / raw)
  To: netdev; +Cc: cyril, srk, mugunthanvnm

I'm using a custom am3359 based board. The first CPSW ports is
connected to ICPlus IP1001 phy via RGMII interface. I have no problem
with 100mbit link, but as soon as I connect my board to a 1Gbit switch
the communication fails. I can see that some data goes on wire, but
switch refuses to forward it. I can't receive anything either. Phy
detects 1Gbit link correctly.

My kernel: https://github.com/koenkooi/linux

I also define phy interface as RGMII:

static struct cpsw_slave_data am33xx_cpsw_slaves[] = {
        {
                .slave_reg_ofs  = 0x208,
                .sliver_reg_ofs = 0xd80,
                .phy_id         = "0:02",
                .phy_if               = PHY_INTERFACE_MODE_RGMII,
        },
        {
                .slave_reg_ofs  = 0x308,
                .sliver_reg_ofs = 0xdc0,
                .phy_id         = "0:01",
        },
};

As far as I can see in the mainline cpsw driver
PHY_INTERFACE_MODE_RGMII will be ignored. Why? In the current driver
it sets two bits in mac_control register:

if (phy->interface == PHY_INTERFACE_MODE_RGMII) /* RGMII */
                        mac_control |= (BIT(15)|BIT(16));

Any idea where should I look to solve the problem?

^ permalink raw reply

* Re: [PATCH 2/5] drivers/net/ethernet/dec/tulip: Use standard __set_bit_le() function
From: Takuya Yoshikawa @ 2012-06-13 12:41 UTC (permalink / raw)
  To: Akinobu Mita
  Cc: Takuya Yoshikawa, akpm, bhutchings, grundler, arnd, benh, avi,
	mtosatti, linux-net-drivers, netdev, linux-kernel, linux-arch,
	kvm
In-Reply-To: <CAC5umyj582T+9GbOYDzOAanmMcVZ-Fdxr7i-8GWf3gTSmtAKUA@mail.gmail.com>

On Wed, 13 Jun 2012 18:43:40 +0900
Akinobu Mita <akinobu.mita@gmail.com> wrote:

> Should this hash_table be converted from u16 hash_table[32] to
> DECLARE_BITMAP(hash_table, 16 * 32) to ensure that it is aligned
> on long-word boundary?

I think hash_table is already long-word aligned because it is placed
right after a pointer.

	Takuya

^ permalink raw reply

* [PATCH] usbnet: Activate halt interrupt endpoint before re-submit URB
From: Huajun Li @ 2012-06-13 12:50 UTC (permalink / raw)
  To: David Miller; +Cc: Ming Lei, Alan Stern, lud, netdev, Huajun Li

intr_complete() submits URB even the interrupt endpoint stalls.
This patch will try to activate the endpoint once the exception
occurs, and then re-submit the URB if the endpoint works again.

Signed-off-by: Huajun Li <huajun.li.lee@gmail.com>
---
 drivers/net/usb/usbnet.c   |   31 +++++++++++++++++++++++++++++++
 include/linux/usb/usbnet.h |   13 +++++++------
 2 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index ac2e493..314aaea 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -198,6 +198,10 @@ static void intr_complete (struct urb *urb)
 			  "intr shutdown, code %d\n", status);
 		return;

+	case -EPIPE:
+		usbnet_defer_kevent(dev, EVENT_STS_HALT);
+		return;
+
 	/* NOTE:  not throttling like RX/TX, since this endpoint
 	 * already polls infrequently
 	 */
@@ -964,6 +968,33 @@ fail_halt:
 		}
 	}

+	if (test_bit(EVENT_STS_HALT, &dev->flags)) {
+		unsigned pipe;
+		struct usb_endpoint_descriptor *desc;
+
+		desc = &dev->status->desc;
+		pipe = usb_rcvintpipe(dev->udev,
+			desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+		status = usb_autopm_get_interface(dev->intf);
+		if (status < 0)
+			goto fail_sts;
+		status = usb_clear_halt(dev->udev, pipe);
+		if (status < 0) {
+			usb_autopm_put_interface(dev->intf);
+fail_sts:
+			netdev_err(dev->net,
+				"can't clear intr halt, status %d\n", status);
+		} else {
+			clear_bit(EVENT_STS_HALT, &dev->flags);
+			status = usb_submit_urb(dev->interrupt, GFP_KERNEL);
+			if (status != 0)
+				netif_err(dev, timer, dev->net,
+					"intr resubmit --> %d\n", status);
+
+			usb_autopm_put_interface(dev->intf);
+		}
+	}
+
 	/* tasklet could resubmit itself forever if memory is tight */
 	if (test_bit (EVENT_RX_MEMORY, &dev->flags)) {
 		struct urb	*urb = NULL;
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index f87cf62..81b4473 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -62,12 +62,13 @@ struct usbnet {
 	unsigned long		flags;
 #		define EVENT_TX_HALT	0
 #		define EVENT_RX_HALT	1
-#		define EVENT_RX_MEMORY	2
-#		define EVENT_STS_SPLIT	3
-#		define EVENT_LINK_RESET	4
-#		define EVENT_RX_PAUSED	5
-#		define EVENT_DEV_ASLEEP 6
-#		define EVENT_DEV_OPEN	7
+#		define EVENT_STS_HALT	2
+#		define EVENT_RX_MEMORY	3
+#		define EVENT_STS_SPLIT	4
+#		define EVENT_LINK_RESET	5
+#		define EVENT_RX_PAUSED	6
+#		define EVENT_DEV_ASLEEP 7
+#		define EVENT_DEV_OPEN	8
 };

 static inline struct usb_driver *driver_of(struct usb_interface *intf)
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 1/8] dcbnl: Prepare framework to shorten handling functions
From: Thomas Graf @ 2012-06-13 12:54 UTC (permalink / raw)
  To: davem; +Cc: netdev, lucy.liu, john.r.fastabend, alexander.h.duyck
In-Reply-To: <cover.1339591572.git.tgraf@suug.ch>

There is no need to allocate and send the reply message in each
handling function separately. Instead, the reply skb can be allocated
and sent in dcb_doit() directly.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
 net/dcb/dcbnl.c |   71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 656c7c7..5520e43 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -196,6 +196,34 @@ static const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = {
 static LIST_HEAD(dcb_app_list);
 static DEFINE_SPINLOCK(dcb_lock);
 
+static struct sk_buff *dcbnl_newmsg(int type, u8 cmd, u32 port, u32 seq,
+				    u32 flags, struct nlmsghdr **nlhp)
+{
+	struct sk_buff *skb;
+	struct dcbmsg *dcb;
+	struct nlmsghdr *nlh;
+
+	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!skb)
+		return NULL;
+
+	nlh = nlmsg_put(skb, port, seq, type, sizeof(*dcb), flags);
+	if (!nlh) {
+		/* header should always fit, allocation must be buggy */
+		BUG();
+	}
+
+	dcb = nlmsg_data(nlh);
+	dcb->dcb_family = AF_UNSPEC;
+	dcb->cmd = cmd;
+	dcb->dcb_pad = 0;
+
+	if (nlhp)
+		*nlhp = nlh;
+
+	return skb;
+}
+
 /* standard netlink reply call */
 static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
                        u32 seq, u16 flags)
@@ -1922,6 +1950,19 @@ static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
 	return err;
 }
 
+struct reply_func {
+	/* reply netlink message type */
+	int	type;
+
+	/* function to fill message contents */
+	int   (*cb)(struct net_device *, struct nlmsghdr *, u32,
+		    struct nlattr **, struct sk_buff *);
+};
+
+static const struct reply_func reply_funcs[DCB_CMD_MAX+1] = {
+	/* FIXME: add reply defs */
+};
+
 static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
 	struct net *net = sock_net(skb->sk);
@@ -1930,6 +1971,9 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 	struct nlattr *tb[DCB_ATTR_MAX + 1];
 	u32 pid = skb ? NETLINK_CB(skb).pid : 0;
 	int ret = -EINVAL;
+	struct sk_buff *reply_skb;
+	struct nlmsghdr *reply_nlh;
+	const struct reply_func *fn;
 
 	if (!net_eq(net, &init_net))
 		return -EINVAL;
@@ -1939,6 +1983,14 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 	if (ret < 0)
 		return ret;
 
+	if (dcb->cmd > DCB_CMD_MAX)
+		return -EINVAL;
+
+	/* check if a reply function has been defined for the command */
+	fn = &reply_funcs[dcb->cmd];
+	if (!fn->cb)
+		return -EOPNOTSUPP;
+
 	if (!tb[DCB_ATTR_IFNAME])
 		return -EINVAL;
 
@@ -1949,6 +2001,25 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 	if (!netdev->dcbnl_ops)
 		goto errout;
 
+	reply_skb = dcbnl_newmsg(fn->type, dcb->cmd, pid, nlh->nlmsg_seq,
+				 nlh->nlmsg_flags, &reply_nlh);
+	if (!reply_skb) {
+		ret = -ENOBUFS;
+		goto out;
+	}
+
+	ret = fn->cb(netdev, nlh, nlh->nlmsg_seq, tb, reply_skb);
+	if (ret < 0) {
+		nlmsg_free(reply_skb);
+		goto out;
+	}
+
+	nlmsg_end(reply_skb, reply_nlh);
+
+	ret = rtnl_unicast(reply_skb, &init_net, pid);
+	if (ret)
+		goto out;
+
 	switch (dcb->cmd) {
 	case DCB_CMD_GSTATE:
 		ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq,
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH 0/8] dcbnl: Major simplifications
From: Thomas Graf @ 2012-06-13 12:54 UTC (permalink / raw)
  To: davem; +Cc: netdev, lucy.liu, john.r.fastabend, alexander.h.duyck

The dcbnl code is overly complicated when constructing the reply
message. This series of patches simplifies the process and
introduces consistent error codes allowing user space to figure
out what went wrong.

Patches have been tested with ixgbe in a FCoE setup.

Thomas Graf (8):
  dcbnl: Prepare framework to shorten handling functions
  dcbnl: Shorten all command handling functions
  dcbnl: Remove now unused dcbnl_reply()
  dcbnl: Use dcbnl_newmsg() where possible
  dcbnl: Return consistent error codes
  dcbnl: Move dcb app lookup code into dcb_app_lookup()
  dcbnl: Move dcb app allocation into dcb_app_add()
  dcbnl: Use type safe nlmsg_data()

 net/dcb/dcbnl.c | 1169 +++++++++++++++++++------------------------------------
 1 files changed, 401 insertions(+), 768 deletions(-)

-- 
1.7.7.6

^ permalink raw reply

* [PATCH 3/8] dcbnl: Remove now unused dcbnl_reply()
From: Thomas Graf @ 2012-06-13 12:54 UTC (permalink / raw)
  To: davem; +Cc: netdev, lucy.liu, john.r.fastabend, alexander.h.duyck
In-Reply-To: <cover.1339591572.git.tgraf@suug.ch>

Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
 net/dcb/dcbnl.c |   37 -------------------------------------
 1 files changed, 0 insertions(+), 37 deletions(-)

diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 5e392b8..5ed7167 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -224,43 +224,6 @@ static struct sk_buff *dcbnl_newmsg(int type, u8 cmd, u32 port, u32 seq,
 	return skb;
 }
 
-/* standard netlink reply call */
-static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
-                       u32 seq, u16 flags)
-{
-	struct sk_buff *dcbnl_skb;
-	struct dcbmsg *dcb;
-	struct nlmsghdr *nlh;
-	int ret = -EINVAL;
-
-	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!dcbnl_skb)
-		return ret;
-
-	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags);
-
-	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;
-
-	/* 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;
-}
-
 static int dcbnl_getstate(struct net_device *netdev, struct nlmsghdr *nlh,
 			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
 {
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH 2/8] dcbnl: Shorten all command handling functions
From: Thomas Graf @ 2012-06-13 12:54 UTC (permalink / raw)
  To: davem; +Cc: netdev, lucy.liu, john.r.fastabend, alexander.h.duyck
In-Reply-To: <cover.1339591572.git.tgraf@suug.ch>

Allocating and sending the skb in dcb_doit() allows for much
shorter and cleaner command handling functions.

The huge switch statement is replaced with an array based definition
of the handling function and reply message type.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
 net/dcb/dcbnl.c |  722 +++++++++++++------------------------------------------
 1 files changed, 172 insertions(+), 550 deletions(-)

diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 5520e43..5e392b8 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -261,27 +261,20 @@ err:
 	return ret;
 }
 
-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 -EINVAL;
 
-	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;
@@ -295,19 +288,9 @@ static int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb,
 	                       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;
+		goto err;
 
-	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG);
+	nest = nla_nest_start(skb, DCB_ATTR_PFC_CFG);
 	if (!nest)
 		goto err;
 
@@ -320,76 +303,35 @@ 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);
+			nla_nest_cancel(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_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 -EINVAL;
 
 	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;
@@ -404,19 +346,9 @@ static int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb,
 	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);
+	nest = nla_nest_start(skb, DCB_ATTR_CAP);
 	if (!nest)
-		goto err;
+		goto err_out;
 
 	if (data[DCB_CAP_ATTR_ALL])
 		getall = 1;
@@ -426,36 +358,23 @@ 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);
+				goto err_out;
 			}
 		}
 	}
-	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;
@@ -472,22 +391,10 @@ static int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb,
 		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;
-
-	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS);
+	nest = nla_nest_start(skb, DCB_ATTR_NUMTCS);
 	if (!nest) {
 		ret = -EINVAL;
-		goto err;
+		goto err_out;
 	}
 
 	if (data[DCB_NUMTCS_ATTR_ALL])
@@ -499,37 +406,25 @@ 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);
+				nla_nest_cancel(skb, nest);
 				ret = -EINVAL;
-				goto err;
+				goto err_out;
 			}
 		} else {
-			goto err;
+			goto err_out;
 		}
 	}
-	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;
-	}
+	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;
@@ -542,10 +437,8 @@ static int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb,
 	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 -EINVAL;
 
 	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
 		if (data[i] == NULL)
@@ -554,59 +447,41 @@ 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 -EINVAL;
 
-	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;
+		return -EINVAL;
 
 	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;
@@ -645,51 +520,34 @@ 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;
+		goto out;
 
-	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;
 
 out_cancel:
-	nla_nest_cancel(dcbnl_skb, app_nest);
-nlmsg_failure:
-	kfree_skb(dcbnl_skb);
+	nla_nest_cancel(skb, app_nest);
 out:
 	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;
 	u16 id;
@@ -730,19 +588,15 @@ static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb,
 		err = 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];
@@ -764,19 +618,9 @@ static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb,
 	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;
-
-	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;
+		goto err_out;
 
 	if (pg_tb[DCB_PG_ATTR_TC_ALL])
 		getall = 1;
@@ -794,7 +638,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;
 
@@ -817,33 +661,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])
@@ -866,66 +710,53 @@ 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);
+	nla_nest_cancel(skb, pg_nest);
 err_out:
 	ret  = -EINVAL;
 	return ret;
 }
 
-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;
+		return -EINVAL;
 
 	value = nla_get_u8(tb[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;
+	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;
@@ -949,29 +780,29 @@ 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);
+	return nla_put_u8(skb, DCB_ATTR_PFC_CFG, 0);
 err:
 	return ret;
 }
 
-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;
 
 	if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall)
 		return ret;
 
-	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];
@@ -1054,32 +885,27 @@ 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);
+	ret = nla_put_u8(skb, (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG), 0);
 
 err:
 	return ret;
 }
 
-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;
@@ -1098,19 +924,9 @@ static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb,
 	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;
-
-	bcn_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_BCN);
+	bcn_nest = nla_nest_start(skb, DCB_ATTR_BCN);
 	if (!bcn_nest)
-		goto err;
+		goto err_out;
 
 	if (bcn_tb[DCB_BCN_ATTR_ALL])
 		getall = true;
@@ -1121,7 +937,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;
 	}
@@ -1132,33 +948,24 @@ 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);
+	nla_nest_cancel(skb, bcn_nest);
 err_out:
 	ret  = -EINVAL;
 	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;
@@ -1192,8 +999,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);
+	ret = nla_put_u8(skb, DCB_ATTR_BCN, 0);
 err:
 	return ret;
 }
@@ -1618,8 +1424,8 @@ EXPORT_SYMBOL(dcbnl_cee_notify);
  * 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)
+static int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh,
+			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
 {
 	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
 	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
@@ -1677,54 +1483,24 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
 	}
 
 err:
-	dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
-		    pid, seq, flags);
+	err = nla_put_u8(skb, DCB_ATTR_IEEE, err);
 	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0);
 	return err;
 }
 
-static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
-			  u32 pid, u32 seq, u16 flags)
+static int dcbnl_ieee_get(struct net_device *netdev, struct nlmsghdr *nlh,
+			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
 {
-	struct net *net = dev_net(netdev);
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	struct dcbmsg *dcb;
 	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_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
-	if (nlh == NULL) {
-		nlmsg_free(skb);
-		return -EMSGSIZE;
-	}
-
-	dcb = NLMSG_DATA(nlh);
-	dcb->dcb_family = AF_UNSPEC;
-	dcb->cmd = DCB_CMD_IEEE_GET;
-
-	err = dcbnl_ieee_fill(skb, netdev);
-
-	if (err < 0) {
-		nlmsg_cancel(skb, nlh);
-		kfree_skb(skb);
-	} else {
-		nlmsg_end(skb, nlh);
-		err = rtnl_unicast(skb, net, pid);
-	}
-
-	return err;
+	return dcbnl_ieee_fill(skb, netdev);
 }
 
-static int dcbnl_ieee_del(struct net_device *netdev, struct nlattr **tb,
-			  u32 pid, u32 seq, u16 flags)
+static int dcbnl_ieee_del(struct net_device *netdev, struct nlmsghdr *nlh,
+			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
 {
 	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
 	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
@@ -1761,32 +1537,26 @@ static int dcbnl_ieee_del(struct net_device *netdev, struct nlattr **tb,
 	}
 
 err:
-	dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_DEL, DCB_ATTR_IEEE,
-		    pid, seq, flags);
+	err = nla_put_u8(skb, DCB_ATTR_IEEE, err);
 	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0);
 	return err;
 }
 
 
 /* DCBX configuration */
-static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
-			 u32 pid, u32 seq, u16 flags)
+static int dcbnl_getdcbx(struct net_device *netdev, struct nlmsghdr *nlh,
+			 u32 seq, struct nlattr **tb, struct sk_buff *skb)
 {
-	int ret;
-
 	if (!netdev->dcbnl_ops->getdcbx)
 		return -EOPNOTSUPP;
 
-	ret = dcbnl_reply(netdev->dcbnl_ops->getdcbx(netdev), RTM_GETDCB,
-			  DCB_CMD_GDCBX, DCB_ATTR_DCBX, pid, seq, flags);
-
-	return ret;
+	return nla_put_u8(skb, DCB_ATTR_DCBX,
+			  netdev->dcbnl_ops->getdcbx(netdev));
 }
 
-static int dcbnl_setdcbx(struct net_device *netdev, struct nlattr **tb,
-			 u32 pid, u32 seq, u16 flags)
+static int dcbnl_setdcbx(struct net_device *netdev, struct nlmsghdr *nlh,
+			 u32 seq, struct nlattr **tb, struct sk_buff *skb)
 {
-	int ret;
 	u8 value;
 
 	if (!netdev->dcbnl_ops->setdcbx)
@@ -1797,19 +1567,13 @@ static int dcbnl_setdcbx(struct net_device *netdev, struct nlattr **tb,
 
 	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;
+	return nla_put_u8(skb, DCB_ATTR_DCBX,
+			  netdev->dcbnl_ops->setdcbx(netdev, value));
 }
 
-static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb,
-			    u32 pid, u32 seq, u16 flags)
+static int dcbnl_getfeatcfg(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_FEATCFG_ATTR_MAX + 1], *nest;
 	u8 value;
 	int ret, i;
@@ -1824,25 +1588,11 @@ static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb,
 	ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
 			       dcbnl_featcfg_nest);
 	if (ret)
-		goto err_out;
-
-	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!dcbnl_skb) {
-		ret = -ENOBUFS;
-		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;
+		return ret;
 
-	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_FEATCFG);
-	if (!nest) {
-		ret = -EMSGSIZE;
-		goto nla_put_failure;
-	}
+	nest = nla_nest_start(skb, DCB_ATTR_FEATCFG);
+	if (!nest)
+		return -EMSGSIZE;
 
 	if (data[DCB_FEATCFG_ATTR_ALL])
 		getall = 1;
@@ -1853,28 +1603,21 @@ static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb,
 
 		ret = netdev->dcbnl_ops->getfeatcfg(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);
+			nla_nest_cancel(skb, nest);
 			goto nla_put_failure;
 		}
 	}
-	nla_nest_end(dcbnl_skb, nest);
-
-	nlmsg_end(dcbnl_skb, nlh);
+	nla_nest_end(skb, nest);
 
-	return rtnl_unicast(dcbnl_skb, &init_net, pid);
 nla_put_failure:
-	nlmsg_cancel(dcbnl_skb, nlh);
-nlmsg_failure:
-	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)
+static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh,
+			    u32 seq, struct nlattr **tb, struct sk_buff *skb)
 {
 	struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1];
 	int ret, i;
@@ -1904,50 +1647,21 @@ static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlattr **tb,
 			goto err;
 	}
 err:
-	dcbnl_reply(ret, RTM_SETDCB, DCB_CMD_SFEATCFG, DCB_ATTR_FEATCFG,
-		    pid, seq, flags);
+	ret = nla_put_u8(skb, DCB_ATTR_FEATCFG, ret);
 
 	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)
+static int dcbnl_cee_get(struct net_device *netdev, struct nlmsghdr *nlh,
+			 u32 seq, struct nlattr **tb, struct sk_buff *skb)
 {
-	struct net *net = dev_net(netdev);
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	struct dcbmsg *dcb;
 	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_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
-	if (nlh == NULL) {
-		nlmsg_free(skb);
-		return -EMSGSIZE;
-	}
-
-	dcb = NLMSG_DATA(nlh);
-	dcb->dcb_family = AF_UNSPEC;
-	dcb->cmd = DCB_CMD_CEE_GET;
-
-	err = dcbnl_cee_fill(skb, netdev);
-
-	if (err < 0) {
-		nlmsg_cancel(skb, nlh);
-		nlmsg_free(skb);
-	} else {
-		nlmsg_end(skb, nlh);
-		err = rtnl_unicast(skb, net, pid);
-	}
-	return err;
+	return dcbnl_cee_fill(skb, netdev);
 }
 
 struct reply_func {
@@ -1960,7 +1674,33 @@ struct reply_func {
 };
 
 static const struct reply_func reply_funcs[DCB_CMD_MAX+1] = {
-	/* FIXME: add reply defs */
+	[DCB_CMD_GSTATE]	= { RTM_GETDCB, dcbnl_getstate },
+	[DCB_CMD_SSTATE]	= { RTM_SETDCB, dcbnl_setstate },
+	[DCB_CMD_PFC_GCFG]	= { RTM_GETDCB, dcbnl_getpfccfg },
+	[DCB_CMD_PFC_SCFG]	= { RTM_SETDCB, dcbnl_setpfccfg },
+	[DCB_CMD_GPERM_HWADDR]	= { RTM_GETDCB, dcbnl_getperm_hwaddr },
+	[DCB_CMD_GCAP]		= { RTM_GETDCB, dcbnl_getcap },
+	[DCB_CMD_GNUMTCS]	= { RTM_GETDCB, dcbnl_getnumtcs },
+	[DCB_CMD_SNUMTCS]	= { RTM_SETDCB, dcbnl_setnumtcs },
+	[DCB_CMD_PFC_GSTATE]	= { RTM_GETDCB, dcbnl_getpfcstate },
+	[DCB_CMD_PFC_SSTATE]	= { RTM_SETDCB, dcbnl_setpfcstate },
+	[DCB_CMD_GAPP]		= { RTM_GETDCB, dcbnl_getapp },
+	[DCB_CMD_SAPP]		= { RTM_SETDCB, dcbnl_setapp },
+	[DCB_CMD_PGTX_GCFG]	= { RTM_GETDCB, dcbnl_pgtx_getcfg },
+	[DCB_CMD_PGTX_SCFG]	= { RTM_SETDCB, dcbnl_pgtx_setcfg },
+	[DCB_CMD_PGRX_GCFG]	= { RTM_GETDCB, dcbnl_pgrx_getcfg },
+	[DCB_CMD_PGRX_SCFG]	= { RTM_SETDCB, dcbnl_pgrx_setcfg },
+	[DCB_CMD_SET_ALL]	= { RTM_SETDCB, dcbnl_setall },
+	[DCB_CMD_BCN_GCFG]	= { RTM_GETDCB, dcbnl_bcn_getcfg },
+	[DCB_CMD_BCN_SCFG]	= { RTM_SETDCB, dcbnl_bcn_setcfg },
+	[DCB_CMD_IEEE_GET]	= { RTM_GETDCB, dcbnl_ieee_get },
+	[DCB_CMD_IEEE_SET]	= { RTM_SETDCB, dcbnl_ieee_set },
+	[DCB_CMD_IEEE_DEL]	= { RTM_SETDCB, dcbnl_ieee_del },
+	[DCB_CMD_GDCBX]		= { RTM_GETDCB, dcbnl_getdcbx },
+	[DCB_CMD_SDCBX]		= { RTM_SETDCB, dcbnl_setdcbx },
+	[DCB_CMD_GFEATCFG]	= { RTM_GETDCB, dcbnl_getfeatcfg },
+	[DCB_CMD_SFEATCFG]	= { RTM_SETDCB, dcbnl_setfeatcfg },
+	[DCB_CMD_CEE_GET]	= { RTM_GETDCB, dcbnl_cee_get },
 };
 
 static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
@@ -2017,124 +1757,6 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 	nlmsg_end(reply_skb, reply_nlh);
 
 	ret = rtnl_unicast(reply_skb, &init_net, pid);
-	if (ret)
-		goto out;
-
-	switch (dcb->cmd) {
-	case DCB_CMD_GSTATE:
-		ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq,
-		                     nlh->nlmsg_flags);
-		goto out;
-	case DCB_CMD_PFC_GCFG:
-		ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
-		                      nlh->nlmsg_flags);
-		goto out;
-	case DCB_CMD_GPERM_HWADDR:
-		ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq,
-		                           nlh->nlmsg_flags);
-		goto out;
-	case DCB_CMD_PGTX_GCFG:
-		ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
-		                        nlh->nlmsg_flags);
-		goto out;
-	case DCB_CMD_PGRX_GCFG:
-		ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
-		                        nlh->nlmsg_flags);
-		goto out;
-	case DCB_CMD_BCN_GCFG:
-		ret = dcbnl_bcn_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
-		                       nlh->nlmsg_flags);
-		goto out;
-	case DCB_CMD_SSTATE:
-		ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq,
-		                     nlh->nlmsg_flags);
-		goto out;
-	case DCB_CMD_PFC_SCFG:
-		ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
-		                      nlh->nlmsg_flags);
-		goto out;
-
-	case DCB_CMD_SET_ALL:
-		ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq,
-		                   nlh->nlmsg_flags);
-		goto out;
-	case DCB_CMD_PGTX_SCFG:
-		ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
-		                        nlh->nlmsg_flags);
-		goto out;
-	case DCB_CMD_PGRX_SCFG:
-		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;
-	case DCB_CMD_GNUMTCS:
-		ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
-		                      nlh->nlmsg_flags);
-		goto out;
-	case DCB_CMD_SNUMTCS:
-		ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
-		                      nlh->nlmsg_flags);
-		goto out;
-	case DCB_CMD_PFC_GSTATE:
-		ret = dcbnl_getpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
-		                        nlh->nlmsg_flags);
-		goto out;
-	case DCB_CMD_PFC_SSTATE:
-		ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
-		                        nlh->nlmsg_flags);
-		goto out;
-	case DCB_CMD_BCN_SCFG:
-		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;
-	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;
-	case DCB_CMD_IEEE_DEL:
-		ret = dcbnl_ieee_del(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;
-	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;
-	case DCB_CMD_CEE_GET:
-		ret = dcbnl_cee_get(netdev, tb, pid, nlh->nlmsg_seq,
-				    nlh->nlmsg_flags);
-		goto out;
-	default:
-		goto errout;
-	}
-errout:
-	ret = -EINVAL;
 out:
 	dev_put(netdev);
 	return ret;
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH 4/8] dcbnl: Use dcbnl_newmsg() where possible
From: Thomas Graf @ 2012-06-13 12:54 UTC (permalink / raw)
  To: davem; +Cc: netdev, lucy.liu, john.r.fastabend, alexander.h.duyck
In-Reply-To: <cover.1339591572.git.tgraf@suug.ch>

Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
 net/dcb/dcbnl.c |   16 ++--------------
 1 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 5ed7167..4d9e0ef 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1328,27 +1328,16 @@ static int dcbnl_notify(struct net_device *dev, int event, int cmd,
 	struct net *net = dev_net(dev);
 	struct sk_buff *skb;
 	struct nlmsghdr *nlh;
-	struct dcbmsg *dcb;
 	const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
 	int err;
 
 	if (!ops)
 		return -EOPNOTSUPP;
 
-	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	skb = dcbnl_newmsg(event, cmd, pid, seq, 0, &nlh);
 	if (!skb)
 		return -ENOBUFS;
 
-	nlh = nlmsg_put(skb, pid, 0, event, sizeof(*dcb), 0);
-	if (nlh == NULL) {
-		nlmsg_free(skb);
-		return -EMSGSIZE;
-	}
-
-	dcb = NLMSG_DATA(nlh);
-	dcb->dcb_family = AF_UNSPEC;
-	dcb->cmd = cmd;
-
 	if (dcbx_ver == DCB_CAP_DCBX_VER_IEEE)
 		err = dcbnl_ieee_fill(skb, dev);
 	else
@@ -1356,8 +1345,7 @@ static int dcbnl_notify(struct net_device *dev, int event, int cmd,
 
 	if (err < 0) {
 		/* Report error to broadcast listeners */
-		nlmsg_cancel(skb, nlh);
-		kfree_skb(skb);
+		nlmsg_free(skb);
 		rtnl_set_sk_err(net, RTNLGRP_DCB, err);
 	} else {
 		/* End nlmsg and notify broadcast listeners */
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH 5/8] dcbnl: Return consistent error codes
From: Thomas Graf @ 2012-06-13 12:54 UTC (permalink / raw)
  To: davem; +Cc: netdev, lucy.liu, john.r.fastabend, alexander.h.duyck
In-Reply-To: <cover.1339591572.git.tgraf@suug.ch>

EMSGSIZE - ran out of space while constructing message
EOPNOTSUPP - driver/hardware does not support operation
ENODEV - network device not found
EINVAL - invalid message

Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
 net/dcb/dcbnl.c |  273 ++++++++++++++++++++++++++++---------------------------
 1 files changed, 138 insertions(+), 135 deletions(-)

diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 4d9e0ef..5a5bc25 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -229,7 +229,7 @@ static int dcbnl_getstate(struct net_device *netdev, struct nlmsghdr *nlh,
 {
 	/* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */
 	if (!netdev->dcbnl_ops->getstate)
-		return -EINVAL;
+		return -EOPNOTSUPP;
 
 	return nla_put_u8(skb, DCB_ATTR_STATE,
 			  netdev->dcbnl_ops->getstate(netdev));
@@ -240,22 +240,25 @@ static int dcbnl_getpfccfg(struct net_device *netdev, struct nlmsghdr *nlh,
 {
 	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;
+		return ret;
 
 	nest = nla_nest_start(skb, DCB_ATTR_PFC_CFG);
 	if (!nest)
-		goto err;
+		return -EMSGSIZE;
 
 	if (data[DCB_PFC_UP_ATTR_ALL])
 		getall = 1;
@@ -269,14 +272,12 @@ static int dcbnl_getpfccfg(struct net_device *netdev, struct nlmsghdr *nlh,
 		ret = nla_put_u8(skb, i, value);
 		if (ret) {
 			nla_nest_cancel(skb, nest);
-			goto err;
+			return ret;
 		}
 	}
 	nla_nest_end(skb, nest);
 
 	return 0;
-err:
-	return -EINVAL;
 }
 
 static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlmsghdr *nlh,
@@ -285,7 +286,7 @@ static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlmsghdr *nlh,
 	u8 perm_addr[MAX_ADDR_LEN];
 
 	if (!netdev->dcbnl_ops->getpermhwaddr)
-		return -EINVAL;
+		return -EOPNOTSUPP;
 
 	netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
 
@@ -297,21 +298,24 @@ static int dcbnl_getcap(struct net_device *netdev, struct nlmsghdr *nlh,
 {
 	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;
+		return ret;
 
 	nest = nla_nest_start(skb, DCB_ATTR_CAP);
 	if (!nest)
-		goto err_out;
+		return -EMSGSIZE;
 
 	if (data[DCB_CAP_ATTR_ALL])
 		getall = 1;
@@ -324,15 +328,13 @@ static int dcbnl_getcap(struct net_device *netdev, struct nlmsghdr *nlh,
 			ret = nla_put_u8(skb, i, value);
 			if (ret) {
 				nla_nest_cancel(skb, nest);
-				goto err_out;
+				return ret;
 			}
 		}
 	}
 	nla_nest_end(skb, nest);
 
 	return 0;
-err_out:
-	return -EINVAL;
 }
 
 static int dcbnl_getnumtcs(struct net_device *netdev, struct nlmsghdr *nlh,
@@ -340,25 +342,24 @@ static int dcbnl_getnumtcs(struct net_device *netdev, struct nlmsghdr *nlh,
 {
 	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;
-	}
+	if (ret)
+		return ret;
 
 	nest = nla_nest_start(skb, DCB_ATTR_NUMTCS);
-	if (!nest) {
-		ret = -EINVAL;
-		goto err_out;
-	}
+	if (!nest)
+		return -EMSGSIZE;
 
 	if (data[DCB_NUMTCS_ATTR_ALL])
 		getall = 1;
@@ -372,36 +373,34 @@ static int dcbnl_getnumtcs(struct net_device *netdev, struct nlmsghdr *nlh,
 			ret = nla_put_u8(skb, i, value);
 			if (ret) {
 				nla_nest_cancel(skb, nest);
-				ret = -EINVAL;
-				goto err_out;
+				return ret;
 			}
-		} else {
-			goto err_out;
-		}
+		} else
+			return -EINVAL;
 	}
 	nla_nest_end(skb, nest);
 
 	return 0;
-err_out:
-	return ret;
 }
 
 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)
-		return -EINVAL;
+		return ret;
 
 	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
 		if (data[i] == NULL)
@@ -421,7 +420,7 @@ static int dcbnl_getpfcstate(struct net_device *netdev, struct nlmsghdr *nlh,
 			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
 {
 	if (!netdev->dcbnl_ops->getpfcstate)
-		return -EINVAL;
+		return -EOPNOTSUPP;
 
 	return nla_put_u8(skb, DCB_ATTR_PFC_STATE,
 			  netdev->dcbnl_ops->getpfcstate(netdev));
@@ -432,9 +431,12 @@ static int dcbnl_setpfcstate(struct net_device *netdev, struct nlmsghdr *nlh,
 {
 	u8 value;
 
-	if (!tb[DCB_ATTR_PFC_STATE] || !netdev->dcbnl_ops->setpfcstate)
+	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);
@@ -449,27 +451,26 @@ static int dcbnl_getapp(struct net_device *netdev, struct nlmsghdr *nlh,
 	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]);
 
@@ -485,7 +486,7 @@ static int dcbnl_getapp(struct net_device *netdev, struct nlmsghdr *nlh,
 
 	app_nest = nla_nest_start(skb, DCB_ATTR_APP);
 	if (!app_nest)
-		goto out;
+		return -EMSGSIZE;
 
 	ret = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE, idtype);
 	if (ret)
@@ -501,59 +502,57 @@ static int dcbnl_getapp(struct net_device *netdev, struct nlmsghdr *nlh,
 
 	nla_nest_end(skb, app_nest);
 
-	goto out;
+	return 0;
 
 out_cancel:
 	nla_nest_cancel(skb, app_nest);
-out:
 	return ret;
 }
 
 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 = nla_put_u8(skb, DCB_ATTR_APP, ret);
 	dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SAPP, seq, 0);
-out:
+
 	return ret;
 }
 
@@ -564,26 +563,27 @@ static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
 	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;
+		return ret;
 
 	pg_nest = nla_nest_start(skb, DCB_ATTR_PG_CFG);
 	if (!pg_nest)
-		goto err_out;
+		return -EMSGSIZE;
 
 	if (pg_tb[DCB_PG_ATTR_TC_ALL])
 		getall = 1;
@@ -674,7 +674,6 @@ static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
 					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
 		}
 		ret = nla_put_u8(skb, i, tc_pct);
-
 		if (ret)
 			goto err_pg;
 	}
@@ -687,9 +686,8 @@ err_param:
 	nla_nest_cancel(skb, param_nest);
 err_pg:
 	nla_nest_cancel(skb, pg_nest);
-err_out:
-	ret  = -EINVAL;
-	return ret;
+
+	return -EMSGSIZE;
 }
 
 static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
@@ -709,9 +707,12 @@ static int dcbnl_setstate(struct net_device *netdev, struct nlmsghdr *nlh,
 {
 	u8 value;
 
-	if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate)
+	if (!tb[DCB_ATTR_STATE])
 		return -EINVAL;
 
+	if (!netdev->dcbnl_ops->setstate)
+		return -EOPNOTSUPP;
+
 	value = nla_get_u8(tb[DCB_ATTR_STATE]);
 
 	return nla_put_u8(skb, DCB_ATTR_STATE,
@@ -723,17 +724,20 @@ static int dcbnl_setpfccfg(struct net_device *netdev, struct nlmsghdr *nlh,
 {
 	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)
@@ -744,17 +748,18 @@ static int dcbnl_setpfccfg(struct net_device *netdev, struct nlmsghdr *nlh,
 	}
 
 	return nla_put_u8(skb, DCB_ATTR_PFC_CFG, 0);
-err:
-	return ret;
 }
 
 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 = nla_put_u8(skb, DCB_ATTR_SET_ALL,
 			 netdev->dcbnl_ops->setall(netdev));
@@ -769,24 +774,26 @@ static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
 {
 	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])
@@ -795,7 +802,7 @@ static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
 		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;
@@ -848,10 +855,8 @@ static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
 		}
 	}
 
-	ret = nla_put_u8(skb, (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG), 0);
-
-err:
-	return ret;
+	return nla_put_u8(skb,
+			  (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG), 0);
 }
 
 static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
@@ -873,23 +878,25 @@ static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
 	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;
+		return ret;
 
 	bcn_nest = nla_nest_start(skb, DCB_ATTR_BCN);
 	if (!bcn_nest)
-		goto err_out;
+		return -EMSGSIZE;
 
 	if (bcn_tb[DCB_BCN_ATTR_ALL])
 		getall = true;
@@ -922,8 +929,6 @@ static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
 
 err_bcn:
 	nla_nest_cancel(skb, bcn_nest);
-err_out:
-	ret  = -EINVAL;
 	return ret;
 }
 
@@ -932,19 +937,22 @@ static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
 {
 	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)
@@ -962,9 +970,7 @@ static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
 	                                     i, value_int);
 	}
 
-	ret = nla_put_u8(skb, DCB_ATTR_BCN, 0);
-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,
@@ -1030,20 +1036,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) {
@@ -1053,7 +1060,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;
 		}
 	}
 
@@ -1062,12 +1069,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) {
@@ -1076,7 +1083,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;
 			}
 		}
 	}
@@ -1095,7 +1102,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) {
@@ -1103,7 +1110,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) {
@@ -1112,20 +1119,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,
@@ -1137,13 +1141,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 <= DCB_PG_ATTR_TC_7; i++) {
 		struct nlattr *tc_nest = nla_nest_start(skb, i);
 
 		if (!tc_nest)
-			goto nla_put_failure;
+			return -EMSGSIZE;
 
 		pgid = DCB_ATTR_VALUE_UNDEFINED;
 		prio = DCB_ATTR_VALUE_UNDEFINED;
@@ -1161,7 +1165,7 @@ static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
 		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map) ||
 		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio) ||
 		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct))
-			goto nla_put_failure;
+			return -EMSGSIZE;
 		nla_nest_end(skb, tc_nest);
 	}
 
@@ -1175,13 +1179,10 @@ static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
 			ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0,
 					   &tc_pct);
 		if (nla_put_u8(skb, i, tc_pct))
-			goto nla_put_failure;
+			return -EMSGSIZE;
 	}
 	nla_nest_end(skb, pg);
 	return 0;
-
-nla_put_failure:
-	return -EMSGSIZE;
 }
 
 static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
@@ -1380,10 +1381,10 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh,
 {
 	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
 	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
-	int err = -EOPNOTSUPP;
+	int err;
 
 	if (!ops)
-		return err;
+		return -EOPNOTSUPP;
 
 	if (!tb[DCB_ATTR_IEEE])
 		return -EINVAL;
@@ -1455,7 +1456,7 @@ static int dcbnl_ieee_del(struct net_device *netdev, struct nlmsghdr *nlh,
 {
 	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
 	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
-	int err = -EOPNOTSUPP;
+	int err;
 
 	if (!ops)
 		return -EOPNOTSUPP;
@@ -1687,10 +1688,12 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 
 	netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME]));
 	if (!netdev)
-		return -EINVAL;
+		return -ENODEV;
 
-	if (!netdev->dcbnl_ops)
-		goto errout;
+	if (!netdev->dcbnl_ops) {
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
 
 	reply_skb = dcbnl_newmsg(fn->type, dcb->cmd, pid, nlh->nlmsg_seq,
 				 nlh->nlmsg_flags, &reply_nlh);
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH 6/8] dcbnl: Move dcb app lookup code into dcb_app_lookup()
From: Thomas Graf @ 2012-06-13 12:54 UTC (permalink / raw)
  To: davem; +Cc: netdev, lucy.liu, john.r.fastabend, alexander.h.duyck
In-Reply-To: <cover.1339591572.git.tgraf@suug.ch>

Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
 net/dcb/dcbnl.c |   81 +++++++++++++++++++++++-------------------------------
 1 files changed, 35 insertions(+), 46 deletions(-)

diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 5a5bc25..6817f14 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1716,6 +1716,22 @@ out:
 	return ret;
 }
 
+static struct dcb_app_type *dcb_app_lookup(const struct dcb_app *app,
+					   int ifindex, int prio)
+{
+	struct dcb_app_type *itr;
+
+	list_for_each_entry(itr, &dcb_app_list, list) {
+		if (itr->app.selector == app->selector &&
+		    itr->app.protocol == app->protocol &&
+		    itr->ifindex == ifindex &&
+		    (!prio || itr->app.priority == prio))
+			return itr;
+	}
+
+	return NULL;
+}
+
 /**
  * dcb_getapp - retrieve the DCBX application user priority
  *
@@ -1729,14 +1745,8 @@ u8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
 	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 &&
-		    itr->ifindex == dev->ifindex) {
-			prio = itr->app.priority;
-			break;
-		}
-	}
+	if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
+		prio = itr->app.priority;
 	spin_unlock(&dcb_lock);
 
 	return prio;
@@ -1762,18 +1772,14 @@ int dcb_setapp(struct net_device *dev, struct dcb_app *new)
 
 	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 &&
-		    itr->ifindex == dev->ifindex) {
-			if (new->priority)
-				itr->app.priority = new->priority;
-			else {
-				list_del(&itr->list);
-				kfree(itr);
-			}
-			goto out;
+	if ((itr = dcb_app_lookup(new, dev->ifindex, 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) {
@@ -1808,13 +1814,8 @@ u8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
 	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 &&
-		    itr->ifindex == dev->ifindex) {
-			prio |= 1 << itr->app.priority;
-		}
-	}
+	if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
+		prio |= 1 << itr->app.priority;
 	spin_unlock(&dcb_lock);
 
 	return prio;
@@ -1830,7 +1831,7 @@ EXPORT_SYMBOL(dcb_ieee_getapp_mask);
  */
 int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
 {
-	struct dcb_app_type *itr, *entry;
+	struct dcb_app_type *entry;
 	struct dcb_app_type event;
 	int err = 0;
 
@@ -1841,14 +1842,9 @@ int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
 
 	spin_lock(&dcb_lock);
 	/* Search for existing match and abort if found */
-	list_for_each_entry(itr, &dcb_app_list, list) {
-		if (itr->app.selector == new->selector &&
-		    itr->app.protocol == new->protocol &&
-		    itr->app.priority == new->priority &&
-		    itr->ifindex == dev->ifindex) {
-			err = -EEXIST;
-			goto out;
-		}
+	if (dcb_app_lookup(new, dev->ifindex, new->priority)) {
+		err = -EEXIST;
+		goto out;
 	}
 
 	/* App entry does not exist add new entry */
@@ -1887,19 +1883,12 @@ int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
 
 	spin_lock(&dcb_lock);
 	/* Search for existing match and remove it. */
-	list_for_each_entry(itr, &dcb_app_list, list) {
-		if (itr->app.selector == del->selector &&
-		    itr->app.protocol == del->protocol &&
-		    itr->app.priority == del->priority &&
-		    itr->ifindex == dev->ifindex) {
-			list_del(&itr->list);
-			kfree(itr);
-			err = 0;
-			goto out;
-		}
+	if ((itr = dcb_app_lookup(del, dev->ifindex, del->priority))) {
+		list_del(&itr->list);
+		kfree(itr);
+		err = 0;
 	}
 
-out:
 	spin_unlock(&dcb_lock);
 	if (!err)
 		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH 7/8] dcbnl: Move dcb app allocation into dcb_app_add()
From: Thomas Graf @ 2012-06-13 12:55 UTC (permalink / raw)
  To: davem; +Cc: netdev, lucy.liu, john.r.fastabend, alexander.h.duyck
In-Reply-To: <cover.1339591572.git.tgraf@suug.ch>

Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
 net/dcb/dcbnl.c |   47 ++++++++++++++++++++++-------------------------
 1 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 6817f14..6e1c324 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1732,6 +1732,21 @@ static struct dcb_app_type *dcb_app_lookup(const struct dcb_app *app,
 	return NULL;
 }
 
+static int dcb_app_add(const struct dcb_app *app, int ifindex)
+{
+	struct dcb_app_type *entry;
+
+	entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+	if (!entry)
+		return -ENOMEM;
+
+	memcpy(&entry->app, app, sizeof(*app));
+	entry->ifindex = ifindex;
+	list_add(&entry->list, &dcb_app_list);
+
+	return 0;
+}
+
 /**
  * dcb_getapp - retrieve the DCBX application user priority
  *
@@ -1764,6 +1779,7 @@ int dcb_setapp(struct net_device *dev, struct dcb_app *new)
 {
 	struct dcb_app_type *itr;
 	struct dcb_app_type event;
+	int err = 0;
 
 	event.ifindex = dev->ifindex;
 	memcpy(&event.app, new, sizeof(event.app));
@@ -1782,22 +1798,13 @@ int dcb_setapp(struct net_device *dev, struct dcb_app *new)
 		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));
-		entry->ifindex = dev->ifindex;
-		list_add(&entry->list, &dcb_app_list);
-	}
+	if (new->priority)
+		err = dcb_app_add(new, dev->ifindex);
 out:
 	spin_unlock(&dcb_lock);
-	call_dcbevent_notifiers(DCB_APP_EVENT, &event);
-	return 0;
+	if (!err)
+		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
+	return err;
 }
 EXPORT_SYMBOL(dcb_setapp);
 
@@ -1831,7 +1838,6 @@ EXPORT_SYMBOL(dcb_ieee_getapp_mask);
  */
 int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
 {
-	struct dcb_app_type *entry;
 	struct dcb_app_type event;
 	int err = 0;
 
@@ -1847,16 +1853,7 @@ int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
 		goto out;
 	}
 
-	/* App entry does not exist add new entry */
-	entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
-	if (!entry) {
-		err = -ENOMEM;
-		goto out;
-	}
-
-	memcpy(&entry->app, new, sizeof(*new));
-	entry->ifindex = dev->ifindex;
-	list_add(&entry->list, &dcb_app_list);
+	err = dcb_app_add(new, dev->ifindex);
 out:
 	spin_unlock(&dcb_lock);
 	if (!err)
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH 8/8] dcbnl: Use type safe nlmsg_data()
From: Thomas Graf @ 2012-06-13 12:55 UTC (permalink / raw)
  To: davem; +Cc: netdev, lucy.liu, john.r.fastabend, alexander.h.duyck
In-Reply-To: <cover.1339591572.git.tgraf@suug.ch>

Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
 net/dcb/dcbnl.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 6e1c324..70bba3e 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1659,7 +1659,7 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
 	struct net *net = sock_net(skb->sk);
 	struct net_device *netdev;
-	struct dcbmsg  *dcb = (struct dcbmsg *)NLMSG_DATA(nlh);
+	struct dcbmsg *dcb = nlmsg_data(nlh);
 	struct nlattr *tb[DCB_ATTR_MAX + 1];
 	u32 pid = skb ? NETLINK_CB(skb).pid : 0;
 	int ret = -EINVAL;
-- 
1.7.7.6

^ permalink raw reply related

* Re: [PATCH 2/5] drivers/net/ethernet/dec/tulip: Use standard __set_bit_le() function
From: Akinobu Mita @ 2012-06-13 13:31 UTC (permalink / raw)
  To: Takuya Yoshikawa
  Cc: Takuya Yoshikawa, akpm, bhutchings, grundler, arnd, benh, avi,
	mtosatti, linux-net-drivers, netdev, linux-kernel, linux-arch,
	kvm
In-Reply-To: <20120613214157.0a5179d5358ec7f1b2646606@gmail.com>

2012/6/13 Takuya Yoshikawa <takuya.yoshikawa@gmail.com>:
> On Wed, 13 Jun 2012 18:43:40 +0900
> Akinobu Mita <akinobu.mita@gmail.com> wrote:
>
>> Should this hash_table be converted from u16 hash_table[32] to
>> DECLARE_BITMAP(hash_table, 16 * 32) to ensure that it is aligned
>> on long-word boundary?
>
> I think hash_table is already long-word aligned because it is placed
> right after a pointer.

I recommend converting to proper bitmap.  Because such an implicit
assumption is easily broken by someone touching this function.

^ permalink raw reply

* Re: [PATCH] bnx2x: fix checksum validation
From: Eilon Greenstein @ 2012-06-13 13:42 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David Miller, netdev, Tom Herbert, Robert Evans, Willem de Bruijn,
	Yaniv Rosner, Merav Sicron, Yuval Mintz
In-Reply-To: <1339581004.22704.340.camel@edumazet-glaptop>

On Wed, 2012-06-13 at 11:50 +0200, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
> 
> bnx2x driver incorrectly sets ip_summed to CHECKSUM_UNNECESSARY on
> encapsulated segments. TCP stack happily accepts frames with bad
> checksums, if they are inside a GRE or IPIP encapsulation.

So what you are saying is that the indication that the checksum is valid
is interpreted as the encapsulated checksum and not just the IP
header... This was not the intention of this code, it was meant to
indicate that the IP header is valid.

> Our understanding is that if no IP or L4 csum validation was done by the
> hardware, we should leave ip_summed as is (CHECKSUM_NONE), since
> hardware doesn't provide CHECKSUM_COMPLETE support in its cqe.
> 
> Then, if IP/L4 checksumming was done by the hardware, set
> CHECKSUM_UNNECESSARY if no error was flagged.
> 
> Patch based on findings and analysis from Robert Evans

I must admit that the code looks much better with this change. The only
down side is that there is no longer IP checksum offload for pure IP
packets, but that's negligible. The only thing that bothers me is that
there is no way to indicate anything about the encapsulated packet
separately from the outer header. Is that the way we want to keep it?

> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Eilon Greenstein <eilong@broadcom.com>
> Cc: Yaniv Rosner <yanivr@broadcom.com>
> Cc: Merav Sicron <meravs@broadcom.com>
> Cc: Tom Herbert <therbert@google.com>
> Cc: Robert Evans <evansr@google.com>
> Cc: Willem de Bruijn <willemb@google.com>
> ---
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x.h     |   15 -------
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c |   27 ++++++++++----
>  2 files changed, 21 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
> index e30e2a2..7de8241 100644
> --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
> +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
> @@ -747,21 +747,6 @@ struct bnx2x_fastpath {
>  
>  #define ETH_RX_ERROR_FALGS		ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG
>  
> -#define BNX2X_IP_CSUM_ERR(cqe) \
> -			(!((cqe)->fast_path_cqe.status_flags & \
> -			   ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG) && \
> -			 ((cqe)->fast_path_cqe.type_error_flags & \
> -			  ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG))
> -
> -#define BNX2X_L4_CSUM_ERR(cqe) \
> -			(!((cqe)->fast_path_cqe.status_flags & \
> -			   ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) && \
> -			 ((cqe)->fast_path_cqe.type_error_flags & \
> -			  ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG))
> -
> -#define BNX2X_RX_CSUM_OK(cqe) \
> -			(!(BNX2X_L4_CSUM_ERR(cqe) || BNX2X_IP_CSUM_ERR(cqe)))
> -
>  #define BNX2X_PRS_FLAG_OVERETH_IPV4(flags) \
>  				(((le16_to_cpu(flags) & \
>  				   PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) >> \
> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
> index ad0743b..cbc56f2 100644
> --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
> +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
> @@ -617,6 +617,25 @@ static int bnx2x_alloc_rx_data(struct bnx2x *bp,
>  	return 0;
>  }
>  
> +static void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe,
> +				struct bnx2x_fastpath *fp)
> +{
> +	/* Do nothing if no IP/L4 csum validation was done */
> +
> +	if (cqe->fast_path_cqe.status_flags &
> +	    (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG |
> +	     ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG))
> +		return;
> +
> +	/* If both IP/L4 validation were done, check if an error was found. */
> +
> +	if (cqe->fast_path_cqe.type_error_flags &
> +	    (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG |
> +	     ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG))
> +		fp->eth_q_stats.hw_csum_err++;
> +	else
> +		skb->ip_summed = CHECKSUM_UNNECESSARY;
> +}
>  
>  int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
>  {
> @@ -806,13 +825,9 @@ reuse_rx:
>  
>  		skb_checksum_none_assert(skb);
>  
> -		if (bp->dev->features & NETIF_F_RXCSUM) {
> +		if (bp->dev->features & NETIF_F_RXCSUM)
> +			bnx2x_csum_validate(skb, cqe, fp);
>  
> -			if (likely(BNX2X_RX_CSUM_OK(cqe)))
> -				skb->ip_summed = CHECKSUM_UNNECESSARY;
> -			else
> -				fp->eth_q_stats.hw_csum_err++;
> -		}
>  
>  		skb_record_rx_queue(skb, fp->rx_queue);
>  
> 
> 
> 

^ permalink raw reply

* Re: PPPoE performance regression
From: David Woodhouse @ 2012-06-13 13:50 UTC (permalink / raw)
  To: Nathan Williams
  Cc: Karl Hiramoto, David S. Miller, netdev, Paul Mackerras,
	John Crispin
In-Reply-To: <1339581421.11011.18.camel@shinybook.infradead.org>

[-- Attachment #1: Type: text/plain, Size: 2129 bytes --]

On Wed, 2012-06-13 at 10:57 +0100, David Woodhouse wrote:
> This doesn't look *so* evil... if the basic concept of using
> skb_orphan() and then setting our own destructor is OK, then I'll work
> out the rest of the details and do it for l2tp too.

Stupid dwmw2. With patch this time...

diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index cbf7047..ddaf156 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -689,6 +689,8 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
 		sk->sk_state = PPPOX_CONNECTED;
 	}
 
+	atomic_set(&po->inflight, -2);
+
 	po->num = sp->sa_addr.pppoe.sid;
 
 end:
@@ -952,9 +954,34 @@ abort:
  * sends PPP frame over PPPoE socket
  *
  ***********************************************************************/
+static void pppoe_skb_destructor(struct sk_buff *skb)
+{
+	struct sock *sk = skb->sk;
+	struct pppox_sock *po = pppox_sk(sk);
+
+	atomic_dec(&po->inflight);
+	/* Schedule a call to ppp_output_wakeup(chan), if it was already blocked.
+	   Mind for race conditions with another CPU which is in pppoe_xmit() 
+	   right now. See commit 9d02daf7 in pppoatm. */
+	sock_put(sk);
+}
+
 static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb)
 {
 	struct sock *sk = (struct sock *)chan->private;
+	struct pppox_sock *po = pppox_sk(sk);
+
+	if (!atomic_inc_not_zero(&po->inflight))
+		return 0;
+
+	/* mine! all mine! */
+	skb_orphan(skb);
+	skb->destructor = pppoe_skb_destructor;
+	/* XXX: Are there other implications of setting this? Should we use ->cb? */
+	skb->sk = sk;
+
+	sock_hold(sk);
+
 	return __pppoe_xmit(sk, skb);
 }
 
diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
index 09c474c..339c75d 100644
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -186,6 +186,7 @@ struct pppox_sock {
 	/* struct sock must be the first member of pppox_sock */
 	struct sock sk;
 	struct ppp_channel chan;
+	atomic_t inflight;
 	struct pppox_sock	*next;	  /* for hash table */
 	union {
 		struct pppoe_opt pppoe;

-- 
dwmw2

[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 6171 bytes --]

^ permalink raw reply related

* Re: [net-next patch 8/12] bnx2x: Allow up to 63 RSS queues default 8 queues
From: Eric Dumazet @ 2012-06-13 13:59 UTC (permalink / raw)
  To: eilong; +Cc: Merav Sicron, davem, netdev
In-Reply-To: <1339595609.13000.15.camel@lb-tlvb-eilong.il.broadcom.com>

On Wed, 2012-06-13 at 16:53 +0300, Eilon Greenstein wrote:
> On Wed, 2012-06-13 at 18:14 +0300, Merav Sicron wrote:
> > Hi Eric,
> > 
> > On Wed, 2012-06-13 at 11:52 +0200, Eric Dumazet wrote:
> > > On Wed, 2012-06-13 at 15:44 +0300, Merav Sicron wrote:
> > > > This patch removed the limitation in the code for 16 RSS queues. The default
> > > > (without other instruction from the user) number of queues is determined
> > > > according to the number of MSI-X vectors supported for that function, the number
> > > > of CPUs in the system, and a maximum of 8 queues.
> > > 
> > > Thats a very confusing changelog
> > > 
> > > You meant : " a minimum of 8 queues" ?
> > > 
> > No, I meant maximum...for example in a system with 16 CPUs we will
> > allocate 8 RSS queues. We saw that in most scenarios we tested there was
> > no need for more than 8 queues to get the maximal throughput, and by
> > limiting to 8 by default we reduce the allocated memory. We do provide
> > ethtool -L support so that the user could request more RSS queues if
> > desired.
> > 
> > > You should give more explanations, because its a sensible area for
> > > performances.
> > > 
> 
> Just to emphasis, since this is the patch series that enable the users
> to control the number of queues, we can reduce the default number and
> allow the user to increase it if he has a setup that needs more than 8
> parallel CPUs to receive the traffic. When using a new FW on the board,
> the number can be increased up to 64, so using the maximal number can be
> an overkill (even if the machine has 64 CPUs, it does not mean that the
> user would like us to consume 64 MSI-X vectors and all the memory to set
> up 64 queues) - so a lower default value can be used to satisfy most
> users while allowing them to increase the number if they wish.

I am all for a reduction of default number of queues.

Even a laptop has now 8 cpus, so on servers, using one queue per cpu is
overkill for most uses.

Thanks

^ permalink raw reply

* Re: [PATCH] netpoll: fix netpoll_send_udp() bugs
From: Cong Wang @ 2012-06-13 13:59 UTC (permalink / raw)
  To: netdev
In-Reply-To: <1339565421.22704.310.camel@edumazet-glaptop>

On Wed, 13 Jun 2012 at 05:30 GMT, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> Bogdan Hamciuc diagnosed and fixed following bug in netpoll_send_udp() :
>
> "skb->len += len;" instead of "skb_put(skb, len);"
>
> Meaning that _if_ a network driver needs to call skb_realloc_headroom(),
> only packet headers would be copied, leaving garbage in the payload.
>
> However the skb_realloc_headroom() must be avoided as much as possible
> since it requires memory and netpoll tries hard to work even if memory
> is exhausted (using a pool of preallocated skbs)
>
> It appears netpoll_send_udp() reserved 16 bytes for the ethernet header,
> which happens to work for typicall drivers but not all.
>
> Right thing is to use LL_RESERVED_SPACE(dev)
> (And also add dev->needed_tailroom of tailroom)
>
> This patch combines both fixes.
>
> Many thanks to Bogdan for raising this issue.
>

Reviewed-by: Cong Wang <xiyou.wangcong@gmail.com>

Need to apply to -stable?

Thanks.

^ permalink raw reply

* Re: [PATCH 2/5] drivers/net/ethernet/dec/tulip: Use standard __set_bit_le() function
From: Takuya Yoshikawa @ 2012-06-13 14:00 UTC (permalink / raw)
  To: Akinobu Mita
  Cc: Takuya Yoshikawa, akpm, bhutchings, grundler, arnd, benh, avi,
	mtosatti, linux-net-drivers, netdev, linux-kernel, linux-arch,
	kvm
In-Reply-To: <CAC5umygutE35hVObuooWj=ADP6PZDy4cqLtxGnRtxRX8uTtGSw@mail.gmail.com>

On Wed, 13 Jun 2012 22:31:13 +0900
Akinobu Mita <akinobu.mita@gmail.com> wrote:

> >> Should this hash_table be converted from u16 hash_table[32] to
> >> DECLARE_BITMAP(hash_table, 16 * 32) to ensure that it is aligned
> >> on long-word boundary?
> >
> > I think hash_table is already long-word aligned because it is placed
> > right after a pointer.
> 
> I recommend converting to proper bitmap.  Because such an implicit
> assumption is easily broken by someone touching this function.

Do you mean something like:
	DECLARE_BITMAP(__hash_table, 16 * 32);
	u16 *hash_table = (u16 *)__hash_table;
?

Grant, what do you think about this?

	Takuya


===
drivers/net/ethernet/dec/tulip/tulip_core.c:

static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
{
	struct tulip_private *tp = netdev_priv(dev);
	u16 hash_table[32];
	...
}

drivers/net/ethernet/dec/tulip/de2104x.c:

static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
{
	struct de_private *de = netdev_priv(dev);
	u16 hash_table[32];
	...
}

^ permalink raw reply

* Re: [net-next patch 8/12] bnx2x: Allow up to 63 RSS queues default 8 queues
From: Eilon Greenstein @ 2012-06-13 13:53 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Merav Sicron, davem, netdev
In-Reply-To: <1339600460.17240.69.camel@lb-tlvb-meravs.il.broadcom.com>

On Wed, 2012-06-13 at 18:14 +0300, Merav Sicron wrote:
> Hi Eric,
> 
> On Wed, 2012-06-13 at 11:52 +0200, Eric Dumazet wrote:
> > On Wed, 2012-06-13 at 15:44 +0300, Merav Sicron wrote:
> > > This patch removed the limitation in the code for 16 RSS queues. The default
> > > (without other instruction from the user) number of queues is determined
> > > according to the number of MSI-X vectors supported for that function, the number
> > > of CPUs in the system, and a maximum of 8 queues.
> > 
> > Thats a very confusing changelog
> > 
> > You meant : " a minimum of 8 queues" ?
> > 
> No, I meant maximum...for example in a system with 16 CPUs we will
> allocate 8 RSS queues. We saw that in most scenarios we tested there was
> no need for more than 8 queues to get the maximal throughput, and by
> limiting to 8 by default we reduce the allocated memory. We do provide
> ethtool -L support so that the user could request more RSS queues if
> desired.
> 
> > You should give more explanations, because its a sensible area for
> > performances.
> > 

Just to emphasis, since this is the patch series that enable the users
to control the number of queues, we can reduce the default number and
allow the user to increase it if he has a setup that needs more than 8
parallel CPUs to receive the traffic. When using a new FW on the board,
the number can be increased up to 64, so using the maximal number can be
an overkill (even if the machine has 64 CPUs, it does not mean that the
user would like us to consume 64 MSI-X vectors and all the memory to set
up 64 queues) - so a lower default value can be used to satisfy most
users while allowing them to increase the number if they wish.

Thanks,
Eilon

^ permalink raw reply

* Re: [PATCH] bnx2x: fix checksum validation
From: Eric Dumazet @ 2012-06-13 14:10 UTC (permalink / raw)
  To: eilong
  Cc: David Miller, netdev, Tom Herbert, Robert Evans, Willem de Bruijn,
	Yaniv Rosner, Merav Sicron, Yuval Mintz
In-Reply-To: <1339594957.13000.7.camel@lb-tlvb-eilong.il.broadcom.com>

On Wed, 2012-06-13 at 16:42 +0300, Eilon Greenstein wrote:

> So what you are saying is that the indication that the checksum is valid
> is interpreted as the encapsulated checksum and not just the IP
> header... This was not the intention of this code, it was meant to
> indicate that the IP header is valid.
> 

IP header is always checked by our stack.

Its so fast that there is no point spending a bit in skb, and testing
this bit.

Yes, CHECKSUM_UNNECESSARY really means everything was checked up to L4

> I must admit that the code looks much better with this change. The only
> down side is that there is no longer IP checksum offload for pure IP
> packets, but that's negligible. The only thing that bothers me is that
> there is no way to indicate anything about the encapsulated packet
> separately from the outer header. Is that the way we want to keep it?

Some NIC allow for csum L3 offloading, providing the 16bit csum.

We then can :

skb->csum = csum;
skb->ip_summed = CHECKSUM_COMPLETE;

Check drivers/net/ethernet/ibm/ehea/ehea_main.c,
drivers/net/ethernet/marvell/skge.c ,
drivers/net/ethernet/marvell/sky2.c , ... for examples.


When a layer is removed(pulled), we can use skb_postpull_rcsum() and
friends (check net/ipv4/ip_gre.c for example) to keep skb->csum up2date.


If bnx2x provides this csum (for non TCP/UCP packets or fragments), you
could fallback to this CHECKSUM_COMPLETE stuff.

^ permalink raw reply

* Re: [PATCH] bnx2x: fix checksum validation
From: Eilon Greenstein @ 2012-06-13 14:21 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David Miller, netdev, Tom Herbert, Robert Evans, Willem de Bruijn,
	Yaniv Rosner, Merav Sicron, Yuval Mintz
In-Reply-To: <1339596605.22704.363.camel@edumazet-glaptop>

On Wed, 2012-06-13 at 16:10 +0200, Eric Dumazet wrote:
> On Wed, 2012-06-13 at 16:42 +0300, Eilon Greenstein wrote:
> 
> > So what you are saying is that the indication that the checksum is valid
> > is interpreted as the encapsulated checksum and not just the IP
> > header... This was not the intention of this code, it was meant to
> > indicate that the IP header is valid.
> > 
> 
> IP header is always checked by our stack.
> 
> Its so fast that there is no point spending a bit in skb, and testing
> this bit.
> 
> Yes, CHECKSUM_UNNECESSARY really means everything was checked up to L4
> 
> > I must admit that the code looks much better with this change. The only
> > down side is that there is no longer IP checksum offload for pure IP
> > packets, but that's negligible. The only thing that bothers me is that
> > there is no way to indicate anything about the encapsulated packet
> > separately from the outer header. Is that the way we want to keep it?
> 
> Some NIC allow for csum L3 offloading, providing the 16bit csum.
> 
> We then can :
> 
> skb->csum = csum;
> skb->ip_summed = CHECKSUM_COMPLETE;
> 
> Check drivers/net/ethernet/ibm/ehea/ehea_main.c,
> drivers/net/ethernet/marvell/skge.c ,
> drivers/net/ethernet/marvell/sky2.c , ... for examples.
> 
> 
> When a layer is removed(pulled), we can use skb_postpull_rcsum() and
> friends (check net/ipv4/ip_gre.c for example) to keep skb->csum up2date.
> 
> 
> If bnx2x provides this csum (for non TCP/UCP packets or fragments), you
> could fallback to this CHECKSUM_COMPLETE stuff.
> 
> 

Thanks Erik. This leaves me with just one thing to add:
Acked-by: Eilon Greenstein <eilong@broadcom.com>

^ permalink raw reply

* RE: [net-next 1/9] igb: Add support functions to access thermal data.
From: Wyborny, Carolyn @ 2012-06-13 14:53 UTC (permalink / raw)
  To: Ben Hutchings, Kirsher, Jeffrey T
  Cc: davem@davemloft.net, netdev@vger.kernel.org, gospo@redhat.com,
	sassmann@redhat.com
In-Reply-To: <1339289333.21665.156.camel@deadeye.wl.decadent.org.uk>

>-----Original Message-----
>From: Ben Hutchings [mailto:bhutchings@solarflare.com]
>Sent: Saturday, June 09, 2012 5:49 PM
>To: Kirsher, Jeffrey T
>Cc: davem@davemloft.net; Wyborny, Carolyn; netdev@vger.kernel.org;
>gospo@redhat.com; sassmann@redhat.com
>Subject: Re: [net-next 1/9] igb: Add support functions to access thermal
>data.
>
>On Sat, 2012-06-09 at 01:20 -0700, Jeff Kirsher wrote:
>> From: Carolyn Wyborny <carolyn.wyborny@intel.com>
>>
>> Some i350 devices contain thermal data that we can get to via an i2c
>> interface.  These functions provide support to get at that data.  A
>> following patch will export this data.
>[...]
>
>We already have an I2C subsystem - so don't replicate i2c-algo-bit etc.
>
>It's possible we also have an hwmon driver for whatever temperature
>sensor is on these boards, which you can then probe by calling
>i2c_new_device().

I am not sure that our sensors will be compatible, but I will research it to be sure.  I will also take a look at what we can do with the i2c interface that already exists and make sure we are not duplicating any of it.

Thanks,

Carolyn

Carolyn Wyborny
Linux Development
LAN Access Division
Intel Corporation



^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox