Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next] ipv6: drop fragmented ndisc packets by default (RFC 6980)
From: Hannes Frederic Sowa @ 2013-08-27  3:48 UTC (permalink / raw)
  To: Loganaden Velvindron; +Cc: netdev, Fernando Gont, yoshfuji
In-Reply-To: <CAOp4FwRWze=HG-8bp8R5nicC0b=R1ZRc6e6+fseXvn==gLqn0w@mail.gmail.com>

On Tue, Aug 27, 2013 at 07:40:21AM +0400, Loganaden Velvindron wrote:
> On Tue, Aug 27, 2013 at 3:36 AM, Hannes Frederic Sowa
> <hannes@stressinduktion.org> wrote:
> > This patch implements RFC6980: Drop fragmented ndisc packets by
> > default. If a fragmented ndisc packet is received the user is informed
> > that it is possible to disable the check.
> >
> 
> It's similar to the older patch except that now it's under a sysctl ?

Yes, logic is the same + warning message + can be disabled via sysctl.

Greetings,

  Hannes

^ permalink raw reply

* Re: [PATCH net-next] ipv6: drop fragmented ndisc packets by default (RFC 6980)
From: Loganaden Velvindron @ 2013-08-27  3:40 UTC (permalink / raw)
  To: netdev, Fernando Gont, yoshfuji
In-Reply-To: <20130826233651.GA9183@order.stressinduktion.org>

On Tue, Aug 27, 2013 at 3:36 AM, Hannes Frederic Sowa
<hannes@stressinduktion.org> wrote:
> This patch implements RFC6980: Drop fragmented ndisc packets by
> default. If a fragmented ndisc packet is received the user is informed
> that it is possible to disable the check.
>

It's similar to the older patch except that now it's under a sysctl ?


> Cc: Fernando Gont <fernando@gont.com.ar>
> Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
> ---
>  Documentation/networking/ip-sysctl.txt |  6 ++++++
>  include/linux/ipv6.h                   |  1 +
>  include/uapi/linux/ipv6.h              |  1 +
>  net/ipv6/addrconf.c                    | 10 ++++++++++
>  net/ipv6/ndisc.c                       | 17 +++++++++++++++++
>  5 files changed, 35 insertions(+)
>
> diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
> index debfe85..a2be556 100644
> --- a/Documentation/networking/ip-sysctl.txt
> +++ b/Documentation/networking/ip-sysctl.txt
> @@ -1349,6 +1349,12 @@ mldv2_unsolicited_report_interval - INTEGER
>         MLDv2 report retransmit will take place.
>         Default: 1000 (1 second)
>
> +suppress_frag_ndisc - INTEGER
> +       Control RFC 6980 (Security Implications of IPv6 Fragmentation
> +       with IPv6 Neighbor Discovery) behavior:
> +       1 - (default) discard fragmented neighbor discovery packets
> +       0 - allow fragmented neighbor discovery packets
> +
>  icmp/*:
>  ratelimit - INTEGER
>         Limit the maximal rates for sending ICMPv6 packets.
> diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
> index 9ac5047..28ea384 100644
> --- a/include/linux/ipv6.h
> +++ b/include/linux/ipv6.h
> @@ -50,6 +50,7 @@ struct ipv6_devconf {
>         __s32           accept_dad;
>         __s32           force_tllao;
>         __s32           ndisc_notify;
> +       __s32           suppress_frag_ndisc;
>         void            *sysctl;
>  };
>
> diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
> index d07ac69..593b0e3 100644
> --- a/include/uapi/linux/ipv6.h
> +++ b/include/uapi/linux/ipv6.h
> @@ -162,6 +162,7 @@ enum {
>         DEVCONF_NDISC_NOTIFY,
>         DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL,
>         DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL,
> +       DEVCONF_SUPPRESS_FRAG_NDISC,
>         DEVCONF_MAX
>  };
>
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index 2d6d179..a7183fc 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -204,6 +204,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
>         .accept_source_route    = 0,    /* we do not accept RH0 by default. */
>         .disable_ipv6           = 0,
>         .accept_dad             = 1,
> +       .suppress_frag_ndisc    = 1,
>  };
>
>  static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
> @@ -241,6 +242,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
>         .accept_source_route    = 0,    /* we do not accept RH0 by default. */
>         .disable_ipv6           = 0,
>         .accept_dad             = 1,
> +       .suppress_frag_ndisc    = 1,
>  };
>
>  /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
> @@ -4188,6 +4190,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
>         array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
>         array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
>         array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify;
> +       array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc;
>  }
>
>  static inline size_t inet6_ifla6_size(void)
> @@ -5002,6 +5005,13 @@ static struct addrconf_sysctl_table
>                         .proc_handler   = proc_dointvec
>                 },
>                 {
> +                       .procname       = "suppress_frag_ndisc",
> +                       .data           = &ipv6_devconf.suppress_frag_ndisc,
> +                       .maxlen         = sizeof(int),
> +                       .mode           = 0644,
> +                       .proc_handler   = proc_dointvec
> +               },
> +               {
>                         /* sentinel */
>                 }
>         },
> diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
> index 04d31c2..41720fe 100644
> --- a/net/ipv6/ndisc.c
> +++ b/net/ipv6/ndisc.c
> @@ -1519,10 +1519,27 @@ static void pndisc_redo(struct sk_buff *skb)
>         kfree_skb(skb);
>  }
>
> +static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
> +{
> +       struct inet6_dev *idev = __in6_dev_get(skb->dev);
> +
> +       if (!idev)
> +               return true;
> +       if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED &&
> +           idev->cnf.suppress_frag_ndisc) {
> +               net_warn_ratelimited("Received fragmented ndisc packet. Carefully consider disabling suppress_frag_ndisc.\n");
> +               return true;
> +       }
> +       return false;
> +}
> +
>  int ndisc_rcv(struct sk_buff *skb)
>  {
>         struct nd_msg *msg;
>
> +       if (ndisc_suppress_frag_ndisc(skb))
> +               return 0;
> +
>         if (skb_linearize(skb))
>                 return 0;
>
> --
> 1.8.3.1
>
> --
> 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



-- 
This message is strictly personal and the opinions expressed do not
represent those of my employers, either past or present.

^ permalink raw reply

* Is fallback vhost_net to qemu for live migrate available?
From: Qin Chuanyu @ 2013-08-27  3:32 UTC (permalink / raw)
  To: Michael S. Tsirkin, jasowang; +Cc: kvm, netdev, qianhuibin

Hi all

I am participating in a project which try to port vhost_net on Xen。

By change the memory copy and notify mechanism ,currently virtio-net 
with vhost_net could run on Xen with good performance。TCP receive 
throughput of single vnic from 2.77Gbps up to 6Gps。In VM receive 
side,I instead grant_copy with grant_map + memcopy,it efficiently 
reduce the cost of grant_table spin_lock of dom0,So the hole server TCP 
performance from 5.33Gps up to 9.5Gps。

Now I am consider the live migrate of vhost_net on Xen,vhost_net use 
vhost_log for live migrate on Kvm,but qemu on Xen havn't manage the 
hole memory of VM,So I am trying to fallback datapath from vhost_net to 
qemu when doing live migrate ,and fallback datapath from qemu to
vhost_net again after vm migrate to new server。

My question is:
	why didn't vhost_net do the same fallback operation for live migrate on 
KVM,but use vhost_log to mark the dirty page?
	Is there any mechanism fault for the idea of fallback datapath from 
vhost_net to qemu for live migrate?

any question about the detail of vhost_net on Xen is welcome。

Thanks

^ permalink raw reply

* RE: [PATCH net-next] {ipv4,xfrm}: Introduce xfrm_tunnel_notifier for xfrm tunnel mode callback
From: Saurabh Mohan @ 2013-08-27  1:52 UTC (permalink / raw)
  To: Fan Du, steffen.klassert@secunet.com,
	herbert@gondor.hengli.com.au
  Cc: davem@davemloft.net, netdev@vger.kernel.org
In-Reply-To: <1377240424-11758-1-git-send-email-fan.du@windriver.com>



> -----Original Message-----
> From: Fan Du [mailto:fan.du@windriver.com]
> Sent: Thursday, August 22, 2013 11:47 PM
> To: steffen.klassert@secunet.com; Saurabh Mohan;
> herbert@gondor.hengli.com.au
> Cc: davem@davemloft.net; netdev@vger.kernel.org
> Subject: [PATCH net-next] {ipv4,xfrm}: Introduce xfrm_tunnel_notifier for
> xfrm tunnel mode callback
> 
> Some thoughts on IPv4 VTI implementation:
> 
> The connection between VTI receiving part and xfrm tunnel mode input
> process is hardly a "xfrm_tunnel", xfrm_tunnel is used in places where, e.g
> ipip/sit and xfrm4_tunnel, acts like a true "tunnel" device.
> 
> In addition, IMHO, VTI doesn't need vti_err to do something meaningful, as
> all VTI needs is just a notifier to be called whenever xfrm_input ingress a
> packet to update statistics.
> 
> So this patch introduce xfrm_tunnel_notifier and meanwhile wipe out
> vti_erri code.
> 
> Signed-off-by: Fan Du <fan.du@windriver.com>
Looks good. Thanks.
Reviewed-by: Saurabh Mohan <saurabh.mohan@vyatta.com>

^ permalink raw reply

* Re: [PATCH net-next] {ipv4,xfrm}: Introduce xfrm_tunnel_notifier for xfrm tunnel mode callback
From: Fan Du @ 2013-08-27  1:40 UTC (permalink / raw)
  To: Steffen Klassert; +Cc: saurabh.mohan, herbert, davem, netdev
In-Reply-To: <20130826113559.GM26773@secunet.com>

Hi, Steffen

Thanks for your attention :)

On 2013年08月26日 19:35, Steffen Klassert wrote:
> On Fri, Aug 23, 2013 at 02:47:04PM +0800, Fan Du wrote:
>> Some thoughts on IPv4 VTI implementation:
>>
>> The connection between VTI receiving part and xfrm tunnel mode input process
>> is hardly a "xfrm_tunnel", xfrm_tunnel is used in places where, e.g ipip/sit
>> and xfrm4_tunnel, acts like a true "tunnel" device.
>>
>> In addition, IMHO, VTI doesn't need vti_err to do something meaningful, as all
>> VTI needs is just a notifier to be called whenever xfrm_input ingress a packet
>> to update statistics.
>>
>> So this patch introduce xfrm_tunnel_notifier and meanwhile wipe out vti_erri
>> code.
>
> Btw. who calls vti_err()? I don't see a hook which would call the vti
> error handler. I'm still not absolutely sure whether we need it or not,
> but we should either remove it or add a hook to call it.

Yes, nobody calls vti_err. Maybe the vti_err comes from ipip_err as comments in
the file header said ip_vti.c cloned from ipip.c.

I have describe my statement in the reply for Dave's question. Please review.

-- 
浮沉随浪只记今朝笑

--fan

^ permalink raw reply

* Re: [PATCH net-next] {ipv4,xfrm}: Introduce xfrm_tunnel_notifier for xfrm tunnel mode callback
From: Fan Du @ 2013-08-27  1:29 UTC (permalink / raw)
  To: David Miller; +Cc: steffen.klassert, saurabh.mohan, herbert, netdev
In-Reply-To: <20130826.162135.1765443562851401512.davem@davemloft.net>

Hi, Dave

Thanks for your reply :)

On 2013年08月27日 04:21, David Miller wrote:
> From: Fan Du<fan.du@windriver.com>
> Date: Fri, 23 Aug 2013 14:47:04 +0800
>
>> Some thoughts on IPv4 VTI implementation:
>>
>> The connection between VTI receiving part and xfrm tunnel mode input process
>> is hardly a "xfrm_tunnel", xfrm_tunnel is used in places where, e.g ipip/sit
>> and xfrm4_tunnel, acts like a true "tunnel" device.
>>
>> In addition, IMHO, VTI doesn't need vti_err to do something meaningful, as all
>> VTI needs is just a notifier to be called whenever xfrm_input ingress a packet
>> to update statistics.
>>
>> So this patch introduce xfrm_tunnel_notifier and meanwhile wipe out vti_erri
>> code.
>>
>> Signed-off-by: Fan Du<fan.du@windriver.com>
>
> I don't understand why VTI doesn't need to propagate a PMTU update via
> ipv4_update_pmtu().  Why is it different from a real xfrm_tunnel?
   ^^^^^^^^^^^^^^^^

A IPsec protected packet is first handled by protocol handlers, e.g AH/ESP,
to check packet authentication or encryption rightness. PMTU update is taken
care of in this stage by protocol error handler.

Then the packet is rearranged properly depending on whether it's transport
mode or tunnel mode packed by mode "input" handler. The VTI handler code
takes effects in this stage in tunnel mode only. So it neither need propagate
PMTU, as it has already been done if necessary, nor the VTI handler is
qualified as a xfrm_tunnel.

IMHO, xfrm_tunnel is protocol layer specific only, which denotes a method
how IPPROTO_IPIP inner packet is handled, while as VTI reform XFRM policy into
a routable net device. That's the difference between them.

>
> Your changelog has to explain this better and in more detail.
> Thanks.
>

-- 
浮沉随浪只记今朝笑

--fan

^ permalink raw reply

* [patch -next] qlcnic: underflow in qlcnic_validate_max_tx_rings()
From: Dan Carpenter @ 2013-08-27  1:16 UTC (permalink / raw)
  To: Himanshu Madhani
  Cc: Rajesh Borundia, Shahed Shaikh, Jitendra Kalsaria, Sony Chacko,
	Sucheta Chakraborty, linux-driver, netdev, kernel-janitors

This function checks the upper bound but it doesn't check for negative
numbers:

	if (txq > QLCNIC_MAX_TX_RINGS) {

I've solved this by making "txq" a u32 type.  I chose that because
->tx_count in the ethtool_channels struct is a __u32.

This bug was added in aa4a1f7df7 ('qlcnic: Enable Tx queue changes using
ethtool for 82xx Series adapter.').

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 3f03856..ae9b444 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1537,7 +1537,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test);
 netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
 int qlcnic_set_max_rss(struct qlcnic_adapter *, u8, int);
 int qlcnic_validate_max_rss(struct qlcnic_adapter *, __u32);
-int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *, int);
+int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *, u32 txq);
 void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
 void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *);
 int qlcnic_enable_msix(struct qlcnic_adapter *, u32);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 8321d1a..88e3c97 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -3524,7 +3524,7 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
 	return err;
 }
 
-int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *adapter, int txq)
+int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *adapter, u32 txq)
 {
 	struct net_device *netdev = adapter->netdev;
 	u8 max_hw = QLCNIC_MAX_TX_RINGS;

^ permalink raw reply related

* Re: [PATCH 0/2] Rename nsproxy.pid_ns and fix a related security bug
From: Eric W. Biederman @ 2013-08-27  1:03 UTC (permalink / raw)
  To: David Miller; +Cc: luto, security, linux-kernel, netdev
In-Reply-To: <20130826.155909.1859861206590524940.davem@davemloft.net>

David Miller <davem@davemloft.net> writes:

> From: Andy Lutomirski <luto@amacapital.net>
> Date: Thu, 22 Aug 2013 11:39:14 -0700
>
>>     commit 92f28d973cce45ef5823209aab3138eb45d8b349
>>     Author: Eric W. Biederman <ebiederm@xmission.com>
>>     Date:   Fri Mar 15 01:03:33 2013 -0700
>> 
>>         scm: Require CAP_SYS_ADMIN over the current pidns to spoof pids.
>> 
>> Eric fell for my bogus claim that nsproxy->pid_ns was the current'
>> process's pid ns.  This isn't true.
>> 
>> Let's fix the bug and rename pid_ns so that no one gets this wrong again.
>> 
>> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
>
> Eric please take the time to review these changes, thanks.

Reviewed they are good.

My apologies for the delay life got in my way and I fell behind on
dealing with patches.

Eric

^ permalink raw reply

* Re: [PATCH 2/2] Rename nsproxy.pid_ns to nsproxy.pid_ns_for_children
From: Eric W. Biederman @ 2013-08-27  1:02 UTC (permalink / raw)
  To: Andy Lutomirski; +Cc: security, linux-kernel, netdev
In-Reply-To: <a5db0606160dbd1412828be0d91a4a115a84abf6.1377196394.git.luto@amacapital.net>

Andy Lutomirski <luto@amacapital.net> writes:

> nsproxy.pid_ns is *not* the task's pid namespace.  The name should clarify
> that.
>
> This makes it more obvious that setns on a pid namespace is weird --
> it won't change the pid namespace shown in procfs.

Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com>

> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
> ---
>  include/linux/nsproxy.h |  6 +++++-
>  kernel/fork.c           |  5 +++--
>  kernel/nsproxy.c        | 27 ++++++++++++++-------------
>  kernel/pid_namespace.c  |  4 ++--
>  4 files changed, 24 insertions(+), 18 deletions(-)
>
> diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
> index 10e5947..b4ec59d 100644
> --- a/include/linux/nsproxy.h
> +++ b/include/linux/nsproxy.h
> @@ -14,6 +14,10 @@ struct fs_struct;
>   * A structure to contain pointers to all per-process
>   * namespaces - fs (mount), uts, network, sysvipc, etc.
>   *
> + * The pid namespace is an exception -- it's accessed using
> + * task_active_pid_ns.  The pid namespace here is the
> + * namespace that children will use.
> + *
>   * 'count' is the number of tasks holding a reference.
>   * The count for each namespace, then, will be the number
>   * of nsproxies pointing to it, not the number of tasks.
> @@ -27,7 +31,7 @@ struct nsproxy {
>  	struct uts_namespace *uts_ns;
>  	struct ipc_namespace *ipc_ns;
>  	struct mnt_namespace *mnt_ns;
> -	struct pid_namespace *pid_ns;
> +	struct pid_namespace *pid_ns_for_children;
>  	struct net 	     *net_ns;
>  };
>  extern struct nsproxy init_nsproxy;
> diff --git a/kernel/fork.c b/kernel/fork.c
> index e23bb19..bf46287 100644
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -1177,7 +1177,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
>  	 * don't allow the creation of threads.
>  	 */
>  	if ((clone_flags & (CLONE_VM|CLONE_NEWPID)) &&
> -	    (task_active_pid_ns(current) != current->nsproxy->pid_ns))
> +	    (task_active_pid_ns(current) !=
> +	     current->nsproxy->pid_ns_for_children))
>  		return ERR_PTR(-EINVAL);
>  
>  	retval = security_task_create(clone_flags);
> @@ -1351,7 +1352,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
>  
>  	if (pid != &init_struct_pid) {
>  		retval = -ENOMEM;
> -		pid = alloc_pid(p->nsproxy->pid_ns);
> +		pid = alloc_pid(p->nsproxy->pid_ns_for_children);
>  		if (!pid)
>  			goto bad_fork_cleanup_io;
>  	}
> diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
> index 364ceab..997cbb9 100644
> --- a/kernel/nsproxy.c
> +++ b/kernel/nsproxy.c
> @@ -29,15 +29,15 @@
>  static struct kmem_cache *nsproxy_cachep;
>  
>  struct nsproxy init_nsproxy = {
> -	.count	= ATOMIC_INIT(1),
> -	.uts_ns	= &init_uts_ns,
> +	.count			= ATOMIC_INIT(1),
> +	.uts_ns			= &init_uts_ns,
>  #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
> -	.ipc_ns	= &init_ipc_ns,
> +	.ipc_ns			= &init_ipc_ns,
>  #endif
> -	.mnt_ns	= NULL,
> -	.pid_ns	= &init_pid_ns,
> +	.mnt_ns			= NULL,
> +	.pid_ns_for_children	= &init_pid_ns,
>  #ifdef CONFIG_NET
> -	.net_ns	= &init_net,
> +	.net_ns			= &init_net,
>  #endif
>  };
>  
> @@ -85,9 +85,10 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
>  		goto out_ipc;
>  	}
>  
> -	new_nsp->pid_ns = copy_pid_ns(flags, user_ns, tsk->nsproxy->pid_ns);
> -	if (IS_ERR(new_nsp->pid_ns)) {
> -		err = PTR_ERR(new_nsp->pid_ns);
> +	new_nsp->pid_ns_for_children =
> +		copy_pid_ns(flags, user_ns, tsk->nsproxy->pid_ns_for_children);
> +	if (IS_ERR(new_nsp->pid_ns_for_children)) {
> +		err = PTR_ERR(new_nsp->pid_ns_for_children);
>  		goto out_pid;
>  	}
>  
> @@ -100,8 +101,8 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
>  	return new_nsp;
>  
>  out_net:
> -	if (new_nsp->pid_ns)
> -		put_pid_ns(new_nsp->pid_ns);
> +	if (new_nsp->pid_ns_for_children)
> +		put_pid_ns(new_nsp->pid_ns_for_children);
>  out_pid:
>  	if (new_nsp->ipc_ns)
>  		put_ipc_ns(new_nsp->ipc_ns);
> @@ -174,8 +175,8 @@ void free_nsproxy(struct nsproxy *ns)
>  		put_uts_ns(ns->uts_ns);
>  	if (ns->ipc_ns)
>  		put_ipc_ns(ns->ipc_ns);
> -	if (ns->pid_ns)
> -		put_pid_ns(ns->pid_ns);
> +	if (ns->pid_ns_for_children)
> +		put_pid_ns(ns->pid_ns_for_children);
>  	put_net(ns->net_ns);
>  	kmem_cache_free(nsproxy_cachep, ns);
>  }
> diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
> index 6917e8e..601bb36 100644
> --- a/kernel/pid_namespace.c
> +++ b/kernel/pid_namespace.c
> @@ -349,8 +349,8 @@ static int pidns_install(struct nsproxy *nsproxy, void *ns)
>  	if (ancestor != active)
>  		return -EINVAL;
>  
> -	put_pid_ns(nsproxy->pid_ns);
> -	nsproxy->pid_ns = get_pid_ns(new);
> +	put_pid_ns(nsproxy->pid_ns_for_children);
> +	nsproxy->pid_ns_for_children = get_pid_ns(new);
>  	return 0;
>  }

^ permalink raw reply

* Re: [PATCH 1/2] net: Check the correct namespace when spoofing pid over SCM_RIGHTS
From: Eric W. Biederman @ 2013-08-27  1:02 UTC (permalink / raw)
  To: Andy Lutomirski; +Cc: security, linux-kernel, netdev, stable
In-Reply-To: <ff9dd301d8c91ec02362d52494b4a640f370bc68.1377196394.git.luto@amacapital.net>

Andy Lutomirski <luto@amacapital.net> writes:

> This is a security bug.
>
> The follow-up will fix nsproxy to discourage this type of issue from
> happening again.

Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com>
>
> Cc: stable@vger.kernel.org
> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
> ---
>  net/core/scm.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/core/scm.c b/net/core/scm.c
> index 03795d0..b4da80b 100644
> --- a/net/core/scm.c
> +++ b/net/core/scm.c
> @@ -54,7 +54,7 @@ static __inline__ int scm_check_creds(struct ucred *creds)
>  		return -EINVAL;
>  
>  	if ((creds->pid == task_tgid_vnr(current) ||
> -	     ns_capable(current->nsproxy->pid_ns->user_ns, CAP_SYS_ADMIN)) &&
> +	     ns_capable(task_active_pid_ns(current)->user_ns, CAP_SYS_ADMIN)) &&
>  	    ((uid_eq(uid, cred->uid)   || uid_eq(uid, cred->euid) ||
>  	      uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) &&
>  	    ((gid_eq(gid, cred->gid)   || gid_eq(gid, cred->egid) ||

^ permalink raw reply

* Re: [PATCH v2 net-next] tcp: TSO packets automatic sizing
From: Eric Dumazet @ 2013-08-27  0:47 UTC (permalink / raw)
  To: David Miller
  Cc: netdev, Neal Cardwell, Yuchung Cheng, Van Jacobson, Tom Herbert
In-Reply-To: <1377491162.8828.116.camel@edumazet-glaptop>

On Sun, 2013-08-25 at 21:26 -0700, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>

>  
> v2: Neal Cardwell reported a suspect deferring of last two segments on
> initial write of 10 MSS, I had to change tcp_tso_should_defer() to take
> into account tp->xmit_size_goal_segs 

Please do not apply, will send a v3, because srtt can be zero in some
occasions (divide by 0)

^ permalink raw reply

* Re: [PATCH] tipc: set sk_err correctly when connection fails
From: Ying Xue @ 2013-08-27  0:45 UTC (permalink / raw)
  To: erik.hugne; +Cc: netdev, jon.maloy, paul.gortmaker, tipc-discussion, nhan.tt.vo
In-Reply-To: <1377266200-26691-1-git-send-email-erik.hugne@ericsson.com>

On 08/23/2013 09:56 PM, erik.hugne@ericsson.com wrote:
> From: Erik Hugne <erik.hugne@ericsson.com>
> 
> This fixes a problem when connect() fails and returns the error
> code as a positive value, whereas errno itself is never set. The
> reason is that error codes set in sk_err should never be inverted.
> 
> Signed-off-by: Erik Hugne <erik.hugne@ericsson.com>

Acked-by: Ying Xue <ying.xue@windriver.com>

> ---
>  net/tipc/socket.c |    4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/net/tipc/socket.c b/net/tipc/socket.c
> index ce8249c..6cc7ddd 100644
> --- a/net/tipc/socket.c
> +++ b/net/tipc/socket.c
> @@ -1257,7 +1257,7 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
>  		/* Accept only ACK or NACK message */
>  		if (unlikely(msg_errcode(msg))) {
>  			sock->state = SS_DISCONNECTING;
> -			sk->sk_err = -ECONNREFUSED;
> +			sk->sk_err = ECONNREFUSED;
>  			retval = TIPC_OK;
>  			break;
>  		}
> @@ -1268,7 +1268,7 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
>  		res = auto_connect(sock, msg);
>  		if (res) {
>  			sock->state = SS_DISCONNECTING;
> -			sk->sk_err = res;
> +			sk->sk_err = -res;
>  			retval = TIPC_OK;
>  			break;
>  		}
> 

^ permalink raw reply

* Re: [PATCH net-next] pkt_sched: fq: Fair Queue packet scheduler
From: Eric Dumazet @ 2013-08-27  0:45 UTC (permalink / raw)
  To: Vijay Subramanian; +Cc: netdev
In-Reply-To: <CAGK4HS_9cwEFdifYpe4Lq+daH2dzgaXCYOBNA+rkAnYw=imvfg@mail.gmail.com>

On Mon, 2013-08-26 at 17:28 -0700, Vijay Subramanian wrote:
> (Resending this as my earlier email to netdev bounced).
> 
>  On 24 August 2013 23:53, David Miller <davem@davemloft.net> wrote:
> >
> >
> > This depends upon your TCP patch, I knew this but you really should
> > be explicit about dependencies. :-)
> 
> Eric,
> If you are planning to resend this patch, you may want to take care of
> some trailing space issues reported by checkpatch plus some other
> warnings.

Thanks, will do ;)

^ permalink raw reply

* Re: [PATCH net-next] pkt_sched: fq: Fair Queue packet scheduler
From: Vijay Subramanian @ 2013-08-27  0:28 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev
In-Reply-To: <CAGK4HS9T_aXJiSDaTbPfX92Z6Cqo7+EcS-k5jh6oc65yA5bf5A@mail.gmail.com>

(Resending this as my earlier email to netdev bounced).

 On 24 August 2013 23:53, David Miller <davem@davemloft.net> wrote:
>
>
> This depends upon your TCP patch, I knew this but you really should
> be explicit about dependencies. :-)

Eric,
If you are planning to resend this patch, you may want to take care of
some trailing space issues reported by checkpatch plus some other
warnings.

Applying: pkt_sched: fq: Fair Queue packet scheduler
/usr/src/net-next/.git/rebase-apply/patch:555: trailing whitespace.
/usr/src/net-next/.git/rebase-apply/patch:613: trailing whitespace.
/usr/src/net-next/.git/rebase-apply/patch:751: trailing whitespace.
}
/usr/src/net-next/.git/rebase-apply/patch:755: trailing whitespace.
qdisc_watchdog_cancel(&q->watchdog);
/usr/src/net-next/.git/rebase-apply/patch:821: trailing whitespace.


Thanks,
Vijay

^ permalink raw reply

* Re: pcie_get_minimum_link returns 0 width
From: Bjorn Helgaas @ 2013-08-26 23:57 UTC (permalink / raw)
  To: Yuval Mintz
  Cc: jacob.e.keller@intel.com, linux-pci@vger.kernel.org,
	netdev@vger.kernel.org
In-Reply-To: <979A8436335E3744ADCD3A9F2A2B68A52AD13D0C@SJEXCHMB10.corp.ad.broadcom.com>

On Mon, Aug 26, 2013 at 5:36 PM, Yuval Mintz <yuvalmin@broadcom.com> wrote:
>> > Hi,
>> >
>> > I tried adding support for the newly added 'pcie_get_minimum_link' into
>> the
>> > bnx2x driver, but found out the some of my devices started showing width
>> x0.
>> >
>> > By adding debug prints, I've found out there were devices up the chain that
>> > Showed 0 when their PCI_EXP_LNKSTA was read by said function.
>> > However, when I tried looking via lspci the output claimed the width was
>> x4.
>>
>> I don't see a 'pcie_get_minimum_link()' function in my current tree
>> (git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git "next"
>> branch).  Maybe seeing your patch (with the debug prints) would give
>> me a hook for somewhere to start looking.
>
> You've acked the patch and it was applied in net-next; Obviously it has yet
> to migrate to your tree.

Oh, yeah, that's right.  I knew it sounded familiar, but I didn't
remember where it went.

Looking at its implementation, one obvious difference is that
pcie_get_minimum_link() traverses up the hierarchy and keeps track of
the minimum values it finds.  lspci, on the other hand, just reads
PCI_EXP_LNKSTA from a single device and decodes it.

You said lspci reports x4 for every device from the Root Port all the
way down to your NIC, so I would think the minimum from
pcie_get_minimum_link() would be x4.  But apparently it's not.  Maybe
there's a bug in it.  Can you post the complete "lspci -vv" output
along with your debug patch and output?

Bjorn

^ permalink raw reply

* [PATCH net-next] ipv6: drop fragmented ndisc packets by default (RFC 6980)
From: Hannes Frederic Sowa @ 2013-08-26 23:36 UTC (permalink / raw)
  To: netdev; +Cc: fernando, yoshfuji

This patch implements RFC6980: Drop fragmented ndisc packets by
default. If a fragmented ndisc packet is received the user is informed
that it is possible to disable the check.

Cc: Fernando Gont <fernando@gont.com.ar>
Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
 Documentation/networking/ip-sysctl.txt |  6 ++++++
 include/linux/ipv6.h                   |  1 +
 include/uapi/linux/ipv6.h              |  1 +
 net/ipv6/addrconf.c                    | 10 ++++++++++
 net/ipv6/ndisc.c                       | 17 +++++++++++++++++
 5 files changed, 35 insertions(+)

diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index debfe85..a2be556 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1349,6 +1349,12 @@ mldv2_unsolicited_report_interval - INTEGER
 	MLDv2 report retransmit will take place.
 	Default: 1000 (1 second)
 
+suppress_frag_ndisc - INTEGER
+	Control RFC 6980 (Security Implications of IPv6 Fragmentation
+	with IPv6 Neighbor Discovery) behavior:
+	1 - (default) discard fragmented neighbor discovery packets
+	0 - allow fragmented neighbor discovery packets
+
 icmp/*:
 ratelimit - INTEGER
 	Limit the maximal rates for sending ICMPv6 packets.
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 9ac5047..28ea384 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -50,6 +50,7 @@ struct ipv6_devconf {
 	__s32		accept_dad;
 	__s32		force_tllao;
 	__s32           ndisc_notify;
+	__s32		suppress_frag_ndisc;
 	void		*sysctl;
 };
 
diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
index d07ac69..593b0e3 100644
--- a/include/uapi/linux/ipv6.h
+++ b/include/uapi/linux/ipv6.h
@@ -162,6 +162,7 @@ enum {
 	DEVCONF_NDISC_NOTIFY,
 	DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL,
 	DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL,
+	DEVCONF_SUPPRESS_FRAG_NDISC,
 	DEVCONF_MAX
 };
 
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 2d6d179..a7183fc 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -204,6 +204,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
 	.accept_source_route	= 0,	/* we do not accept RH0 by default. */
 	.disable_ipv6		= 0,
 	.accept_dad		= 1,
+	.suppress_frag_ndisc	= 1,
 };
 
 static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -241,6 +242,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
 	.accept_source_route	= 0,	/* we do not accept RH0 by default. */
 	.disable_ipv6		= 0,
 	.accept_dad		= 1,
+	.suppress_frag_ndisc	= 1,
 };
 
 /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -4188,6 +4190,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
 	array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
 	array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
 	array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify;
+	array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc;
 }
 
 static inline size_t inet6_ifla6_size(void)
@@ -5002,6 +5005,13 @@ static struct addrconf_sysctl_table
 			.proc_handler   = proc_dointvec
 		},
 		{
+			.procname	= "suppress_frag_ndisc",
+			.data		= &ipv6_devconf.suppress_frag_ndisc,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= proc_dointvec
+		},
+		{
 			/* sentinel */
 		}
 	},
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 04d31c2..41720fe 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1519,10 +1519,27 @@ static void pndisc_redo(struct sk_buff *skb)
 	kfree_skb(skb);
 }
 
+static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
+{
+	struct inet6_dev *idev = __in6_dev_get(skb->dev);
+
+	if (!idev)
+		return true;
+	if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED &&
+	    idev->cnf.suppress_frag_ndisc) {
+		net_warn_ratelimited("Received fragmented ndisc packet. Carefully consider disabling suppress_frag_ndisc.\n");
+		return true;
+	}
+	return false;
+}
+
 int ndisc_rcv(struct sk_buff *skb)
 {
 	struct nd_msg *msg;
 
+	if (ndisc_suppress_frag_ndisc(skb))
+		return 0;
+
 	if (skb_linearize(skb))
 		return 0;
 
-- 
1.8.3.1

^ permalink raw reply related

* RE: pcie_get_minimum_link returns 0 width
From: Yuval Mintz @ 2013-08-26 23:36 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: jacob.e.keller@intel.com, linux-pci@vger.kernel.org,
	netdev@vger.kernel.org
In-Reply-To: <CAErSpo4NmL0RWcBompuweHNYmhNmLXU_21_gvaqfDEzi+HBp5g@mail.gmail.com>

> > Hi,
> >
> > I tried adding support for the newly added 'pcie_get_minimum_link' into
> the
> > bnx2x driver, but found out the some of my devices started showing width
> x0.
> >
> > By adding debug prints, I've found out there were devices up the chain that
> > Showed 0 when their PCI_EXP_LNKSTA was read by said function.
> > However, when I tried looking via lspci the output claimed the width was
> x4.
> 
> I don't see a 'pcie_get_minimum_link()' function in my current tree
> (git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git "next"
> branch).  Maybe seeing your patch (with the debug prints) would give
> me a hook for somewhere to start looking.

You've acked the patch and it was applied in net-next; Obviously it has yet
to migrate to your tree. 

> 
> Can you figure out why lspci shows the correct value and this kernel
> interface does not?  The current lspci source is in
> git://git.kernel.org/pub/scm/utils/pciutils/pciutils.git and the
> relevant code is probably in cap_express_link() here:
> http://git.kernel.org/cgit/utils/pciutils/pciutils.git/tree/ls-caps.c#n750

Traced the read as going via the pci-sysfs. Where should I look for the bus's
read ops?

Thanks,
Yuval

^ permalink raw reply

* Re: [PATCH net-next 07/16] sfc: Limit scope of a Falcon A1 IRQ workaround
From: Ben Hutchings @ 2013-08-26 22:47 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: David Miller, netdev, linux-net-drivers
In-Reply-To: <521B4AA9.9000906@cogentembedded.com>

On Mon, 2013-08-26 at 16:31 +0400, Sergei Shtylyov wrote:
> Hello.
> 
> On 26-08-2013 3:03, Ben Hutchings wrote:
> 
> > We unconditionally acknowledge legacy interrupts just before disabling
> > them.  This workaround is needed on Falcon A1 but probably not on
> > later chips where the legacy interrupt mechanism is different.  It was
> > also originally done after the IRQ handler was removed, not before.
> > Restore the original behaviour for Falcon A1 only by doing this
> > acknowledgement in the efx_nic_type::fini operation.
> 
> > Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
> > ---
> >   drivers/net/ethernet/sfc/falcon.c |    4 ++--
> >   drivers/net/ethernet/sfc/nic.c    |    7 -------
> >   drivers/net/ethernet/sfc/nic.h    |    1 -
> >   3 files changed, 2 insertions(+), 10 deletions(-)
> 
> > diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
> > index f8de382..4492129 100644
> > --- a/drivers/net/ethernet/sfc/falcon.c
> > +++ b/drivers/net/ethernet/sfc/falcon.c
> > @@ -336,7 +336,7 @@ static void falcon_prepare_flush(struct efx_nic *efx)
> >    *
> >    * NB most hardware supports MSI interrupts
> >    */
> > -inline void falcon_irq_ack_a1(struct efx_nic *efx)
> > +static inline void falcon_irq_ack_a1(struct efx_nic *efx)
> 
>     Does inline make sense still when this now is referenced indirectly?

It's not inlined in the cleanup code, either before or after this
change.  But we do want this to be inlined in the following function,
falcon_legacy_interrupt_a1().  So I think it does make sense.

Ben.

> >   {
> >   	efx_dword_t reg;
> >
> > @@ -2343,7 +2343,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
> >   	.remove = falcon_remove_nic,
> >   	.init = falcon_init_nic,
> >   	.dimension_resources = falcon_dimension_resources,
> > -	.fini = efx_port_dummy_op_void,
> > +	.fini = falcon_irq_ack_a1,
> >   	.monitor = falcon_monitor,
> >   	.map_reset_reason = falcon_map_reset_reason,
> >   	.map_reset_flags = falcon_map_reset_flags,
> 
> WBR, Sergei
> 

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* [PATCH 04/11] net: calxedaxgmac: fix possible skb free before tx complete
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

The TX completion code may have freed an skb before the entire sg list
was transmitted. The DMA unmap calls for the fragments could also get
skipped. Now set the skb pointer on every entry in the ring, not just
the head of the sg list. We then use the FS (first segment) bit in the
descriptors to determine skb head vs. fragment.

This also fixes similar bug in xgmac_free_tx_skbufs where clean-up of
a sg list that wraps at the end of the ring buffer would not get
unmapped.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 55 ++++++++++++++++--------------------
 1 file changed, 24 insertions(+), 31 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index df7e3e2..64854ad 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -470,6 +470,11 @@ static inline int desc_get_tx_ls(struct xgmac_dma_desc *p)
 	return le32_to_cpu(p->flags) & TXDESC_LAST_SEG;
 }
 
+static inline int desc_get_tx_fs(struct xgmac_dma_desc *p)
+{
+	return le32_to_cpu(p->flags) & TXDESC_FIRST_SEG;
+}
+
 static inline u32 desc_get_buf_addr(struct xgmac_dma_desc *p)
 {
 	return le32_to_cpu(p->buf1_addr);
@@ -796,7 +801,7 @@ static void xgmac_free_rx_skbufs(struct xgmac_priv *priv)
 
 static void xgmac_free_tx_skbufs(struct xgmac_priv *priv)
 {
-	int i, f;
+	int i;
 	struct xgmac_dma_desc *p;
 
 	if (!priv->tx_skbuff)
@@ -807,16 +812,15 @@ static void xgmac_free_tx_skbufs(struct xgmac_priv *priv)
 			continue;
 
 		p = priv->dma_tx + i;
-		dma_unmap_single(priv->device, desc_get_buf_addr(p),
-				 desc_get_buf_len(p), DMA_TO_DEVICE);
-
-		for (f = 0; f < skb_shinfo(priv->tx_skbuff[i])->nr_frags; f++) {
-			p = priv->dma_tx + i++;
+		if (desc_get_tx_fs(p))
+			dma_unmap_single(priv->device, desc_get_buf_addr(p),
+					 desc_get_buf_len(p), DMA_TO_DEVICE);
+		else
 			dma_unmap_page(priv->device, desc_get_buf_addr(p),
 				       desc_get_buf_len(p), DMA_TO_DEVICE);
-		}
 
-		dev_kfree_skb_any(priv->tx_skbuff[i]);
+		if (desc_get_tx_ls(p))
+			dev_kfree_skb_any(priv->tx_skbuff[i]);
 		priv->tx_skbuff[i] = NULL;
 	}
 }
@@ -853,8 +857,6 @@ static void xgmac_free_dma_desc_rings(struct xgmac_priv *priv)
  */
 static void xgmac_tx_complete(struct xgmac_priv *priv)
 {
-	int i;
-
 	while (dma_ring_cnt(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ)) {
 		unsigned int entry = priv->tx_tail;
 		struct sk_buff *skb = priv->tx_skbuff[entry];
@@ -864,33 +866,24 @@ static void xgmac_tx_complete(struct xgmac_priv *priv)
 		if (desc_get_owner(p))
 			break;
 
-		/* Verify tx error by looking at the last segment */
-		if (desc_get_tx_ls(p))
-			desc_get_tx_status(priv, p);
-
 		netdev_dbg(priv->dev, "tx ring: curr %d, dirty %d\n",
 			priv->tx_head, priv->tx_tail);
 
-		dma_unmap_single(priv->device, desc_get_buf_addr(p),
-				 desc_get_buf_len(p), DMA_TO_DEVICE);
-
-		priv->tx_skbuff[entry] = NULL;
-		priv->tx_tail = dma_ring_incr(entry, DMA_TX_RING_SZ);
-
-		if (!skb) {
-			continue;
-		}
-
-		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			entry = priv->tx_tail = dma_ring_incr(priv->tx_tail,
-							      DMA_TX_RING_SZ);
-			p = priv->dma_tx + priv->tx_tail;
-
+		if (desc_get_tx_fs(p))
+			dma_unmap_single(priv->device, desc_get_buf_addr(p),
+					 desc_get_buf_len(p), DMA_TO_DEVICE);
+		else
 			dma_unmap_page(priv->device, desc_get_buf_addr(p),
 				       desc_get_buf_len(p), DMA_TO_DEVICE);
+
+		/* Check tx error on the last segment */
+		if (desc_get_tx_ls(p)) {
+			desc_get_tx_status(priv, p);
+			dev_kfree_skb(skb);
 		}
 
-		dev_kfree_skb(skb);
+		priv->tx_skbuff[entry] = NULL;
+		priv->tx_tail = dma_ring_incr(entry, DMA_TX_RING_SZ);
 	}
 
 	if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) >
@@ -1110,7 +1103,7 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 		entry = dma_ring_incr(entry, DMA_TX_RING_SZ);
 		desc = priv->dma_tx + entry;
-		priv->tx_skbuff[entry] = NULL;
+		priv->tx_skbuff[entry] = skb;
 
 		desc_set_buf_addr_and_size(desc, paddr, len);
 		if (i < (nfrags - 1))
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 11/11] net: calxedaxgmac: fix xgmac_xmit DMA mapping error handling
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

On a DMA mapping error in xgmac_xmit, we should simply free the skb and
return NETDEV_TX_OK rather than -EIO. In the case of errors in mapping
frags, we need to undo everything that has been setup.

Reported-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index f149c08..0022887 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -466,6 +466,13 @@ static inline void desc_set_tx_owner(struct xgmac_dma_desc *p, u32 flags)
 	p->flags = cpu_to_le32(tmpflags);
 }
 
+static inline void desc_clear_tx_owner(struct xgmac_dma_desc *p)
+{
+	u32 tmpflags = le32_to_cpu(p->flags);
+	tmpflags &= TXDESC_END_RING;
+	p->flags = cpu_to_le32(tmpflags);
+}
+
 static inline int desc_get_tx_ls(struct xgmac_dma_desc *p)
 {
 	return le32_to_cpu(p->flags) & TXDESC_LAST_SEG;
@@ -1103,7 +1110,7 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 	paddr = dma_map_single(priv->device, skb->data, len, DMA_TO_DEVICE);
 	if (dma_mapping_error(priv->device, paddr)) {
 		dev_kfree_skb(skb);
-		return -EIO;
+		return NETDEV_TX_OK;
 	}
 	priv->tx_skbuff[entry] = skb;
 	desc_set_buf_addr_and_size(desc, paddr, len);
@@ -1115,10 +1122,8 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 		paddr = skb_frag_dma_map(priv->device, frag, 0, len,
 					 DMA_TO_DEVICE);
-		if (dma_mapping_error(priv->device, paddr)) {
-			dev_kfree_skb(skb);
-			return -EIO;
-		}
+		if (dma_mapping_error(priv->device, paddr))
+			goto dma_err;
 
 		entry = dma_ring_incr(entry, DMA_TX_RING_SZ);
 		desc = priv->dma_tx + entry;
@@ -1154,6 +1159,22 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 			netif_wake_queue(dev);
 	}
 	return NETDEV_TX_OK;
+
+dma_err:
+	entry = priv->tx_head;
+	for ( ; i > 0; i--) {
+		entry = dma_ring_incr(entry, DMA_TX_RING_SZ);
+		desc = priv->dma_tx + entry;
+		priv->tx_skbuff[entry] = NULL;
+		dma_unmap_page(priv->device, desc_get_buf_addr(desc),
+			       desc_get_buf_len(desc), DMA_TO_DEVICE);
+		desc_clear_tx_owner(desc);
+	}
+	desc = first;
+	dma_unmap_single(priv->device, desc_get_buf_addr(desc),
+			 desc_get_buf_len(desc), DMA_TO_DEVICE);
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
 }
 
 static int xgmac_rx(struct xgmac_priv *priv, int limit)
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 10/11] net: calxedaxgmac: fix rx DMA mapping API size mismatches
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

Fix the mismatch in the DMA mapping and unmapping sizes for receive. The
unmap size must be equal to the map size and should not be the actual
received frame length. The map size should also be adjusted by the
NET_IP_ALIGN size since the h/w buffer size (dma_buf_sz) includes this
offset.

Also, add a missing dma_mapping_error check in xgmac_rx_refill.

Reported-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index b206268..f149c08 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -695,9 +695,14 @@ static void xgmac_rx_refill(struct xgmac_priv *priv)
 			if (unlikely(skb == NULL))
 				break;
 
-			priv->rx_skbuff[entry] = skb;
 			paddr = dma_map_single(priv->device, skb->data,
-					       bufsz, DMA_FROM_DEVICE);
+					       priv->dma_buf_sz - NET_IP_ALIGN,
+					       DMA_FROM_DEVICE);
+			if (dma_mapping_error(priv->device, paddr)) {
+				dev_kfree_skb_any(skb);
+				break;
+			}
+			priv->rx_skbuff[entry] = skb;
 			desc_set_buf_addr(p, paddr, priv->dma_buf_sz);
 		}
 
@@ -794,13 +799,14 @@ static void xgmac_free_rx_skbufs(struct xgmac_priv *priv)
 		return;
 
 	for (i = 0; i < DMA_RX_RING_SZ; i++) {
-		if (priv->rx_skbuff[i] == NULL)
+		struct sk_buff *skb = priv->rx_skbuff[i];
+		if (skb == NULL)
 			continue;
 
 		p = priv->dma_rx + i;
 		dma_unmap_single(priv->device, desc_get_buf_addr(p),
-				 priv->dma_buf_sz, DMA_FROM_DEVICE);
-		dev_kfree_skb_any(priv->rx_skbuff[i]);
+				 priv->dma_buf_sz - NET_IP_ALIGN, DMA_FROM_DEVICE);
+		dev_kfree_skb_any(skb);
 		priv->rx_skbuff[i] = NULL;
 	}
 }
@@ -1190,7 +1196,7 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit)
 
 		skb_put(skb, frame_len);
 		dma_unmap_single(priv->device, desc_get_buf_addr(p),
-				 frame_len, DMA_FROM_DEVICE);
+				 priv->dma_buf_sz - NET_IP_ALIGN, DMA_FROM_DEVICE);
 
 		skb->protocol = eth_type_trans(skb, priv->dev);
 		skb->ip_summed = ip_checksum;
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 09/11] net: calxedaxgmac: remove some unused statistic counters
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

rx_sa_filter_fail and tx_undeflow events are unused and impossible
to occur based on how the h/w is used. We never filter on source MAC
address and TX store and forward mode prevents underflow events.

Reported-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 9b6eff5..b206268 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -353,11 +353,9 @@ struct xgmac_extra_stats {
 	/* Receive errors */
 	unsigned long rx_watchdog;
 	unsigned long rx_da_filter_fail;
-	unsigned long rx_sa_filter_fail;
 	unsigned long rx_payload_error;
 	unsigned long rx_ip_header_error;
 	/* Tx/Rx IRQ errors */
-	unsigned long tx_undeflow;
 	unsigned long tx_process_stopped;
 	unsigned long rx_buf_unav;
 	unsigned long rx_process_stopped;
@@ -1584,7 +1582,6 @@ static const struct xgmac_stats xgmac_gstrings_stats[] = {
 	XGMAC_STAT(rx_payload_error),
 	XGMAC_STAT(rx_ip_header_error),
 	XGMAC_STAT(rx_da_filter_fail),
-	XGMAC_STAT(rx_sa_filter_fail),
 	XGMAC_STAT(fatal_bus_error),
 	XGMAC_HW_STAT(rx_watchdog, XGMAC_MMC_RXWATCHDOG),
 	XGMAC_HW_STAT(tx_vlan, XGMAC_MMC_TXVLANFRAME),
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 08/11] net: calxedaxgmac: fix various errors in xgmac_set_rx_mode
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

Fix xgmac_set_rx_mode to handle several conditions that were not handled
correctly as Lennert Buytenhek describes:

If we have, say, 100 unicast addresses, and 5 multicast addresses, the
unicast address count check will evaluate to true, and set use_hash to
true.  The multicast address check will however evaluate to false, and
use_hash won't be set to true again, and XGMAC_FRAME_FILTER_HMC won't
be OR'd into XGMAC_FRAME_FILTER, but since use_hash was still true
from the unicast check, netdev_for_each_mc_addr() will program the
multicast addresses into the hash table instead of using the MAC
address registers, but since the HMC bit wasn't set, the hash table
won't be checked for multicast addresses on receive, and we'll stop
receiving multicast packets entirely.

Also, there is no code that zeroes out MAC address registers reg..31
at the end of this function, meaning that under the right conditions,
unicast/multicast addresses that were previously in the filter but
were then deleted won't be cleared out.

Reported-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 385eca0..9b6eff5 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -618,10 +618,15 @@ static void xgmac_set_mac_addr(void __iomem *ioaddr, unsigned char *addr,
 {
 	u32 data;
 
-	data = (addr[5] << 8) | addr[4] | (num ? XGMAC_ADDR_AE : 0);
-	writel(data, ioaddr + XGMAC_ADDR_HIGH(num));
-	data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
-	writel(data, ioaddr + XGMAC_ADDR_LOW(num));
+	if (addr) {
+		data = (addr[5] << 8) | addr[4] | (num ? XGMAC_ADDR_AE : 0);
+		writel(data, ioaddr + XGMAC_ADDR_HIGH(num));
+		data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
+		writel(data, ioaddr + XGMAC_ADDR_LOW(num));
+	} else {
+		writel(0, ioaddr + XGMAC_ADDR_HIGH(num));
+		writel(0, ioaddr + XGMAC_ADDR_LOW(num));
+	}
 }
 
 static void xgmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
@@ -1297,6 +1302,8 @@ static void xgmac_set_rx_mode(struct net_device *dev)
 	if ((netdev_mc_count(dev) + reg - 1) > XGMAC_MAX_FILTER_ADDR) {
 		use_hash = true;
 		value |= XGMAC_FRAME_FILTER_HMC | XGMAC_FRAME_FILTER_HPF;
+	} else {
+		use_hash = false;
 	}
 	netdev_for_each_mc_addr(ha, dev) {
 		if (use_hash) {
@@ -1313,6 +1320,8 @@ static void xgmac_set_rx_mode(struct net_device *dev)
 	}
 
 out:
+	for (i = reg; i < XGMAC_MAX_FILTER_ADDR; i++)
+		xgmac_set_mac_addr(ioaddr, NULL, reg);
 	for (i = 0; i < XGMAC_NUM_HASH; i++)
 		writel(hash_filter[i], ioaddr + XGMAC_HASH(i));
 
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 07/11] net: calxedaxgmac: enable interrupts after napi_enable
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

Fix a race condition where the interrupt handler may have called
napi_schedule before napi_enable is called. This would disable interrupts
and never actually schedule napi to run.

Reported-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index cd5872c..385eca0 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -962,9 +962,7 @@ static int xgmac_hw_init(struct net_device *dev)
 		DMA_BUS_MODE_FB | DMA_BUS_MODE_ATDS | DMA_BUS_MODE_AAL;
 	writel(value, ioaddr + XGMAC_DMA_BUS_MODE);
 
-	/* Enable interrupts */
-	writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_STATUS);
-	writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_INTR_ENA);
+	writel(0, ioaddr + XGMAC_DMA_INTR_ENA);
 
 	/* Mask power mgt interrupt */
 	writel(XGMAC_INT_STAT_PMTIM, ioaddr + XGMAC_INT_STAT);
@@ -1032,6 +1030,10 @@ static int xgmac_open(struct net_device *dev)
 	napi_enable(&priv->napi);
 	netif_start_queue(dev);
 
+	/* Enable interrupts */
+	writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_STATUS);
+	writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_INTR_ENA);
+
 	return 0;
 }
 
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 06/11] net: calxedaxgmac: fix race with tx queue stop/wake
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

Since the xgmac transmit start and completion work locklessly, it is
possible for xgmac_xmit to stop the tx queue after the xgmac_tx_complete
has run resulting in the tx queue never being woken up. Fix this by
ensuring that ring buffer index updates are visible and serialize the
queue wake with netif_tx_lock.

The implementation used here was copied from
drivers/net/ethernet/broadcom/tg3.c.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index f630855..cd5872c 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -410,6 +410,9 @@ struct xgmac_priv {
 #define dma_ring_space(h, t, s)	CIRC_SPACE(h, t, s)
 #define dma_ring_cnt(h, t, s)	CIRC_CNT(h, t, s)
 
+#define tx_dma_ring_space(p) \
+	dma_ring_space((p)->tx_head, (p)->tx_tail, DMA_TX_RING_SZ)
+
 /* XGMAC Descriptor Access Helpers */
 static inline void desc_set_buf_len(struct xgmac_dma_desc *p, u32 buf_sz)
 {
@@ -886,9 +889,14 @@ static void xgmac_tx_complete(struct xgmac_priv *priv)
 		priv->tx_tail = dma_ring_incr(entry, DMA_TX_RING_SZ);
 	}
 
-	if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) >
-	    MAX_SKB_FRAGS)
-		netif_wake_queue(priv->dev);
+	/* Ensure tx_tail is visible to xgmac_xmit */
+	smp_mb();
+	if (unlikely(netif_queue_stopped(priv->dev))) {
+		netif_tx_lock(priv->dev);
+		if (tx_dma_ring_space(priv) > MAX_SKB_FRAGS)
+			netif_wake_queue(priv->dev);
+		netif_tx_unlock(priv->dev);
+	}
 }
 
 static void xgmac_tx_timeout_work(struct work_struct *work)
@@ -1125,10 +1133,15 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	priv->tx_head = dma_ring_incr(entry, DMA_TX_RING_SZ);
 
-	if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) <
-	    MAX_SKB_FRAGS)
+	/* Ensure tx_head update is visible to tx completion */
+	smp_mb();
+	if (unlikely(tx_dma_ring_space(priv) < MAX_SKB_FRAGS)) {
 		netif_stop_queue(dev);
-
+		/* Ensure netif_stop_queue is visible to tx completion */
+		smp_mb();
+		if (tx_dma_ring_space(priv) > MAX_SKB_FRAGS)
+			netif_wake_queue(dev);
+	}
 	return NETDEV_TX_OK;
 }
 
-- 
1.8.1.2

^ permalink raw reply related


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