Netdev List
 help / color / mirror / Atom feed
* Re: [RFC net-next PATCH V2 2/3] qdisc: bulk dequeue support for qdiscs with TCQ_F_ONETXQUEUE
From: Jesper Dangaard Brouer @ 2014-09-05  8:28 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: netdev, David S. Miller, Tom Herbert, Hannes Frederic Sowa,
	Florian Westphal, Daniel Borkmann, Jamal Hadi Salim,
	Alexander Duyck, John Fastabend, brouer
In-Reply-To: <1409837383.26422.113.camel@edumazet-glaptop2.roam.corp.google.com>

On Thu, 04 Sep 2014 06:29:43 -0700
Eric Dumazet <eric.dumazet@gmail.com> wrote:

> On Thu, 2014-09-04 at 14:55 +0200, Jesper Dangaard Brouer wrote:
> > Based on DaveM's recent API work on dev_hard_start_xmit(), that allows
> > sending/processing an entire skb list.
> > 
> > This patch implements qdisc bulk dequeue, by allowing multiple packets
> > to be dequeued in dequeue_skb().
> > 
> > The optimization principle for this is two fold, (1) to amortize
> > locking cost and (2) avoid expensive tailptr update for notifying HW.
> >  (1) Several packets are dequeued while holding the qdisc root_lock,
> > amortizing locking cost over several packet.  The dequeued SKB list is
> > processed under the TXQ lock in dev_hard_start_xmit(), thus also
> > amortizing the cost of the TXQ lock.
> >  (2) Further more, dev_hard_start_xmit() will utilize the skb->xmit_more
> > API to delay HW tailptr update, which also reduces the cost per
> > packet.
> > 
> > One restriction of the new API is that every SKB must belong to the
> > same TXQ.  This patch takes the easy way out, by restricting bulk
> > dequeue to qdisc's with the TCQ_F_ONETXQUEUE flag, that specifies the
> > qdisc only have attached a single TXQ.
> > 
> > Some detail about the flow; dev_hard_start_xmit() will process the skb
> > list, and transmit packets individually towards the driver (see
> > xmit_one()).  In case the driver stops midway in the list, the
> > remaining skb list is returned by dev_hard_start_xmit().  In
> > sch_direct_xmit() this returned list is requeued by dev_requeue_skb().
> > 
> > The patch also tries to limit the amount of bytes dequeued, based on
> > the drivers BQL limits.  It also tries to avoid and stop dequeuing
> > when seeing a GSO packet (both real GSO and segmented GSO skb lists).
> > 
> > Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
> > 
> > ---
> > V2:
> >  - Restruct functions, split out functionality
> >  - Use BQL bytelimit to avoid overshooting driver limits, causing
> >    too large skb lists to be sitting on the requeue gso_skb.
> > 
> >  net/sched/sch_generic.c |   67 +++++++++++++++++++++++++++++++++++++++++++++--
> >  1 files changed, 64 insertions(+), 3 deletions(-)
> > 
> > diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
> > index 19696eb..a0c8070 100644
> > --- a/net/sched/sch_generic.c
> > +++ b/net/sched/sch_generic.c
> > @@ -56,6 +56,67 @@ static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q)
> >  	return 0;
> >  }
> >  
> > +static inline bool qdisc_may_bulk(const struct Qdisc *qdisc,
> > +				  const struct sk_buff *skb)
> 
> Why skb is passed here ?

Just a left over, when the func did more checking.

> > +{
> > +	return (qdisc->flags & TCQ_F_ONETXQUEUE);
> 	
> 	return qdisc->flags & TCQ_F_ONETXQUEUE;

Sure, nitpick ;-)


> > +}
> > +
> > +static inline struct sk_buff *qdisc_dequeue_validate(struct Qdisc *qdisc)
> > +{
> > +	struct sk_buff *skb = qdisc->dequeue(qdisc);
> > +
> > +	if (skb != NULL)
> > +		skb = validate_xmit_skb(skb, qdisc_dev(qdisc));
> 
> > +
> > +	return skb;
> > +}
> > +
> > +static inline struct sk_buff *qdisc_bulk_dequeue_skb(struct Qdisc *q,
> > +						     struct sk_buff *head)
> > +{
> > +	struct sk_buff *new, *skb = head;
> > +	struct netdev_queue *txq = q->dev_queue;
> > +	int bytelimit = netdev_tx_avail_queue(txq);
> > +	int limit = 5;
> > +
> > +	if (bytelimit <= 0)
> > +		return head;
> > +
> > +	do {
> > +		if (skb->next || skb_is_gso(skb)) {
> 
> A GSO packet should not 'stop the processing' if the device is TSO
> capable : It should look as a normal packet.

So, I cannot see if it is a TSO packet via the skb_is_gso(skb) check?
Will skb->len be the length of the full TSO packet size?

This check (skb->next) also guards against new=qdisc_dequeue_validate()
returned a list (GSO segmenting), in last "round" (now here skb=new),
as I then can assign the next "new" packet directly to skb->next=new
(without checking if new is a skb list).


> > +			/* Stop processing if the skb is already a skb
> > +			 * list (e.g a segmented GSO packet) or a real
> > +			 * GSO packet */
> > +			break;
> > +		}
> > +		new = qdisc_dequeue_validate(q);
> 
> Thats broken.
> 
> After validate_xmit_skb()  @new might be the head of a list. (GSO split)

As described above, I think, I'm handling this case, as I don't allow
further processing if I detect that this was an skb list.
 
> 
> 
> > +		if (new) {
> > +			skb->next = new;
> 
> 
> > +			skb = new;
> 
> and new is only the first element on the list.
> 
> > +			bytelimit -= skb->len;
> 
> skb->len is the length of first segment.

Damn, yes, then I will have to walk the "new" skb in-case it is a list,
I was hoping to avoid that.


> > +			cnt++;
(ups, debug left over)

> > +			/* One problem here is it is difficult to
> > +			 * requeue the "new" dequeued skb, e.g. in
> > +			 * case of GSO, thus a "normal" packet can
> > +			 * have a GSO packet on its ->next ptr.
> > +			 *
> > +			 * Requeue is difficult because if requeuing
> > +			 * on q->gso_skb, then a second requeue can
> > +			 * happen from sch_direct_xmit e.g. if driver
> > +			 * returns NETDEV_TX_BUSY, which would
> > +			 * overwrite this requeue.
> > +			 */
> 
> It should not overwrite, but insert back. Thats what need to be done.

Okay, guess that should/could be handled in dev_requeue_skb().

In this case with (TCQ_F_ONETXQUEUE) the end result of not requeuing
here is almost the same.  In case dev_hard_start_xmit() didn't xmit the
entire list, it will be placed back on the requeue (q->gso_skb) anyway.
Thus we might be better off just sending this to the device, instead of
requeuing explicitly here.


> > +		}
> > +	} while (new && --limit && (bytelimit > 0));
> > +	skb = head;
> > +
> > +	return skb;
> > +}
> > +
> 
> 
> Idea is really the following :
> 
> Once qdisc dequeue bulk is done, and skb validated, we have a list of
> skb to send to the device.
> 
> We iterate the list and try to send the individual skb.
> 
> As soon as device returns NETDEV_TX_BUSY (or even better, when the queue
> is stopped), we requeue the remaining list.

Yes, that is also my understanding.

The "dangerous" part is the size (in bytes) of the requeued remaining
list.  In the-meantime while the driver/queue have been stopped, a high
priority packet might have been queued in the qdisc.  When we start to
dequeue again, then the requeued list is transmitted *before* dequeuing
the high prio packet sitting in the real qdisc queue. (That is what you
call head-of-line blocking right)


> BQL never tried to find the exact split point :
> 
> If available budget is 25000 bytes, and next TSO packet is 45000 bytes,
> we send it.

Okay, so it is okay to overshoot, which I also think this patch does.


> So the bql validation should be done before the eventual
> validate_xmit_skb() : This way you dont care of GSO or TSO.

If do a skb=q->dequeue(q), and the packet is a GSO packet, then
skb->len should be valid/cover-hole-packet right? (I could use that,
and avoid walking the gso list).


-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Sr. Network Kernel Developer at Red Hat
  Author of http://www.iptv-analyzer.org
  LinkedIn: http://www.linkedin.com/in/brouer

^ permalink raw reply

* [PATCH net-next] netfilter: create audit records for ebtables replaces
From: Nicolas Dichtel @ 2014-09-05  8:50 UTC (permalink / raw)
  To: pablo, kaber, kadlec, stephen, davem, netfilter-devel, bridge,
	netdev, linux-audit
  Cc: nicolas.dichtel

This is already done for x_tables (family AF_INET and AF_INET6), let's do it
for AF_BRIDGE also.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 net/bridge/netfilter/ebtables.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 6d69631b9f4d..4ba0c5c78778 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -26,6 +26,7 @@
 #include <asm/uaccess.h>
 #include <linux/smp.h>
 #include <linux/cpumask.h>
+#include <linux/audit.h>
 #include <net/sock.h>
 /* needed for logical [in,out]-dev filtering */
 #include "../br_private.h"
@@ -1126,6 +1127,20 @@ static int do_replace(struct net *net, const void __user *user,
 	}
 
 	ret = do_replace_finish(net, &tmp, newinfo);
+#ifdef CONFIG_AUDIT
+	if (audit_enabled) {
+		struct audit_buffer *ab;
+
+		ab = audit_log_start(current->audit_context, GFP_KERNEL,
+				     AUDIT_NETFILTER_CFG);
+		if (ab) {
+			audit_log_format(ab, "table=%s family=%u entries=%u",
+					 tmp.name, AF_BRIDGE,
+					 tmp.nentries);
+			audit_log_end(ab);
+		}
+	}
+#endif
 	if (ret == 0)
 		return ret;
 free_entries:
-- 
1.9.0

^ permalink raw reply related

* Re: [RFC v2 3/6] kthread: warn on kill signal if not OOM
From: Mike Galbraith @ 2014-09-05  9:14 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Tejun Heo, Greg Kroah-Hartman, Dmitry Torokhov, Wu Zhangjin,
	Takashi Iwai, Arjan van de Ven, linux-kernel@vger.kernel.org,
	Oleg Nesterov, hare, Andrew Morton, Tetsuo Handa,
	Joseph Salisbury, Benjamin Poirier, Santosh Rastapur, Kay Sievers,
	One Thousand Gnomes, Tim Gardner, Pierre Fersing,
	Nagalakshmi Nandigama, Praveen Krishnamoorthy,
	Sreekanth Reddy <sreekanth.reddy
In-Reply-To: <CAB=NE6Wti1RpAFk5q_YeZn2F9Rd=wsiwhyPszu74nG9fXwH5vQ@mail.gmail.com>

On Fri, 2014-09-05 at 00:47 -0700, Luis R. Rodriguez wrote: 
> On Fri, Sep 5, 2014 at 12:19 AM, Tejun Heo <tj@kernel.org> wrote:
> > On Thu, Sep 04, 2014 at 11:37:24PM -0700, Luis R. Rodriguez wrote:
> > ...
> >> +             /*
> >> +              * I got SIGKILL, but wait for 60 more seconds for completion
> >> +              * unless chosen by the OOM killer. This delay is there as a
> >> +              * workaround for boot failure caused by SIGKILL upon device
> >> +              * driver initialization timeout.
> >> +              *
> >> +              * N.B. this will actually let the thread complete regularly,
> >> +              * wait_for_completion() will be used eventually, the 60 second
> >> +              * try here is just to check for the OOM over that time.
> >> +              */
> >> +             WARN_ONCE(!test_thread_flag(TIF_MEMDIE),
> >> +                       "Got SIGKILL but not from OOM, if this issue is on probe use .driver.async_probe\n");
> >> +             for (i = 0; i < 60 && !test_thread_flag(TIF_MEMDIE); i++)
> >> +                     if (wait_for_completion_timeout(&done, HZ))
> >> +                             goto wait_done;
> >> +
> >
> > Ugh... Jesus, this is way too hacky, so now we fail on 90s timeout
> > instead of 30?
> 
> Nope! I fell into the same trap and only with tons of patience by part
> of Tetsuo with me was I able to grok that the 60 seconds here are not
> for increasing the timeout, this is just time spent checking to ensure
> that the OOM wasn't the one who triggered the SIGKILL. Even if the
> drivers took eons it should be fine now, I tried it :D
> 
> >  Why do we even need this with the proposed async
> > probing changes?
> 
> Ah -- well without it the way we "find" drivers that need this new
> "async feature" is by a bug report and folks saying their system can't
> boot, or they say their device doesn't come up. That's all. Tracing
> this to systemd and a timeout was one of the most ugliest things ever.
> There two insane bug reports you can go check:
> 
> mptsas was the first:
> 
> http://article.gmane.org/gmane.linux.kernel/1669550
> https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/1297248

<quote>
(2) Currently systemd-udevd unconditionally sends SIGKILL upon hardcoded
    30 seconds timeout. As a result, finit_module() of mptsas kernel
    module receives SIGKILL when waiting for error handler thread to be
    started.
</quote>

Hm.  Why is this not a systemd-udevd bug for running around killing
stuff when it has no idea whether progress is being made or not?

-Mike

^ permalink raw reply

* [patch net-next] bonding: add slave netlink policy and put slave-related ops together
From: Jiri Pirko @ 2014-09-05  9:36 UTC (permalink / raw)
  To: netdev; +Cc: davem, j.vosburgh, nikolay, vfalico, andy

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 drivers/net/bonding/bond_netlink.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index 1570dea..e1489d9 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -96,6 +96,10 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
 	[IFLA_BOND_AD_INFO]		= { .type = NLA_NESTED },
 };
 
+static const struct nla_policy bond_slave_policy[IFLA_BOND_SLAVE_MAX + 1] = {
+	[IFLA_BOND_SLAVE_QUEUE_ID]	= { .type = NLA_U16 },
+};
+
 static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
 {
 	if (tb[IFLA_ADDRESS]) {
@@ -580,17 +584,18 @@ struct rtnl_link_ops bond_link_ops __read_mostly = {
 	.priv_size		= sizeof(struct bonding),
 	.setup			= bond_setup,
 	.maxtype		= IFLA_BOND_MAX,
-	.slave_maxtype		= IFLA_BOND_SLAVE_MAX,
 	.policy			= bond_policy,
 	.validate		= bond_validate,
 	.newlink		= bond_newlink,
 	.changelink		= bond_changelink,
-	.slave_changelink	= bond_slave_changelink,
 	.get_size		= bond_get_size,
 	.fill_info		= bond_fill_info,
 	.get_num_tx_queues	= bond_get_num_tx_queues,
 	.get_num_rx_queues	= bond_get_num_tx_queues, /* Use the same number
 							     as for TX queues */
+	.slave_maxtype		= IFLA_BOND_SLAVE_MAX,
+	.slave_policy		= bond_slave_policy,
+	.slave_changelink	= bond_slave_changelink,
 	.get_slave_size		= bond_get_slave_size,
 	.fill_slave_info	= bond_fill_slave_info,
 };
-- 
1.9.3

^ permalink raw reply related

* [PATCH iproute2] Revert "ip: check for missing dev arg when doing VF rate"
From: Nicolas Dichtel @ 2014-09-05  9:37 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

This reverts commit 9a02651a87d0fd56e2e7eedd63921a050a42b3ec.

This commit breaks backward compatibility. Before the commit, this kind of
command was allowed:
ip link add myiface type ...
Now, it returns an error, we should add the arg 'name':
ip link add name myiface type ...

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 ip/iplink.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/ip/iplink.c b/ip/iplink.c
index 1a907d998a87..bbcdc83d4c91 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -349,7 +349,6 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
 
 	if (new_rate_api) {
 		int tmin, tmax;
-
 		if (tivt.min_tx_rate == -1 || tivt.max_tx_rate == -1) {
 			ipaddr_get_vf_rate(tivt.vf, &tmin, &tmax, dev_index);
 			if (tivt.min_tx_rate == -1)
@@ -382,7 +381,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 	int vf = -1;
 	int numtxqueues = -1;
 	int numrxqueues = -1;
-	int dev_index = 0;
+	int dev_index;
 
 	*group = -1;
 	ret = argc;
@@ -495,9 +494,6 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 			}
 			vflist = addattr_nest(&req->n, sizeof(*req),
 					      IFLA_VFINFO_LIST);
-			if (dev_index == 0)
-				missarg("dev");
-
 			len = iplink_parse_vf(vf, &argc, &argv, req, dev_index);
 			if (len < 0)
 				return -1;
@@ -593,8 +589,6 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 				duparg2("dev", *argv);
 			*dev = *argv;
 			dev_index = ll_name_to_index(*dev);
-			if (dev_index == 0)
-				invarg("Unknown device", *argv);
 		}
 		argc--; argv++;
 	}
-- 
1.9.0

^ permalink raw reply related

* [PATCH v2 iproute2] ip link: restore backward compatibility with 'ip link add ifname'
From: Nicolas Dichtel @ 2014-09-05 10:00 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel
In-Reply-To: <1409909845-7126-1-git-send-email-nicolas.dichtel@6wind.com>

Commit 9a02651a87d0 ("ip: check for missing dev arg when doing VF rate"),
breaks backward compatibility. Before the commit, this kind of
command was allowed:
ip link add myiface type ...
Now, it returns an error, we should add the arg 'name':
ip link add name myiface type ...

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 ip/iplink.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/ip/iplink.c b/ip/iplink.c
index 1a907d998a87..ea06871b7c81 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -593,8 +593,6 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 				duparg2("dev", *argv);
 			*dev = *argv;
 			dev_index = ll_name_to_index(*dev);
-			if (dev_index == 0)
-				invarg("Unknown device", *argv);
 		}
 		argc--; argv++;
 	}
-- 
1.9.0

^ permalink raw reply related

* Re: [PATCH 09/28] Remove ATHEROS_AR231X
From: Paul Bolle @ 2014-09-05 10:10 UTC (permalink / raw)
  To: Jiri Slaby, Nick Kossifidis, Luis R. Rodriguez, John W. Linville
  Cc: Sergey Ryazanov, Oleksij Rempel, Richard Weinberger,
	Jonathan Bither, Hauke Mehrtens, ath5k-devel, open, list,
	antonynpavlov, openwrt-devel, linux-wireless, netdev,
	linux-kernel
In-Reply-To: <1403091974.1984.102.camel@x220>

Jiri, Nick, Luis, John,

On Wed, 2014-06-18 at 13:46 +0200, Paul Bolle wrote:
> Having this conversation every rc1 is getting a bit silly. Could Jiri
> e.a. perhaps set some specific deadline for ATHEROS_AR231X to be
> submitted?

I waited until rc3. Have you seen any activity on this front? If not,
should I resend the patch that removes the code in mainline that depends
on ATHEROS_AR231X (ie, AHB bus support)?

And to repeat the obvious: the removed code can always be re-added once
ATHEROS_AR231X gets actually added to the tree.

Thanks,


Paul Bolle

^ permalink raw reply

* Re: [PATCH iproute2] Revert "ip: check for missing dev arg when doing VF rate"
From: Vadim Kochan @ 2014-09-05 10:11 UTC (permalink / raw)
  To: Nicolas Dichtel; +Cc: shemminger, netdev
In-Reply-To: <1409909845-7126-1-git-send-email-nicolas.dichtel@6wind.com>

Was it not fixed by f1b66ff83a0 in master branch ?

On Fri, Sep 5, 2014 at 12:37 PM, Nicolas Dichtel
<nicolas.dichtel@6wind.com> wrote:
> This reverts commit 9a02651a87d0fd56e2e7eedd63921a050a42b3ec.
>
> This commit breaks backward compatibility. Before the commit, this kind of
> command was allowed:
> ip link add myiface type ...
> Now, it returns an error, we should add the arg 'name':
> ip link add name myiface type ...
>
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
>  ip/iplink.c | 8 +-------
>  1 file changed, 1 insertion(+), 7 deletions(-)
>
> diff --git a/ip/iplink.c b/ip/iplink.c
> index 1a907d998a87..bbcdc83d4c91 100644
> --- a/ip/iplink.c
> +++ b/ip/iplink.c
> @@ -349,7 +349,6 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
>
>         if (new_rate_api) {
>                 int tmin, tmax;
> -
>                 if (tivt.min_tx_rate == -1 || tivt.max_tx_rate == -1) {
>                         ipaddr_get_vf_rate(tivt.vf, &tmin, &tmax, dev_index);
>                         if (tivt.min_tx_rate == -1)
> @@ -382,7 +381,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
>         int vf = -1;
>         int numtxqueues = -1;
>         int numrxqueues = -1;
> -       int dev_index = 0;
> +       int dev_index;
>
>         *group = -1;
>         ret = argc;
> @@ -495,9 +494,6 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
>                         }
>                         vflist = addattr_nest(&req->n, sizeof(*req),
>                                               IFLA_VFINFO_LIST);
> -                       if (dev_index == 0)
> -                               missarg("dev");
> -
>                         len = iplink_parse_vf(vf, &argc, &argv, req, dev_index);
>                         if (len < 0)
>                                 return -1;
> @@ -593,8 +589,6 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
>                                 duparg2("dev", *argv);
>                         *dev = *argv;
>                         dev_index = ll_name_to_index(*dev);
> -                       if (dev_index == 0)
> -                               invarg("Unknown device", *argv);
>                 }
>                 argc--; argv++;
>         }
> --
> 1.9.0
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [patch net-next] bonding: add slave netlink policy and put slave-related ops together
From: Nikolay Aleksandrov @ 2014-09-05 10:21 UTC (permalink / raw)
  To: Jiri Pirko, netdev; +Cc: davem, j.vosburgh, vfalico, andy
In-Reply-To: <1409909794-7664-1-git-send-email-jiri@resnulli.us>

On 05/09/14 11:36, Jiri Pirko wrote:
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
> ---
>   drivers/net/bonding/bond_netlink.c | 9 +++++++--
>   1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
> index 1570dea..e1489d9 100644
> --- a/drivers/net/bonding/bond_netlink.c
> +++ b/drivers/net/bonding/bond_netlink.c
> @@ -96,6 +96,10 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
>   	[IFLA_BOND_AD_INFO]		= { .type = NLA_NESTED },
>   };
>
> +static const struct nla_policy bond_slave_policy[IFLA_BOND_SLAVE_MAX + 1] = {
> +	[IFLA_BOND_SLAVE_QUEUE_ID]	= { .type = NLA_U16 },
> +};
> +
>   static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
>   {
>   	if (tb[IFLA_ADDRESS]) {
> @@ -580,17 +584,18 @@ struct rtnl_link_ops bond_link_ops __read_mostly = {
>   	.priv_size		= sizeof(struct bonding),
>   	.setup			= bond_setup,
>   	.maxtype		= IFLA_BOND_MAX,
> -	.slave_maxtype		= IFLA_BOND_SLAVE_MAX,
>   	.policy			= bond_policy,
>   	.validate		= bond_validate,
>   	.newlink		= bond_newlink,
>   	.changelink		= bond_changelink,
> -	.slave_changelink	= bond_slave_changelink,
>   	.get_size		= bond_get_size,
>   	.fill_info		= bond_fill_info,
>   	.get_num_tx_queues	= bond_get_num_tx_queues,
>   	.get_num_rx_queues	= bond_get_num_tx_queues, /* Use the same number
>   							     as for TX queues */
> +	.slave_maxtype		= IFLA_BOND_SLAVE_MAX,
> +	.slave_policy		= bond_slave_policy,
> +	.slave_changelink	= bond_slave_changelink,
>   	.get_slave_size		= bond_get_slave_size,
>   	.fill_slave_info	= bond_fill_slave_info,
>   };
>

Right, the validation policy, I knew I forgot something :-)

Acked-by: Nikolay Aleksandrov <nikolay@redhat.com>

^ permalink raw reply

* Mrs.Alimah Negedo.!//
From: Mrs.Alimah Negedo @ 2014-09-05 10:39 UTC (permalink / raw)


-- 
PIease i choose to contact you from this media, for easy
communication. I want to invest some capital left behind by my late
husband there in your country and I need your assistance to wisely put
the capital into a good profit business, under your full control.
Mrs.Alimah Negedo

^ permalink raw reply

* Re: [PATCH 1/3] virtio_net: pass well-formed sgs to virtqueue_add_*()
From: Paolo Bonzini @ 2014-09-05 10:40 UTC (permalink / raw)
  To: Rusty Russell, netdev; +Cc: virtualization, Andy Lutomirski, Michael S. Tsirkin
In-Reply-To: <1409718556-3041-2-git-send-email-rusty__16380.2289790057$1409718628$gmane$org@rustcorp.com.au>

Il 03/09/2014 06:29, Rusty Russell ha scritto:
> +	sg_init_table(rq->sg, MAX_SKB_FRAGS + 2);

I think 2 is enough here.  That said...

>  	sg_set_buf(rq->sg, &hdr->hdr, sizeof hdr->hdr);
> -
>  	skb_to_sgvec(skb, rq->sg + 1, 0, skb->len);
>  
>  	err = virtqueue_add_inbuf(rq->vq, rq->sg, 2, skb, gfp);

... skb_to_sgvec will already make the sg well formed, so the
sg_init_table is _almost_ redundant; it is only there to remove
intermediate end marks.  The block layer takes care to remove
them, but skb_to_sgvec doesn't.

If the following patch can be accepted to net/core/skbuff.c, the
sg_init_table in virtnet_alloc_queues will suffice.

Paolo

-------------------- 8< -------------------
From: Paolo Bonzini <pbonzini@redhat.com>
Subject: [PATCH] net: skb_to_sgvec: do not leave intermediate marks in the sgvec

sg_set_buf/sg_set_page will leave the end mark in place in their
argument, which may be in the middle of a scatterlist.  If we
remove the mark before calling them, we can avoid calls to
sg_init_table before skb_to_sgvec.

However, users of skb_to_sgvec_nomark now need to be careful and
possibly restore the mark.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 163b673f9e62..a3108ef1f1c0 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3265,6 +3265,7 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
 	if (copy > 0) {
 		if (copy > len)
 			copy = len;
+		sg_unmark_end(sg);
 		sg_set_buf(sg, skb->data + offset, copy);
 		elt++;
 		if ((len -= copy) == 0)
@@ -3283,6 +3284,7 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
 
 			if (copy > len)
 				copy = len;
+			sg_unmark_end(&sg[elt]);
 			sg_set_page(&sg[elt], skb_frag_page(frag), copy,
 					frag->page_offset+offset-start);
 			elt++;
@@ -3322,7 +3324,7 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
  * Scenario to use skb_to_sgvec_nomark:
  * 1. sg_init_table
  * 2. skb_to_sgvec_nomark(payload1)
- * 3. skb_to_sgvec_nomark(payload2)
+ * 3. skb_to_sgvec(payload2)
  *
  * This is equivalent to:
  * 1. sg_init_table
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index a2afa89513a0..9ae5756d9e5f 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -227,6 +227,7 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
 		*seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
 		sg_set_buf(seqhisg, seqhi, seqhi_len);
 	}
+	sg_mark_end(&sg[nfrags + sglists]);
 	ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
 	ahash_request_set_callback(req, 0, ah_output_done, skb);
 
@@ -395,6 +396,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
 		*seqhi = XFRM_SKB_CB(skb)->seq.input.hi;
 		sg_set_buf(seqhisg, seqhi, seqhi_len);
 	}
+	sg_mark_end(&sg[nfrags + sglists]);
 	ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
 	ahash_request_set_callback(req, 0, ah_input_done, skb);
 
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 72a4930bdc0a..c680d82e43de 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -430,6 +430,8 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
 		*seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
 		sg_set_buf(seqhisg, seqhi, seqhi_len);
 	}
+	sg_mark_end(&sg[nfrags + sglists]);
+
 	ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
 	ahash_request_set_callback(req, 0, ah6_output_done, skb);
 
@@ -608,6 +610,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
 		*seqhi = XFRM_SKB_CB(skb)->seq.input.hi;
 		sg_set_buf(seqhisg, seqhi, seqhi_len);
 	}
+	sg_mark_end(&sg[nfrags + sglists]);
 
 	ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
 	ahash_request_set_callback(req, 0, ah6_input_done, skb);

^ permalink raw reply related

* [PATCH v2] iproute2: Refactor: using new nl_msg struct for the all Netlink handlers
From: Vadim Kochan @ 2014-09-05 10:35 UTC (permalink / raw)
  To: netdev; +Cc: Vadim Kochan

It will easy to extend with new parameters in future.

Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
---
 bridge/br_common.h   | 10 +++------
 bridge/fdb.c         |  5 +++--
 bridge/link.c        |  6 +++---
 bridge/mdb.c         |  5 +++--
 bridge/monitor.c     | 12 +++++------
 bridge/vlan.c        |  7 +++----
 genl/ctrl.c          | 10 +++++----
 genl/genl.c          |  5 ++---
 genl/genl_utils.h    |  2 +-
 include/libnetlink.h |  9 ++++++--
 include/ll_map.h     |  3 +--
 ip/ip_common.h       | 32 +++++++++--------------------
 ip/ipaddress.c       | 52 ++++++++++++++++++++++++----------------------
 ip/ipaddrlabel.c     |  8 +++++---
 ip/ipl2tp.c          |  8 ++++----
 ip/iplink.c          |  8 +++++---
 ip/ipmonitor.c       | 26 +++++++++++------------
 ip/ipmroute.c        |  5 +++--
 ip/ipneigh.c         |  5 +++--
 ip/ipnetconf.c       |  5 +++--
 ip/ipntable.c        |  5 +++--
 ip/ipprefix.c        |  5 +++--
 ip/iproute.c         | 28 ++++++++++++++++---------
 ip/iprule.c          |  8 +++++---
 ip/iptoken.c         |  3 ++-
 ip/rtmon.c           |  6 +++---
 ip/tcp_metrics.c     | 10 +++++----
 ip/xfrm.h            |  6 ++----
 ip/xfrm_monitor.c    | 58 ++++++++++++++++++++++++++--------------------------
 ip/xfrm_policy.c     | 15 +++++++-------
 ip/xfrm_state.c      | 19 +++++++++--------
 lib/libnetlink.c     | 16 ++++++++++++---
 lib/ll_map.c         |  4 ++--
 misc/ifstat.c        |  4 ++--
 tc/m_action.c        | 17 ++++++++-------
 tc/tc_class.c        |  6 +++---
 tc/tc_common.h       |  8 ++++----
 tc/tc_filter.c       |  7 +++----
 tc/tc_monitor.c      | 14 ++++++-------
 tc/tc_qdisc.c        |  7 +++----
 40 files changed, 248 insertions(+), 221 deletions(-)

diff --git a/bridge/br_common.h b/bridge/br_common.h
index 12fce3e..620c045 100644
--- a/bridge/br_common.h
+++ b/bridge/br_common.h
@@ -1,10 +1,6 @@
-extern int print_linkinfo(const struct sockaddr_nl *who,
-			  struct nlmsghdr *n,
-			  void *arg);
-extern int print_fdb(const struct sockaddr_nl *who,
-		     struct nlmsghdr *n, void *arg);
-extern int print_mdb(const struct sockaddr_nl *who,
-		     struct nlmsghdr *n, void *arg);
+extern int print_linkinfo(struct nl_msg *msg, void *arg);
+extern int print_fdb(struct nl_msg *msg, void *arg);
+extern int print_mdb(struct nl_msg *msg, void *arg);
 
 extern int do_fdb(int argc, char **argv);
 extern int do_mdb(int argc, char **argv);
diff --git a/bridge/fdb.c b/bridge/fdb.c
index a55fac1..1b66d48 100644
--- a/bridge/fdb.c
+++ b/bridge/fdb.c
@@ -58,9 +58,10 @@ static const char *state_n2a(unsigned s)
 	return buf;
 }
 
-int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int print_fdb(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct ndmsg *r = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr * tb[NDA_MAX+1];
diff --git a/bridge/link.c b/bridge/link.c
index 90d9e7f..67ad8da 100644
--- a/bridge/link.c
+++ b/bridge/link.c
@@ -96,10 +96,10 @@ static void print_hwmode(FILE *f, __u16 mode)
 		fprintf(f, "hwmode %s ", hw_mode[mode]);
 }
 
-int print_linkinfo(const struct sockaddr_nl *who,
-		   struct nlmsghdr *n, void *arg)
+int print_linkinfo(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	int len = n->nlmsg_len;
 	struct ifinfomsg *ifi = NLMSG_DATA(n);
 	struct rtattr * tb[IFLA_MAX+1];
diff --git a/bridge/mdb.c b/bridge/mdb.c
index 6c1c938..3678045 100644
--- a/bridge/mdb.c
+++ b/bridge/mdb.c
@@ -77,9 +77,10 @@ static void br_print_mdb_entry(FILE *f, int ifindex, struct rtattr *attr)
 	}
 }
 
-int print_mdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int print_mdb(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct br_port_msg *r = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr * tb[MDBA_MAX+1];
diff --git a/bridge/monitor.c b/bridge/monitor.c
index 76e7d47..e1a5c2b 100644
--- a/bridge/monitor.c
+++ b/bridge/monitor.c
@@ -46,10 +46,10 @@ static int show_mark(FILE *fp, const struct nlmsghdr *n)
 	return 0;
 }
 
-static int accept_msg(const struct sockaddr_nl *who,
-		      struct nlmsghdr *n, void *arg)
+static int accept_msg(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 
 	if (timestamp)
 		print_timestamp(fp);
@@ -60,19 +60,19 @@ static int accept_msg(const struct sockaddr_nl *who,
 		if (prefix_banner)
 			fprintf(fp, "[LINK]");
 
-		return print_linkinfo(who, n, arg);
+		return print_linkinfo(msg, arg);
 
 	case RTM_NEWNEIGH:
 	case RTM_DELNEIGH:
 		if (prefix_banner)
 			fprintf(fp, "[NEIGH]");
-		return print_fdb(who, n, arg);
+		return print_fdb(msg, arg);
 
 	case RTM_NEWMDB:
 	case RTM_DELMDB:
 		if (prefix_banner)
 			fprintf(fp, "[MDB]");
-		return print_mdb(who, n, arg);
+		return print_mdb(msg, arg);
 
 	case 15:
 		return show_mark(fp, n);
diff --git a/bridge/vlan.c b/bridge/vlan.c
index 3bd7b0d..c8ba98d 100644
--- a/bridge/vlan.c
+++ b/bridge/vlan.c
@@ -101,11 +101,10 @@ static int vlan_modify(int cmd, int argc, char **argv)
 	return 0;
 }
 
-static int print_vlan(const struct sockaddr_nl *who,
-		      struct nlmsghdr *n,
-		      void *arg)
+static int print_vlan(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct ifinfomsg *ifm = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr * tb[IFLA_MAX+1];
diff --git a/genl/ctrl.c b/genl/ctrl.c
index 3546129..f8a3ce5 100644
--- a/genl/ctrl.c
+++ b/genl/ctrl.c
@@ -177,14 +177,14 @@ static int print_ctrl_grp(FILE *fp, struct rtattr *arg, __u32 ctrl_ver)
 /*
  * The controller sends one nlmsg per family
 */
-static int print_ctrl(const struct sockaddr_nl *who, struct nlmsghdr *n,
-		      void *arg)
+static int print_ctrl(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	struct rtattr *tb[CTRL_ATTR_MAX + 1];
 	struct genlmsghdr *ghdr = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr *attrs;
-	FILE *fp = (FILE *) arg;
+	FILE *fp = (FILE *)arg;
 	__u32 ctrl_v = 0x1;
 
 	if (n->nlmsg_type !=  GENL_ID_CTRL) {
@@ -292,6 +292,7 @@ static int ctrl_list(int cmd, int argc, char **argv)
 		struct nlmsghdr         n;
 		char                    buf[4096];
 	} req;
+	struct nl_msg msg = {};
 
 	memset(&req, 0, sizeof(req));
 
@@ -339,7 +340,8 @@ static int ctrl_list(int cmd, int argc, char **argv)
 			goto ctrl_done;
 		}
 
-		if (print_ctrl(NULL, nlh, (void *) stdout) < 0) {
+		msg.n = nlh;
+		if (print_ctrl(&msg, (void *)stdout) < 0) {
 			fprintf(stderr, "Dump terminated\n");
 			goto ctrl_done;
 		}
diff --git a/genl/genl.c b/genl/genl.c
index 49b6596..4d643d5 100644
--- a/genl/genl.c
+++ b/genl/genl.c
@@ -36,10 +36,9 @@ static void *BODY;
 static struct genl_util * genl_list;
 
 
-static int print_nofopt(const struct sockaddr_nl *who, struct nlmsghdr *n,
-			void *arg)
+static int print_nofopt(struct nl_msg *msg, void *arg)
 {
-	fprintf((FILE *) arg, "unknown genl type ..\n");
+	fprintf((FILE *)arg, "unknown genl type ..\n");
 	return 0;
 }
 
diff --git a/genl/genl_utils.h b/genl/genl_utils.h
index 85b5183..fd04de2 100644
--- a/genl/genl_utils.h
+++ b/genl/genl_utils.h
@@ -9,7 +9,7 @@ struct genl_util
 	struct  genl_util *next;
 	char	name[16];
 	int	(*parse_genlopt)(struct genl_util *fu, int argc, char **argv);
-	int	(*print_genlopt)(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
+	int	(*print_genlopt)(struct nl_msg *msg, void *arg);
 };
 
 extern int genl_ctrl_resolve_family(const char *family);
diff --git a/include/libnetlink.h b/include/libnetlink.h
index fe7d5d3..da476a1 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -39,8 +39,13 @@ extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req,
 			     int len)
 	__attribute__((warn_unused_result));
 
-typedef int (*rtnl_filter_t)(const struct sockaddr_nl *,
-			     struct nlmsghdr *n, void *);
+struct nl_msg
+{
+	struct sockaddr_nl *who;
+	struct nlmsghdr *n;
+};
+
+typedef int (*rtnl_filter_t)(struct nl_msg *msg, void *arg);
 
 struct rtnl_dump_filter_arg
 {
diff --git a/include/ll_map.h b/include/ll_map.h
index 4c78498..075e4b4 100644
--- a/include/ll_map.h
+++ b/include/ll_map.h
@@ -1,8 +1,7 @@
 #ifndef __LL_MAP_H__
 #define __LL_MAP_H__ 1
 
-extern int ll_remember_index(const struct sockaddr_nl *who,
-			     struct nlmsghdr *n, void *arg);
+extern int ll_remember_index(struct nl_msg *msg, void *arg);
 
 extern void ll_init_map(struct rtnl_handle *rth);
 extern unsigned ll_name_to_index(const char *name);
diff --git a/ip/ip_common.h b/ip/ip_common.h
index e56d1ac..8aaa770 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -1,16 +1,9 @@
 extern int get_operstate(const char *name);
-extern int print_linkinfo(const struct sockaddr_nl *who,
-			  struct nlmsghdr *n,
-			  void *arg);
-extern int print_addrinfo(const struct sockaddr_nl *who,
-			  struct nlmsghdr *n,
-			  void *arg);
-extern int print_addrlabel(const struct sockaddr_nl *who,
-			   struct nlmsghdr *n, void *arg);
-extern int print_neigh(const struct sockaddr_nl *who,
-		       struct nlmsghdr *n, void *arg);
-extern int print_ntable(const struct sockaddr_nl *who,
-			struct nlmsghdr *n, void *arg);
+extern int print_linkinfo(struct nl_msg *msg, void *arg);
+extern int print_addrinfo(struct nl_msg *msg, void *arg);
+extern int print_addrlabel(struct nl_msg *msg, void *arg);
+extern int print_neigh(struct nl_msg *msg, void *arg);
+extern int print_ntable(struct nl_msg *msg, void *arg);
 extern int ipaddr_list(int argc, char **argv);
 extern int ipaddr_list_link(int argc, char **argv);
 extern int iproute_monitor(int argc, char **argv);
@@ -21,16 +14,11 @@ void ipaddr_get_vf_rate(int, int *, int *, int);
 extern void ipaddr_reset_filter(int);
 extern void ipneigh_reset_filter(void);
 extern void ipntable_reset_filter(void);
-extern int print_route(const struct sockaddr_nl *who,
-		       struct nlmsghdr *n, void *arg);
-extern int print_mroute(const struct sockaddr_nl *who,
-			struct nlmsghdr *n, void *arg);
-extern int print_prefix(const struct sockaddr_nl *who,
-			struct nlmsghdr *n, void *arg);
-extern int print_rule(const struct sockaddr_nl *who,
-		      struct nlmsghdr *n, void *arg);
-extern int print_netconf(const struct sockaddr_nl *who,
-			 struct nlmsghdr *n, void *arg);
+extern int print_route(struct nl_msg *msg, void *arg);
+extern int print_mroute(struct nl_msg *msg, void *arg);
+extern int print_prefix(struct nl_msg *msg, void *arg);
+extern int print_rule(struct nl_msg *msg, void *arg);
+extern int print_netconf(struct nl_msg *msg, void *arg);
 extern int do_ipaddr(int argc, char **argv);
 extern int do_ipaddrlabel(int argc, char **argv);
 extern int do_iproute(int argc, char **argv);
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 245df39..3e28b03 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -425,10 +425,10 @@ static void print_link_stats(FILE *fp, const struct rtnl_link_stats *s,
 	}
 }
 
-int print_linkinfo(const struct sockaddr_nl *who,
-		   struct nlmsghdr *n, void *arg)
+int print_linkinfo(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct ifinfomsg *ifi = NLMSG_DATA(n);
 	struct rtattr * tb[IFLA_MAX+1];
 	int len = n->nlmsg_len;
@@ -597,10 +597,10 @@ static unsigned int get_ifa_flags(struct ifaddrmsg *ifa,
 				ifa->ifa_flags;
 }
 
-int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
-		   void *arg)
+int print_addrinfo(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct ifaddrmsg *ifa = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	int deprecated = 0;
@@ -796,26 +796,24 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
 	return 0;
 }
 
-static int print_addrinfo_primary(const struct sockaddr_nl *who,
-				  struct nlmsghdr *n, void *arg)
+static int print_addrinfo_primary(struct nl_msg *msg, void *arg)
 {
-	struct ifaddrmsg *ifa = NLMSG_DATA(n);
+	struct ifaddrmsg *ifa = NLMSG_DATA(msg->n);
 
 	if (ifa->ifa_flags & IFA_F_SECONDARY)
 		return 0;
 
-	return print_addrinfo(who, n, arg);
+	return print_addrinfo(msg, arg);
 }
 
-static int print_addrinfo_secondary(const struct sockaddr_nl *who,
-				    struct nlmsghdr *n, void *arg)
+static int print_addrinfo_secondary(struct nl_msg *msg, void *arg)
 {
-	struct ifaddrmsg *ifa = NLMSG_DATA(n);
+	struct ifaddrmsg *ifa = NLMSG_DATA(msg->n);
 
 	if (!(ifa->ifa_flags & IFA_F_SECONDARY))
 		return 0;
 
-	return print_addrinfo(who, n, arg);
+	return print_addrinfo(msg, arg);
 }
 
 struct nlmsg_list
@@ -835,6 +833,7 @@ static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *
 	for ( ;ainfo ;  ainfo = ainfo->next) {
 		struct nlmsghdr *n = &ainfo->h;
 		struct ifaddrmsg *ifa = NLMSG_DATA(n);
+		struct nl_msg msg = { .n = n };
 
 		if (n->nlmsg_type != RTM_NEWADDR)
 			continue;
@@ -846,15 +845,15 @@ static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *
 		    (filter.family && filter.family != ifa->ifa_family))
 			continue;
 
-		print_addrinfo(NULL, n, fp);
+		print_addrinfo(&msg, fp);
 	}
 	return 0;
 }
 
 
-static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n,
-		       void *arg)
+static int store_nlmsg(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	struct nlmsg_chain *lchain = (struct nlmsg_chain *)arg;
 	struct nlmsg_list *h;
 
@@ -871,7 +870,7 @@ static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n,
 		lchain->head = h;
 	lchain->tail = h;
 
-	ll_remember_index(who, n, NULL);
+	ll_remember_index(msg, arg);
 	return 0;
 }
 
@@ -914,9 +913,9 @@ static int ipadd_dump_check_magic(void)
 	return 0;
 }
 
-static int save_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n,
-		       void *arg)
+static int save_nlmsg(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	int ret;
 
 	ret = write(STDOUT_FILENO, n, n->nlmsg_len);
@@ -928,12 +927,12 @@ static int save_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n,
 	return ret == n->nlmsg_len ? 0 : ret;
 }
 
-static int show_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg)
+static int show_handler(struct nl_msg *msg, void *arg)
 {
-	struct ifaddrmsg *ifa = NLMSG_DATA(n);
+	struct ifaddrmsg *ifa = NLMSG_DATA(msg->n);
 
 	printf("if%d:\n", ifa->ifa_index);
-	print_addrinfo(NULL, n, stdout);
+	print_addrinfo(msg, (void *)stdout);
 	return 0;
 }
 
@@ -945,8 +944,9 @@ static int ipaddr_showdump(void)
 	exit(rtnl_from_file(stdin, &show_handler, NULL));
 }
 
-static int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg)
+static int restore_handler(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	int ret;
 
 	n->nlmsg_flags |= NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
@@ -1282,7 +1282,9 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
 	}
 
 	for (l = linfo.head; l; l = l->next) {
-		if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) {
+		struct nl_msg msg = { .n = &l->h };
+
+		if (no_link || print_linkinfo(&msg, (void *)stdout) == 0) {
 			struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
 			if (filter.family != AF_PACKET)
 				print_selected_addrinfo(ifi->ifi_index,
diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c
index b34dd8b..c46ad41 100644
--- a/ip/ipaddrlabel.c
+++ b/ip/ipaddrlabel.c
@@ -53,9 +53,10 @@ static void usage(void)
 	exit(-1);
 }
 
-int print_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int print_addrlabel(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct ifaddrlblmsg *ifal = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr *tb[IFAL_MAX+1];
@@ -189,8 +190,9 @@ static int ipaddrlabel_modify(int cmd, int argc, char **argv)
 }
 
 
-static int flush_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+static int flush_addrlabel(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	struct rtnl_handle rth2;
 	struct rtmsg *r = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c
index 5cd8632..eef4428 100644
--- a/ip/ipl2tp.c
+++ b/ip/ipl2tp.c
@@ -354,9 +354,9 @@ static int get_response(struct nlmsghdr *n, void *arg)
 	return 0;
 }
 
-static int session_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+static int session_nlmsg(struct nl_msg *msg, void *arg)
 {
-	int ret = get_response(n, arg);
+	int ret = get_response(msg->n, arg);
 
 	if (ret == 0)
 		print_session(arg);
@@ -388,9 +388,9 @@ static int get_session(struct l2tp_data *p)
 	return 0;
 }
 
-static int tunnel_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+static int tunnel_nlmsg(struct nl_msg *msg, void *arg)
 {
-	int ret = get_response(n, arg);
+	int ret = get_response(msg->n, arg);
 
 	if (ret == 0)
 		print_tunnel(arg);
diff --git a/ip/iplink.c b/ip/iplink.c
index ea06871..121e405 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -174,9 +174,9 @@ static int get_addr_gen_mode(const char *mode)
 #if IPLINK_IOCTL_COMPAT
 static int have_rtnl_newlink = -1;
 
-static int accept_msg(const struct sockaddr_nl *who,
-		      struct nlmsghdr *n, void *arg)
+static int accept_msg(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n);
 
 	if (n->nlmsg_type == NLMSG_ERROR &&
@@ -734,6 +734,7 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
 	int len;
 	struct iplink_req req;
 	char answer[16384];
+	struct nl_msg msg = {};
 
 	memset(&req, 0, sizeof(req));
 
@@ -756,7 +757,8 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
 	if (rtnl_talk(&rth, &req.n, 0, 0, (struct nlmsghdr *)answer) < 0)
 		return -2;
 
-	print_linkinfo(NULL, (struct nlmsghdr *)answer, stdout);
+	msg.n = (struct nlmsghdr *)answer;
+	print_linkinfo(&msg, (void *)stdout);
 
 	return 0;
 }
diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c
index 70f2a7a..c7de38f 100644
--- a/ip/ipmonitor.c
+++ b/ip/ipmonitor.c
@@ -36,10 +36,10 @@ static void usage(void)
 	exit(-1);
 }
 
-static int accept_msg(const struct sockaddr_nl *who,
-		      struct nlmsghdr *n, void *arg)
+static int accept_msg(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 
 	if (timestamp)
 		print_timestamp(fp);
@@ -57,32 +57,32 @@ static int accept_msg(const struct sockaddr_nl *who,
 		    r->rtm_family == RTNL_FAMILY_IP6MR) {
 			if (prefix_banner)
 				fprintf(fp, "[MROUTE]");
-			print_mroute(who, n, arg);
+			print_mroute(msg, arg);
 			return 0;
 		} else {
 			if (prefix_banner)
 				fprintf(fp, "[ROUTE]");
-			print_route(who, n, arg);
+			print_route(msg, arg);
 			return 0;
 		}
 	}
 	if (n->nlmsg_type == RTM_NEWLINK || n->nlmsg_type == RTM_DELLINK) {
-		ll_remember_index(who, n, NULL);
+		ll_remember_index(msg, arg);
 		if (prefix_banner)
 			fprintf(fp, "[LINK]");
-		print_linkinfo(who, n, arg);
+		print_linkinfo(msg, arg);
 		return 0;
 	}
 	if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) {
 		if (prefix_banner)
 			fprintf(fp, "[ADDR]");
-		print_addrinfo(who, n, arg);
+		print_addrinfo(msg, arg);
 		return 0;
 	}
 	if (n->nlmsg_type == RTM_NEWADDRLABEL || n->nlmsg_type == RTM_DELADDRLABEL) {
 		if (prefix_banner)
 			fprintf(fp, "[ADDRLABEL]");
-		print_addrlabel(who, n, arg);
+		print_addrlabel(msg, arg);
 		return 0;
 	}
 	if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH ||
@@ -96,25 +96,25 @@ static int accept_msg(const struct sockaddr_nl *who,
 
 		if (prefix_banner)
 			fprintf(fp, "[NEIGH]");
-		print_neigh(who, n, arg);
+		print_neigh(msg, arg);
 		return 0;
 	}
 	if (n->nlmsg_type == RTM_NEWPREFIX) {
 		if (prefix_banner)
 			fprintf(fp, "[PREFIX]");
-		print_prefix(who, n, arg);
+		print_prefix(msg, arg);
 		return 0;
 	}
 	if (n->nlmsg_type == RTM_NEWRULE || n->nlmsg_type == RTM_DELRULE) {
 		if (prefix_banner)
 			fprintf(fp, "[RULE]");
-		print_rule(who, n, arg);
+		print_rule(msg, arg);
 		return 0;
 	}
 	if (n->nlmsg_type == RTM_NEWNETCONF) {
 		if (prefix_banner)
 			fprintf(fp, "[NETCONF]");
-		print_netconf(who, n, arg);
+		print_netconf(msg, arg);
 		return 0;
 	}
 	if (n->nlmsg_type == 15) {
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index be93a98..97d74f4 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -53,9 +53,10 @@ struct rtfilter
 	inet_prefix msrc;
 } filter;
 
-int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int print_mroute(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct rtmsg *r = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr * tb[RTA_MAX+1];
diff --git a/ip/ipneigh.c b/ip/ipneigh.c
index 71a4100..311336f 100644
--- a/ip/ipneigh.c
+++ b/ip/ipneigh.c
@@ -181,9 +181,10 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
 }
 
 
-int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int print_neigh(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct ndmsg *r = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr * tb[NDA_MAX+1];
diff --git a/ip/ipnetconf.c b/ip/ipnetconf.c
index 0e44cc8..d7c79dc 100644
--- a/ip/ipnetconf.c
+++ b/ip/ipnetconf.c
@@ -40,9 +40,10 @@ static void usage(void)
 
 #define NETCONF_RTA(r)	((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct netconfmsg))))
 
-int print_netconf(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int print_netconf(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct netconfmsg *ncm = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr *tb[NETCONFA_MAX+1];
diff --git a/ip/ipntable.c b/ip/ipntable.c
index ea7ca2d..0ca0d29 100644
--- a/ip/ipntable.c
+++ b/ip/ipntable.c
@@ -349,9 +349,10 @@ static const char *ntable_strtime_delta(__u32 msec)
 	return str;
 }
 
-int print_ntable(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int print_ntable(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct ndtmsg *ndtm = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr *tb[NDTA_MAX+1];
diff --git a/ip/ipprefix.c b/ip/ipprefix.c
index 02c0efc..ffec211 100644
--- a/ip/ipprefix.c
+++ b/ip/ipprefix.c
@@ -35,9 +35,10 @@
 #define IF_PREFIX_ONLINK	0x01
 #define IF_PREFIX_AUTOCONF	0x02
 
-int print_prefix(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int print_prefix(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct prefixmsg *prefix = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr * tb[RTA_MAX+1];
diff --git a/ip/iproute.c b/ip/iproute.c
index d77b1e3..4eee858 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -280,9 +280,10 @@ static int calc_host_len(const struct rtmsg *r)
 		return -1;
 }
 
-int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int print_route(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct rtmsg *r = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr * tb[RTA_MAX+1];
@@ -1078,9 +1079,9 @@ static int iproute_flush_cache(void)
 
 static __u32 route_dump_magic = 0x45311224;
 
-static int save_route(const struct sockaddr_nl *who, struct nlmsghdr *n,
-		      void *arg)
+static int save_route(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	int ret;
 	int len = n->nlmsg_len;
 	struct rtmsg *r = NLMSG_DATA(n);
@@ -1382,6 +1383,7 @@ static int iproute_get(int argc, char **argv)
 	int connected = 0;
 	int from_ok = 0;
 	unsigned int mark = 0;
+	struct nl_msg msg = {};
 
 	memset(&req, 0, sizeof(req));
 
@@ -1483,12 +1485,13 @@ static int iproute_get(int argc, char **argv)
 	if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0)
 		exit(2);
 
+	msg.n = &req.n;
 	if (connected && !from_ok) {
 		struct rtmsg *r = NLMSG_DATA(&req.n);
 		int len = req.n.nlmsg_len;
 		struct rtattr * tb[RTA_MAX+1];
 
-		if (print_route(NULL, &req.n, (void*)stdout) < 0) {
+		if (print_route(&msg, (void *)stdout) < 0) {
 			fprintf(stderr, "An error :-)\n");
 			exit(1);
 		}
@@ -1525,7 +1528,7 @@ static int iproute_get(int argc, char **argv)
 			exit(2);
 	}
 
-	if (print_route(NULL, &req.n, (void*)stdout) < 0) {
+	if (print_route(&msg, (void *)stdout) < 0) {
 		fprintf(stderr, "An error :-)\n");
 		exit(1);
 	}
@@ -1533,9 +1536,9 @@ static int iproute_get(int argc, char **argv)
 	exit(0);
 }
 
-static int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n,
-			   void *arg)
+static int restore_handler(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	int ret;
 
 	n->nlmsg_flags |= NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
@@ -1576,9 +1579,14 @@ static int iproute_restore(void)
 	exit(rtnl_from_file(stdin, &restore_handler, NULL));
 }
 
-static int show_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg)
+static int show_handler(struct nl_msg *msg, void *arg)
 {
-	print_route(nl, n, stdout);
+	struct nl_msg rt_param = {};
+
+	rt_param.n = msg->n;
+       	rt_param.who = msg->who;
+
+	print_route(&rt_param, (void *)stdout);
 	return 0;
 }
 
diff --git a/ip/iprule.c b/ip/iprule.c
index 366878e..a272795 100644
--- a/ip/iprule.c
+++ b/ip/iprule.c
@@ -46,9 +46,10 @@ static void usage(void)
 	exit(-1);
 }
 
-int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int print_rule(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct rtmsg *r = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	int host_len = -1;
@@ -392,8 +393,9 @@ static int iprule_modify(int cmd, int argc, char **argv)
 }
 
 
-static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+static int flush_rule(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	struct rtnl_handle rth2;
 	struct rtmsg *r = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
diff --git a/ip/iptoken.c b/ip/iptoken.c
index 5689c2e..f8bf02c 100644
--- a/ip/iptoken.c
+++ b/ip/iptoken.c
@@ -42,8 +42,9 @@ static void usage(void)
 	exit(-1);
 }
 
-static int print_token(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+static int print_token(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	struct rtnl_dump_args *args = arg;
 	FILE *fp = args->fp;
 	int ifindex = args->ifindex;
diff --git a/ip/rtmon.c b/ip/rtmon.c
index 9227eac..e43dcc7 100644
--- a/ip/rtmon.c
+++ b/ip/rtmon.c
@@ -45,10 +45,10 @@ static void write_stamp(FILE *fp)
 	fwrite((void*)n1, 1, NLMSG_ALIGN(n1->nlmsg_len), fp);
 }
 
-static int dump_msg(const struct sockaddr_nl *who, struct nlmsghdr *n,
-		    void *arg)
+static int dump_msg(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	if (!init_phase)
 		write_stamp(fp);
 	fwrite((void*)n, 1, NLMSG_ALIGN(n->nlmsg_len), fp);
diff --git a/ip/tcp_metrics.c b/ip/tcp_metrics.c
index e0f0344..d25a657 100644
--- a/ip/tcp_metrics.c
+++ b/ip/tcp_metrics.c
@@ -88,10 +88,10 @@ static int flush_update(void)
 	return 0;
 }
 
-static int process_msg(const struct sockaddr_nl *who, struct nlmsghdr *n,
-		       void *arg)
+static int process_msg(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE *) arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct genlmsghdr *ghdr;
 	struct rtattr *attrs[TCP_METRICS_ATTR_MAX + 1], *a;
 	int len = n->nlmsg_len;
@@ -295,6 +295,7 @@ static int tcpm_do_cmd(int cmd, int argc, char **argv)
 	TCPM_REQUEST(req, 1024, TCP_METRICS_CMD_GET, NLM_F_REQUEST);
 	int atype = -1, stype = -1;
 	int ack;
+	struct nl_msg msg = {};
 
 	memset(&f, 0, sizeof(f));
 	f.daddr.bitlen = -1;
@@ -455,7 +456,8 @@ static int tcpm_do_cmd(int cmd, int argc, char **argv)
 	} else if (atype >= 0) {
 		if (rtnl_talk(&grth, &req.n, 0, 0, &req.n) < 0)
 			return -2;
-		if (process_msg(NULL, &req.n, stdout) < 0) {
+		msg.n = &req.n;
+		if (process_msg(&msg, (void *)stdout) < 0) {
 			fprintf(stderr, "Dump terminated\n");
 			exit(1);
 		}
diff --git a/ip/xfrm.h b/ip/xfrm.h
index 773c92e..1b170f5 100644
--- a/ip/xfrm.h
+++ b/ip/xfrm.h
@@ -107,10 +107,8 @@ struct xfrm_filter {
 
 extern struct xfrm_filter filter;
 
-int xfrm_state_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
-		     void *arg);
-int xfrm_policy_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
-		      void *arg);
+int xfrm_state_print(struct nl_msg *msg, void *arg);
+int xfrm_policy_print(struct nl_msg *msg, void *arg);
 int do_xfrm_state(int argc, char **argv);
 int do_xfrm_policy(int argc, char **argv);
 int do_xfrm_monitor(int argc, char **argv);
diff --git a/ip/xfrm_monitor.c b/ip/xfrm_monitor.c
index 79453e4..01b20e0 100644
--- a/ip/xfrm_monitor.c
+++ b/ip/xfrm_monitor.c
@@ -40,10 +40,10 @@ static void usage(void)
 	exit(-1);
 }
 
-static int xfrm_acquire_print(const struct sockaddr_nl *who,
-			      struct nlmsghdr *n, void *arg)
+static int xfrm_acquire_print(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct xfrm_user_acquire *xacq = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr * tb[XFRMA_MAX+1];
@@ -101,10 +101,10 @@ static int xfrm_acquire_print(const struct sockaddr_nl *who,
 	return 0;
 }
 
-static int xfrm_state_flush_print(const struct sockaddr_nl *who,
-				  struct nlmsghdr *n, void *arg)
+static int xfrm_state_flush_print(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct xfrm_usersa_flush *xsf = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	const char *str;
@@ -131,11 +131,11 @@ static int xfrm_state_flush_print(const struct sockaddr_nl *who,
 	return 0;
 }
 
-static int xfrm_policy_flush_print(const struct sockaddr_nl *who,
-				   struct nlmsghdr *n, void *arg)
+static int xfrm_policy_flush_print(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	struct rtattr * tb[XFRMA_MAX+1];
-	FILE *fp = (FILE*)arg;
+	FILE *fp = (FILE *)arg;
 	int len = n->nlmsg_len;
 
 	len -= NLMSG_SPACE(0);
@@ -169,10 +169,10 @@ static int xfrm_policy_flush_print(const struct sockaddr_nl *who,
 	return 0;
 }
 
-static int xfrm_report_print(const struct sockaddr_nl *who,
-			     struct nlmsghdr *n, void *arg)
+static int xfrm_report_print(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct xfrm_user_report *xrep = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr * tb[XFRMA_MAX+1];
@@ -234,10 +234,10 @@ static void xfrm_usersa_print(const struct xfrm_usersa_id *sa_id, __u32 reqid, F
 	fprintf(fp, " SPI 0x%x", ntohl(sa_id->spi));
 }
 
-static int xfrm_ae_print(const struct sockaddr_nl *who,
-			     struct nlmsghdr *n, void *arg)
+static int xfrm_ae_print(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct xfrm_aevent_id *id = NLMSG_DATA(n);
 	char abuf[256];
 
@@ -264,10 +264,10 @@ static void xfrm_print_addr(FILE *fp, int family, xfrm_address_t *a)
 	fprintf(fp, "%s", rt_addr_n2a(family, a, buf, sizeof(buf)));
 }
 
-static int xfrm_mapping_print(const struct sockaddr_nl *who,
-			     struct nlmsghdr *n, void *arg)
+static int xfrm_mapping_print(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct xfrm_user_mapping *map = NLMSG_DATA(n);
 
 	fprintf(fp, "Mapping change ");
@@ -284,10 +284,10 @@ static int xfrm_mapping_print(const struct sockaddr_nl *who,
 	return 0;
 }
 
-static int xfrm_accept_msg(const struct sockaddr_nl *who,
-			   struct nlmsghdr *n, void *arg)
+static int xfrm_accept_msg(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 
 	if (timestamp)
 		print_timestamp(fp);
@@ -297,31 +297,31 @@ static int xfrm_accept_msg(const struct sockaddr_nl *who,
 	case XFRM_MSG_DELSA:
 	case XFRM_MSG_UPDSA:
 	case XFRM_MSG_EXPIRE:
-		xfrm_state_print(who, n, arg);
+		xfrm_state_print(msg, arg);
 		return 0;
 	case XFRM_MSG_NEWPOLICY:
 	case XFRM_MSG_DELPOLICY:
 	case XFRM_MSG_UPDPOLICY:
 	case XFRM_MSG_POLEXPIRE:
-		xfrm_policy_print(who, n, arg);
+		xfrm_policy_print(msg, arg);
 		return 0;
 	case XFRM_MSG_ACQUIRE:
-		xfrm_acquire_print(who, n, arg);
+		xfrm_acquire_print(msg, arg);
 		return 0;
 	case XFRM_MSG_FLUSHSA:
-		xfrm_state_flush_print(who, n, arg);
+		xfrm_state_flush_print(msg, arg);
 		return 0;
 	case XFRM_MSG_FLUSHPOLICY:
-		xfrm_policy_flush_print(who, n, arg);
+		xfrm_policy_flush_print(msg, arg);
 		return 0;
 	case XFRM_MSG_REPORT:
-		xfrm_report_print(who, n, arg);
+		xfrm_report_print(msg, arg);
 		return 0;
 	case XFRM_MSG_NEWAE:
-		xfrm_ae_print(who, n, arg);
+		xfrm_ae_print(msg, arg);
 		return 0;
 	case XFRM_MSG_MAPPING:
-		xfrm_mapping_print(who, n, arg);
+		xfrm_mapping_print(msg, arg);
 		return 0;
 	default:
 		break;
diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c
index 2337d35..9c4a31b 100644
--- a/ip/xfrm_policy.c
+++ b/ip/xfrm_policy.c
@@ -456,16 +456,16 @@ static int xfrm_policy_filter_match(struct xfrm_userpolicy_info *xpinfo,
 	return 1;
 }
 
-int xfrm_policy_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
-		      void *arg)
+int xfrm_policy_print(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	struct rtattr * tb[XFRMA_MAX+1];
 	struct rtattr * rta;
 	struct xfrm_userpolicy_info *xpinfo = NULL;
 	struct xfrm_user_polexpire *xpexp = NULL;
 	struct xfrm_userpolicy_id *xpid = NULL;
 	__u8 ptype = XFRM_POLICY_TYPE_MAIN;
-	FILE *fp = (FILE*)arg;
+	FILE *fp = (FILE *)arg;
 	int len = n->nlmsg_len;
 
 	if (n->nlmsg_type != XFRM_MSG_NEWPOLICY &&
@@ -686,12 +686,14 @@ static int xfrm_policy_get(int argc, char **argv)
 {
 	char buf[NLMSG_BUF_SIZE];
 	struct nlmsghdr *n = (struct nlmsghdr *)buf;
+	struct nl_msg msg = {};
 
 	memset(buf, 0, sizeof(buf));
 
 	xfrm_policy_get_or_delete(argc, argv, 0, n);
 
-	if (xfrm_policy_print(NULL, n, (void*)stdout) < 0) {
+	msg.n = n;
+	if (xfrm_policy_print(&msg, (void *)stdout) < 0) {
 		fprintf(stderr, "An error :-)\n");
 		exit(1);
 	}
@@ -703,10 +705,9 @@ static int xfrm_policy_get(int argc, char **argv)
  * With an existing policy of nlmsg, make new nlmsg for deleting the policy
  * and store it to buffer.
  */
-static int xfrm_policy_keep(const struct sockaddr_nl *who,
-			    struct nlmsghdr *n,
-			    void *arg)
+static int xfrm_policy_keep(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	struct xfrm_buffer *xb = (struct xfrm_buffer *)arg;
 	struct rtnl_handle *rth = xb->rth;
 	struct xfrm_userpolicy_info *xpinfo = NLMSG_DATA(n);
diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c
index fe7708e..8b315a4 100644
--- a/ip/xfrm_state.c
+++ b/ip/xfrm_state.c
@@ -665,6 +665,7 @@ static int xfrm_state_allocspi(int argc, char **argv)
 	struct xfrm_mark mark = {0, 0};
 	char res_buf[NLMSG_BUF_SIZE];
 	struct nlmsghdr *res_n = (struct nlmsghdr *)res_buf;
+	struct nl_msg msg = {};
 
 	memset(res_buf, 0, sizeof(res_buf));
 
@@ -783,7 +784,8 @@ static int xfrm_state_allocspi(int argc, char **argv)
 	if (rtnl_talk(&rth, &req.n, 0, 0, res_n) < 0)
 		exit(2);
 
-	if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) {
+	msg.n = res_n;
+	if (xfrm_state_print(&msg, (void *)stdout) < 0) {
 		fprintf(stderr, "An error :-)\n");
 		exit(1);
 	}
@@ -821,10 +823,10 @@ static int xfrm_state_filter_match(struct xfrm_usersa_info *xsinfo)
 	return 1;
 }
 
-int xfrm_state_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
-		     void *arg)
+int xfrm_state_print(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct rtattr * tb[XFRMA_MAX+1];
 	struct rtattr * rta;
 	struct xfrm_usersa_info *xsinfo = NULL;
@@ -975,13 +977,15 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete)
 	} else {
 		char buf[NLMSG_BUF_SIZE];
 		struct nlmsghdr *res_n = (struct nlmsghdr *)buf;
+		struct nl_msg msg = {};
 
 		memset(buf, 0, sizeof(buf));
 
 		if (rtnl_talk(&rth, &req.n, 0, 0, res_n) < 0)
 			exit(2);
 
-		if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) {
+		msg.n = res_n;
+		if (xfrm_state_print(&msg, (void *)stdout) < 0) {
 			fprintf(stderr, "An error :-)\n");
 			exit(1);
 		}
@@ -996,10 +1000,9 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete)
  * With an existing state of nlmsg, make new nlmsg for deleting the state
  * and store it to buffer.
  */
-static int xfrm_state_keep(const struct sockaddr_nl *who,
-			   struct nlmsghdr *n,
-			   void *arg)
+static int xfrm_state_keep(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	struct xfrm_buffer *xb = (struct xfrm_buffer *)arg;
 	struct rtnl_handle *rth = xb->rth;
 	struct xfrm_usersa_info *xsinfo = NLMSG_DATA(n);
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index 9e2a795..d9a9756 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -220,6 +220,7 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
 		}
 
 		for (a = arg; a->filter; a++) {
+			struct nl_msg msg = {};
 			struct nlmsghdr *h = (struct nlmsghdr*)buf;
 			msglen = status;
 
@@ -249,7 +250,10 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
 					}
 					return -1;
 				}
-				err = a->filter(&nladdr, h, a->arg1);
+
+				msg.who = &nladdr;
+				msg.n = h;
+				err = a->filter(&msg, a->arg1);
 				if (err < 0)
 					return err;
 
@@ -450,6 +454,7 @@ int rtnl_listen(struct rtnl_handle *rtnl,
 			exit(1);
 		}
 		for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
+			struct nl_msg m = {};
 			int err;
 			int len = h->nlmsg_len;
 			int l = len - sizeof(*h);
@@ -463,7 +468,9 @@ int rtnl_listen(struct rtnl_handle *rtnl,
 				exit(1);
 			}
 
-			err = handler(&nladdr, h, jarg);
+			m.who = &nladdr;
+			m.n = h;
+			err = handler(&m, jarg);
 			if (err < 0)
 				return err;
 
@@ -495,6 +502,7 @@ int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler,
 	nladdr.nl_groups = 0;
 
 	while (1) {
+		struct nl_msg msg = {};
 		int err, len;
 		int l;
 
@@ -529,7 +537,9 @@ int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler,
 			return -1;
 		}
 
-		err = handler(&nladdr, h, jarg);
+		msg.who = &nladdr;
+		msg.n = h;
+		err = handler(&msg, jarg);
 		if (err < 0)
 			return err;
 	}
diff --git a/lib/ll_map.c b/lib/ll_map.c
index db34a2a..b3308c7 100644
--- a/lib/ll_map.c
+++ b/lib/ll_map.c
@@ -78,9 +78,9 @@ static struct ll_cache *ll_get_by_name(const char *name)
 	return NULL;
 }
 
-int ll_remember_index(const struct sockaddr_nl *who,
-		      struct nlmsghdr *n, void *arg)
+int ll_remember_index(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *n = msg->n;
 	unsigned int h;
 	const char *ifname;
 	struct ifinfomsg *ifi = NLMSG_DATA(n);
diff --git a/misc/ifstat.c b/misc/ifstat.c
index a47c046..0807905 100644
--- a/misc/ifstat.c
+++ b/misc/ifstat.c
@@ -105,9 +105,9 @@ static int match(const char *id)
 	return 0;
 }
 
-static int get_nlmsg(const struct sockaddr_nl *who,
-		     struct nlmsghdr *m, void *arg)
+static int get_nlmsg(struct nl_msg *msg, void *arg)
 {
+	struct nlmsghdr *m = msg->n;
 	struct ifinfomsg *ifi = NLMSG_DATA(m);
 	struct rtattr * tb[IFLA_MAX+1];
 	int len = m->nlmsg_len;
diff --git a/tc/m_action.c b/tc/m_action.c
index 7dbcf5b..55fa50d 100644
--- a/tc/m_action.c
+++ b/tc/m_action.c
@@ -319,11 +319,10 @@ tc_print_action(FILE * f, const struct rtattr *arg)
 	return 0;
 }
 
-int print_action(const struct sockaddr_nl *who,
-			   struct nlmsghdr *n,
-			   void *arg)
+int print_action(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct tcamsg *t = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr * tb[TCAA_MAX+1];
@@ -460,9 +459,13 @@ static int tc_action_gd(int cmd, unsigned flags, int *argc_p, char ***argv_p)
 		return 1;
 	}
 
-	if (ans && print_action(NULL, &req.n, (void*)stdout) < 0) {
-		fprintf(stderr, "Dump terminated\n");
-		return 1;
+	if (ans) {
+		struct nl_msg msg = {};
+		msg.n = &req.n;
+		if (print_action(&msg, (void *)stdout) < 0) {
+			fprintf(stderr, "Dump terminated\n");
+			return 1;
+		}
 	}
 
 	*argc_p = argc;
diff --git a/tc/tc_class.c b/tc/tc_class.c
index e56bf07..2d6c138 100644
--- a/tc/tc_class.c
+++ b/tc/tc_class.c
@@ -148,10 +148,10 @@ int filter_ifindex;
 __u32 filter_qdisc;
 __u32 filter_classid;
 
-int print_class(const struct sockaddr_nl *who,
-		       struct nlmsghdr *n, void *arg)
+int print_class(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct tcmsg *t = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr * tb[TCA_MAX+1];
diff --git a/tc/tc_common.h b/tc/tc_common.h
index 4f88856..df56ffa 100644
--- a/tc/tc_common.h
+++ b/tc/tc_common.h
@@ -7,10 +7,10 @@ extern int do_class(int argc, char **argv);
 extern int do_filter(int argc, char **argv);
 extern int do_action(int argc, char **argv);
 extern int do_tcmonitor(int argc, char **argv);
-extern int print_action(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
-extern int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
-extern int print_qdisc(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
-extern int print_class(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
+extern int print_action(struct nl_msg *msg, void *arg);
+extern int print_filter(struct nl_msg *msg, void *arg);
+extern int print_qdisc(struct nl_msg *msg, void *arg);
+extern int print_class(struct nl_msg *msg, void *arg);
 extern void print_size_table(FILE *fp, const char *prefix, struct rtattr *rta);
 
 struct tc_estimator;
diff --git a/tc/tc_filter.c b/tc/tc_filter.c
index c3f2d5f..7f1c73b 100644
--- a/tc/tc_filter.c
+++ b/tc/tc_filter.c
@@ -181,11 +181,10 @@ static __u32 filter_prio;
 static __u32 filter_protocol;
 __u16 f_proto = 0;
 
-int print_filter(const struct sockaddr_nl *who,
-			struct nlmsghdr *n,
-			void *arg)
+int print_filter(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct tcmsg *t = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr * tb[TCA_MAX+1];
diff --git a/tc/tc_monitor.c b/tc/tc_monitor.c
index 0efe034..4734529 100644
--- a/tc/tc_monitor.c
+++ b/tc/tc_monitor.c
@@ -35,26 +35,26 @@ static void usage(void)
 }
 
 
-static int accept_tcmsg(const struct sockaddr_nl *who,
-			struct nlmsghdr *n, void *arg)
+static int accept_tcmsg(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 
 	if (n->nlmsg_type == RTM_NEWTFILTER || n->nlmsg_type == RTM_DELTFILTER) {
-		print_filter(who, n, arg);
+		print_filter(msg, arg);
 		return 0;
 	}
 	if (n->nlmsg_type == RTM_NEWTCLASS || n->nlmsg_type == RTM_DELTCLASS) {
-		print_class(who, n, arg);
+		print_class(msg, arg);
 		return 0;
 	}
 	if (n->nlmsg_type == RTM_NEWQDISC || n->nlmsg_type == RTM_DELQDISC) {
-		print_qdisc(who, n, arg);
+		print_qdisc(msg, arg);
 		return 0;
 	}
 	if (n->nlmsg_type == RTM_GETACTION || n->nlmsg_type == RTM_NEWACTION ||
 	    n->nlmsg_type == RTM_DELACTION) {
-		print_action(who, n, arg);
+		print_action(msg, arg);
 		return 0;
 	}
 	if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP &&
diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c
index e304858..ce0be74 100644
--- a/tc/tc_qdisc.c
+++ b/tc/tc_qdisc.c
@@ -195,11 +195,10 @@ static int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv)
 
 static int filter_ifindex;
 
-int print_qdisc(const struct sockaddr_nl *who,
-		       struct nlmsghdr *n,
-		       void *arg)
+int print_qdisc(struct nl_msg *msg, void *arg)
 {
-	FILE *fp = (FILE*)arg;
+	struct nlmsghdr *n = msg->n;
+	FILE *fp = (FILE *)arg;
 	struct tcmsg *t = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr * tb[TCA_MAX+1];
-- 
2.1.0

^ permalink raw reply related

* Re: [patch net-next RFC 10/12] openvswitch: add support for datapath hardware offload
From: Jamal Hadi Salim @ 2014-09-05 10:46 UTC (permalink / raw)
  To: Scott Feldman, Simon Horman
  Cc: Sergey Ryazanov, jasowang-H+wXaHxf7aLQT0dZR+AlfA, John Fastabend,
	Neil.Jerram-QnUH15yq9NYqDJ6do+/SaQ, Eric Dumazet, Andy Gospodarek,
	dev-yBygre7rU0TnMu66kgdUjQ, Felix Fietkau, Florian Fainelli,
	ronye-VPRAkNaXOzVWk0Htik3J/w, Jeff Kirsher, ogerlitz,
	Ben Hutchings, Lennert Buytenhek, Jiri Pirko, Roopa Prabhu,
	Aviad Raveh, nicolas.dichtel-pdR9zngts4EAvxtiuMwx3w,
	Vlad Yasevich, Neil Horman, netdev, Stephen Hemminger, dborkman,
	ebiederm-aS9lmoZGLiVWk0Htik3J/w, David Miller
In-Reply-To: <E3C7797F-081E-484F-918E-937C705B43D6-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR@public.gmane.org>

On 09/05/14 03:02, Scott Feldman wrote:

>> On Thu, Sep 04, 2014 at 09:30:45AM -0700, Scott Feldman wrote:
>>>

> Correct, for the particular switch implementation we’re working with.

Do you have L2/3 working with this interface on said switch?
I am interested.

cheers,
jamal

^ permalink raw reply

* Re: [PATCH 3/3] virtio_ring: unify direct/indirect code paths.
From: Paolo Bonzini @ 2014-09-05 10:55 UTC (permalink / raw)
  To: Rusty Russell, netdev; +Cc: virtualization, Andy Lutomirski, Michael S. Tsirkin
In-Reply-To: <1409718556-3041-4-git-send-email-rusty@rustcorp.com.au>

Il 03/09/2014 06:29, Rusty Russell ha scritto:
> + 	desc = kmalloc(total_sg * sizeof(struct vring_desc), gfp);
> + 	if (!desc)
> +		return NULL;
>  
> -	return head;
> +	for (i = 0; i < total_sg; i++)
> +		desc[i].next = i+1;
> +	return desc;
>  }

Would it make sense to keep a cache of a few (say) 8- or 16-element
indirect descriptors?  You'd only have to do this ugly (and slowish) for
loop on the first allocation.

Also, since this is mostly an aesthetic patch,

> +	if (indirect)
> +		vq->free_head = vq->vring.desc[head].next;
> +	else
> +		vq->free_head = i;

I'd move the indirect case above, where the vring.desc[head] is actually
allocated.

Paolo

^ permalink raw reply

* Re: [RFC v2 3/6] kthread: warn on kill signal if not OOM
From: Oleg Nesterov @ 2014-09-05 10:59 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gregkh, dmitry.torokhov, falcon, tiwai, tj, arjan, linux-kernel,
	hare, akpm, penguin-kernel, joseph.salisbury, bpoirier, santosh,
	Luis R. Rodriguez, Kay Sievers, One Thousand Gnomes, Tim Gardner,
	Pierre Fersing, Nagalakshmi Nandigama, Praveen Krishnamoorthy,
	Sreekanth Reddy, Abhijit Mahajan, Casey Leedom, Hariprasad S,
	MPT-FusionLinux.pdl, linux-scsi, netdev
In-Reply-To: <1409899047-13045-4-git-send-email-mcgrof@do-not-panic.com>

On 09/04, Luis R. Rodriguez wrote:
>
> From: "Luis R. Rodriguez" <mcgrof@suse.com>
>
> The new umh kill option has allowed kthreads to receive
> kill signals but they are generally accepting all sources
> of kill signals

And I think this is right,

> while the original motivation was to enable
> through the OOM from sending the kill.

even if the main concern was OOM.

> Users can provide a log output and it should be clear on
> the trace what probe / driver got the kill signal.

Well, if you need a WARN output, perhaps you could just add
WARN_ON(fatal_signal_pending()) at the end of load_module() ?

Not only kthread_create() can fail if systemd sends SIGKILL.

> Although Oleg had rejected a
> similar change a while ago

And honestly, I still dislike this change.

Oleg.

^ permalink raw reply

* Re: [PATCH 09/28] Remove ATHEROS_AR231X
From: Sergey Ryazanov @ 2014-09-05 11:12 UTC (permalink / raw)
  To: Paul Bolle
  Cc: openwrt-devel, Jiri Slaby, open, Richard Weinberger, ath5k-devel,
	linux-wireless, John W. Linville, Oleksij Rempel, netdev,
	Nick Kossifidis, Hauke Mehrtens, list, linux-kernel,
	antonynpavlov
In-Reply-To: <1409911856.7832.9.camel@x220>

Hello Paul,

2014-09-05 14:10 GMT+04:00, Paul Bolle <pebolle@tiscali.nl>:
> Jiri, Nick, Luis, John,
>
> On Wed, 2014-06-18 at 13:46 +0200, Paul Bolle wrote:
>> Having this conversation every rc1 is getting a bit silly. Could Jiri
>> e.a. perhaps set some specific deadline for ATHEROS_AR231X to be
>> submitted?
>
> I waited until rc3. Have you seen any activity on this front? If not,
> should I resend the patch that removes the code in mainline that depends
> on ATHEROS_AR231X (ie, AHB bus support)?
>
Recent activity always could be found in [1]. Now I finish another one
round of cleanups and have a plan to fix several things (you can
always find something that you really want to improve). But if you
insist I could immediately switch to "send upstream" mode. And seems
that this would be better approach.

1. https://dev.openwrt.org/log/trunk/target/linux/atheros

-- 
BR,
Sergey

^ permalink raw reply

* Re: [PATCH net-next 2/2] bonding: Simplify the xmit function for modes that use xmit_hash
From: Nikolay Aleksandrov @ 2014-09-05 11:26 UTC (permalink / raw)
  To: Mahesh Bandewar
  Cc: Jay Vosburgh, Veaceslav Falico, Andy Gospodarek, David Miller,
	netdev, Eric Dumazet, Maciej Zenczykowski
In-Reply-To: <CAF2d9ji2Dsi9dr6B0HKy4oQ841CN-00zWcOxCa+oTyPp79hOHA@mail.gmail.com>

On 05/09/14 02:10, Mahesh Bandewar wrote:
> On Thu, Sep 4, 2014 at 6:16 AM, Nikolay Aleksandrov <nikolay@redhat.com> wrote:
>> On 03/09/14 23:47, Mahesh Bandewar wrote:
>>>
>>> Earlier change to use usable slave array for TLB mode had an additional
>>> performance advantage. So extending the same logic to all other modes
>>> that use xmit-hash for slave selection (viz 802.3AD, and XOR modes).
>>> Also consolidating this with the earlier TLB change.
>>>
>>> The main idea is to build the usable slaves array in the control path
>>> and use that array for slave selection during xmit operation.
>>>
>>> Measured performance in a setup with a bond of 4x1G NICs with 200
>>> instances of netperf for the modes involved (3ad, xor, tlb)
>>> cmd: netperf -t TCP_RR -H <TargetHost> -l 60 -s 5
>>>
>>> Mode        TPS-Before   TPS-After
>>>
>>> 802.3ad   : 468,694      493,101
>>> TLB (lb=0): 392,583      392,965
>>> XOR       : 475,696      484,517
>>>
>>> Signed-off-by: Mahesh Bandewar <maheshb@google.com>
>>> ---
>>
<<<<<snip>>>>>>
>>> -       bond_xmit_slave_id(bond, skb, bond_xmit_hash(bond, skb) %
>>> bond->slave_cnt);
>>> +       old_arr = rcu_dereference_protected(bond->slave_arr,
>>> +                                           lockdep_rtnl_is_held() ||
>>> +                                           lockdep_is_held(&bond->lock)
>>> ||
>>> +
>>> lockdep_is_held(&bond->curr_slave_lock));
>>
>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> This line is the most troublesome for me, which lock is it ? Does this mean
>> that whichever I hold from the three I can update the slave array ?
>> I don't think this is worked out well, you should explicitly specify how and
>> why it is safe to update this under each of the locks and maybe you'll be
>> able to reduce the lock list :-)
>>
> This is primarily because of different code paths it's taking to reach
> here. In all these cases, one of those locks is held. Unfortunately
> there are three such locks  that I have identified (for all three
> modes involved) and hence the above line.
>

True, but I did a little grepping and here's my analysis of the call sites which 
I can't guarantee is full or complete, but it shows at least 1 problem.
bond_update_slave_arr() callers:

1. 3ad mode
1.1. bond_3ad_state_machine_handler -> ad_mux_machine -> 
ad_(en|dis)able_collecting_distributing
  - read_lock(bond->lock), rcu_read_lock, state_machine_lock
1.2. __bond_release_one -> bond_3ad_unbind_slave
  - rtnl, write_lock(bond->lock)
1.3. bond_change_active_slave -> bond_3ad_handle_link_change
  -  from 4. rtnl, new_active != NULL -> write_lock(curr_slave_lock)
1.4. bond_miimon_commit -> bond_3ad_handle_link_change
  - rtnl

2. TLB
2.1. __bond_release_one -> bond_alb_deinit_slave
  - rtnl
2.2. bond_change_active_slave -> bond_alb_handle_link_change
  - from 4. rtnl, new_active != NULL -> write_lock(curr_slave_lock)
2.3. bond_miimon_commit -> bond_alb_handle_link_change
  - rtnl

3. XOR
3.1. __bond_release_one
  - rtnl
3.2. bond_miimon_commit
  - rtnl

4. bond_change_active_slave:
1. bond_select_active_slave -> bond_change_active_slave
1.1. bond_enslave -> bond_select_active_slave
  - rtnl, write_lock(curr_slave_lock)
1.2. __bond_release_one -> bond_select_active_slave
  - rtnl, write_lock(curr_slave_lock)
1.3. bond_miimon_commit -> bond_select_active_slave
  - rtnl, write_lock(curr_slave_lock)
1.4. bond_loadbalance_arp_mon -> bond_select_active_slave
  - rtnl, write_lock(curr_slave_lock)
1.5. bond_ab_arp_commit -> bond_select_active_slave
  - rtnl, write_lock(curr_slave_lock)
1.6. bond_slave_netdev_event -> bond_select_active_slave
  - rtnl, write_lock(curr_slave_lock)
1.7. bond_options.c (all callers)
  - rtnl, write_lock(curr_slave_lock)


Almost all callers of slave_update_arr() currently have rtnl acquired, but 
there's 1 troubling caller: bond_3ad_state_machine_handler() which is called 
from a workqueue. Now if we're able to execute anything with that workqueue, we 
have a race condition, good candidates are all options which don't acquire 
write_lock(bond->lock), I think the only one that can call 
bond_slave_update_arr() of those is primary_reselect right now.
So if you come up with some way to deal with that, you probably can use only 
rtnl for syncing the array and simplify this.
Again I might be wrong since this is done only via grepping :-)

Cheers,
  Nik

^ permalink raw reply

* Re: [RFC v2 2/6] driver-core: add driver async_probe support
From: Oleg Nesterov @ 2014-09-05 11:24 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gregkh, dmitry.torokhov, falcon, tiwai, tj, arjan, linux-kernel,
	hare, akpm, penguin-kernel, joseph.salisbury, bpoirier, santosh,
	Luis R. Rodriguez, Kay Sievers, One Thousand Gnomes, Tim Gardner,
	Pierre Fersing, Nagalakshmi Nandigama, Praveen Krishnamoorthy,
	Sreekanth Reddy, Abhijit Mahajan, Casey Leedom, Hariprasad S,
	MPT-FusionLinux.pdl, linux-scsi, netdev
In-Reply-To: <1409899047-13045-3-git-send-email-mcgrof@do-not-panic.com>

On 09/04, Luis R. Rodriguez wrote:
>
>  struct driver_private {
>  	struct kobject kobj;
>  	struct klist klist_devices;
>  	struct klist_node knode_bus;
>  	struct module_kobject *mkobj;
> +	struct driver_attach_work *attach_work;
>  	struct device_driver *driver;

I am not arguing, just curious...

Are you trying to shrink sizeof(driver_private) ? The code can be simpler
if you just embedd "struct work_struct attach_work" into driver_private,
and you do not need "struct driver_attach_work" or another ->driver pointer
this way.

Oleg.

^ permalink raw reply

* Re: [PATCH 09/28] Remove ATHEROS_AR231X
From: Paul Bolle @ 2014-09-05 11:33 UTC (permalink / raw)
  To: Sergey Ryazanov
  Cc: Jiri Slaby, Nick Kossifidis, Luis R. Rodriguez, John W. Linville,
	Oleksij Rempel, Richard Weinberger, Jonathan Bither,
	Hauke Mehrtens, ath5k-devel-juf53994utBLZpfksSYvnA,
	open-5/S+JYg5SzeELgA04lAiVw, list-5/S+JYg5SzeELgA04lAiVw,
	antonynpavlov-Re5JQEeQqe8AvxtiuMwx3w,
	openwrt-devel-ZwoEplunGu0+xA9t4nZiwti2O/JbrIOy,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <CAHNKnsRipRHicKOUW4dCutD1-sUG6qPnP2QuOveH_t1MFX9XgQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

Hi Sergey,

On Fri, 2014-09-05 at 15:12 +0400, Sergey Ryazanov wrote:
> 2014-09-05 14:10 GMT+04:00, Paul Bolle <pebolle-IWqWACnzNjzz+pZb47iToQ@public.gmane.org>:
> > On Wed, 2014-06-18 at 13:46 +0200, Paul Bolle wrote:
> >> Having this conversation every rc1 is getting a bit silly. Could Jiri
> >> e.a. perhaps set some specific deadline for ATHEROS_AR231X to be
> >> submitted?
> >
> > I waited until rc3. Have you seen any activity on this front? If not,
> > should I resend the patch that removes the code in mainline that depends
> > on ATHEROS_AR231X (ie, AHB bus support)?
> >
> Recent activity always could be found in [1]. Now I finish another one
> round of cleanups and have a plan to fix several things (you can
> always find something that you really want to improve). But if you
> insist I could immediately switch to "send upstream" mode. And seems
> that this would be better approach.
> 
> 1. https://dev.openwrt.org/log/trunk/target/linux/atheros

And where can the related PULL requests or patch submissions be found?


Paul Bolle

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH iproute2] Revert "ip: check for missing dev arg when doing VF rate"
From: Nicolas Dichtel @ 2014-09-05 11:45 UTC (permalink / raw)
  To: Vadim Kochan; +Cc: shemminger, netdev
In-Reply-To: <CAMw6YJKoEzMQOjmJ66ojfYGn6Xp4ec_m5edZWQBymjZtVyB13w@mail.gmail.com>

Le 05/09/2014 12:11, Vadim Kochan a écrit :
> Was it not fixed by f1b66ff83a0 in master branch ?
You're right. I've missed it, sorry for the noise.


Regards,
Nicolas

^ permalink raw reply

* Re: [PATCH net-next 2/2] bonding: Simplify the xmit function for modes that use xmit_hash
From: Nikolay Aleksandrov @ 2014-09-05 11:49 UTC (permalink / raw)
  To: Mahesh Bandewar
  Cc: Jay Vosburgh, Veaceslav Falico, Andy Gospodarek, David Miller,
	netdev, Eric Dumazet, Maciej Zenczykowski
In-Reply-To: <54099DD3.20109@redhat.com>

On 05/09/14 13:26, Nikolay Aleksandrov wrote:
> On 05/09/14 02:10, Mahesh Bandewar wrote:
>> On Thu, Sep 4, 2014 at 6:16 AM, Nikolay Aleksandrov <nikolay@redhat.com> wrote:
>>> On 03/09/14 23:47, Mahesh Bandewar wrote:
>>>>
>>>> Earlier change to use usable slave array for TLB mode had an additional
>>>> performance advantage. So extending the same logic to all other modes
>>>> that use xmit-hash for slave selection (viz 802.3AD, and XOR modes).
>>>> Also consolidating this with the earlier TLB change.
>>>>
>>>> The main idea is to build the usable slaves array in the control path
>>>> and use that array for slave selection during xmit operation.
>>>>
>>>> Measured performance in a setup with a bond of 4x1G NICs with 200
>>>> instances of netperf for the modes involved (3ad, xor, tlb)
>>>> cmd: netperf -t TCP_RR -H <TargetHost> -l 60 -s 5
>>>>
>>>> Mode        TPS-Before   TPS-After
>>>>
>>>> 802.3ad   : 468,694      493,101
>>>> TLB (lb=0): 392,583      392,965
>>>> XOR       : 475,696      484,517
>>>>
>>>> Signed-off-by: Mahesh Bandewar <maheshb@google.com>
>>>> ---
>>>
> <<<<<snip>>>>>>
>>>> -       bond_xmit_slave_id(bond, skb, bond_xmit_hash(bond, skb) %
>>>> bond->slave_cnt);
>>>> +       old_arr = rcu_dereference_protected(bond->slave_arr,
>>>> +                                           lockdep_rtnl_is_held() ||
>>>> +                                           lockdep_is_held(&bond->lock)
>>>> ||
>>>> +
>>>> lockdep_is_held(&bond->curr_slave_lock));
>>>
>>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>> This line is the most troublesome for me, which lock is it ? Does this mean
>>> that whichever I hold from the three I can update the slave array ?
>>> I don't think this is worked out well, you should explicitly specify how and
>>> why it is safe to update this under each of the locks and maybe you'll be
>>> able to reduce the lock list :-)
>>>
>> This is primarily because of different code paths it's taking to reach
>> here. In all these cases, one of those locks is held. Unfortunately
>> there are three such locks  that I have identified (for all three
>> modes involved) and hence the above line.
>>
>
> True, but I did a little grepping and here's my analysis of the call sites which
> I can't guarantee is full or complete, but it shows at least 1 problem.
> bond_update_slave_arr() callers:
>
> 1. 3ad mode
> 1.1. bond_3ad_state_machine_handler -> ad_mux_machine ->
> ad_(en|dis)able_collecting_distributing
>    - read_lock(bond->lock), rcu_read_lock, state_machine_lock
> 1.2. __bond_release_one -> bond_3ad_unbind_slave
>    - rtnl, write_lock(bond->lock)
> 1.3. bond_change_active_slave -> bond_3ad_handle_link_change
>    -  from 4. rtnl, new_active != NULL -> write_lock(curr_slave_lock)
> 1.4. bond_miimon_commit -> bond_3ad_handle_link_change
>    - rtnl
^^^^^^
missed the state_machine_lock here

>
> 2. TLB
> 2.1. __bond_release_one -> bond_alb_deinit_slave
>    - rtnl
> 2.2. bond_change_active_slave -> bond_alb_handle_link_change
>    - from 4. rtnl, new_active != NULL -> write_lock(curr_slave_lock)
> 2.3. bond_miimon_commit -> bond_alb_handle_link_change
>    - rtnl
>
> 3. XOR
> 3.1. __bond_release_one
>    - rtnl
> 3.2. bond_miimon_commit
>    - rtnl
>
> 4. bond_change_active_slave:
> 1. bond_select_active_slave -> bond_change_active_slave
> 1.1. bond_enslave -> bond_select_active_slave
>    - rtnl, write_lock(curr_slave_lock)
> 1.2. __bond_release_one -> bond_select_active_slave
>    - rtnl, write_lock(curr_slave_lock)
> 1.3. bond_miimon_commit -> bond_select_active_slave
>    - rtnl, write_lock(curr_slave_lock)
> 1.4. bond_loadbalance_arp_mon -> bond_select_active_slave
>    - rtnl, write_lock(curr_slave_lock)
> 1.5. bond_ab_arp_commit -> bond_select_active_slave
>    - rtnl, write_lock(curr_slave_lock)
> 1.6. bond_slave_netdev_event -> bond_select_active_slave
>    - rtnl, write_lock(curr_slave_lock)
> 1.7. bond_options.c (all callers)
>    - rtnl, write_lock(curr_slave_lock)
>
>
> Almost all callers of slave_update_arr() currently have rtnl acquired, but
> there's 1 troubling caller: bond_3ad_state_machine_handler() which is called
> from a workqueue. Now if we're able to execute anything with that workqueue, we
> have a race condition, good candidates are all options which don't acquire
> write_lock(bond->lock), I think the only one that can call
> bond_slave_update_arr() of those is primary_reselect right now.
^^^^^^^^^^^^^^^^
Though even that might not be a problem since the state_machine_lock would save 
you, so it looks like it's not a problem but the convoluted locking requirements 
are a problem waiting to happen by themselves.

Anyway that is a longstanding problem so I don't mind if you keep the code like 
this, too. Just wanted to make sure that it doesn't create any new subtle race 
conditions.

> So if you come up with some way to deal with that, you probably can use only
> rtnl for syncing the array and simplify this.
> Again I might be wrong since this is done only via grepping :-)
>
> Cheers,
>    Nik

^ permalink raw reply

* Re: [PATCH 09/28] Remove ATHEROS_AR231X
From: Sergey Ryazanov @ 2014-09-05 12:02 UTC (permalink / raw)
  To: Paul Bolle
  Cc: Jiri Slaby, Nick Kossifidis, Luis R. Rodriguez, John W. Linville,
	Oleksij Rempel, Richard Weinberger, Jonathan Bither,
	Hauke Mehrtens, ath5k-devel, open,
	list@hauke-m.de:NETWORKING DRIVERS, antonynpavlov@gmail.com,
	OpenWrt Development List, linux-wireless@vger.kernel.org,
	list@hauke-m.de:NETWORKING DRIVERS, open list
In-Reply-To: <1409916824.7832.20.camel@x220>

2014-09-05 15:33 GMT+04:00 Paul Bolle <pebolle@tiscali.nl>:
> Hi Sergey,
>
> On Fri, 2014-09-05 at 15:12 +0400, Sergey Ryazanov wrote:
>> 2014-09-05 14:10 GMT+04:00, Paul Bolle <pebolle@tiscali.nl>:
>> > On Wed, 2014-06-18 at 13:46 +0200, Paul Bolle wrote:
>> >> Having this conversation every rc1 is getting a bit silly. Could Jiri
>> >> e.a. perhaps set some specific deadline for ATHEROS_AR231X to be
>> >> submitted?
>> >
>> > I waited until rc3. Have you seen any activity on this front? If not,
>> > should I resend the patch that removes the code in mainline that depends
>> > on ATHEROS_AR231X (ie, AHB bus support)?
>> >
>> Recent activity always could be found in [1]. Now I finish another one
>> round of cleanups and have a plan to fix several things (you can
>> always find something that you really want to improve). But if you
>> insist I could immediately switch to "send upstream" mode. And seems
>> that this would be better approach.
>>
>> 1. https://dev.openwrt.org/log/trunk/target/linux/atheros
>
> And where can the related PULL requests or patch submissions be found?
>
I have not sent patches yet, since I thought that it would be easier
to cleanup them in openwrt tree and then send them upstream.

-- 
BR,
Sergey

^ permalink raw reply

* [PATCH] greth: moved TX ring cleaning to NAPI rx poll func
From: Daniel Hellstrom @ 2014-09-05 11:13 UTC (permalink / raw)
  To: davem; +Cc: netdev, software

This patch does not affect the 10/100 GRETH MAC.

Before all GBit GRETH TX descriptor ring cleaning was done in
start_xmit(), when descriptor list became full it activated
TX interrupt to start the NAPI rx poll function to do TX ring
cleaning.

With this patch the TX descriptor ring is always cleaned from
the NAPI rx poll function, triggered via TX or RX interrupt.
Otherwise we could end up in TX frames being sent but not
reported to the stack being sent. On the 10/100 GRETH this
is not an issue since the SKB is copied&aligned into private
buffers so that the SKB can be freed directly on start_xmit()

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 drivers/net/ethernet/aeroflex/greth.c |   86 ++++++++++++++++++--------------
 drivers/net/ethernet/aeroflex/greth.h |    2 +-
 2 files changed, 49 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index 23578df..3005155 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -123,6 +123,12 @@ static inline void greth_enable_tx(struct greth_private *greth)
 	GRETH_REGORIN(greth->regs->control, GRETH_TXEN);
 }
 
+static inline void greth_enable_tx_and_irq(struct greth_private *greth)
+{
+	wmb(); /* BDs must been written to memory before enabling TX */
+	GRETH_REGORIN(greth->regs->control, GRETH_TXEN | GRETH_TXI);
+}
+
 static inline void greth_disable_tx(struct greth_private *greth)
 {
 	GRETH_REGANDIN(greth->regs->control, ~GRETH_TXEN);
@@ -447,29 +453,30 @@ out:
 	return err;
 }
 
+static inline u16 greth_num_free_bds(u16 tx_last, u16 tx_next)
+{
+	if (tx_next < tx_last)
+		return (tx_last - tx_next) - 1;
+	else
+		return GRETH_TXBD_NUM - (tx_next - tx_last) - 1;
+}
 
 static netdev_tx_t
 greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct greth_private *greth = netdev_priv(dev);
 	struct greth_bd *bdp;
-	u32 status = 0, dma_addr, ctrl;
+	u32 status, dma_addr;
 	int curr_tx, nr_frags, i, err = NETDEV_TX_OK;
 	unsigned long flags;
+	u16 tx_last;
 
 	nr_frags = skb_shinfo(skb)->nr_frags;
+	tx_last = greth->tx_last;
+	rmb(); /* tx_last is updated by the poll task */
 
-	/* Clean TX Ring */
-	greth_clean_tx_gbit(dev);
-
-	if (greth->tx_free < nr_frags + 1) {
-		spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/
-		ctrl = GRETH_REGLOAD(greth->regs->control);
-		/* Enable TX IRQ only if not already in poll() routine */
-		if (ctrl & GRETH_RXI)
-			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI);
+	if (greth_num_free_bds(tx_last, greth->tx_next) < nr_frags + 1) {
 		netif_stop_queue(dev);
-		spin_unlock_irqrestore(&greth->devlock, flags);
 		err = NETDEV_TX_BUSY;
 		goto out;
 	}
@@ -488,6 +495,8 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
 	/* Linear buf */
 	if (nr_frags != 0)
 		status = GRETH_TXBD_MORE;
+	else
+		status = GRETH_BD_IE;
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
 		status |= GRETH_TXBD_CSALL;
@@ -545,14 +554,12 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
 
 	/* Enable the descriptor chain by enabling the first descriptor */
 	bdp = greth->tx_bd_base + greth->tx_next;
-	greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN);
-	greth->tx_next = curr_tx;
-	greth->tx_free -= nr_frags + 1;
-
-	wmb();
+	greth_write_bd(&bdp->stat,
+		       greth_read_bd(&bdp->stat) | GRETH_BD_EN);
 
 	spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
-	greth_enable_tx(greth);
+	greth->tx_next = curr_tx;
+	greth_enable_tx_and_irq(greth);
 	spin_unlock_irqrestore(&greth->devlock, flags);
 
 	return NETDEV_TX_OK;
@@ -648,7 +655,6 @@ static void greth_clean_tx(struct net_device *dev)
 	if (greth->tx_free > 0) {
 		netif_wake_queue(dev);
 	}
-
 }
 
 static inline void greth_update_tx_stats(struct net_device *dev, u32 stat)
@@ -670,20 +676,22 @@ static void greth_clean_tx_gbit(struct net_device *dev)
 {
 	struct greth_private *greth;
 	struct greth_bd *bdp, *bdp_last_frag;
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	u32 stat;
 	int nr_frags, i;
+	u16 tx_last;
 
 	greth = netdev_priv(dev);
+	tx_last = greth->tx_last;
 
-	while (greth->tx_free < GRETH_TXBD_NUM) {
+	while (tx_last != greth->tx_next) {
 
-		skb = greth->tx_skbuff[greth->tx_last];
+		skb = greth->tx_skbuff[tx_last];
 
 		nr_frags = skb_shinfo(skb)->nr_frags;
 
 		/* We only clean fully completed SKBs */
-		bdp_last_frag = greth->tx_bd_base + SKIP_TX(greth->tx_last, nr_frags);
+		bdp_last_frag = greth->tx_bd_base + SKIP_TX(tx_last, nr_frags);
 
 		GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX);
 		mb();
@@ -692,14 +700,14 @@ static void greth_clean_tx_gbit(struct net_device *dev)
 		if (stat & GRETH_BD_EN)
 			break;
 
-		greth->tx_skbuff[greth->tx_last] = NULL;
+		greth->tx_skbuff[tx_last] = NULL;
 
 		greth_update_tx_stats(dev, stat);
 		dev->stats.tx_bytes += skb->len;
 
-		bdp = greth->tx_bd_base + greth->tx_last;
+		bdp = greth->tx_bd_base + tx_last;
 
-		greth->tx_last = NEXT_TX(greth->tx_last);
+		tx_last = NEXT_TX(tx_last);
 
 		dma_unmap_single(greth->dev,
 				 greth_read_bd(&bdp->addr),
@@ -708,21 +716,26 @@ static void greth_clean_tx_gbit(struct net_device *dev)
 
 		for (i = 0; i < nr_frags; i++) {
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-			bdp = greth->tx_bd_base + greth->tx_last;
+			bdp = greth->tx_bd_base + tx_last;
 
 			dma_unmap_page(greth->dev,
 				       greth_read_bd(&bdp->addr),
 				       skb_frag_size(frag),
 				       DMA_TO_DEVICE);
 
-			greth->tx_last = NEXT_TX(greth->tx_last);
+			tx_last = NEXT_TX(tx_last);
 		}
-		greth->tx_free += nr_frags+1;
 		dev_kfree_skb(skb);
 	}
+	if (skb) { /* skb is set only if the above while loop was entered */
+		wmb();
+		greth->tx_last = tx_last;
 
-	if (netif_queue_stopped(dev) && (greth->tx_free > (MAX_SKB_FRAGS+1)))
-		netif_wake_queue(dev);
+		if (netif_queue_stopped(dev) &&
+		    (greth_num_free_bds(tx_last, greth->tx_next) >
+		    (MAX_SKB_FRAGS+1)))
+			netif_wake_queue(dev);
+	}
 }
 
 static int greth_rx(struct net_device *dev, int limit)
@@ -965,16 +978,12 @@ static int greth_poll(struct napi_struct *napi, int budget)
 	greth = container_of(napi, struct greth_private, napi);
 
 restart_txrx_poll:
-	if (netif_queue_stopped(greth->netdev)) {
-		if (greth->gbit_mac)
-			greth_clean_tx_gbit(greth->netdev);
-		else
-			greth_clean_tx(greth->netdev);
-	}
-
 	if (greth->gbit_mac) {
+		greth_clean_tx_gbit(greth->netdev);
 		work_done += greth_rx_gbit(greth->netdev, budget - work_done);
 	} else {
+		if (netif_queue_stopped(greth->netdev))
+			greth_clean_tx(greth->netdev);
 		work_done += greth_rx(greth->netdev, budget - work_done);
 	}
 
@@ -983,7 +992,8 @@ restart_txrx_poll:
 		spin_lock_irqsave(&greth->devlock, flags);
 
 		ctrl = GRETH_REGLOAD(greth->regs->control);
-		if (netif_queue_stopped(greth->netdev)) {
+		if ((greth->gbit_mac && (greth->tx_last != greth->tx_next)) ||
+		    (!greth->gbit_mac && netif_queue_stopped(greth->netdev))) {
 			GRETH_REGSAVE(greth->regs->control,
 					ctrl | GRETH_TXI | GRETH_RXI);
 			mask = GRETH_INT_RX | GRETH_INT_RE |
diff --git a/drivers/net/ethernet/aeroflex/greth.h b/drivers/net/ethernet/aeroflex/greth.h
index 232a622..ae16ac9 100644
--- a/drivers/net/ethernet/aeroflex/greth.h
+++ b/drivers/net/ethernet/aeroflex/greth.h
@@ -107,7 +107,7 @@ struct greth_private {
 
 	u16 tx_next;
 	u16 tx_last;
-	u16 tx_free;
+	u16 tx_free; /* only used on 10/100Mbit */
 	u16 rx_cur;
 
 	struct greth_regs *regs;	/* Address of controller registers. */
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH net-next] bonding: limit primary_reselect to modes that use primary only
From: Nikolay Aleksandrov @ 2014-09-05 12:13 UTC (permalink / raw)
  To: netdev; +Cc: vfalico, j.vosburgh, andy, davem, Nikolay Aleksandrov

Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
---
 drivers/net/bonding/bond_options.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index d8dc17faa6b4..591c1fbb7c8d 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -316,6 +316,9 @@ static const struct bond_option bond_opts[] = {
 		.id = BOND_OPT_PRIMARY_RESELECT,
 		.name = "primary_reselect",
 		.desc = "Reselect primary slave once it comes up",
+		.unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_ACTIVEBACKUP) |
+						BIT(BOND_MODE_TLB) |
+						BIT(BOND_MODE_ALB)),
 		.values = bond_primary_reselect_tbl,
 		.set = bond_option_primary_reselect_set
 	},
-- 
1.9.3

^ permalink raw reply related

* Re: [PATCH net-next] bonding: limit primary_reselect to modes that use primary only
From: Nikolay Aleksandrov @ 2014-09-05 12:17 UTC (permalink / raw)
  To: netdev; +Cc: vfalico, j.vosburgh, andy, davem
In-Reply-To: <1409919210-28944-1-git-send-email-nikolay@redhat.com>

On 05/09/14 14:13, Nikolay Aleksandrov wrote:
> Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
> ---
>   drivers/net/bonding/bond_options.c | 3 +++
>   1 file changed, 3 insertions(+)
>
> diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
> index d8dc17faa6b4..591c1fbb7c8d 100644
> --- a/drivers/net/bonding/bond_options.c
> +++ b/drivers/net/bonding/bond_options.c
> @@ -316,6 +316,9 @@ static const struct bond_option bond_opts[] = {
>   		.id = BOND_OPT_PRIMARY_RESELECT,
>   		.name = "primary_reselect",
>   		.desc = "Reselect primary slave once it comes up",
> +		.unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_ACTIVEBACKUP) |
> +						BIT(BOND_MODE_TLB) |
> +						BIT(BOND_MODE_ALB)),
>   		.values = bond_primary_reselect_tbl,
>   		.set = bond_option_primary_reselect_set
>   	},
>

Actually, self-nak as this adds option dependency.
Sorry for the noise

Nik

^ 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