* RE: [PATCH net v2 2/3] r8152: modify the tx flow
From: hayeswang @ 2013-11-05 12:46 UTC (permalink / raw)
To: 'David Miller'
Cc: netdev, 'nic_swsd', linux-kernel, linux-usb
In-Reply-To: <20131104.155320.2172500441669637943.davem@davemloft.net>
David Miller [mailto:davem@davemloft.net]
> Sent: Tuesday, November 05, 2013 4:53 AM
> To: Hayeswang
> Cc: netdev@vger.kernel.org; nic_swsd;
> linux-kernel@vger.kernel.org; linux-usb@vger.kernel.org
> Subject: Re: [PATCH net v2 2/3] r8152: modify the tx flow
[...]
> The more TX work you push into the workqueue handler, the longer the
> latency for releasing the SKB and releasing all the queues that are
> waiting for release of that packet.
>
> Do you know that sockets, queueing discplines, etc. all rely upon
> there being a timely release of SKBs once they are successfully
> transmitted? It must happen at the earliest moment possible that
> can be reasonable obtained.
Thanks for your answer. I would resend the patches after finishing the
setting of the queue length.
^ permalink raw reply
* Re: [PATCH ] net_sched: actions - Add default lookup
From: Jamal Hadi Salim @ 2013-11-05 12:19 UTC (permalink / raw)
To: David Miller, eric.dumazet; +Cc: netdev, ebiederm, alexander.h.duyck
In-Reply-To: <20131103.231232.1438716028901698864.davem@davemloft.net>
Apologies for the latency
My intention was to eventually remove it everywhere since this is needed
by all actions. An action could override it, otherwise they get the
default.
cheers,
jamal
On 11/03/13 23:12, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Wed, 30 Oct 2013 07:00:05 -0700
>
>> On Wed, 2013-10-30 at 07:25 -0400, Jamal Hadi Salim wrote:
>>> Attached. Tested with simple action.
>>>
>>> cheers,
>>> jamal
>>
>> Why not setting .lookup to tcf_hash_search
>> in the few actions not already doing that ?
>>
>> This would be more consistent.
>> # git grep -n tcf_hash_search
>> include/net/act_api.h:92:int tcf_hash_search(struct tc_action *a, u32 index);
>> net/sched/act_api.c:198:int tcf_hash_search(struct tc_action *a, u32 index)
>> net/sched/act_api.c:209:EXPORT_SYMBOL(tcf_hash_search);
>> net/sched/act_csum.c:588: .lookup = tcf_hash_search,
>> net/sched/act_gact.c:209: .lookup = tcf_hash_search,
>> net/sched/act_ipt.c:301: .lookup = tcf_hash_search,
>> net/sched/act_ipt.c:315: .lookup = tcf_hash_search,
>> net/sched/act_mirred.c:274: .lookup = tcf_hash_search,
>> net/sched/act_nat.c:311: .lookup = tcf_hash_search,
>> net/sched/act_pedit.c:246: .lookup = tcf_hash_search,
>> net/sched/act_police.c:410: .lookup = tcf_hash_search,
>
> Right, and BUG() if we try to register and action with a NULL .lookup
> member.
>
^ permalink raw reply
* Re: [PATCH 1/4] wl1251: split wl251 platform data to a separate structure
From: Pavel Machek @ 2013-11-05 12:13 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Sebastian Reichel, Luciano Coelho, Rob Herring, Pawel Moll,
Mark Rutland, Stephen Warren, Ian Campbell, Rob Landley,
Tony Lindgren, Russell King, John W. Linville, Felipe Balbi,
Sachin Kamat, Greg Kroah-Hartman, Bill Pemberton,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, Luciano Coelho
In-Reply-To: <1382890469-25286-2-git-send-email-sre-8fiUuRrzOP0dnm+yROfE0A@public.gmane.org>
On Sun 2013-10-27 17:14:26, Sebastian Reichel wrote:
> From: Luciano Coelho <coelho-l0cyMroinI0@public.gmane.org>
>
> Move the wl1251 part of the wl12xx platform data structure into a new
> structure specifically for wl1251. Change the platform data built-in
> block and board files accordingly.
>
> Cc: Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
> Signed-off-by: Luciano Coelho <coelho-l0cyMroinI0@public.gmane.org>
> Acked-by: Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
> Reviewed-by: Felipe Balbi <balbi-l0cyMroinI0@public.gmane.org>
Reviewed-by: Pavel Machek <pavel-+ZI9xUNit7I@public.gmane.org>
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
--
To unsubscribe from this list: send the line "unsubscribe devicetree" 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 net-next 3/3] fix skb_morph to preserve skb->sk and skb->destructor pointers
From: Marcelo Ricardo Leitner @ 2013-11-05 11:50 UTC (permalink / raw)
To: Jiri Pirko, netdev
Cc: davem, pablo, netfilter-devel, yoshfuji, kadlec, kaber, kuznet,
jmorris, wensong, horms, ja, edumazet, pshelar, jasowang,
alexander.h.duyck, coreteam, fw
In-Reply-To: <1383649333-6321-4-git-send-email-jiri@resnulli.us>
Em 05-11-2013 09:02, Jiri Pirko escreveu:
> Currently __skb_clone sets skb->sk and skb->destructor to NULL. This is
> not right for skb_morph use case because skb->sk may be previously
> set (e. g. by xt_TPROXY).
>
> Also, during skb_morph the destructor should not be called. It might be
> previously set, e. g. by xt_TPROXY to sock_edemux, and that would cause
> put sk while skb is still in flight.
>
> This patch fixes these.
>
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Marcelo Ricardo Leitner <mleitner@redhat.com>
> ---
> net/core/skbuff.c | 44 +++++++++++++++++++++++++++-----------------
> 1 file changed, 27 insertions(+), 17 deletions(-)
>
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 3735fad..21b320e 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -515,7 +515,7 @@ static void skb_free_head(struct sk_buff *skb)
> kfree(skb->head);
> }
>
> -static void skb_release_data(struct sk_buff *skb)
> +static void __skb_release_data(struct sk_buff *skb)
> {
> if (!skb->cloned ||
> !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
> @@ -579,16 +579,12 @@ static void kfree_skbmem(struct sk_buff *skb)
> }
> }
>
> -static void skb_release_head_state(struct sk_buff *skb)
> +static void __skb_release_head_state(struct sk_buff *skb)
> {
> skb_dst_drop(skb);
> #ifdef CONFIG_XFRM
> secpath_put(skb->sp);
> #endif
> - if (skb->destructor) {
> - WARN_ON(in_irq());
> - skb->destructor(skb);
> - }
> #if IS_ENABLED(CONFIG_NF_CONNTRACK)
> nf_conntrack_put(skb->nfct);
> #endif
> @@ -607,12 +603,19 @@ static void skb_release_head_state(struct sk_buff *skb)
> #endif
> }
>
> -/* Free everything but the sk_buff shell. */
> -static void skb_release_all(struct sk_buff *skb)
> +static void skb_release_head_state(struct sk_buff *skb)
> +{
> + if (skb->destructor) {
> + WARN_ON(in_irq());
> + skb->destructor(skb);
> + }
> + __skb_release_head_state(skb);
> +}
> +
> +static void skb_release_data(struct sk_buff *skb)
> {
> - skb_release_head_state(skb);
> if (likely(skb->head))
> - skb_release_data(skb);
> + __skb_release_data(skb);
> }
>
> /**
> @@ -626,7 +629,8 @@ static void skb_release_all(struct sk_buff *skb)
>
> void __kfree_skb(struct sk_buff *skb)
> {
> - skb_release_all(skb);
> + skb_release_head_state(skb);
> + skb_release_data(skb);
> kfree_skbmem(skb);
> }
> EXPORT_SYMBOL(__kfree_skb);
> @@ -761,12 +765,11 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
> * You should not add any new code to this function. Add it to
> * __copy_skb_header above instead.
> */
> -static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
> +static struct sk_buff *___skb_clone(struct sk_buff *n, struct sk_buff *skb)
> {
> #define C(x) n->x = skb->x
>
> n->next = n->prev = NULL;
> - n->sk = NULL;
> __copy_skb_header(n, skb);
>
> C(len);
> @@ -775,7 +778,6 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
> n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
> n->cloned = 1;
> n->nohdr = 0;
> - n->destructor = NULL;
> C(tail);
> C(end);
> C(head);
> @@ -791,6 +793,13 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
> #undef C
> }
>
> +static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
> +{
> + n->sk = NULL;
> + n->destructor = NULL;
> + return ___skb_clone(n, skb);
> +}
> +
> /**
> * skb_morph - morph one skb into another
> * @dst: the skb to receive the contents
> @@ -803,8 +812,9 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
> */
> struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src)
> {
> - skb_release_all(dst);
> - return __skb_clone(dst, src);
> + __skb_release_head_state(dst);
> + skb_release_data(dst);
> + return ___skb_clone(dst, src);
> }
> EXPORT_SYMBOL_GPL(skb_morph);
>
> @@ -1107,7 +1117,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
> if (skb_has_frag_list(skb))
> skb_clone_fraglist(skb);
>
> - skb_release_data(skb);
> + __skb_release_data(skb);
> } else {
> skb_free_head(skb);
> }
>
^ permalink raw reply
* Re: [patch net-next 2/3] netfilter: ip6_tables: use reasm skb for matching
From: Marcelo Ricardo Leitner @ 2013-11-05 11:50 UTC (permalink / raw)
To: Jiri Pirko, netdev
Cc: davem, pablo, netfilter-devel, yoshfuji, kadlec, kaber, kuznet,
jmorris, wensong, horms, ja, edumazet, pshelar, jasowang,
alexander.h.duyck, coreteam, fw
In-Reply-To: <1383649333-6321-3-git-send-email-jiri@resnulli.us>
Em 05-11-2013 09:02, Jiri Pirko escreveu:
> Currently, when ipv6 fragment goes through the netfilter, match
> functions are called on them directly. This might cause match function
> to fail. So benefit from the fact that nf_defrag_ipv6 constructs
> reassembled skb for us and use this reassembled skb for matching.
>
> This patch fixes for example following situation:
> On HOSTA do:
> ip6tables -I INPUT -p icmpv6 -j DROP
> ip6tables -I INPUT -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT
>
> and on HOSTB you do:
> ping6 HOSTA -s2000 (MTU is 1500)
>
> Incoming echo requests will be filtered out on HOSTA. This issue does
> not occur with smaller packets than MTU (where fragmentation does not happen).
>
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Marcelo Ricardo Leitner <mleitner@redhat.com>
> ---
> net/ipv6/netfilter/ip6_tables.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
> index 710238f..ec9cb1a 100644
> --- a/net/ipv6/netfilter/ip6_tables.c
> +++ b/net/ipv6/netfilter/ip6_tables.c
> @@ -328,6 +328,10 @@ ip6t_do_table(struct sk_buff *skb,
> const struct xt_table_info *private;
> struct xt_action_param acpar;
> unsigned int addend;
> + struct sk_buff *reasm = skb_nfct_reasm(skb);
> +
> + if (!reasm)
> + reasm = skb;
>
> /* Initialization */
> indev = in ? in->name : nulldevname;
> @@ -368,7 +372,7 @@ ip6t_do_table(struct sk_buff *skb,
>
> IP_NF_ASSERT(e);
> acpar.thoff = 0;
> - if (!ip6_packet_match(skb, indev, outdev, &e->ipv6,
> + if (!ip6_packet_match(reasm, indev, outdev, &e->ipv6,
> &acpar.thoff, &acpar.fragoff, &acpar.hotdrop)) {
> no_match:
> e = ip6t_next_entry(e);
> @@ -378,7 +382,7 @@ ip6t_do_table(struct sk_buff *skb,
> xt_ematch_foreach(ematch, e) {
> acpar.match = ematch->u.kernel.match;
> acpar.matchinfo = ematch->data;
> - if (!acpar.match->match(skb, &acpar))
> + if (!acpar.match->match(reasm, &acpar))
> goto no_match;
> }
>
>
^ permalink raw reply
* Re: [patch net-next 1/3] move skb_nfct_reasm into skbuff.h
From: Marcelo Ricardo Leitner @ 2013-11-05 11:50 UTC (permalink / raw)
To: Jiri Pirko, netdev
Cc: davem, pablo, netfilter-devel, yoshfuji, kadlec, kaber, kuznet,
jmorris, wensong, horms, ja, edumazet, pshelar, jasowang,
alexander.h.duyck, coreteam, fw
In-Reply-To: <1383649333-6321-2-git-send-email-jiri@resnulli.us>
Em 05-11-2013 09:02, Jiri Pirko escreveu:
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Marcelo Ricardo Leitner <mleitner@redhat.com>
> ---
> include/linux/skbuff.h | 11 +++++++++++
> include/net/ip_vs.h | 8 --------
> net/netfilter/ipvs/ip_vs_core.c | 1 +
> 3 files changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index 2e153b6..ececdad 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -2606,6 +2606,17 @@ static inline void nf_conntrack_put_reasm(struct sk_buff *skb)
> kfree_skb(skb);
> }
> #endif
> +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
> +static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
> +{
> + return skb->nfct_reasm;
> +}
> +#else
> +static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
> +{
> + return NULL;
> +}
> +#endif
> #ifdef CONFIG_BRIDGE_NETFILTER
> static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
> {
> diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
> index cd7275f..6dff2b6 100644
> --- a/include/net/ip_vs.h
> +++ b/include/net/ip_vs.h
> @@ -119,10 +119,6 @@ struct ip_vs_iphdr {
>
> /* Dependency to module: nf_defrag_ipv6 */
> #if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
> -static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
> -{
> - return skb->nfct_reasm;
> -}
> static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
> int len, void *buffer,
> const struct ip_vs_iphdr *ipvsh)
> @@ -134,10 +130,6 @@ static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
> return skb_header_pointer(skb, offset, len, buffer);
> }
> #else
> -static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
> -{
> - return NULL;
> -}
> static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
> int len, void *buffer,
> const struct ip_vs_iphdr *ipvsh)
> diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
> index 34fda62..085c242 100644
> --- a/net/netfilter/ipvs/ip_vs_core.c
> +++ b/net/netfilter/ipvs/ip_vs_core.c
> @@ -43,6 +43,7 @@
> #include <net/ip6_checksum.h>
> #include <net/netns/generic.h> /* net_generic() */
>
> +#include <linux/skbuff.h>
> #include <linux/netfilter.h>
> #include <linux/netfilter_ipv4.h>
>
>
^ permalink raw reply
* [patch net-next 2/3] netfilter: ip6_tables: use reasm skb for matching
From: Jiri Pirko @ 2013-11-05 11:02 UTC (permalink / raw)
To: netdev
Cc: davem, pablo, netfilter-devel, yoshfuji, kadlec, kaber, mleitner,
kuznet, jmorris, wensong, horms, ja, edumazet, pshelar, jasowang,
alexander.h.duyck, coreteam, fw
In-Reply-To: <1383649333-6321-1-git-send-email-jiri@resnulli.us>
Currently, when ipv6 fragment goes through the netfilter, match
functions are called on them directly. This might cause match function
to fail. So benefit from the fact that nf_defrag_ipv6 constructs
reassembled skb for us and use this reassembled skb for matching.
This patch fixes for example following situation:
On HOSTA do:
ip6tables -I INPUT -p icmpv6 -j DROP
ip6tables -I INPUT -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT
and on HOSTB you do:
ping6 HOSTA -s2000 (MTU is 1500)
Incoming echo requests will be filtered out on HOSTA. This issue does
not occur with smaller packets than MTU (where fragmentation does not happen).
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
net/ipv6/netfilter/ip6_tables.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 710238f..ec9cb1a 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -328,6 +328,10 @@ ip6t_do_table(struct sk_buff *skb,
const struct xt_table_info *private;
struct xt_action_param acpar;
unsigned int addend;
+ struct sk_buff *reasm = skb_nfct_reasm(skb);
+
+ if (!reasm)
+ reasm = skb;
/* Initialization */
indev = in ? in->name : nulldevname;
@@ -368,7 +372,7 @@ ip6t_do_table(struct sk_buff *skb,
IP_NF_ASSERT(e);
acpar.thoff = 0;
- if (!ip6_packet_match(skb, indev, outdev, &e->ipv6,
+ if (!ip6_packet_match(reasm, indev, outdev, &e->ipv6,
&acpar.thoff, &acpar.fragoff, &acpar.hotdrop)) {
no_match:
e = ip6t_next_entry(e);
@@ -378,7 +382,7 @@ ip6t_do_table(struct sk_buff *skb,
xt_ematch_foreach(ematch, e) {
acpar.match = ematch->u.kernel.match;
acpar.matchinfo = ematch->data;
- if (!acpar.match->match(skb, &acpar))
+ if (!acpar.match->match(reasm, &acpar))
goto no_match;
}
--
1.8.3.1
^ permalink raw reply related
* [patch net-next 1/3] move skb_nfct_reasm into skbuff.h
From: Jiri Pirko @ 2013-11-05 11:02 UTC (permalink / raw)
To: netdev
Cc: davem, pablo, netfilter-devel, yoshfuji, kadlec, kaber, mleitner,
kuznet, jmorris, wensong, horms, ja, edumazet, pshelar, jasowang,
alexander.h.duyck, coreteam, fw
In-Reply-To: <1383649333-6321-1-git-send-email-jiri@resnulli.us>
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
include/linux/skbuff.h | 11 +++++++++++
include/net/ip_vs.h | 8 --------
net/netfilter/ipvs/ip_vs_core.c | 1 +
3 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 2e153b6..ececdad 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2606,6 +2606,17 @@ static inline void nf_conntrack_put_reasm(struct sk_buff *skb)
kfree_skb(skb);
}
#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
+static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
+{
+ return skb->nfct_reasm;
+}
+#else
+static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
+{
+ return NULL;
+}
+#endif
#ifdef CONFIG_BRIDGE_NETFILTER
static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
{
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index cd7275f..6dff2b6 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -119,10 +119,6 @@ struct ip_vs_iphdr {
/* Dependency to module: nf_defrag_ipv6 */
#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
-static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
-{
- return skb->nfct_reasm;
-}
static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
int len, void *buffer,
const struct ip_vs_iphdr *ipvsh)
@@ -134,10 +130,6 @@ static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
return skb_header_pointer(skb, offset, len, buffer);
}
#else
-static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
-{
- return NULL;
-}
static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
int len, void *buffer,
const struct ip_vs_iphdr *ipvsh)
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 34fda62..085c242 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -43,6 +43,7 @@
#include <net/ip6_checksum.h>
#include <net/netns/generic.h> /* net_generic() */
+#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
--
1.8.3.1
^ permalink raw reply related
* [patch net-next 3/3] fix skb_morph to preserve skb->sk and skb->destructor pointers
From: Jiri Pirko @ 2013-11-05 11:02 UTC (permalink / raw)
To: netdev
Cc: davem, pablo, netfilter-devel, yoshfuji, kadlec, kaber, mleitner,
kuznet, jmorris, wensong, horms, ja, edumazet, pshelar, jasowang,
alexander.h.duyck, coreteam, fw
In-Reply-To: <1383649333-6321-1-git-send-email-jiri@resnulli.us>
Currently __skb_clone sets skb->sk and skb->destructor to NULL. This is
not right for skb_morph use case because skb->sk may be previously
set (e. g. by xt_TPROXY).
Also, during skb_morph the destructor should not be called. It might be
previously set, e. g. by xt_TPROXY to sock_edemux, and that would cause
put sk while skb is still in flight.
This patch fixes these.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
net/core/skbuff.c | 44 +++++++++++++++++++++++++++-----------------
1 file changed, 27 insertions(+), 17 deletions(-)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3735fad..21b320e 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -515,7 +515,7 @@ static void skb_free_head(struct sk_buff *skb)
kfree(skb->head);
}
-static void skb_release_data(struct sk_buff *skb)
+static void __skb_release_data(struct sk_buff *skb)
{
if (!skb->cloned ||
!atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
@@ -579,16 +579,12 @@ static void kfree_skbmem(struct sk_buff *skb)
}
}
-static void skb_release_head_state(struct sk_buff *skb)
+static void __skb_release_head_state(struct sk_buff *skb)
{
skb_dst_drop(skb);
#ifdef CONFIG_XFRM
secpath_put(skb->sp);
#endif
- if (skb->destructor) {
- WARN_ON(in_irq());
- skb->destructor(skb);
- }
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
nf_conntrack_put(skb->nfct);
#endif
@@ -607,12 +603,19 @@ static void skb_release_head_state(struct sk_buff *skb)
#endif
}
-/* Free everything but the sk_buff shell. */
-static void skb_release_all(struct sk_buff *skb)
+static void skb_release_head_state(struct sk_buff *skb)
+{
+ if (skb->destructor) {
+ WARN_ON(in_irq());
+ skb->destructor(skb);
+ }
+ __skb_release_head_state(skb);
+}
+
+static void skb_release_data(struct sk_buff *skb)
{
- skb_release_head_state(skb);
if (likely(skb->head))
- skb_release_data(skb);
+ __skb_release_data(skb);
}
/**
@@ -626,7 +629,8 @@ static void skb_release_all(struct sk_buff *skb)
void __kfree_skb(struct sk_buff *skb)
{
- skb_release_all(skb);
+ skb_release_head_state(skb);
+ skb_release_data(skb);
kfree_skbmem(skb);
}
EXPORT_SYMBOL(__kfree_skb);
@@ -761,12 +765,11 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
* You should not add any new code to this function. Add it to
* __copy_skb_header above instead.
*/
-static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
+static struct sk_buff *___skb_clone(struct sk_buff *n, struct sk_buff *skb)
{
#define C(x) n->x = skb->x
n->next = n->prev = NULL;
- n->sk = NULL;
__copy_skb_header(n, skb);
C(len);
@@ -775,7 +778,6 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
n->cloned = 1;
n->nohdr = 0;
- n->destructor = NULL;
C(tail);
C(end);
C(head);
@@ -791,6 +793,13 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
#undef C
}
+static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
+{
+ n->sk = NULL;
+ n->destructor = NULL;
+ return ___skb_clone(n, skb);
+}
+
/**
* skb_morph - morph one skb into another
* @dst: the skb to receive the contents
@@ -803,8 +812,9 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
*/
struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src)
{
- skb_release_all(dst);
- return __skb_clone(dst, src);
+ __skb_release_head_state(dst);
+ skb_release_data(dst);
+ return ___skb_clone(dst, src);
}
EXPORT_SYMBOL_GPL(skb_morph);
@@ -1107,7 +1117,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
if (skb_has_frag_list(skb))
skb_clone_fraglist(skb);
- skb_release_data(skb);
+ __skb_release_data(skb);
} else {
skb_free_head(skb);
}
--
1.8.3.1
^ permalink raw reply related
* [patch net-next 0/3] couple of reasm fixes
From: Jiri Pirko @ 2013-11-05 11:02 UTC (permalink / raw)
To: netdev
Cc: davem, pablo, netfilter-devel, yoshfuji, kadlec, kaber, mleitner,
kuznet, jmorris, wensong, horms, ja, edumazet, pshelar, jasowang,
alexander.h.duyck, coreteam, fw
Couple of patches to fix issues which were found on
TPROXY vs. IPV6 frag packets use cases.
Jiri Pirko (3):
move skb_nfct_reasm into skbuff.h
netfilter: ip6_tables: use reasm skb for matching
fix skb_morph to preserve skb->sk and skb->destructor pointers
include/linux/skbuff.h | 11 +++++++++++
include/net/ip_vs.h | 8 --------
net/core/skbuff.c | 44 +++++++++++++++++++++++++----------------
net/ipv6/netfilter/ip6_tables.c | 8 ++++++--
net/netfilter/ipvs/ip_vs_core.c | 1 +
5 files changed, 45 insertions(+), 27 deletions(-)
--
1.8.3.1
^ permalink raw reply
* [RESEND PATCH net-next] virtio-net: switch to use XPS to choose txq
From: Jason Wang @ 2013-11-05 10:19 UTC (permalink / raw)
To: rusty, mst, virtualization, netdev, linux-kernel, davem
We used to use a percpu structure vq_index to record the cpu to queue
mapping, this is suboptimal since it duplicates the work of XPS and
loses all other XPS functionality such as allowing user to configure
their own transmission steering strategy.
So this patch switches to use XPS and suggest a default mapping when
the number of cpus is equal to the number of queues. With XPS support,
there's no need for keeping per-cpu vq_index and .ndo_select_queue(),
so they were removed also.
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Rusty Russell <rusty@rustcorp.com.au>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
Resend since the previous complie warning disappears after commit
3573540cafa4296dd60f8be02f2aecaa31047525
(netif_set_xps_queue: make cpu mask const).
---
drivers/net/virtio_net.c | 48 ++----------------------------------------------
1 file changed, 2 insertions(+), 46 deletions(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index a7e9ad9..01f4eb5 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -132,9 +132,6 @@ struct virtnet_info {
/* Does the affinity hint is set for virtqueues? */
bool affinity_hint_set;
- /* Per-cpu variable to show the mapping from CPU to virtqueue */
- int __percpu *vq_index;
-
/* CPU hot plug notifier */
struct notifier_block nb;
};
@@ -1114,7 +1111,6 @@ static int virtnet_vlan_rx_kill_vid(struct net_device *dev,
static void virtnet_clean_affinity(struct virtnet_info *vi, long hcpu)
{
int i;
- int cpu;
if (vi->affinity_hint_set) {
for (i = 0; i < vi->max_queue_pairs; i++) {
@@ -1124,16 +1120,6 @@ static void virtnet_clean_affinity(struct virtnet_info *vi, long hcpu)
vi->affinity_hint_set = false;
}
-
- i = 0;
- for_each_online_cpu(cpu) {
- if (cpu == hcpu) {
- *per_cpu_ptr(vi->vq_index, cpu) = -1;
- } else {
- *per_cpu_ptr(vi->vq_index, cpu) =
- ++i % vi->curr_queue_pairs;
- }
- }
}
static void virtnet_set_affinity(struct virtnet_info *vi)
@@ -1155,7 +1141,7 @@ static void virtnet_set_affinity(struct virtnet_info *vi)
for_each_online_cpu(cpu) {
virtqueue_set_affinity(vi->rq[i].vq, cpu);
virtqueue_set_affinity(vi->sq[i].vq, cpu);
- *per_cpu_ptr(vi->vq_index, cpu) = i;
+ netif_set_xps_queue(vi->dev, cpumask_of(cpu), i);
i++;
}
@@ -1269,28 +1255,6 @@ static int virtnet_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-/* To avoid contending a lock hold by a vcpu who would exit to host, select the
- * txq based on the processor id.
- */
-static u16 virtnet_select_queue(struct net_device *dev, struct sk_buff *skb)
-{
- int txq;
- struct virtnet_info *vi = netdev_priv(dev);
-
- if (skb_rx_queue_recorded(skb)) {
- txq = skb_get_rx_queue(skb);
- } else {
- txq = *__this_cpu_ptr(vi->vq_index);
- if (txq == -1)
- txq = 0;
- }
-
- while (unlikely(txq >= dev->real_num_tx_queues))
- txq -= dev->real_num_tx_queues;
-
- return txq;
-}
-
static const struct net_device_ops virtnet_netdev = {
.ndo_open = virtnet_open,
.ndo_stop = virtnet_close,
@@ -1302,7 +1266,6 @@ static const struct net_device_ops virtnet_netdev = {
.ndo_get_stats64 = virtnet_stats,
.ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
- .ndo_select_queue = virtnet_select_queue,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = virtnet_netpoll,
#endif
@@ -1613,10 +1576,6 @@ static int virtnet_probe(struct virtio_device *vdev)
if (vi->stats == NULL)
goto free;
- vi->vq_index = alloc_percpu(int);
- if (vi->vq_index == NULL)
- goto free_stats;
-
mutex_init(&vi->config_lock);
vi->config_enable = true;
INIT_WORK(&vi->config_work, virtnet_config_changed_work);
@@ -1643,7 +1602,7 @@ static int virtnet_probe(struct virtio_device *vdev)
/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
err = init_vqs(vi);
if (err)
- goto free_index;
+ goto free_stats;
netif_set_real_num_tx_queues(dev, 1);
netif_set_real_num_rx_queues(dev, 1);
@@ -1696,8 +1655,6 @@ free_vqs:
virtnet_del_vqs(vi);
if (vi->alloc_frag.page)
put_page(vi->alloc_frag.page);
-free_index:
- free_percpu(vi->vq_index);
free_stats:
free_percpu(vi->stats);
free:
@@ -1736,7 +1693,6 @@ static void virtnet_remove(struct virtio_device *vdev)
flush_work(&vi->config_work);
- free_percpu(vi->vq_index);
free_percpu(vi->stats);
free_netdev(vi->dev);
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH net] vti: fix spd lookup: match plaintext pkt, not ipsec pkt
From: Christophe Gouault @ 2013-11-05 10:16 UTC (permalink / raw)
To: Steffen Klassert, David S. Miller
Cc: Herbert Xu, Saurabh Mohan, netdev, Christophe Gouault
The vti interface inbound and outbound SPD lookups are based on the
ipsec packet instead of the plaintext packet.
Not only is it counterintuitive, it also restricts vti interfaces
to a single policy (whose selector must match the tunnel local and
remote addresses).
The policy selector is supposed to match the plaintext packet, before
encryption or after decryption.
This patch performs the SPD lookup based on the plaintext packet. It
enables to create several polices bound to the vti interface (via a
mark equal to the vti interface okey).
It remains possible to apply the same policy to all packets entering
the vti interface, by setting an any-to-any selector (src 0.0.0.0/0
dst 0.0.0.0/0 proto any mark OKEY).
Signed-off-by: Christophe Gouault <christophe.gouault@6wind.com>
---
net/ipv4/ip_vti.c | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 6e87f85..a7e03c0 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -126,6 +126,7 @@ static int vti_rcv(struct sk_buff *skb)
if (tunnel != NULL) {
struct pcpu_tstats *tstats;
u32 oldmark = skb->mark;
+ u16 netoff = skb_network_header(skb) - skb->data;
int ret;
@@ -133,7 +134,12 @@ static int vti_rcv(struct sk_buff *skb)
* only match policies with this mark.
*/
skb->mark = be32_to_cpu(tunnel->parms.o_key);
+ /* the packet is decrypted, but not yet decapsulated.
+ * Temporarily make network_header point to the inner header
+ * for policy check */
+ skb_reset_network_header(skb);
ret = xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb);
+ skb_set_network_header(skb, netoff);
skb->mark = oldmark;
if (!ret)
return -1;
@@ -166,6 +172,8 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
struct iphdr *old_iph = ip_hdr(skb);
__be32 dst = tiph->daddr;
struct flowi4 fl4;
+ struct flowi fl;
+ u32 oldmark = skb->mark;
int err;
if (skb->protocol != htons(ETH_P_IP))
@@ -173,17 +181,35 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
tos = old_iph->tos;
+ /* SPD lookup: we must provide a dst_entry to xfrm_lookup, normally the
+ * route to the final destination. However this route is a route via
+ * the vti interface. Now vti interfaces typically have the NOXFRM
+ * flag, hence xfrm_lookup would bypass IPsec.
+ *
+ * Therefore, we feed xfrm_lookup with a route to the vti tunnel remote
+ * endpoint instead.
+ */
memset(&fl4, 0, sizeof(fl4));
flowi4_init_output(&fl4, tunnel->parms.link,
be32_to_cpu(tunnel->parms.o_key), RT_TOS(tos),
RT_SCOPE_UNIVERSE,
IPPROTO_IPIP, 0,
dst, tiph->saddr, 0, 0);
- rt = ip_route_output_key(dev_net(dev), &fl4);
+ rt = __ip_route_output_key(tunnel->net, &fl4);
if (IS_ERR(rt)) {
dev->stats.tx_carrier_errors++;
goto tx_error_icmp;
}
+
+ memset(&fl, 0, sizeof(fl));
+ /* temporarily mark the skb with the tunnel o_key, to look up
+ * for a policy with this mark, matching the plaintext traffic.
+ */
+ skb->mark = be32_to_cpu(tunnel->parms.o_key);
+ __xfrm_decode_session(skb, &fl, AF_INET, 0);
+ skb->mark = oldmark;
+ rt = (struct rtable *)xfrm_lookup(tunnel->net, &rt->dst, &fl, NULL, 0);
+
/* if there is no transform then this tunnel is not functional.
* Or if the xfrm is not mode tunnel.
*/
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH] net: mv643xx_eth: Add missing phy_addr_set in DT mode
From: Sebastian Hesselbarth @ 2013-11-05 9:04 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Andrew Lunn, Jason Cooper, netdev, linux-kernel, linux-arm-kernel,
linuxppc-dev, David Miller, Lennert Buytenhek
In-Reply-To: <1383611239-14556-1-git-send-email-jgunthorpe@obsidianresearch.com>
On 11/05/2013 01:27 AM, Jason Gunthorpe wrote:
> Commit cc9d4598 'net: mv643xx_eth: use of_phy_connect if phy_node
> present' made the call to phy_scan optional, if the DT has a link to
> the phy node.
>
> However phy_scan has the side effect of calling phy_addr_set, which
> writes the phy MDIO address to the ethernet controller. If phy_addr_set
> is not called, and the bootloader has not set the correct address then
> the driver will fail to function.
>
> Tested on Kirkwood.
>
> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> ---
Jason,
thanks for catching this! I do my kirkwood testing on Dockstar,
which has PHY addr 0x0 - also the reset default, which may be
why it slipped through.
Acked-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> ---
> drivers/net/ethernet/marvell/mv643xx_eth.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
> index 2c210ec..00e43b5 100644
> --- a/drivers/net/ethernet/marvell/mv643xx_eth.c
> +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
> @@ -2890,6 +2890,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
> PHY_INTERFACE_MODE_GMII);
> if (!mp->phy)
> err = -ENODEV;
> + phy_addr_set(mp, mp->phy->addr);
> } else if (pd->phy_addr != MV643XX_ETH_PHY_NONE) {
> mp->phy = phy_scan(mp, pd->phy_addr);
>
>
^ permalink raw reply
* Re: Bluetooth 6LoWPAN and routing
From: Alexander Aring @ 2013-11-05 8:55 UTC (permalink / raw)
To: Jukka Rissanen; +Cc: Claudio Takahasi, netdev
In-Reply-To: <1383640589.12691.36.camel@jrissane-mobl.ger.corp.intel.com>
On Tue, Nov 05, 2013 at 10:36:29AM +0200, Jukka Rissanen wrote:
> Hi Claudio,
>
> On ma, 2013-11-04 at 19:46 -0200, Claudio Takahasi wrote:
> > Hi Jukka,
> >
> > On Thu, Oct 24, 2013 at 9:48 AM, Jukka Rissanen
> > <jukka.rissanen@linux.intel.com> wrote:
> > > Hi Alexander,
> > >
> > >
> > > On 24.10.2013 15:25, Alexander Aring wrote:
> > >>
> > >> Hi Jukka,
> > >>
> > >> On Thu, Oct 24, 2013 at 09:45:40AM +0300, Jukka Rissanen wrote:
> > >>>
> > >>> Hi,
> > >>>
> > >>> I have been prototyping with BT 6LoWPAN support (using this draft
> > >>> http://tools.ietf.org/html/draft-ietf-6lowpan-btle-12 as a
> > >>> reference). I sent first version yesterday to linux-bluetooth ml
> > >>> http://thread.gmane.org/gmane.linux.bluez.kernel/39394
> > >>>
> > >> I see you take many code from the 6lowpan ieee802154 implementation.
> > >> (Just notice you drop the original authors from there)
> > >
> > >
> > > Hmm, those got dropped, I am sorry about that. I will add the original
> > > authors information of course.
> > >
> > >
> > >>
> > >> I have a couple of patches to fix a lot of bugs in the current 6LoWPAN
> > >> ieee802154 implementation.
> > >>
> > >> Some bugs which I found:
> > >>
> > >> - Fix race conditions in fragmentation handling
> > >> - Fix UDP compression/uncompressionm, which is completly broken
> > >> - Fragmentation handling isn't rfc4944 compatible
> > >>
> > >> And some other improvements. I see your rfc has the same issues (e.g.
> > >> fragmentation race conditions).
> > >>
> > >> Currently I preparing these patches for mainlining.
> > >
> > >
> > > Excellent news!
> >
> >
> > Is it necessary to implement 6loWPAN fragmentation/reassembling? For
> > Bluetooth, I thought L2CAP FAR (Fragmentation and Reassembling) could
> > handle the transfer of IPv6 packets that doesn't fit in one single
> > BTLE PDU.
>
> Yes, the Bluetooth 6lowpan code I sent handles the L2CAP FAR already.
> The question is who handles the IPv6 packets that are larger than
> IPV6_MIN_MTU (1280 bytes), or is that automatically done by other parts
ahh I understand now, yes that's handled by the normal IPv6 Fragmentation.
But you don't want a high payload like this. ;)
- Alex
^ permalink raw reply
* Re: Bluetooth 6LoWPAN and routing
From: Alexander Aring @ 2013-11-05 8:52 UTC (permalink / raw)
To: Jukka Rissanen; +Cc: Claudio Takahasi, netdev
In-Reply-To: <1383640589.12691.36.camel@jrissane-mobl.ger.corp.intel.com>
Hi Jukka,
On Tue, Nov 05, 2013 at 10:36:29AM +0200, Jukka Rissanen wrote:
> Hi Claudio,
>
> On ma, 2013-11-04 at 19:46 -0200, Claudio Takahasi wrote:
> > Hi Jukka,
> >
> > On Thu, Oct 24, 2013 at 9:48 AM, Jukka Rissanen
> > <jukka.rissanen@linux.intel.com> wrote:
> > > Hi Alexander,
> > >
> > >
> > > On 24.10.2013 15:25, Alexander Aring wrote:
> > >>
> > >> Hi Jukka,
> > >>
> > >> On Thu, Oct 24, 2013 at 09:45:40AM +0300, Jukka Rissanen wrote:
> > >>>
> > >>> Hi,
> > >>>
> > >>> I have been prototyping with BT 6LoWPAN support (using this draft
> > >>> http://tools.ietf.org/html/draft-ietf-6lowpan-btle-12 as a
> > >>> reference). I sent first version yesterday to linux-bluetooth ml
> > >>> http://thread.gmane.org/gmane.linux.bluez.kernel/39394
> > >>>
> > >> I see you take many code from the 6lowpan ieee802154 implementation.
> > >> (Just notice you drop the original authors from there)
> > >
> > >
> > > Hmm, those got dropped, I am sorry about that. I will add the original
> > > authors information of course.
> > >
> > >
> > >>
> > >> I have a couple of patches to fix a lot of bugs in the current 6LoWPAN
> > >> ieee802154 implementation.
> > >>
> > >> Some bugs which I found:
> > >>
> > >> - Fix race conditions in fragmentation handling
> > >> - Fix UDP compression/uncompressionm, which is completly broken
> > >> - Fragmentation handling isn't rfc4944 compatible
> > >>
> > >> And some other improvements. I see your rfc has the same issues (e.g.
> > >> fragmentation race conditions).
> > >>
> > >> Currently I preparing these patches for mainlining.
> > >
> > >
> > > Excellent news!
> >
> >
> > Is it necessary to implement 6loWPAN fragmentation/reassembling? For
> > Bluetooth, I thought L2CAP FAR (Fragmentation and Reassembling) could
> > handle the transfer of IPv6 packets that doesn't fit in one single
> > BTLE PDU.
>
> Yes, the Bluetooth 6lowpan code I sent handles the L2CAP FAR already.
> The question is who handles the IPv6 packets that are larger than
> IPV6_MIN_MTU (1280 bytes), or is that automatically done by other parts
> of the networking subsystem.
>
In [1] you use the fragmentation according rfc4944 which isn't for
bluetooth correct. [2] says:
"Since FAR in BT-LE is a function of the L2CAP layer, fragmentation
functionality as defined in RFC 4944 [RFC4944] MUST NOT be used in
BT-LE networks."
MUST NOT, so you can't use it.
[1] http://article.gmane.org/gmane.linux.bluez.kernel/39397
lowpan_process_data function and the first part of evaluating dispatch
value. This code is the most ugly code in 6lowpan but I will rework
it this right now... Only few problems with the skb_checksum because
I uncompress the header after fragmentation(I think so).
Of course that's only the receiving side, you need to check the
transmit side.
[2] http://tools.ietf.org/html/draft-ietf-6lowpan-btle-12#section-3.2
- Alex
^ permalink raw reply
* Re: Bluetooth 6LoWPAN and routing
From: Jukka Rissanen @ 2013-11-05 8:36 UTC (permalink / raw)
To: Claudio Takahasi; +Cc: netdev
In-Reply-To: <CAKT1EBeHs4T3YiFvze2RBbM537pXEj03gTcnCMEZprdBz882hg@mail.gmail.com>
Hi Claudio,
On ma, 2013-11-04 at 19:46 -0200, Claudio Takahasi wrote:
> Hi Jukka,
>
> On Thu, Oct 24, 2013 at 9:48 AM, Jukka Rissanen
> <jukka.rissanen@linux.intel.com> wrote:
> > Hi Alexander,
> >
> >
> > On 24.10.2013 15:25, Alexander Aring wrote:
> >>
> >> Hi Jukka,
> >>
> >> On Thu, Oct 24, 2013 at 09:45:40AM +0300, Jukka Rissanen wrote:
> >>>
> >>> Hi,
> >>>
> >>> I have been prototyping with BT 6LoWPAN support (using this draft
> >>> http://tools.ietf.org/html/draft-ietf-6lowpan-btle-12 as a
> >>> reference). I sent first version yesterday to linux-bluetooth ml
> >>> http://thread.gmane.org/gmane.linux.bluez.kernel/39394
> >>>
> >> I see you take many code from the 6lowpan ieee802154 implementation.
> >> (Just notice you drop the original authors from there)
> >
> >
> > Hmm, those got dropped, I am sorry about that. I will add the original
> > authors information of course.
> >
> >
> >>
> >> I have a couple of patches to fix a lot of bugs in the current 6LoWPAN
> >> ieee802154 implementation.
> >>
> >> Some bugs which I found:
> >>
> >> - Fix race conditions in fragmentation handling
> >> - Fix UDP compression/uncompressionm, which is completly broken
> >> - Fragmentation handling isn't rfc4944 compatible
> >>
> >> And some other improvements. I see your rfc has the same issues (e.g.
> >> fragmentation race conditions).
> >>
> >> Currently I preparing these patches for mainlining.
> >
> >
> > Excellent news!
>
>
> Is it necessary to implement 6loWPAN fragmentation/reassembling? For
> Bluetooth, I thought L2CAP FAR (Fragmentation and Reassembling) could
> handle the transfer of IPv6 packets that doesn't fit in one single
> BTLE PDU.
Yes, the Bluetooth 6lowpan code I sent handles the L2CAP FAR already.
The question is who handles the IPv6 packets that are larger than
IPV6_MIN_MTU (1280 bytes), or is that automatically done by other parts
of the networking subsystem.
> What am I missing here?
>
> It seems that some BLE development kits/firmwares don't support FAR on
> L2CAP Basic Mode, but this is another problem that should be fixed
> soon.
>
> Regards,
> Claudio
Cheers,
Jukka
^ permalink raw reply
* Re: [PATCH net-next v2 2/3] tipc: message reassembly using fragment chain
From: Erik Hugne @ 2013-11-05 8:15 UTC (permalink / raw)
To: David Miller; +Cc: netdev, jon.maloy, maloy, paul.gortmaker, ying.xue
In-Reply-To: <20131104.161254.1576011108092991976.davem@davemloft.net>
On Mon, Nov 04, 2013 at 04:12:54PM -0500, David Miller wrote:
> From: <erik.hugne@ericsson.com>
> Date: Thu, 31 Oct 2013 09:40:13 +0100
>
> > + skb_pull(frag, msg_hdr_sz(msg));
> > + if (fragid == FIRST_FRAGMENT) {
> > + if (*head)
> > + goto out_free;
> > + *head = frag;
> > + skb_frag_list_init(*head);
> > return 0;
> > + } else {
> > + if (!*head)
> > + goto out_free;
> > + if (!skb_has_frag_list(*head))
> > + skb_shinfo(*head)->frag_list = frag;
> > + else
> > + (*tail)->next = frag;
> > + *tail = frag;
> > + (*head)->truesize += frag->truesize;
> > + }
> > + if (fragid == LAST_FRAGMENT) {
> > + *fbuf = *head;
> > + *tail = *head = NULL;
> > + return LINK_REASM_COMPLETE;
> > }
>
> Please use skb_try_coalese(), and only use frag lists if that does not
> succeed.
Will fix.
>
> Also you must be certain to unclone the SKB if you are going to modify
> it in this kind of way.
Is it enough to just unclone the list head skb?
>
> For a good example of how to attend to all of these things, see
> ip_frag_reasm() in net/ipv4/ip_fragment.c
Thanks David.
^ permalink raw reply
* Re: pull request: wireless-next 2013-11-04
From: David Miller @ 2013-11-05 7:35 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20131104202241.GB1989@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Mon, 4 Nov 2013 15:22:42 -0500
> Please accept the following pull request intended for the 3.13 tree...
Pulled, thanks John.
^ permalink raw reply
* Re: [PATCH v2 2/2] ixgbe: enable l2 forwarding acceleration for macvlans
From: John Fastabend @ 2013-11-05 6:24 UTC (permalink / raw)
To: nhorman, alexander.h.duyck; +Cc: netdev, andy, davem, jeffrey.t.kirsher
In-Reply-To: <20131104190154.11802.75724.stgit@jf-dev1-dcblab>
On 11/4/2013 11:01 AM, John Fastabend wrote:
> Now that l2 acceleration ops are in place from the prior patch,
> enable ixgbe to take advantage of these operations. Allow it to
> allocate queues for a macvlan so that when we transmit a frame,
> we can do the switching in hardware inside the ixgbe card, rather
> than in software.
>
> For now this patch limits the hardware to 8 offloaded macvlan ports.
> A follow on patch will remove this limitation but to simplify
> review/validation of the new macvlan offload ops we leave it at 8
> for now.
>
> Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
> CC: Andy Gospodarek <andy@greyhouse.net>
> CC: "David S. Miller" <davem@davemloft.net>
> ---
[...]
>
> #define IXGBE_MAX_RSS_INDICES 16
> -#define IXGBE_MAX_VMDQ_INDICES 64
> +#define IXGBE_MAX_VMDQ_INDICES 8
This define is also used for max VFs in SR-IOV mode so we can't just
redefine it like this without also limiting SR-IOV.
[...]
> +static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
> +{
> + struct ixgbe_fwd_adapter *fwd_adapter = priv;
> + struct ixgbe_adapter *adapter = fwd_adapter->real_adapter;
> +
> + clear_bit(fwd_adapter->pool, &adapter->fwd_bitmask);
> + adapter->num_rx_pools--;
> +
> + ixgbe_fwd_ring_down(fwd_adapter->netdev, fwd_adapter);
> +
> + netdev_dbg(pdev, "pool %i:%i queues %i:%i VSI bitmask %lx\n",
> + fwd_adapter->pool, adapter->num_rx_pools,
> + fwd_adapter->rx_base_queue,
> + fwd_adapter->rx_base_queue + adapter->num_rx_queues_per_pool,
> + adapter->fwd_bitmask);
Missing a kfree(fwd_adapter) here, and a ixgbe_setup_tc() call to
release the queues.
I'm testing a fix now and will send a v3.
Thanks,
John
^ permalink raw reply
* [PATCH] ipv6: drop the judgement in rt6_alloc_cow()
From: Duan Jiong @ 2013-11-05 5:34 UTC (permalink / raw)
To: David Miller; +Cc: netdev
Now rt6_alloc_cow() is only called by ip6_pol_route() when
rt->rt6i_flags doesn't contain both RTF_NONEXTHOP and RTF_GATEWAY,
and rt->rt6i_flags hasn't been changed in ip6_rt_copy().
So there is no neccessary to judge whether rt->rt6i_flags contains
RTF_GATEWAY or not.
Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
---
net/ipv6/route.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index fd399ac..c28cdda 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -871,11 +871,9 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort,
rt = ip6_rt_copy(ort, daddr);
if (rt) {
- if (!(rt->rt6i_flags & RTF_GATEWAY)) {
- if (ort->rt6i_dst.plen != 128 &&
- ipv6_addr_equal(&ort->rt6i_dst.addr, daddr))
- rt->rt6i_flags |= RTF_ANYCAST;
- }
+ if (ort->rt6i_dst.plen != 128 &&
+ ipv6_addr_equal(&ort->rt6i_dst.addr, daddr))
+ rt->rt6i_flags |= RTF_ANYCAST;
rt->rt6i_flags |= RTF_CACHE;
--
1.8.3.1
^ permalink raw reply related
* [PATCH 3/7] IBM Akebono: Add support for a new PHY to the IBM emac driver
From: Alistair Popple @ 2013-11-05 5:31 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alistair Popple, David S. Miller, netdev
In-Reply-To: <1383629471-16979-1-git-send-email-alistair@popple.id.au>
The IBM Akebono board uses a different ethernet PHY that has wake on
lan (WOL) support with the IBM emac. This patch adds suppot to the IBM
emac driver for this new PHY.
At this stage the wake on lan functionality has not been implemented.
Signed-off-by: Alistair Popple <alistair@popple.id.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org
---
.../devicetree/bindings/powerpc/4xx/emac.txt | 9 +
drivers/net/ethernet/ibm/emac/Kconfig | 4 +
drivers/net/ethernet/ibm/emac/Makefile | 1 +
drivers/net/ethernet/ibm/emac/core.c | 50 +++-
drivers/net/ethernet/ibm/emac/core.h | 12 +
drivers/net/ethernet/ibm/emac/rgmii_wol.c | 262 ++++++++++++++++++++
drivers/net/ethernet/ibm/emac/rgmii_wol.h | 62 +++++
7 files changed, 394 insertions(+), 6 deletions(-)
create mode 100644 drivers/net/ethernet/ibm/emac/rgmii_wol.c
create mode 100644 drivers/net/ethernet/ibm/emac/rgmii_wol.h
diff --git a/Documentation/devicetree/bindings/powerpc/4xx/emac.txt b/Documentation/devicetree/bindings/powerpc/4xx/emac.txt
index 712baf6..9928d9d 100644
--- a/Documentation/devicetree/bindings/powerpc/4xx/emac.txt
+++ b/Documentation/devicetree/bindings/powerpc/4xx/emac.txt
@@ -61,6 +61,8 @@
Fox Axon: present, whatever value is appropriate for each
EMAC, that is the content of the current (bogus) "phy-port"
property.
+ - rgmii-wol-device : 1 cell, required iff conntect to a RGMII in the WKUP
+ power domain. phandle of the RGMII-WOL device node.
Optional properties:
- phy-address : 1 cell, optional, MDIO address of the PHY. If absent,
@@ -146,3 +148,10 @@
available.
For Axon: 0x0000012a
+ iv) RGMII-WOL node
+
+ Required properties:
+ - compatible : compatible list, containing 2 entries, first is
+ "ibm,rgmii-wol-CHIP" where CHIP is the host ASIC (like
+ EMAC) and the second is "ibm,rgmii-wol".
+ - reg : <registers mapping>
diff --git a/drivers/net/ethernet/ibm/emac/Kconfig b/drivers/net/ethernet/ibm/emac/Kconfig
index 3f44a30..7425c27 100644
--- a/drivers/net/ethernet/ibm/emac/Kconfig
+++ b/drivers/net/ethernet/ibm/emac/Kconfig
@@ -55,6 +55,10 @@ config IBM_EMAC_RGMII
bool
default n
+config IBM_EMAC_RGMII_WOL
+ bool
+ default n
+
config IBM_EMAC_TAH
bool
default n
diff --git a/drivers/net/ethernet/ibm/emac/Makefile b/drivers/net/ethernet/ibm/emac/Makefile
index eba2183..8843803 100644
--- a/drivers/net/ethernet/ibm/emac/Makefile
+++ b/drivers/net/ethernet/ibm/emac/Makefile
@@ -7,5 +7,6 @@ obj-$(CONFIG_IBM_EMAC) += ibm_emac.o
ibm_emac-y := mal.o core.o phy.o
ibm_emac-$(CONFIG_IBM_EMAC_ZMII) += zmii.o
ibm_emac-$(CONFIG_IBM_EMAC_RGMII) += rgmii.o
+ibm_emac-$(CONFIG_IBM_EMAC_RGMII_WOL) += rgmii_wol.o
ibm_emac-$(CONFIG_IBM_EMAC_TAH) += tah.o
ibm_emac-$(CONFIG_IBM_EMAC_DEBUG) += debug.o
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 6b5c722..fc1a775 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -630,6 +630,8 @@ static int emac_configure(struct emac_instance *dev)
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
rgmii_set_speed(dev->rgmii_dev, dev->rgmii_port,
dev->phy.speed);
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL))
+ rgmii_wol_set_speed(dev->rgmii_wol_dev, dev->phy.speed);
if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII))
zmii_set_speed(dev->zmii_dev, dev->zmii_port, dev->phy.speed);
@@ -797,6 +799,8 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg)
zmii_get_mdio(dev->zmii_dev, dev->zmii_port);
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port);
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL))
+ rgmii_wol_get_mdio(dev->rgmii_wol_dev);
/* Wait for management interface to become idle */
n = 20;
@@ -844,6 +848,8 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg)
DBG2(dev, "mdio_read -> %04x" NL, r);
err = 0;
bail:
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL))
+ rgmii_wol_put_mdio(dev->rgmii_wol_dev);
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
rgmii_put_mdio(dev->rgmii_dev, dev->rgmii_port);
if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII))
@@ -869,6 +875,8 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg,
zmii_get_mdio(dev->zmii_dev, dev->zmii_port);
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port);
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL))
+ rgmii_wol_get_mdio(dev->rgmii_wol_dev);
/* Wait for management interface to be idle */
n = 20;
@@ -907,6 +915,8 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg,
}
err = 0;
bail:
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL))
+ rgmii_wol_put_mdio(dev->rgmii_wol_dev);
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
rgmii_put_mdio(dev->rgmii_dev, dev->rgmii_port);
if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII))
@@ -2275,10 +2285,11 @@ struct emac_depentry {
#define EMAC_DEP_MAL_IDX 0
#define EMAC_DEP_ZMII_IDX 1
#define EMAC_DEP_RGMII_IDX 2
-#define EMAC_DEP_TAH_IDX 3
-#define EMAC_DEP_MDIO_IDX 4
-#define EMAC_DEP_PREV_IDX 5
-#define EMAC_DEP_COUNT 6
+#define EMAC_DEP_RGMII_WOL_IDX 3
+#define EMAC_DEP_TAH_IDX 4
+#define EMAC_DEP_MDIO_IDX 5
+#define EMAC_DEP_PREV_IDX 6
+#define EMAC_DEP_COUNT 7
static int emac_check_deps(struct emac_instance *dev,
struct emac_depentry *deps)
@@ -2356,6 +2367,7 @@ static int emac_wait_deps(struct emac_instance *dev)
deps[EMAC_DEP_MAL_IDX].phandle = dev->mal_ph;
deps[EMAC_DEP_ZMII_IDX].phandle = dev->zmii_ph;
deps[EMAC_DEP_RGMII_IDX].phandle = dev->rgmii_ph;
+ deps[EMAC_DEP_RGMII_WOL_IDX].phandle = dev->rgmii_wol_ph;
if (dev->tah_ph)
deps[EMAC_DEP_TAH_IDX].phandle = dev->tah_ph;
if (dev->mdio_ph)
@@ -2378,6 +2390,7 @@ static int emac_wait_deps(struct emac_instance *dev)
dev->mal_dev = deps[EMAC_DEP_MAL_IDX].ofdev;
dev->zmii_dev = deps[EMAC_DEP_ZMII_IDX].ofdev;
dev->rgmii_dev = deps[EMAC_DEP_RGMII_IDX].ofdev;
+ dev->rgmii_wol_dev = deps[EMAC_DEP_RGMII_WOL_IDX].ofdev;
dev->tah_dev = deps[EMAC_DEP_TAH_IDX].ofdev;
dev->mdio_dev = deps[EMAC_DEP_MDIO_IDX].ofdev;
}
@@ -2583,6 +2596,8 @@ static int emac_init_config(struct emac_instance *dev)
dev->rgmii_ph = 0;
if (emac_read_uint_prop(np, "rgmii-channel", &dev->rgmii_port, 0))
dev->rgmii_port = 0xffffffff;
+ if (emac_read_uint_prop(np, "rgmii-wol-device", &dev->rgmii_wol_ph, 0))
+ dev->rgmii_wol_ph = 0;
if (emac_read_uint_prop(np, "fifo-entry-size", &dev->fifo_entry_size, 0))
dev->fifo_entry_size = 16;
if (emac_read_uint_prop(np, "mal-burst-size", &dev->mal_burst_size, 0))
@@ -2669,6 +2684,16 @@ static int emac_init_config(struct emac_instance *dev)
#endif
}
+ if (dev->rgmii_wol_ph != 0) {
+#ifdef CONFIG_IBM_EMAC_RGMII_WOL
+ dev->features |= EMAC_FTR_HAS_RGMII_WOL;
+#else
+ printk(KERN_ERR "%s: RGMII WOL support not enabled !\n",
+ np->full_name);
+ return -ENXIO;
+#endif
+ }
+
/* Read MAC-address */
p = of_get_property(np, "local-mac-address", NULL);
if (p == NULL) {
@@ -2842,10 +2867,15 @@ static int emac_probe(struct platform_device *ofdev)
(err = rgmii_attach(dev->rgmii_dev, dev->rgmii_port, dev->phy_mode)) != 0)
goto err_detach_zmii;
+ /* Attach to RGMII_WOL, if needed */
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL) &&
+ (err = rgmii_wol_attach(dev->rgmii_wol_dev, dev->phy_mode)) != 0)
+ goto err_detach_rgmii;
+
/* Attach to TAH, if needed */
if (emac_has_feature(dev, EMAC_FTR_HAS_TAH) &&
(err = tah_attach(dev->tah_dev, dev->tah_port)) != 0)
- goto err_detach_rgmii;
+ goto err_detach_rgmii_wol;
/* Set some link defaults before we can find out real parameters */
dev->phy.speed = SPEED_100;
@@ -2918,6 +2948,9 @@ static int emac_probe(struct platform_device *ofdev)
err_detach_tah:
if (emac_has_feature(dev, EMAC_FTR_HAS_TAH))
tah_detach(dev->tah_dev, dev->tah_port);
+ err_detach_rgmii_wol:
+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII_WOL))
+ rgmii_wol_detach(dev->rgmii_wol_dev);
err_detach_rgmii:
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
rgmii_detach(dev->rgmii_dev, dev->rgmii_port);
@@ -3079,12 +3112,17 @@ static int __init emac_init(void)
rc = tah_init();
if (rc)
goto err_rgmii;
- rc = platform_driver_register(&emac_driver);
+ rc = rgmii_wol_init();
if (rc)
goto err_tah;
+ rc = platform_driver_register(&emac_driver);
+ if (rc)
+ goto err_rgmii_wol;
return 0;
+ err_rgmii_wol:
+ rgmii_wol_exit();
err_tah:
tah_exit();
err_rgmii:
diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h
index 7007479..930a6f6 100644
--- a/drivers/net/ethernet/ibm/emac/core.h
+++ b/drivers/net/ethernet/ibm/emac/core.h
@@ -43,6 +43,7 @@
#include "phy.h"
#include "zmii.h"
#include "rgmii.h"
+#include "rgmii_wol.h"
#include "mal.h"
#include "tah.h"
#include "debug.h"
@@ -210,6 +211,10 @@ struct emac_instance {
u32 rgmii_port;
struct platform_device *rgmii_dev;
+ /* RGMII WOL infos if any */
+ u32 rgmii_wol_ph;
+ struct platform_device *rgmii_wol_dev;
+
/* TAH infos if any */
u32 tah_ph;
u32 tah_port;
@@ -333,6 +338,10 @@ struct emac_instance {
* APM821xx does not support Half Duplex mode
*/
#define EMAC_FTR_APM821XX_NO_HALF_DUPLEX 0x00001000
+/*
+ * Set if we have a RGMII with wake on LAN.
+ */
+#define EMAC_FTR_HAS_RGMII_WOL 0x00020000
/* Right now, we don't quite handle the always/possible masks on the
* most optimal way as we don't have a way to say something like
@@ -356,6 +365,9 @@ enum {
#ifdef CONFIG_IBM_EMAC_RGMII
EMAC_FTR_HAS_RGMII |
#endif
+#ifdef CONFIG_IBM_EMAC_RGMII_WOL
+ EMAC_FTR_HAS_RGMII_WOL |
+#endif
#ifdef CONFIG_IBM_EMAC_NO_FLOW_CTRL
EMAC_FTR_NO_FLOW_CONTROL_40x |
#endif
diff --git a/drivers/net/ethernet/ibm/emac/rgmii_wol.c b/drivers/net/ethernet/ibm/emac/rgmii_wol.c
new file mode 100644
index 0000000..8e0dcf6
--- /dev/null
+++ b/drivers/net/ethernet/ibm/emac/rgmii_wol.c
@@ -0,0 +1,262 @@
+/* drivers/net/ethernet/ibm/emac/rgmii_wol.c
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge with
+ * wake on LAN support.
+ *
+ * Copyright 2013 Alistair Popple, IBM Corp.
+ * <alistair@popple.id.au>
+ *
+ * Based on rgmii.h:
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/ethtool.h>
+#include <linux/io.h>
+
+#include "emac.h"
+#include "debug.h"
+
+/* RGMII_WOL_REG */
+
+#define WKUP_ETH_RGSPD 0xC0000000
+#define WKUP_ETH_FCSEN 0x20000000
+#define WKUP_ETH_CRSEN 0x02000000
+#define WKUP_ETH_COLEN 0x01000000
+#define WKUP_ETH_TX_OE 0x00040000
+#define WKUP_ETH_RX_IE 0x00020000
+#define WKUP_ETH_RGMIIEN 0x00010000
+
+#define WKUP_ETH_RGSPD_10 0x00000000
+#define WKUP_ETH_RGSPD_100 0x40000000
+#define WKUP_ETH_RGSPD_1000 0x80000000
+
+/* RGMII bridge supports only GMII/TBI and RGMII/RTBI PHYs */
+static inline int rgmii_valid_mode(int phy_mode)
+{
+ return phy_mode == PHY_MODE_GMII ||
+ phy_mode == PHY_MODE_MII ||
+ phy_mode == PHY_MODE_RGMII ||
+ phy_mode == PHY_MODE_TBI ||
+ phy_mode == PHY_MODE_RTBI;
+}
+
+static inline const char *rgmii_mode_name(int mode)
+{
+ switch (mode) {
+ case PHY_MODE_RGMII:
+ return "RGMII";
+ case PHY_MODE_TBI:
+ return "TBI";
+ case PHY_MODE_GMII:
+ return "GMII";
+ case PHY_MODE_MII:
+ return "MII";
+ case PHY_MODE_RTBI:
+ return "RTBI";
+ default:
+ BUG();
+ }
+}
+
+int rgmii_wol_attach(struct platform_device *ofdev, int mode)
+{
+ struct rgmii_wol_instance *dev = platform_get_drvdata(ofdev);
+
+ dev_dbg(&ofdev->dev, "attach\n");
+
+ /* Check if we need to attach to a RGMII */
+ if (!rgmii_valid_mode(mode)) {
+ dev_err(&ofdev->dev, "unsupported settings !\n");
+ return -ENODEV;
+ }
+
+ mutex_lock(&dev->lock);
+
+ /* Enable this input */
+ out_be32(dev->reg, in_be32(dev->reg) | WKUP_ETH_RGMIIEN
+ | WKUP_ETH_TX_OE | WKUP_ETH_RX_IE);
+ dev_notice(&ofdev->dev, "in %s mode\n", rgmii_mode_name(mode));
+
+ ++dev->users;
+
+ mutex_unlock(&dev->lock);
+
+ return 0;
+}
+
+void rgmii_wol_set_speed(struct platform_device *ofdev, int speed)
+{
+ struct rgmii_wol_instance *dev = platform_get_drvdata(ofdev);
+ u32 reg;
+
+ mutex_lock(&dev->lock);
+
+ reg = in_be32(dev->reg) & ~WKUP_ETH_RGSPD;
+
+ dev_dbg(&ofdev->dev, "speed(%d)\n", speed);
+
+ switch (speed) {
+ case SPEED_1000:
+ reg |= WKUP_ETH_RGSPD_1000;
+ break;
+ case SPEED_100:
+ reg |= WKUP_ETH_RGSPD_100;
+ break;
+ case SPEED_10:
+ reg |= WKUP_ETH_RGSPD_10;
+ break;
+ default:
+ dev_err(&ofdev->dev, "invalid speed set!\n");
+ }
+
+ out_be32(dev->reg, reg);
+
+ mutex_unlock(&dev->lock);
+}
+
+void rgmii_wol_get_mdio(struct platform_device *ofdev)
+{
+ /* MDIO is always enabled when RGMII_WOL is enabled, so we
+ * don't have to do anything here.
+ */
+ dev_dbg(&ofdev->dev, "get_mdio\n");
+}
+
+void rgmii_wol_put_mdio(struct platform_device *ofdev)
+{
+ dev_dbg(&ofdev->dev, "put_mdio\n");
+}
+
+void rgmii_wol_detach(struct platform_device *ofdev)
+{
+ struct rgmii_wol_instance *dev = platform_get_drvdata(ofdev);
+
+ BUG_ON(!dev || dev->users == 0);
+
+ mutex_lock(&dev->lock);
+
+ dev_dbg(&ofdev->dev, "detach\n");
+
+ /* Disable this input */
+ out_be32(dev->reg, 0);
+
+ --dev->users;
+
+ mutex_unlock(&dev->lock);
+}
+
+int rgmii_wol_get_regs_len(struct platform_device *ofdev)
+{
+ return sizeof(struct emac_ethtool_regs_subhdr) +
+ sizeof(u32);
+}
+
+void *rgmii_wol_dump_regs(struct platform_device *ofdev, void *buf)
+{
+ struct rgmii_wol_instance *dev = platform_get_drvdata(ofdev);
+ struct emac_ethtool_regs_subhdr *hdr = buf;
+ u32 *regs = (u32 *)(hdr + 1);
+
+ hdr->version = 0;
+ hdr->index = 0; /* for now, are there chips with more than one
+ * rgmii ? if yes, then we'll add a cell_index
+ * like we do for emac
+ */
+ memcpy_fromio(regs, dev->reg, sizeof(u32));
+ return regs + 1;
+}
+
+
+static int rgmii_wol_probe(struct platform_device *ofdev)
+{
+ struct device_node *np = ofdev->dev.of_node;
+ struct rgmii_wol_instance *dev;
+ int rc;
+
+ rc = -ENOMEM;
+ dev = kzalloc(sizeof(struct rgmii_wol_instance), GFP_KERNEL);
+ if (dev == NULL)
+ goto err_gone;
+
+ mutex_init(&dev->lock);
+
+ dev->reg = of_iomap(np, 0);
+ if (!dev->reg) {
+ dev_err(&ofdev->dev, "Can't map registers\n");
+ rc = -ENXIO;
+ goto err_free;
+ }
+
+ /* Check for RGMII flags */
+ if (of_get_property(ofdev->dev.of_node, "has-mdio", NULL))
+ dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO;
+
+ dev_dbg(&ofdev->dev, " Boot REG = 0x%08x\n", in_be32(dev->reg));
+
+ /* Disable all inputs by default */
+ out_be32(dev->reg, 0);
+
+ dev_info(&ofdev->dev,
+ "RGMII %s initialized with%s MDIO support\n",
+ ofdev->dev.of_node->full_name,
+ (dev->flags & EMAC_RGMII_FLAG_HAS_MDIO) ? "" : "out");
+
+ wmb();
+ platform_set_drvdata(ofdev, dev);
+
+ return 0;
+
+ err_free:
+ kfree(dev);
+ err_gone:
+ return rc;
+}
+
+static int rgmii_wol_remove(struct platform_device *ofdev)
+{
+ struct rgmii_wol_instance *dev = platform_get_drvdata(ofdev);
+
+ WARN_ON(dev->users != 0);
+
+ iounmap(dev->reg);
+ kfree(dev);
+
+ return 0;
+}
+
+static struct of_device_id rgmii_wol_match[] = {
+ {
+ .compatible = "ibm,rgmii-wol",
+ },
+ {
+ .type = "emac-rgmii-wol",
+ },
+ {},
+};
+
+static struct platform_driver rgmii_wol_driver = {
+ .driver = {
+ .name = "emac-rgmii-wol",
+ .owner = THIS_MODULE,
+ .of_match_table = rgmii_wol_match,
+ },
+ .probe = rgmii_wol_probe,
+ .remove = rgmii_wol_remove,
+};
+
+int __init rgmii_wol_init(void)
+{
+ return platform_driver_register(&rgmii_wol_driver);
+}
+
+void rgmii_wol_exit(void)
+{
+ platform_driver_unregister(&rgmii_wol_driver);
+}
diff --git a/drivers/net/ethernet/ibm/emac/rgmii_wol.h b/drivers/net/ethernet/ibm/emac/rgmii_wol.h
new file mode 100644
index 0000000..44ce268
--- /dev/null
+++ b/drivers/net/ethernet/ibm/emac/rgmii_wol.h
@@ -0,0 +1,62 @@
+/* drivers/net/ethernet/ibm/emac/rgmii_wol.h
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge with
+ * wake on LAN support.
+ *
+ * Copyright 2013 Alistair Popple, IBM Corp.
+ * <alistair@popple.id.au>
+ *
+ * Based on rgmii.h:
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __IBM_NEWEMAC_RGMII_WOL_H
+#define __IBM_NEWEMAC_RGMII_WOL_H
+
+/* RGMII device */
+struct rgmii_wol_instance {
+ u32 __iomem *reg;
+
+ /* RGMII bridge flags */
+ int flags;
+#define EMAC_RGMII_FLAG_HAS_MDIO 0x00000001
+
+ /* Only one EMAC whacks us at a time */
+ struct mutex lock;
+
+ /* number of EMACs using this RGMII bridge */
+ int users;
+};
+
+#ifdef CONFIG_IBM_EMAC_RGMII_WOL
+
+extern int rgmii_wol_init(void);
+extern void rgmii_wol_exit(void);
+extern int rgmii_wol_attach(struct platform_device *ofdev, int mode);
+extern void rgmii_wol_detach(struct platform_device *ofdev);
+extern void rgmii_wol_get_mdio(struct platform_device *ofdev);
+extern void rgmii_wol_put_mdio(struct platform_device *ofdev);
+extern void rgmii_wol_set_speed(struct platform_device *ofdev, int speed);
+extern int rgmii_wol_get_regs_len(struct platform_device *ofdev);
+extern void *rgmii_wol_dump_regs(struct platform_device *ofdev, void *buf);
+
+#else
+
+# define rgmii_wol_init() 0
+# define rgmii_wol_exit() do { } while (0)
+# define rgmii_wol_attach(x, y, z) (-ENXIO)
+# define rgmii_wol_detach(x, y) do { } while (0)
+# define rgmii_wol_get_mdio(o, i) do { } while (0)
+# define rgmii_wol_put_mdio(o, i) do { } while (0)
+# define rgmii_wol_set_speed(x, y, z) do { } while (0)
+# define rgmii_wol_get_regs_len(x) 0
+# define rgmii_wol_dump_regs(x, buf) (buf)
+#endif /* !CONFIG_IBM_EMAC_RGMII_WOL */
+
+#endif /* __IBM_NEWEMAC_RGMII_WOL_H */
--
1.7.10.4
^ permalink raw reply related
* [PATCH net] net: sch_red: Fix race between timer and red_destroy()
From: Vijay Subramanian @ 2013-11-05 2:08 UTC (permalink / raw)
To: netdev; +Cc: davem, shemminger, eric.dumazet, Vijay Subramanian
Make sure timer does not fire once qdisc is destroyed.
Signed-off-by: Vijay Subramanian <subramanian.vijay@gmail.com>
---
net/sched/sch_red.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 633e32d..380507e 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -39,6 +39,7 @@
struct red_sched_data {
u32 limit; /* HARD maximal queue length */
unsigned char flags;
+ bool timeron; /* to prevent race on destroy*/
struct timer_list adapt_timer;
struct red_parms parms;
struct red_vars vars;
@@ -166,6 +167,7 @@ static void red_destroy(struct Qdisc *sch)
{
struct red_sched_data *q = qdisc_priv(sch);
+ q->timeron = false;
del_timer_sync(&q->adapt_timer);
qdisc_destroy(q->qdisc);
}
@@ -241,7 +243,8 @@ static inline void red_adaptative_timer(unsigned long arg)
spin_lock(root_lock);
red_adaptative_algo(&q->parms, &q->vars);
- mod_timer(&q->adapt_timer, jiffies + HZ/2);
+ if (q->timeron)
+ mod_timer(&q->adapt_timer, jiffies + HZ/2);
spin_unlock(root_lock);
}
@@ -250,6 +253,7 @@ static int red_init(struct Qdisc *sch, struct nlattr *opt)
struct red_sched_data *q = qdisc_priv(sch);
q->qdisc = &noop_qdisc;
+ q->timeron = true;
setup_timer(&q->adapt_timer, red_adaptative_timer, (unsigned long)sch);
return red_change(sch, opt);
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH net] ipv6: fix headroom calculation in udp6_ufo_fragment
From: Hannes Frederic Sowa @ 2013-11-05 1:41 UTC (permalink / raw)
To: Saran Neti, netdev@vger.kernel.org, pshelar,
dl TSL Vulnerability Research Team
In-Reply-To: <20131103033207.GF30284@order.stressinduktion.org>
Commit 1e2bd517c108816220f262d7954b697af03b5f9c ("udp6: Fix udp
fragmentation for tunnel traffic.") changed the calculation if
there is enough space to include a fragment header in the skb from a
skb->mac_header dervived one to skb_headroom. Because we already peeled
off the skb to transport_header this is wrong. Change this back to check
if we have enough room before the mac_header.
This fixes a panic Saran Neti reported. He used the tbf scheduler which
skb_gso_segments the skb. The offsets get negative and we panic in memcpy
because the skb was erroneously not expanded at the head.
Reported-by: Saran Neti <Saran.Neti@telus.com>
Cc: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
net/ipv6/udp_offload.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index 08e23b0..e7359f9 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -90,7 +90,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
/* Check if there is enough headroom to insert fragment header. */
tnl_hlen = skb_tnl_header_len(skb);
- if (skb_headroom(skb) < (tnl_hlen + frag_hdr_sz)) {
+ if (skb->mac_header < (tnl_hlen + frag_hdr_sz)) {
if (gso_pskb_expand_head(skb, tnl_hlen + frag_hdr_sz))
goto out;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next] ipv4: introduce new IP_MTU_DISCOVER mode IP_PMTUDISC_INTERFACE
From: Hannes Frederic Sowa @ 2013-11-05 1:24 UTC (permalink / raw)
To: netdev; +Cc: davem, fweimer
Sockets marked with IP_PMTUDISC_INTERFACE won't do path mtu discovery,
their sockets won't accept and install new path mtu information and they
will always use the interface mtu for outgoing packets. It is guaranteed
that the packet is not fragmented locally. But we won't set the DF-Flag
on the outgoing frames.
Florian Weimer had the idea to use this flag to ensure DNS servers are
never generating outgoing fragments. They may well be fragmented on the
path, but the server never stores or usees path mtu values, which could
well be forged in an attack.
(The root of the problem with path MTU discovery is that there is
no reliable way to authenticate ICMP Fragmentation Needed But DF Set
messages because they are sent from intermediate routers with their
source addresses, and the IMCP payload will not always contain sufficient
information to identify a flow.)
Recent research in the DNS community showed that it is possible to
implement an attack where DNS cache poisoning is feasible by spoofing
fragments. This work was done by Amir Herzberg and Haya Shulman:
<https://sites.google.com/site/hayashulman/files/fragmentation-poisoning.pdf>
This issue was previously discussed among the DNS community, e.g.
<http://www.ietf.org/mail-archive/web/dnsext/current/msg01204.html>,
without leading to fixes.
This patch depends on the patch "ipv4: fix DO and PROBE pmtu mode
regarding local fragmentation with UFO/CORK" for the enforcement of the
non-fragmentable checks. If other users than ip_append_page/data should
use this semantic too, we have to add a new flag to IPCB(skb)->flags to
suppress local fragmentation and check for this in ip_finish_output.
Many thanks to Florian Weimer for the idea and feedback while implementing
this patch.
Cc: David S. Miller <davem@davemloft.net>
Suggested-by: Florian Weimer <fweimer@redhat.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
include/net/route.h | 16 ++++++++++++----
include/uapi/linux/in.h | 5 +++++
net/dccp/ipv4.c | 1 +
net/ipv4/ip_output.c | 8 ++++----
net/ipv4/ip_sockglue.c | 2 +-
net/ipv4/route.c | 4 ++++
net/ipv4/tcp_ipv4.c | 1 +
7 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/include/net/route.h b/include/net/route.h
index dd4ae00..f68c167 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -313,12 +313,20 @@ static inline int ip4_dst_hoplimit(const struct dst_entry *dst)
return hoplimit;
}
-static inline int ip_skb_dst_mtu(struct sk_buff *skb)
+static inline bool ip_sk_accept_pmtu(const struct sock *sk)
{
- struct inet_sock *inet = skb->sk ? inet_sk(skb->sk) : NULL;
+ return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE;
+}
- return (inet && inet->pmtudisc == IP_PMTUDISC_PROBE) ?
- skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
+static inline bool ip_sk_use_pmtu(const struct sock *sk)
+{
+ return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE;
+}
+
+static inline int ip_skb_dst_mtu(const struct sk_buff *skb)
+{
+ return (!skb->sk || ip_sk_use_pmtu(skb->sk)) ?
+ dst_mtu(skb_dst(skb)) : skb_dst(skb)->dev->mtu;
}
#endif /* _ROUTE_H */
diff --git a/include/uapi/linux/in.h b/include/uapi/linux/in.h
index f9e8e49..393c5de 100644
--- a/include/uapi/linux/in.h
+++ b/include/uapi/linux/in.h
@@ -115,6 +115,11 @@ struct in_addr {
#define IP_PMTUDISC_WANT 1 /* Use per route hints */
#define IP_PMTUDISC_DO 2 /* Always DF */
#define IP_PMTUDISC_PROBE 3 /* Ignore dst pmtu */
+/* Always use interface mtu (ignores dst pmtu) but don't set DF flag.
+ * Also incoming ICMP frag_needed notifications will be ignored on
+ * this socket to prevent accepting spoofed ones.
+ */
+#define IP_PMTUDISC_INTERFACE 4
#define IP_MULTICAST_IF 32
#define IP_MULTICAST_TTL 33
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 720c362..d9f65fc 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -174,6 +174,7 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
mtu = dst_mtu(dst);
if (inet->pmtudisc != IP_PMTUDISC_DONT &&
+ ip_sk_accept_pmtu(sk) &&
inet_csk(sk)->icsk_pmtu_cookie > mtu) {
dccp_sync_mss(sk, mtu);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 51be64e..9124027 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1037,7 +1037,6 @@ error:
static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
struct ipcm_cookie *ipc, struct rtable **rtp)
{
- struct inet_sock *inet = inet_sk(sk);
struct ip_options_rcu *opt;
struct rtable *rt;
@@ -1063,8 +1062,8 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
* We steal reference to this route, caller should not release it
*/
*rtp = NULL;
- cork->fragsize = inet->pmtudisc == IP_PMTUDISC_PROBE ?
- rt->dst.dev->mtu : dst_mtu(&rt->dst);
+ cork->fragsize = ip_sk_use_pmtu(sk) ?
+ dst_mtu(&rt->dst) : rt->dst.dev->mtu;
cork->dst = &rt->dst;
cork->length = 0;
cork->ttl = ipc->ttl;
@@ -1315,7 +1314,8 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
/* DF bit is set when we want to see DF on outgoing frames.
* If local_df is set too, we still allow to fragment this frame
* locally. */
- if (inet->pmtudisc >= IP_PMTUDISC_DO ||
+ if (inet->pmtudisc == IP_PMTUDISC_DO ||
+ inet->pmtudisc == IP_PMTUDISC_PROBE ||
(skb->len <= dst_mtu(&rt->dst) &&
ip_dont_fragment(sk, &rt->dst)))
df = htons(IP_DF);
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 0626f2c..3f85826 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -627,7 +627,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
inet->nodefrag = val ? 1 : 0;
break;
case IP_MTU_DISCOVER:
- if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_PROBE)
+ if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_INTERFACE)
goto e_inval;
inet->pmtudisc = val;
break;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index d2d3253..f428935 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1036,6 +1036,10 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
bool new = false;
bh_lock_sock(sk);
+
+ if (!ip_sk_accept_pmtu(sk))
+ goto out;
+
rt = (struct rtable *) __sk_dst_get(sk);
if (sock_owned_by_user(sk) || !rt) {
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 300ab2c..14bba8a 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -288,6 +288,7 @@ static void tcp_v4_mtu_reduced(struct sock *sk)
mtu = dst_mtu(dst);
if (inet->pmtudisc != IP_PMTUDISC_DONT &&
+ ip_sk_accept_pmtu(sk) &&
inet_csk(sk)->icsk_pmtu_cookie > mtu) {
tcp_sync_mss(sk, mtu);
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH net-next V3 2/2] virtio-net: coalesce rx frags when possible during rx
From: David Miller @ 2013-11-05 1:04 UTC (permalink / raw)
To: jasowang
Cc: mwdalton, mst, netdev, linux-kernel, virtualization, kmindg,
edumazet
In-Reply-To: <1383286068-10421-2-git-send-email-jasowang@redhat.com>
From: Jason Wang <jasowang@redhat.com>
Date: Fri, 1 Nov 2013 14:07:48 +0800
> Commit 2613af0ed18a11d5c566a81f9a6510b73180660a (virtio_net: migrate mergeable
> rx buffers to page frag allocators) try to increase the payload/truesize for
> MTU-sized traffic. But this will introduce the extra overhead for GSO packets
> received because of the frag list. This commit tries to reduce this issue by
> coalesce the possible rx frags when possible during rx. Test result shows the
> about 15% improvement on full size GSO packet receiving (and even better than
> before commit 2613af0ed18a11d5c566a81f9a6510b73180660a).
...
> Cc: Rusty Russell <rusty@rustcorp.com.au>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Cc: Michael Dalton <mwdalton@google.com>
> Cc: Eric Dumazet <edumazet@google.com>
> Acked-by: Michael S. Tsirkin <mst@redhat.com>
> Acked-by: Eric Dumazet <edumazet@google.com>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> Changes from V2:
> - call put_page() instead of depending on skb_coalesce_rx_frag()
Looks fantastic, applied, thanks Jason!
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox