* [PATCH net-next 4/7] udp: Changes to udp_offload to support remote checksum offload
From: Tom Herbert @ 2014-11-01 22:58 UTC (permalink / raw)
To: davem, netdev
In-Reply-To: <1414882683-25484-1-git-send-email-therbert@google.com>
Add a new GSO type, SKB_GSO_TUNNEL_REMCSUM, which indicates remote
checksum offload being done (in this case inner checksum must not
be offloaded to the NIC).
Added logic in __skb_udp_tunnel_segment to handle remote checksum
offload case.
Signed-off-by: Tom Herbert <therbert@google.com>
---
include/linux/netdev_features.h | 4 +++-
include/linux/netdevice.h | 1 +
include/linux/skbuff.h | 4 +++-
net/core/skbuff.c | 4 ++--
net/ipv4/af_inet.c | 1 +
net/ipv4/tcp_offload.c | 1 +
net/ipv4/udp_offload.c | 18 ++++++++++++++++--
net/ipv6/ip6_offload.c | 1 +
net/ipv6/udp_offload.c | 1 +
9 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index dcfdecb..8c94b07 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -48,8 +48,9 @@ enum {
NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */
NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,/* ... UDP TUNNEL with TSO & CSUM */
NETIF_F_GSO_MPLS_BIT, /* ... MPLS segmentation */
+ NETIF_F_GSO_TUNNEL_REMCSUM_BIT, /* ... TUNNEL with TSO & REMCSUM */
/**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */
- NETIF_F_GSO_MPLS_BIT,
+ NETIF_F_GSO_TUNNEL_REMCSUM_BIT,
NETIF_F_FCOE_CRC_BIT, /* FCoE CRC32 */
NETIF_F_SCTP_CSUM_BIT, /* SCTP checksum offload */
@@ -119,6 +120,7 @@ enum {
#define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL)
#define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM)
#define NETIF_F_GSO_MPLS __NETIF_F(GSO_MPLS)
+#define NETIF_F_GSO_TUNNEL_REMCSUM __NETIF_F(GSO_TUNNEL_REMCSUM)
#define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER)
#define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX)
#define NETIF_F_HW_VLAN_STAG_TX __NETIF_F(HW_VLAN_STAG_TX)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c85e065..b2364f0 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3583,6 +3583,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_MPLS != (NETIF_F_GSO_MPLS >> NETIF_F_GSO_SHIFT));
+ BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != (NETIF_F_GSO_TUNNEL_REMCSUM >> NETIF_F_GSO_SHIFT));
return (features & feature) == feature;
}
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index a59d934..a41e101 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -372,6 +372,7 @@ enum {
SKB_GSO_MPLS = 1 << 12,
+ SKB_GSO_TUNNEL_REMCSUM = 1 << 13,
};
#if BITS_PER_LONG > 32
@@ -595,7 +596,8 @@ struct sk_buff {
#endif
__u8 ipvs_property:1;
__u8 inner_protocol_type:1;
- /* 4 or 6 bit hole */
+ __u8 remcsum_offload:1;
+ /* 3 or 5 bit hole */
#ifdef CONFIG_NET_SCHED
__u16 tc_index; /* traffic control index */
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index e48e5c0..7001896 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3013,7 +3013,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
if (nskb->len == len + doffset)
goto perform_csum_check;
- if (!sg) {
+ if (!sg && !nskb->remcsum_offload) {
nskb->ip_summed = CHECKSUM_NONE;
nskb->csum = skb_copy_and_csum_bits(head_skb, offset,
skb_put(nskb, len),
@@ -3085,7 +3085,7 @@ skip_fraglist:
nskb->truesize += nskb->data_len;
perform_csum_check:
- if (!csum) {
+ if (!csum && !nskb->remcsum_offload) {
nskb->csum = skb_checksum(nskb, doffset,
nskb->len - doffset, 0);
nskb->ip_summed = CHECKSUM_NONE;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 8b7fe5b..ed2c672 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1222,6 +1222,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
SKB_GSO_TCPV6 |
SKB_GSO_UDP_TUNNEL |
SKB_GSO_UDP_TUNNEL_CSUM |
+ SKB_GSO_TUNNEL_REMCSUM |
SKB_GSO_MPLS |
0)))
goto out;
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index 5b90f2f..a1b2a56 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -97,6 +97,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
SKB_GSO_MPLS |
SKB_GSO_UDP_TUNNEL |
SKB_GSO_UDP_TUNNEL_CSUM |
+ SKB_GSO_TUNNEL_REMCSUM |
0) ||
!(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))))
goto out;
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index a774711..0a5a70d 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -41,7 +41,8 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
unsigned int oldlen;
bool need_csum = !!(skb_shinfo(skb)->gso_type &
SKB_GSO_UDP_TUNNEL_CSUM);
- bool offload_csum = false, dont_encap = need_csum;
+ bool remcsum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TUNNEL_REMCSUM);
+ bool offload_csum = false, dont_encap = (need_csum || remcsum);
oldlen = (u16)~skb->len;
@@ -55,6 +56,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
skb->mac_len = skb_inner_network_offset(skb);
skb->protocol = new_protocol;
skb->encap_hdr_csum = need_csum;
+ skb->remcsum_offload = remcsum;
/* Try to offload checksum if possible */
offload_csum = !!(need_csum &&
@@ -108,11 +110,22 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
uh->check = ~csum_fold((__force __wsum)
((__force u32)uh->check +
(__force u32)delta));
-
if (offload_csum) {
skb->ip_summed = CHECKSUM_PARTIAL;
skb->csum_start = skb_transport_header(skb) - skb->head;
skb->csum_offset = offsetof(struct udphdr, check);
+ } else if (remcsum) {
+ /* Need to calculate checksum from scratch,
+ * inner checksums are never when doing
+ * remote_checksum_offload.
+ */
+
+ skb->csum = skb_checksum(skb, udp_offset,
+ skb->len - udp_offset,
+ 0);
+ uh->check = csum_fold(skb->csum);
+ if (uh->check == 0)
+ uh->check = CSUM_MANGLED_0;
} else {
uh->check = gso_make_checksum(skb, ~uh->check);
@@ -192,6 +205,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY |
SKB_GSO_UDP_TUNNEL |
SKB_GSO_UDP_TUNNEL_CSUM |
+ SKB_GSO_TUNNEL_REMCSUM |
SKB_GSO_IPIP |
SKB_GSO_GRE | SKB_GSO_GRE_CSUM |
SKB_GSO_MPLS) ||
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index a071563..e976707 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -78,6 +78,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
SKB_GSO_SIT |
SKB_GSO_UDP_TUNNEL |
SKB_GSO_UDP_TUNNEL_CSUM |
+ SKB_GSO_TUNNEL_REMCSUM |
SKB_GSO_MPLS |
SKB_GSO_TCPV6 |
0)))
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index 6b8f543..637ba2e 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -42,6 +42,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
SKB_GSO_DODGY |
SKB_GSO_UDP_TUNNEL |
SKB_GSO_UDP_TUNNEL_CSUM |
+ SKB_GSO_TUNNEL_REMCSUM |
SKB_GSO_GRE |
SKB_GSO_GRE_CSUM |
SKB_GSO_IPIP |
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH net-next 3/7] gue: Add infrastructure for flags and options
From: Tom Herbert @ 2014-11-01 22:57 UTC (permalink / raw)
To: davem, netdev
In-Reply-To: <1414882683-25484-1-git-send-email-therbert@google.com>
Add functions and basic definitions for processing standard flags,
private flags, and control messages. This includes definitions
to compute length of optional fields corresponding to a set of flags.
Flag validation is in validate_gue_flags function. This checks for
unknown flags, and that length of optional fields is <= length
in guehdr hlen.
Signed-off-by: Tom Herbert <therbert@google.com>
---
include/net/fou.h | 11 ++++-
include/net/gue.h | 100 ++++++++++++++++++++++++++++++++++++--
net/ipv4/fou.c | 142 ++++++++++++++++++++++++++++++++++++------------------
3 files changed, 199 insertions(+), 54 deletions(-)
diff --git a/include/net/fou.h b/include/net/fou.h
index cf4ce88..d2d8055 100644
--- a/include/net/fou.h
+++ b/include/net/fou.h
@@ -20,7 +20,16 @@ static size_t fou_encap_hlen(struct ip_tunnel_encap *e)
static size_t gue_encap_hlen(struct ip_tunnel_encap *e)
{
- return sizeof(struct udphdr) + sizeof(struct guehdr);
+ size_t len;
+ bool need_priv = false;
+
+ len = sizeof(struct udphdr) + sizeof(struct guehdr);
+
+ /* Add in lengths flags */
+
+ len += need_priv ? GUE_LEN_PRIV : 0;
+
+ return len;
}
#endif
diff --git a/include/net/gue.h b/include/net/gue.h
index b6c3327..cb68ae8 100644
--- a/include/net/gue.h
+++ b/include/net/gue.h
@@ -1,23 +1,113 @@
#ifndef __NET_GUE_H
#define __NET_GUE_H
+/* Definitions for the GUE header, standard and private flags, lengths
+ * of optional fields are below.
+ *
+ * Diagram of GUE header:
+ *
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |Ver|C| Hlen | Proto/ctype | Standard flags |P|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | |
+ * ~ Fields (optional) ~
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Private flags (optional, P bit is set) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | |
+ * ~ Private fields (optional) ~
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * C bit indicates contol message when set, data message when unset.
+ * For a control message, proto/ctype is interpreted as a type of
+ * control message. For data messages, proto/ctype is the IP protocol
+ * of the next header.
+ *
+ * P bit indicates private flags field is present. The private flags
+ * may refer to options placed after this field.
+ */
+
struct guehdr {
union {
struct {
#if defined(__LITTLE_ENDIAN_BITFIELD)
- __u8 hlen:4,
- version:4;
+ __u8 hlen:5,
+ control:1,
+ version:2;
#elif defined (__BIG_ENDIAN_BITFIELD)
- __u8 version:4,
- hlen:4;
+ __u8 version:2,
+ control:1,
+ hlen:5;
#else
#error "Please fix <asm/byteorder.h>"
#endif
- __u8 next_hdr;
+ __u8 proto_ctype;
__u16 flags;
};
__u32 word;
};
};
+/* Standard flags in GUE header */
+
+#define GUE_FLAG_PRIV htons(1<<0) /* Private flags are in options */
+#define GUE_LEN_PRIV 4
+
+#define GUE_FLAGS_ALL (GUE_FLAG_PRIV)
+
+/* Private flags in the private option extension */
+
+#define GUE_PFLAGS_ALL (0)
+
+/* Functions to compute options length corresponding to flags.
+ * If we ever have a lot of flags this can be potentially be
+ * converted to a more optimized algorithm (table lookup
+ * for instance).
+ */
+static inline size_t guehdr_flags_len(__be16 flags)
+{
+ return ((flags & GUE_FLAG_PRIV) ? GUE_LEN_PRIV : 0);
+}
+
+static inline size_t guehdr_priv_flags_len(__be32 flags)
+{
+ return 0;
+}
+
+/* Validate standard and private flags. Returns non-zero (meaning invalid)
+ * if there is an unknown standard or private flags, or the options length for
+ * the flags exceeds the options length specific in hlen of the GUE header.
+ */
+static inline int validate_gue_flags(struct guehdr *guehdr,
+ size_t optlen)
+{
+ size_t len;
+ __be32 flags = guehdr->flags;
+
+ if (flags & ~GUE_FLAGS_ALL)
+ return 1;
+
+ len = guehdr_flags_len(flags);
+ if (len > optlen)
+ return 1;
+
+ if (flags & GUE_FLAG_PRIV) {
+ /* Private flags are last four bytes accounted in
+ * guehdr_flags_len
+ */
+ flags = *(__be32 *)((void *)&guehdr[1] + len - GUE_LEN_PRIV);
+
+ if (flags & ~GUE_PFLAGS_ALL)
+ return 1;
+
+ len += guehdr_priv_flags_len(flags);
+ if (len > optlen)
+ return 1;
+ }
+
+ return 0;
+}
+
#endif
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index 5446c1c..a3b8c5b 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -38,21 +38,17 @@ static inline struct fou *fou_from_sock(struct sock *sk)
return sk->sk_user_data;
}
-static int fou_udp_encap_recv_deliver(struct sk_buff *skb,
- u8 protocol, size_t len)
+static void fou_recv_pull(struct sk_buff *skb, size_t len)
{
struct iphdr *iph = ip_hdr(skb);
/* Remove 'len' bytes from the packet (UDP header and
- * FOU header if present), modify the protocol to the one
- * we found, and then call rcv_encap.
+ * FOU header if present).
*/
iph->tot_len = htons(ntohs(iph->tot_len) - len);
__skb_pull(skb, len);
skb_postpull_rcsum(skb, udp_hdr(skb), len);
skb_reset_transport_header(skb);
-
- return -protocol;
}
static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
@@ -62,16 +58,24 @@ static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
if (!fou)
return 1;
- return fou_udp_encap_recv_deliver(skb, fou->protocol,
- sizeof(struct udphdr));
+ fou_recv_pull(skb, sizeof(struct udphdr));
+
+ return -fou->protocol;
+}
+
+static int gue_control_message(struct sk_buff *skb, struct guehdr *guehdr)
+{
+ /* No support yet */
+ kfree_skb(skb);
+ return 0;
}
static int gue_udp_recv(struct sock *sk, struct sk_buff *skb)
{
struct fou *fou = fou_from_sock(sk);
- size_t len;
+ size_t len, optlen, hdrlen;
struct guehdr *guehdr;
- struct udphdr *uh;
+ void *data;
if (!fou)
return 1;
@@ -80,25 +84,38 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb)
if (!pskb_may_pull(skb, len))
goto drop;
- uh = udp_hdr(skb);
- guehdr = (struct guehdr *)&uh[1];
+ guehdr = (struct guehdr *)&udp_hdr(skb)[1];
+
+ optlen = guehdr->hlen << 2;
+ len += optlen;
- len += guehdr->hlen << 2;
if (!pskb_may_pull(skb, len))
goto drop;
- uh = udp_hdr(skb);
- guehdr = (struct guehdr *)&uh[1];
+ /* guehdr may change after pull */
+ guehdr = (struct guehdr *)&udp_hdr(skb)[1];
- if (guehdr->version != 0)
- goto drop;
+ hdrlen = sizeof(struct guehdr) + optlen;
- if (guehdr->flags) {
- /* No support yet */
+ if (guehdr->version != 0 || validate_gue_flags(guehdr, optlen))
goto drop;
+
+ /* Pull UDP and GUE headers */
+ fou_recv_pull(skb, len);
+
+ data = &guehdr[1];
+
+ if (guehdr->flags & GUE_FLAG_PRIV) {
+ data += GUE_LEN_PRIV;
+
+ /* Process private flags */
}
- return fou_udp_encap_recv_deliver(skb, guehdr->next_hdr, len);
+ if (unlikely(guehdr->control))
+ return gue_control_message(skb, guehdr);
+
+ return -guehdr->proto_ctype;
+
drop:
kfree_skb(skb);
return 0;
@@ -154,36 +171,47 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head,
const struct net_offload *ops;
struct sk_buff **pp = NULL;
struct sk_buff *p;
- u8 proto;
struct guehdr *guehdr;
- unsigned int hlen, guehlen;
- unsigned int off;
+ size_t len, optlen, hdrlen, off;
+ void *data;
int flush = 1;
off = skb_gro_offset(skb);
- hlen = off + sizeof(*guehdr);
+ len = off + sizeof(*guehdr);
+
guehdr = skb_gro_header_fast(skb, off);
- if (skb_gro_header_hard(skb, hlen)) {
- guehdr = skb_gro_header_slow(skb, hlen, off);
+ if (skb_gro_header_hard(skb, len)) {
+ guehdr = skb_gro_header_slow(skb, len, off);
if (unlikely(!guehdr))
goto out;
}
- proto = guehdr->next_hdr;
+ optlen = guehdr->hlen << 2;
+ len += optlen;
- rcu_read_lock();
- offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
- ops = rcu_dereference(offloads[proto]);
- if (WARN_ON(!ops || !ops->callbacks.gro_receive))
- goto out_unlock;
+ if (skb_gro_header_hard(skb, len)) {
+ guehdr = skb_gro_header_slow(skb, len, off);
+ if (unlikely(!guehdr))
+ goto out;
+ }
- guehlen = sizeof(*guehdr) + (guehdr->hlen << 2);
+ if (unlikely(guehdr->control) || guehdr->version != 0 ||
+ validate_gue_flags(guehdr, optlen))
+ goto out;
- hlen = off + guehlen;
- if (skb_gro_header_hard(skb, hlen)) {
- guehdr = skb_gro_header_slow(skb, hlen, off);
- if (unlikely(!guehdr))
- goto out_unlock;
+ hdrlen = sizeof(*guehdr) + optlen;
+
+ skb_gro_pull(skb, hdrlen);
+
+ /* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/
+ skb_gro_postpull_rcsum(skb, guehdr, hdrlen);
+
+ data = &guehdr[1];
+
+ if (guehdr->flags & GUE_FLAG_PRIV) {
+ data += GUE_LEN_PRIV;
+
+ /* Process private flags */
}
flush = 0;
@@ -197,7 +225,7 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head,
guehdr2 = (struct guehdr *)(p->data + off);
/* Compare base GUE header to be equal (covers
- * hlen, version, next_hdr, and flags.
+ * hlen, version, proto_ctype, and flags.
*/
if (guehdr->word != guehdr2->word) {
NAPI_GRO_CB(p)->same_flow = 0;
@@ -212,10 +240,11 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head,
}
}
- skb_gro_pull(skb, guehlen);
-
- /* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/
- skb_gro_postpull_rcsum(skb, guehdr, guehlen);
+ rcu_read_lock();
+ offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
+ ops = rcu_dereference(offloads[guehdr->proto_ctype]);
+ if (WARN_ON(!ops || !ops->callbacks.gro_receive))
+ goto out_unlock;
pp = ops->callbacks.gro_receive(head, skb);
@@ -236,7 +265,7 @@ static int gue_gro_complete(struct sk_buff *skb, int nhoff)
u8 proto;
int err = -ENOENT;
- proto = guehdr->next_hdr;
+ proto = guehdr->proto_ctype;
guehlen = sizeof(*guehdr) + (guehdr->hlen << 2);
@@ -533,8 +562,12 @@ int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
struct guehdr *guehdr;
- size_t hdr_len = sizeof(struct guehdr);
+ size_t optlen = 0;
__be16 sport;
+ void *data;
+ bool need_priv = false;
+
+ optlen += need_priv ? GUE_LEN_PRIV : 0;
skb = iptunnel_handle_offloads(skb, csum, type);
@@ -545,14 +578,27 @@ int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
skb, 0, 0, false);
- skb_push(skb, hdr_len);
+ skb_push(skb, sizeof(struct guehdr) + optlen);
guehdr = (struct guehdr *)skb->data;
+ guehdr->control = 0;
guehdr->version = 0;
- guehdr->hlen = 0;
+ guehdr->hlen = optlen >> 2;
guehdr->flags = 0;
- guehdr->next_hdr = *protocol;
+ guehdr->proto_ctype = *protocol;
+
+ data = &guehdr[1];
+
+ if (need_priv) {
+ __be32 *flags = data;
+
+ guehdr->flags |= GUE_FLAG_PRIV;
+ *flags = 0;
+ data += GUE_LEN_PRIV;
+
+ /* Add private flags */
+ }
fou_build_udp(skb, e, fl4, protocol, sport);
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH net-next 2/7] udp: Offload outer UDP tunnel csum if available
From: Tom Herbert @ 2014-11-01 22:57 UTC (permalink / raw)
To: davem, netdev
In-Reply-To: <1414882683-25484-1-git-send-email-therbert@google.com>
In __skb_udp_tunnel_segment if outer UDP checksums are enabled and
ip_summed is not already CHECKSUM_PARTIAL, set up checksum offload
if device features allow it.
Signed-off-by: Tom Herbert <therbert@google.com>
---
net/ipv4/udp_offload.c | 52 ++++++++++++++++++++++++++++++++++----------------
1 file changed, 36 insertions(+), 16 deletions(-)
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 6480cea..a774711 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -29,7 +29,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
netdev_features_t features,
struct sk_buff *(*gso_inner_segment)(struct sk_buff *skb,
netdev_features_t features),
- __be16 new_protocol)
+ __be16 new_protocol, bool is_ipv6)
{
struct sk_buff *segs = ERR_PTR(-EINVAL);
u16 mac_offset = skb->mac_header;
@@ -39,7 +39,9 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
netdev_features_t enc_features;
int udp_offset, outer_hlen;
unsigned int oldlen;
- bool need_csum;
+ bool need_csum = !!(skb_shinfo(skb)->gso_type &
+ SKB_GSO_UDP_TUNNEL_CSUM);
+ bool offload_csum = false, dont_encap = need_csum;
oldlen = (u16)~skb->len;
@@ -52,10 +54,12 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
skb_set_network_header(skb, skb_inner_network_offset(skb));
skb->mac_len = skb_inner_network_offset(skb);
skb->protocol = new_protocol;
+ skb->encap_hdr_csum = need_csum;
- need_csum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM);
- if (need_csum)
- skb->encap_hdr_csum = 1;
+ /* Try to offload checksum if possible */
+ offload_csum = !!(need_csum &&
+ (skb->dev->features &
+ (is_ipv6 ? NETIF_F_V6_CSUM : NETIF_F_V4_CSUM)));
/* segment inner packet. */
enc_features = skb->dev->hw_enc_features & features;
@@ -72,11 +76,21 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
do {
struct udphdr *uh;
int len;
-
- skb_reset_inner_headers(skb);
- skb->encapsulation = 1;
+ __be32 delta;
+
+ if (dont_encap) {
+ skb->encapsulation = 0;
+ skb->ip_summed = CHECKSUM_NONE;
+ } else {
+ /* Only set up inner headers if we might be offloading
+ * inner checksum.
+ */
+ skb_reset_inner_headers(skb);
+ skb->encapsulation = 1;
+ }
skb->mac_len = mac_len;
+ skb->protocol = protocol;
skb_push(skb, outer_hlen);
skb_reset_mac_header(skb);
@@ -86,19 +100,25 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
uh = udp_hdr(skb);
uh->len = htons(len);
- if (need_csum) {
- __be32 delta = htonl(oldlen + len);
+ if (!need_csum)
+ continue;
+
+ delta = htonl(oldlen + len);
+
+ uh->check = ~csum_fold((__force __wsum)
+ ((__force u32)uh->check +
+ (__force u32)delta));
- uh->check = ~csum_fold((__force __wsum)
- ((__force u32)uh->check +
- (__force u32)delta));
+ if (offload_csum) {
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ skb->csum_start = skb_transport_header(skb) - skb->head;
+ skb->csum_offset = offsetof(struct udphdr, check);
+ } else {
uh->check = gso_make_checksum(skb, ~uh->check);
if (uh->check == 0)
uh->check = CSUM_MANGLED_0;
}
-
- skb->protocol = protocol;
} while ((skb = skb->next));
out:
return segs;
@@ -134,7 +154,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
}
segs = __skb_udp_tunnel_segment(skb, features, gso_inner_segment,
- protocol);
+ protocol, is_ipv6);
out_unlock:
rcu_read_unlock();
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH net-next 1/7] net: Move fou_build_header into fou.c and refactor
From: Tom Herbert @ 2014-11-01 22:57 UTC (permalink / raw)
To: davem, netdev
In-Reply-To: <1414882683-25484-1-git-send-email-therbert@google.com>
Move fou_build_header out of ip_tunnel.c and into fou.c splitting
it up into fou_build_header, gue_build_header, and fou_build_udp.
This allows for other users for TX of FOU or GUE. Change ip_tunnel_encap
to call fou_build_header or gue_build_header based on the tunnel
encapsulation type. Similarly, added fou_encap_hlen and gue_encap_hlen
functions which are called by ip_encap_hlen. New net/fou.h has
prototypes and defines for this.
Added NET_FOU_IP_TUNNELS configuration. When this is set, IP tunnels
can use FOU/GUE and fou module is also selected.
Signed-off-by: Tom Herbert <therbert@google.com>
---
include/net/fou.h | 26 +++++++++++++++++++
net/ipv4/Kconfig | 9 +++++++
net/ipv4/fou.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++
net/ipv4/ip_tunnel.c | 61 +++++++++----------------------------------
4 files changed, 120 insertions(+), 49 deletions(-)
create mode 100644 include/net/fou.h
diff --git a/include/net/fou.h b/include/net/fou.h
new file mode 100644
index 0000000..cf4ce88
--- /dev/null
+++ b/include/net/fou.h
@@ -0,0 +1,26 @@
+#ifndef __NET_FOU_H
+#define __NET_FOU_H
+
+#include <linux/skbuff.h>
+
+#include <net/flow.h>
+#include <net/gue.h>
+#include <net/ip_tunnels.h>
+#include <net/udp.h>
+
+int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
+ u8 *protocol, struct flowi4 *fl4);
+int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
+ u8 *protocol, struct flowi4 *fl4);
+
+static size_t fou_encap_hlen(struct ip_tunnel_encap *e)
+{
+ return sizeof(struct udphdr);
+}
+
+static size_t gue_encap_hlen(struct ip_tunnel_encap *e)
+{
+ return sizeof(struct udphdr) + sizeof(struct guehdr);
+}
+
+#endif
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index e682b48..bd29016 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -322,6 +322,15 @@ config NET_FOU
network mechanisms and optimizations for UDP (such as ECMP
and RSS) can be leveraged to provide better service.
+config NET_FOU_IP_TUNNELS
+ bool "IP: FOU encapsulation of IP tunnels"
+ depends on NET_IPIP || NET_IPGRE || IPV6_SIT
+ select NET_FOU
+ ---help---
+ Allow configuration of FOU or GUE encapsulation for IP tunnels.
+ When this option is enabled IP tunnels can be configured to use
+ FOU or GUE encapsulation.
+
config GENEVE
tristate "Generic Network Virtualization Encapsulation (Geneve)"
depends on INET
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index 32e7892..5446c1c 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -487,6 +487,79 @@ static const struct genl_ops fou_nl_ops[] = {
},
};
+static void fou_build_udp(struct sk_buff *skb, struct ip_tunnel_encap *e,
+ struct flowi4 *fl4, u8 *protocol, __be16 sport)
+{
+ struct udphdr *uh;
+
+ skb_push(skb, sizeof(struct udphdr));
+ skb_reset_transport_header(skb);
+
+ uh = udp_hdr(skb);
+
+ uh->dest = e->dport;
+ uh->source = sport;
+ uh->len = htons(skb->len);
+ uh->check = 0;
+ udp_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM), skb,
+ fl4->saddr, fl4->daddr, skb->len);
+
+ *protocol = IPPROTO_UDP;
+}
+
+int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
+ u8 *protocol, struct flowi4 *fl4)
+{
+ bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
+ int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
+ __be16 sport;
+
+ skb = iptunnel_handle_offloads(skb, csum, type);
+
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
+ skb, 0, 0, false);
+ fou_build_udp(skb, e, fl4, protocol, sport);
+
+ return 0;
+}
+EXPORT_SYMBOL(fou_build_header);
+
+int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
+ u8 *protocol, struct flowi4 *fl4)
+{
+ bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
+ int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
+ struct guehdr *guehdr;
+ size_t hdr_len = sizeof(struct guehdr);
+ __be16 sport;
+
+ skb = iptunnel_handle_offloads(skb, csum, type);
+
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ /* Get source port (based on flow hash) before skb_push */
+ sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
+ skb, 0, 0, false);
+
+ skb_push(skb, hdr_len);
+
+ guehdr = (struct guehdr *)skb->data;
+
+ guehdr->version = 0;
+ guehdr->hlen = 0;
+ guehdr->flags = 0;
+ guehdr->next_hdr = *protocol;
+
+ fou_build_udp(skb, e, fl4, protocol, sport);
+
+ return 0;
+}
+EXPORT_SYMBOL(gue_build_header);
+
static int __init fou_init(void)
{
int ret;
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 0bb8e14..c3587e1 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -56,7 +56,10 @@
#include <net/netns/generic.h>
#include <net/rtnetlink.h>
#include <net/udp.h>
-#include <net/gue.h>
+
+#if IS_ENABLED(CONFIG_NET_FOU)
+#include <net/fou.h>
+#endif
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ipv6.h>
@@ -494,10 +497,12 @@ static int ip_encap_hlen(struct ip_tunnel_encap *e)
switch (e->type) {
case TUNNEL_ENCAP_NONE:
return 0;
+#if IS_ENABLED(CONFIG_NET_FOU)
case TUNNEL_ENCAP_FOU:
- return sizeof(struct udphdr);
+ return fou_encap_hlen(e);
case TUNNEL_ENCAP_GUE:
- return sizeof(struct udphdr) + sizeof(struct guehdr);
+ return gue_encap_hlen(e);
+#endif
default:
return -EINVAL;
}
@@ -526,60 +531,18 @@ int ip_tunnel_encap_setup(struct ip_tunnel *t,
}
EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup);
-static int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
- size_t hdr_len, u8 *protocol, struct flowi4 *fl4)
-{
- struct udphdr *uh;
- __be16 sport;
- bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
- int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
-
- skb = iptunnel_handle_offloads(skb, csum, type);
-
- if (IS_ERR(skb))
- return PTR_ERR(skb);
-
- /* Get length and hash before making space in skb */
-
- sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
- skb, 0, 0, false);
-
- skb_push(skb, hdr_len);
-
- skb_reset_transport_header(skb);
- uh = udp_hdr(skb);
-
- if (e->type == TUNNEL_ENCAP_GUE) {
- struct guehdr *guehdr = (struct guehdr *)&uh[1];
-
- guehdr->version = 0;
- guehdr->hlen = 0;
- guehdr->flags = 0;
- guehdr->next_hdr = *protocol;
- }
-
- uh->dest = e->dport;
- uh->source = sport;
- uh->len = htons(skb->len);
- uh->check = 0;
- udp_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM), skb,
- fl4->saddr, fl4->daddr, skb->len);
-
- *protocol = IPPROTO_UDP;
-
- return 0;
-}
-
int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
u8 *protocol, struct flowi4 *fl4)
{
switch (t->encap.type) {
case TUNNEL_ENCAP_NONE:
return 0;
+#if IS_ENABLED(CONFIG_NET_FOU)
case TUNNEL_ENCAP_FOU:
+ return fou_build_header(skb, &t->encap, protocol, fl4);
case TUNNEL_ENCAP_GUE:
- return fou_build_header(skb, &t->encap, t->encap_hlen,
- protocol, fl4);
+ return gue_build_header(skb, &t->encap, protocol, fl4);
+#endif
default:
return -EINVAL;
}
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH net-next 0/7] gue: Remote checksum offload
From: Tom Herbert @ 2014-11-01 22:57 UTC (permalink / raw)
To: davem, netdev
This patch set implements remote checksum offload for
GUE, which is a mechanism that provides checksum offload of
encapsulated packets using rudimentary offload capabilities found in
most Network Interface Card (NIC) devices. The outer header checksum
for UDP is enabled in packets and, with some additional meta
information in the GUE header, a receiver is able to deduce the
checksum to be set for an inner encapsulated packet. Effectively this
offloads the computation of the inner checksum. Enabling the outer
checksum in encapsulation has the additional advantage that it covers
more of the packet than the inner checksum including the encapsulation
headers.
Remote checksum offload is described in:
http://tools.ietf.org/html/draft-herbert-remotecsumoffload-00
The GUE transmit and receive paths are modified to support the
remote checksum offload option. The option contains a checksum
offset and checksum start which are directly derived from values
set in stack when doing CHECKSUM_PARTIAL. On receipt of the option, the
operation is to calculate the packet checksum from "start" to end of
the packet (normally derived for checksum complete), and then set
the resultant value at checksum "offset" (the checksum field has
already been primed with the pseudo header). This emulates a NIC
that implements NETIF_F_HW_CSUM.
The primary purpose of this feature is to eliminate cost of performing
checksum calculation over a packet when encpasulating.
In this patch set:
- Move fou_build_header into fou.c and split it into a couple of
functions
- Enable offloading of outer UDP checksum in encapsulation
- Change udp_offload to support remote checksum offload, includes
new GSO type and ensuring encapsulated layers (TCP) doesn't try to
set a checksum covered by RCO
- TX support for RCO with GUE. This is configured through ip_tunnel
and set the option on transmit when packet being encapsulated is
CHECKSUM_PARTIAL
- RX support for RCO with GUE for normal and GRO paths. Includes
resolving the offloaded checksum
Testing:
I ran performance numbers using netperf TCP_STREAM and TCP_RR with 200
streams, comparing GUE with and without remote checksum offload (doing
checksum-unnecessary to complete conversion in both cases). These
were run on mlnx4 and bnx2x. Some mlnx4 results are below.
GRE/GUE
TCP_STREAM
IPv4, with remote checksum offload
9.71% TX CPU utilization
7.42% RX CPU utilization
36380 Mbps
IPv4, without remote checksum offload
12.40% TX CPU utilization
7.36% RX CPU utilization
36591 Mbps
TCP_RR
IPv4, with remote checksum offload
77.79% CPU utilization
91/144/216 90/95/99% latencies
1.95127e+06 tps
IPv4, without remote checksum offload
78.70% CPU utilization
89/152/297 90/95/99% latencies
1.95458e+06 tps
IPIP/GUE
TCP_STREAM
With remote checksum offload
10.30% TX CPU utilization
7.43% RX CPU utilization
36486 Mbps
Without remote checksum offload
12.47% TX CPU utilization
7.49% RX CPU utilization
36694 Mbps
TCP_RR
With remote checksum offload
77.80% CPU utilization
87/153/270 90/95/99% latencies
1.98735e+06 tps
Without remote checksum offload
77.98% CPU utilization
87/150/287 90/95/99% latencies
1.98737e+06 tps
SIT/GUE
TCP_STREAM
With remote checksum offload
9.68% TX CPU utilization
7.36% RX CPU utilization
35971 Mbps
Without remote checksum offload
12.95% TX CPU utilization
8.04% RX CPU utilization
36177 Mbps
TCP_RR
With remote checksum offload
79.32% CPU utilization
94/158/295 90/95/99% latencies
1.88842e+06 tps
Without remote checksum offload
80.23% CPU utilization
94/149/226 90/95/99% latencies
1.90338e+06 tps
VXLAN
TCP_STREAM
35.03% TX CPU utilization
20.85% RX CPU utilization
36230 Mbps
TCP_RR
77.36% CPU utilization
84/146/270 90/95/99% latencies
2.08063e+06 tps
We can also look at CPU time in csum_partial using perf (with bnx2x
setup). For GRE with TCP_STREAM I see:
With remote checksum offload
0.33% TX
1.81% RX
Without remote checksum offload
6.00% TX
0.51% RX
I suspect the fact that time in csum_partial noticably increases
with remote checksum offload for RX is due to taking the cache miss on
the encapsulated header in that function. By similar reasoning, if on
the TX side the packet were not in cache (say we did a splice from a
file whose data was never touched by the CPU) the CPU savings for TX
would probably be more pronounced.
Tom Herbert (7):
net: Move fou_build_header into fou.c and refactor
udp: Offload outer UDP tunnel csum if available
gue: Add infrastructure for flags and options
udp: Changes to udp_offload to support remote checksum offload
gue: Protocol constants for remote checksum offload
gue: TX support for using remote checksum offload option
gue: Receive side of remote checksum offload
include/linux/netdev_features.h | 4 +-
include/linux/netdevice.h | 1 +
include/linux/skbuff.h | 4 +-
include/net/fou.h | 38 ++++
include/net/gue.h | 103 ++++++++++-
include/uapi/linux/if_tunnel.h | 1 +
net/core/skbuff.c | 4 +-
net/ipv4/Kconfig | 9 +
net/ipv4/af_inet.c | 1 +
net/ipv4/fou.c | 388 +++++++++++++++++++++++++++++++++++-----
net/ipv4/ip_tunnel.c | 61 ++-----
net/ipv4/tcp_offload.c | 1 +
net/ipv4/udp_offload.c | 66 +++++--
net/ipv6/ip6_offload.c | 1 +
net/ipv6/udp_offload.c | 1 +
15 files changed, 565 insertions(+), 118 deletions(-)
create mode 100644 include/net/fou.h
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply
* Re: [PATCH] net: mvpp2: fix possible memory leak
From: Thomas Petazzoni @ 2014-11-01 22:24 UTC (permalink / raw)
To: Sudip Mukherjee; +Cc: David S. Miller, netdev, linux-kernel
In-Reply-To: <1414841374-30537-1-git-send-email-sudipm.mukherjee@gmail.com>
Dear Sudip Mukherjee,
On Sat, 1 Nov 2014 16:59:34 +0530, Sudip Mukherjee wrote:
> we are allocating memory using kzalloc for struct mvpp2_prs_entry,
> but later when we are getting error we were just returning the error
> value without releasing the memory.
>
> Signed-off-by: Sudip Mukherjee <sudip@vectorindia.org>
> ---
>
> hi,
> i could not build test after modifying it. I tried to compile using
> multi_v7_defconfig , but the cross compiler i have is not able to
> compile it and giving sevaral warnings from the assembler.
That seems weird. Which compiler are you using, and which errors were
you getting?
In any case, it would have been good to Cc the authors of the driver.
Thanks!
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH net-next v4 0/4] netns: allow to identify peer netns
From: David Miller @ 2014-11-01 21:08 UTC (permalink / raw)
To: ebiederm-aS9lmoZGLiVWk0Htik3J/w
Cc: nicolas.dichtel-pdR9zngts4EAvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
luto-kltTT9wpgjJwATOyAt5JVQ, cwang-xCSkyg8dI+0RB7SZvlqPiA
In-Reply-To: <871tpph03k.fsf-JOvCrm2gF+uungPnsOpG7nhyD016LWXt@public.gmane.org>
From: ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org (Eric W. Biederman)
Date: Thu, 30 Oct 2014 11:41:03 -0700
> Nicolas Dichtel <nicolas.dichtel-pdR9zngts4EAvxtiuMwx3w@public.gmane.org> writes:
>
>> The goal of this serie is to be able to multicast netlink messages with an
>> attribute that identify a peer netns.
>> This is needed by the userland to interpret some informations contained in
>> netlink messages (like IFLA_LINK value, but also some other attributes in case
>> of x-netns netdevice (see also
>> http://thread.gmane.org/gmane.linux.network/315933/focus=316064 and
>> http://thread.gmane.org/gmane.linux.kernel.containers/28301/focus=4239)).
>>
>> Ids of peer netns are set by userland via a new genl messages. These ids are
>> stored per netns and are local (ie only valid in the netns where they are set).
>> To avoid allocating an int for each peer netns, I use idr_for_each() to retrieve
>> the id of a peer netns. Note that it will be possible to add a table (struct net
>> -> id) later to optimize this lookup if needed.
>>
>> Patch 1/4 introduces the netlink API mechanism to set and get these ids.
>> Patch 2/4 and 3/4 implements an example of how to use these ids in rtnetlink
>> messages. And patch 4/4 shows that the netlink messages can be symetric between
>> a GET and a SET.
>>
>> iproute2 patches are available, I can send them on demand.
>
> A quick reply. I think this patchset is in the right general direction.
> There are some oddball details that seem odd/awkward to me such as using
> genetlink instead of rtnetlink to get and set the ids, and not having
> ids if they are not set (that feels like a maintenance/usability challenge).
>
> I would like to give your patches a deep review, but I won't be able to
> do that for a couple of weeks. I am deep in the process of moving,
> and will be mostly offline until about the Nov 11th.
I'm going to mark this patch set 'deferred' in patchwork until things
move forward.
Thanks.
^ permalink raw reply
* Re: [PATCH] smc91x: retrieve IRQ and trigger flags in a modern way
From: David Miller @ 2014-11-01 21:04 UTC (permalink / raw)
To: linus.walleij; +Cc: netdev, nico
In-Reply-To: <1414787526-11197-1-git-send-email-linus.walleij@linaro.org>
From: Linus Walleij <linus.walleij@linaro.org>
Date: Fri, 31 Oct 2014 21:32:06 +0100
> The SMC91x is written to explicitly look up the IRQ resource
> from the platform device and extract the IRQ and flags, however
> the platform_get_irq() does additional things, like call
> of_irq_get() in the device tree case, which will translate
> the IRQ using the irqdomain and defer the probe if the
> IRQ host cannot be found.
>
> As we're not looking up the resource, this will not retrieve
> the IRQ flags, but that is better done using
> irqd_get_trigger_type(), as the trigger is what the driver
> wants to modify. We take care to preserve the semantics that
> will make the trigger type provided from the resource
> override any local specifier.
>
> Tested on the Nomadik NHK15 which has its SMC91x IRQ line
> connected to a STMPE2401 GPIO expander on I2C.
>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH] drivers: net: ethernet: xilinx: xilinx_emaclite: Compatible with 'xlnx,xps-ethernetlite-2.00.b' for QEMU using
From: David Miller @ 2014-11-01 21:03 UTC (permalink / raw)
To: gang.chen.5i5j
Cc: michal.simek, soren.brinkmann, sthokal, manuel.schoelling,
paul.gortmaker, f.fainelli, ebiederm, netdev, linux-arm-kernel,
linux-kernel
In-Reply-To: <54545AB9.70206@gmail.com>
From: Chen Gang <gang.chen.5i5j@gmail.com>
Date: Sat, 01 Nov 2014 11:59:53 +0800
> On 11/1/14 11:08, Chen Gang wrote:
>> When use current latest upstream qemu (current version: 2.1.2), need let
>> driver compatible with 'xlnx,xps-ethernetlite-2.00.b', or can not find
>> net device in microblaze qemu. Related QEMU commands under fedora 20:
>>
>> yum install libvirt
>> yum install tunctl
>> tunctl -b
>> ip link set tap0 up
>> brctl addif virbr0 tap0
>> ./microblaze-softmmu/qemu-system-microblaze -M petalogix-s3adsp1800 \
>> -kernel ../linux-stable.microblaze/arch/microblaze/boot/linux.bin \
>> -no-reboot -append "console=ttyUL0,115200 doreboot" -nographic \
>> -net nic,vlan=0,model=xlnx.xps-ethernetlite,macaddr=00:16:35:AF:94:00 \
>> -net tap,vlan=0,ifname=tap0,script=no,downscript=no
>>
>> in microblaze qemu bash (guest machine):
>>
>> ifconfig eth0 add 192.168.122.1 netmask 255.255.255.0
>
> Oh, sorry, it is 192.168.122.2 (192.168.122.1 is the router address).
>
> Thanks.
>
>> ifconfig eth0 up
>>
>> After add this patch, can find the device, and can be used by 'telnetd'
>> (need cross-build busybox with glibc for it), then outside can telnet to
>> it without password.
>>
>> Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
Applied with correct commit message, thanks.
^ permalink raw reply
* Re: [PATCH net 0/2] net: systemport: TX dma fixes
From: David Miller @ 2014-11-01 19:14 UTC (permalink / raw)
To: f.fainelli; +Cc: netdev
In-Reply-To: <1414795895-31612-1-git-send-email-f.fainelli@gmail.com>
From: Florian Fainelli <f.fainelli@gmail.com>
Date: Fri, 31 Oct 2014 15:51:33 -0700
> This patch series contains two fixes for our transmit path, first one
> is a pretty nasty one since we were not allocating a large enough
> dma coherent pool for our transmit descriptors, which would work most of the
> time, since allocations are contiguous and we could have.
>
> Second patch fixes a less frequent, though highly likley crash when using
> CMA allocations.
Series applied, thanks.
> I just missed your pull request to Linus, though I assume there will be
> another one?
Yes, there should be another one, or two, or three, or...
^ permalink raw reply
* Re: [PATCH] net: mvpp2: fix possible memory leak
From: David Miller @ 2014-11-01 19:12 UTC (permalink / raw)
To: sudipm.mukherjee; +Cc: netdev, linux-kernel
In-Reply-To: <1414841374-30537-1-git-send-email-sudipm.mukherjee@gmail.com>
From: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Date: Sat, 1 Nov 2014 16:59:34 +0530
> we are allocating memory using kzalloc for struct mvpp2_prs_entry,
> but later when we are getting error we were just returning the error
> value without releasing the memory.
>
> Signed-off-by: Sudip Mukherjee <sudip@vectorindia.org>
Applied, thanks.
^ permalink raw reply
* DONATION!!!
From: Mrs Birgit Rausing @ 2014-10-30 21:26 UTC (permalink / raw)
I,Birgit authenticate this email, you can read about me on:
http://en.wikipedia.org/wiki/Birgit_Rausing
I have funds for you to manage and disburse to various charities of your
choice. If you are sure you can handle this, it will be of help to you and
others. Please reply if you are interested for more details.please
Contact my private email;( mrs_BirgitRausin0@qq.com ) for more
information
With love,
Mrs Birgit Rausing
^ permalink raw reply
* Re: [PATCH 0/1] mv643xx_eth: Disable TSO by default
From: Ezequiel Garcia @ 2014-11-01 19:05 UTC (permalink / raw)
To: Eric Dumazet
Cc: netdev, David Miller, Thomas Petazzoni, Gregory Clement,
Tawfik Bayouk, Lior Amsalem, Nadav Haklai
In-Reply-To: <1414863453.31792.8.camel@edumazet-glaptop2.roam.corp.google.com>
[-- Attachment #1: Type: text/plain, Size: 1716 bytes --]
On 11/01/2014 02:37 PM, Eric Dumazet wrote:
> On Sat, 2014-11-01 at 10:26 -0700, Eric Dumazet wrote:
>> On Sat, 2014-11-01 at 12:30 -0300, Ezequiel Garcia wrote:
>>> Several users ([1], [2]) have been reporting data corruption with TSO on
>>> Kirkwood platforms (i.e. using the mv643xx_eth driver).
>>>
>>> Until we manage to find what's causing this, this simple patch will make
>>> the TSO path disabled by default. This patch should be queued for stable,
>>> fixing the TSO feature introduced in v3.16.
>>>
>>> The corruption itself is very easy to reproduce: checking md5sum on a mounted
>>> NFS directory gives a different result each time. Same tests using the mvneta
>>> driver (Armada 370/38x/XP SoC) pass with no issues.
>>>
>>> Frankly, I'm a bit puzzled about this, and so any ideas or debugging hints
>>> are well received.
>>
>> lack of barriers maybe ?
>>
Yup, that was my initial thought as well...
>> It seems you might need to populate all TX descriptors but delay the
>> first, like doing the populate in descending order.
>>
>> If you take a look at txq_submit_skb(), you'll see the final
>> desc->cmd_sts = cmd_sts (line 959) is done _after_ frags were cooked by
>> txq_submit_frag_skb()
>>
>> You should kick the nick only when all TX descriptors are ready and
>> committed to memory.
>>
>
> Untested patch would be :
>
Yeah, it makes sense. I'm still seeing the corruption after applying
your patch.
However, maybe we are onto something. I'll see about taking a closer
look and give this some more thought.
Thanks for the hint!
--
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* Re: [PATCH v2] PPC: bpf_jit_comp: add SKF_AD_PKTTYPE instruction
From: Daniel Borkmann @ 2014-11-01 18:40 UTC (permalink / raw)
To: Denis Kirjanov
Cc: Alexei Starovoitov, Denis Kirjanov, netdev@vger.kernel.org,
linuxppc-dev, Michael Ellerman, Matt Evans
In-Reply-To: <CAHj3AVkpouHa1y0jt9c5dyYvnd6dctociTMW1ORdxaKdsFEbhQ@mail.gmail.com>
On 10/31/2014 07:09 AM, Denis Kirjanov wrote:
> On 10/30/14, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
>> On Wed, Oct 29, 2014 at 11:12 PM, Denis Kirjanov <kda@linux-powerpc.org>
>> wrote:
>>> Add BPF extension SKF_AD_PKTTYPE to ppc JIT to load
>>> skb->pkt_type field.
>>>
>>> Before:
>>> [ 88.262622] test_bpf: #11 LD_IND_NET 86 97 99 PASS
>>> [ 88.265740] test_bpf: #12 LD_PKTTYPE 109 107 PASS
>>>
>>> After:
>>> [ 80.605964] test_bpf: #11 LD_IND_NET 44 40 39 PASS
>>> [ 80.607370] test_bpf: #12 LD_PKTTYPE 9 9 PASS
>>
>> if you'd only quoted #12, it would all make sense ;)
>> but #11 test is not using PKTTYPE. So your patch shouldn't
>> make a difference. Are these numbers with JIT on and off?
>
> Right.
Ok.
Please mention this in future log messages, as it was not quite
clear that "before" was actually with JIT off, and "after" was
with JIT on.
One could have read it that actually both cases were with JIT on,
and thus the inconsistent result for LD_IND_NET is a bit confusing
since you've quoted it here as well.
^ permalink raw reply
* Re: [PATCH v2] PPC: bpf_jit_comp: add SKF_AD_PKTTYPE instruction
From: Daniel Borkmann @ 2014-11-01 18:31 UTC (permalink / raw)
To: David Miller; +Cc: kda, alexei.starovoitov, netdev, linuxppc-dev, mpe, matt
In-Reply-To: <20141101.140035.13626854970331774.davem@davemloft.net>
On 11/01/2014 07:00 PM, David Miller wrote:
> From: Denis Kirjanov <kda@linux-powerpc.org>
> Date: Sat, 1 Nov 2014 21:49:27 +0400
>
>> David, you need a feedback from other guys to apply this patch, right?
>>
>> Alexei wanted some output before/after the patch.
>> Michael Ellerman wanted the explanation what a BPF_ANC | SKF_AD_PKTTYPE means.
The BPF_ANC | SKF_AD_PKTTYPE case means that this is an ancillary
operation aka BPF extension which loads the value of skb->pkt_type
into the accumulator.
A similar transformation, that is, from BPF into eBPF insns can be
found in convert_bpf_extensions() in the SKF_AD_PKTTYPE case, or
commit 709f6c58d4dc ("sparc: bpf_jit: add SKF_AD_PKTTYPE support
to JIT") that recently enabled the same in sparc.
>> So I'm waiting the ack/nack from them...
>
> I don't really think performance metrics are necessary just for adding
> SKF_AD_PKTTYPE support, that's sort of an over the top requirement
> if you ask me.
Right, lib/test_bpf.c actually brings the quoted output w/ numbers
for free. I think the important point was that the 'After:' case
with ``echo 1 > /proc/sys/net/core/bpf_jit_enable'' runs through for
that test case, which has been shown here.
> It's pretty obvious that we should support as many operations as
> possible to each JIT, because all of program has to do is use that
> unsupported opcode and then we have none of that program being JIT'd.
^ permalink raw reply
* Re: [PATCH 0/1] mv643xx_eth: Disable TSO by default
From: Eric Dumazet @ 2014-11-01 18:01 UTC (permalink / raw)
To: Thomas Petazzoni
Cc: Ezequiel Garcia, netdev, David Miller, Gregory Clement,
Tawfik Bayouk, Lior Amsalem, Nadav Haklai
In-Reply-To: <20141101183300.0c04125d@free-electrons.com>
On Sat, 2014-11-01 at 18:33 +0100, Thomas Petazzoni wrote:
> Dear Eric Dumazet,
You can call me Eric ;)
> As far as I know, ARMv5 does not do out-of-order execution, and so on
> ARMv5, mb() == rmb() == wmb() == barrier(). But might be a missing
> compiler barrier, indeed, as that's not specific to the architecture.
>
> Thanks for the hint!
I think the wmb() is needed, but the more worrying problem is the NIC
can start transmitting a segment while the data payload is not yet
placed in TX descriptor.
Normally, the patch I cooked should avoid this.
^ permalink raw reply
* Re: [PATCH v2] PPC: bpf_jit_comp: add SKF_AD_PKTTYPE instruction
From: David Miller @ 2014-11-01 18:00 UTC (permalink / raw)
To: kda; +Cc: alexei.starovoitov, netdev, linuxppc-dev, mpe, matt
In-Reply-To: <CAOJe8K2FzuPTZ5pch8_UK7X==+=k8RKLnfz0mZb2hca19aU4pg@mail.gmail.com>
From: Denis Kirjanov <kda@linux-powerpc.org>
Date: Sat, 1 Nov 2014 21:49:27 +0400
> David, you need a feedback from other guys to apply this patch, right?
>
> Alexei wanted some output before/after the patch.
> Michael Ellerman wanted the explanation what a BPF_ANC | SKF_AD_PKTTYPE means.
> So I'm waiting the ack/nack from them...
I don't really think performance metrics are necessary just for adding
SKF_AD_PKTTYPE support, that's sort of an over the top requirement
if you ask me.
It's pretty obvious that we should support as many operations as
possible to each JIT, because all of program has to do is use that
unsupported opcode and then we have none of that program being JIT'd.
^ permalink raw reply
* Re: [PATCH v2] PPC: bpf_jit_comp: add SKF_AD_PKTTYPE instruction
From: Denis Kirjanov @ 2014-11-01 17:49 UTC (permalink / raw)
To: David Miller; +Cc: netdev, alexei.starovoitov, matt, linuxppc-dev
In-Reply-To: <20141101.133957.1365371956675094081.davem@davemloft.net>
David, you need a feedback from other guys to apply this patch, right?
Alexei wanted some output before/after the patch.
Michael Ellerman wanted the explanation what a BPF_ANC | SKF_AD_PKTTYPE means.
So I'm waiting the ack/nack from them...
On 11/1/14, David Miller <davem@davemloft.net> wrote:
> From: Denis Kirjanov <kda@linux-powerpc.org>
> Date: Sat, 1 Nov 2014 20:19:09 +0400
>
>> ping
>
> What specifically are you waiting for?
>
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH 0/1] mv643xx_eth: Disable TSO by default
From: David Miller @ 2014-11-01 17:42 UTC (permalink / raw)
To: eric.dumazet
Cc: ezequiel.garcia, netdev, thomas.petazzoni, gregory.clement,
tawfik, alior, nadavh
In-Reply-To: <1414862766.31792.7.camel@edumazet-glaptop2.roam.corp.google.com>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sat, 01 Nov 2014 10:26:06 -0700
> On Sat, 2014-11-01 at 12:30 -0300, Ezequiel Garcia wrote:
>> Several users ([1], [2]) have been reporting data corruption with TSO on
>> Kirkwood platforms (i.e. using the mv643xx_eth driver).
>>
>> Until we manage to find what's causing this, this simple patch will make
>> the TSO path disabled by default. This patch should be queued for stable,
>> fixing the TSO feature introduced in v3.16.
>>
>> The corruption itself is very easy to reproduce: checking md5sum on a mounted
>> NFS directory gives a different result each time. Same tests using the mvneta
>> driver (Armada 370/38x/XP SoC) pass with no issues.
>>
>> Frankly, I'm a bit puzzled about this, and so any ideas or debugging hints
>> are well received.
>
> lack of barriers maybe ?
>
> It seems you might need to populate all TX descriptors but delay the
> first, like doing the populate in descending order.
>
> If you take a look at txq_submit_skb(), you'll see the final
> desc->cmd_sts = cmd_sts (line 959) is done _after_ frags were cooked by
> txq_submit_frag_skb()
>
> You should kick the nick only when all TX descriptors are ready and
> committed to memory.
Yes, please look into whether doing something like this fixes the
problem.
^ permalink raw reply
* Re: [stable request <= 3.11] net/mlx4_en: Fix BlueFlame race
From: David Miller @ 2014-11-01 17:41 UTC (permalink / raw)
To: cwang; +Cc: ben, vlee, amirv, ogerlitz, jackm, eugenia, matanb, netdev
In-Reply-To: <CAHA+R7OyLv2YO8AduNhnEgW3RyYZwWNEHY6W-v_HXgVT9AOaKw@mail.gmail.com>
From: Cong Wang <cwang@twopensource.com>
Date: Sat, 1 Nov 2014 10:17:43 -0700
> On Fri, Oct 31, 2014 at 6:29 PM, Ben Hutchings <ben@decadent.org.uk> wrote:
>> On Sat, 2014-10-18 at 14:14 -0700, Vinson Lee wrote:
>>> Hi.
>>>
>>> Please consider backporting upstream commit
>>> 2d4b646613d6b12175b017aca18113945af1faf3 "net/mlx4_en: Fix BlueFlame
>>> race" to stable kernels <= 3.11.
>>>
>>> commit 2d4b646613d6b12175b017aca18113945af1faf3
>>> Author: Eugenia Emantayev <eugenia@mellanox.com>
>>> Date: Thu Jul 25 19:21:23 2013 +0300
>>>
>>> net/mlx4_en: Fix BlueFlame race
>> [...]
>>
>> David doesn't support anything older than 3.12 now, so you should send
>> requests for older stable branches directly to the stable list.
>
> Interesting, is there a document saying which stable kernels netdev
> supports? and how are they chosen?
>
> I thought netdev supports all -stable maintainers support.
>
> Anyway, we will send the request directly to Greg then.
There is no documented way nor do I wish to state anything so strictly.
I want maximum flexibility for such a time consuming task.
I tend to go back 3 or 4 releases at most, and it really depends upon
the difficulty of the backports and my own time constraints.
^ permalink raw reply
* Re: [PATCH 1/1] net: mv643xx_eth: Make TSO disabled by default
From: David Miller @ 2014-11-01 17:40 UTC (permalink / raw)
To: thomas.petazzoni
Cc: ezequiel.garcia, netdev, gregory.clement, tawfik, alior, nadavh
In-Reply-To: <20141101180037.087b7a95@free-electrons.com>
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Date: Sat, 1 Nov 2014 18:00:37 +0100
> Dear Ezequiel Garcia,
>
> On Sat, 1 Nov 2014 12:30:20 -0300, Ezequiel Garcia wrote:
>> Data corruption has been observed to be produced by TSO. For instance,
>> accessing files on a NFS-server with TSO enabled results in different data
>> transferred each time.
>>
>> This has been observed only on Kirkwood platforms, i.e. with the mv643xx_eth
>> driver. Same tests on platforms using the mvneta ethernet driver have
>> passed without errors.
>>
>> Make TSO disabled by default for now, until we can found a proper fix
>> for the regression.
>>
>> Fixes: 3ae8f4e0b98 ('net: mv643xx_eth: Implement software TSO')
>> Reported-by: Slawomir Gajzner <slawomir.gajzner@gmail.com>
>> Reported-by: Julien D'Ascenzio <jdascenzio@yahoo.fr>
>> Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
>
> Shouldn't you have a:
>
> Cc: <stable@vger.kernel.org> # v3.16+
Networking patches do not get sent to -stable that way.
Instead, people specifically request that I queue up the change
for -stable and I submit it by hand at the appropriate time.
^ permalink raw reply
* Re: [PATCH v2] PPC: bpf_jit_comp: add SKF_AD_PKTTYPE instruction
From: David Miller @ 2014-11-01 17:39 UTC (permalink / raw)
To: kda; +Cc: kirjanov, alexei.starovoitov, netdev, linuxppc-dev, mpe, matt
In-Reply-To: <CAOJe8K31iB9+7c1BnS=6DdriU08WUisM7sYgj8nOBo4Fg=XUBg@mail.gmail.com>
From: Denis Kirjanov <kda@linux-powerpc.org>
Date: Sat, 1 Nov 2014 20:19:09 +0400
> ping
What specifically are you waiting for?
^ permalink raw reply
* Re: [PATCH 0/1] mv643xx_eth: Disable TSO by default
From: Eric Dumazet @ 2014-11-01 17:37 UTC (permalink / raw)
To: Ezequiel Garcia
Cc: netdev, David Miller, Thomas Petazzoni, Gregory Clement,
Tawfik Bayouk, Lior Amsalem, Nadav Haklai
In-Reply-To: <1414862766.31792.7.camel@edumazet-glaptop2.roam.corp.google.com>
On Sat, 2014-11-01 at 10:26 -0700, Eric Dumazet wrote:
> On Sat, 2014-11-01 at 12:30 -0300, Ezequiel Garcia wrote:
> > Several users ([1], [2]) have been reporting data corruption with TSO on
> > Kirkwood platforms (i.e. using the mv643xx_eth driver).
> >
> > Until we manage to find what's causing this, this simple patch will make
> > the TSO path disabled by default. This patch should be queued for stable,
> > fixing the TSO feature introduced in v3.16.
> >
> > The corruption itself is very easy to reproduce: checking md5sum on a mounted
> > NFS directory gives a different result each time. Same tests using the mvneta
> > driver (Armada 370/38x/XP SoC) pass with no issues.
> >
> > Frankly, I'm a bit puzzled about this, and so any ideas or debugging hints
> > are well received.
>
> lack of barriers maybe ?
>
> It seems you might need to populate all TX descriptors but delay the
> first, like doing the populate in descending order.
>
> If you take a look at txq_submit_skb(), you'll see the final
> desc->cmd_sts = cmd_sts (line 959) is done _after_ frags were cooked by
> txq_submit_frag_skb()
>
> You should kick the nick only when all TX descriptors are ready and
> committed to memory.
>
Untested patch would be :
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index b151a949f352a20ec8e74b4f3a7b6bb194ce841c..44789cc9a263992f91e46006d7e12703a2824cb4 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -773,7 +773,8 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq,
}
static inline void
-txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length)
+txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length,
+ struct tx_desc **pdesc, u32 *cmd)
{
struct mv643xx_eth_private *mp = txq_to_mp(txq);
int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
@@ -797,9 +798,13 @@ txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length)
desc->byte_cnt = hdr_len;
desc->buf_ptr = txq->tso_hdrs_dma +
txq->tx_curr_desc * TSO_HEADER_SIZE;
- desc->cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA | TX_FIRST_DESC |
- GEN_CRC;
-
+ cmd_csum |= BUFFER_OWNED_BY_DMA | TX_FIRST_DESC | GEN_CRC;
+ if (*pdesc == NULL) {
+ *pdesc = desc;
+ *cmd = cmd_csum;
+ } else {
+ desc->cmd_sts = cmd_csum;
+ }
txq->tx_curr_desc++;
if (txq->tx_curr_desc == txq->tx_ring_size)
txq->tx_curr_desc = 0;
@@ -813,6 +818,8 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
int desc_count = 0;
struct tso_t tso;
int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ struct tx_desc *desc = NULL;
+ u32 cmd_sts = 0;
/* Count needed descriptors */
if ((txq->tx_desc_count + tso_count_descs(skb)) >= txq->tx_ring_size) {
@@ -834,7 +841,7 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
/* prepare packet headers: MAC + IP + TCP */
hdr = txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE;
tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0);
- txq_put_hdr_tso(skb, txq, data_left);
+ txq_put_hdr_tso(skb, txq, data_left, &desc, &cmd_sts);
while (data_left > 0) {
int size;
@@ -854,6 +861,10 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
__skb_queue_tail(&txq->tx_skb, skb);
skb_tx_timestamp(skb);
+ /* ensure all other descriptors are written before first cmd_sts */
+ wmb();
+ desc->cmd_sts = cmd_sts;
+
/* clear TX_END status */
mp->work_tx_end &= ~(1 << txq->index);
^ permalink raw reply related
* Re: [PATCH 0/1] mv643xx_eth: Disable TSO by default
From: Thomas Petazzoni @ 2014-11-01 17:33 UTC (permalink / raw)
To: Eric Dumazet
Cc: Ezequiel Garcia, netdev, David Miller, Gregory Clement,
Tawfik Bayouk, Lior Amsalem, Nadav Haklai
In-Reply-To: <1414862766.31792.7.camel@edumazet-glaptop2.roam.corp.google.com>
Dear Eric Dumazet,
On Sat, 01 Nov 2014 10:26:06 -0700, Eric Dumazet wrote:
> On Sat, 2014-11-01 at 12:30 -0300, Ezequiel Garcia wrote:
> > Several users ([1], [2]) have been reporting data corruption with TSO on
> > Kirkwood platforms (i.e. using the mv643xx_eth driver).
> >
> > Until we manage to find what's causing this, this simple patch will make
> > the TSO path disabled by default. This patch should be queued for stable,
> > fixing the TSO feature introduced in v3.16.
> >
> > The corruption itself is very easy to reproduce: checking md5sum on a mounted
> > NFS directory gives a different result each time. Same tests using the mvneta
> > driver (Armada 370/38x/XP SoC) pass with no issues.
> >
> > Frankly, I'm a bit puzzled about this, and so any ideas or debugging hints
> > are well received.
>
> lack of barriers maybe ?
>
> It seems you might need to populate all TX descriptors but delay the
> first, like doing the populate in descending order.
>
> If you take a look at txq_submit_skb(), you'll see the final
> desc->cmd_sts = cmd_sts (line 959) is done _after_ frags were cooked by
> txq_submit_frag_skb()
>
> You should kick the nick only when all TX descriptors are ready and
> committed to memory.
As far as I know, ARMv5 does not do out-of-order execution, and so on
ARMv5, mb() == rmb() == wmb() == barrier(). But might be a missing
compiler barrier, indeed, as that's not specific to the architecture.
Thanks for the hint!
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH 0/1] mv643xx_eth: Disable TSO by default
From: Eric Dumazet @ 2014-11-01 17:26 UTC (permalink / raw)
To: Ezequiel Garcia
Cc: netdev, David Miller, Thomas Petazzoni, Gregory Clement,
Tawfik Bayouk, Lior Amsalem, Nadav Haklai
In-Reply-To: <1414855820-15094-1-git-send-email-ezequiel.garcia@free-electrons.com>
On Sat, 2014-11-01 at 12:30 -0300, Ezequiel Garcia wrote:
> Several users ([1], [2]) have been reporting data corruption with TSO on
> Kirkwood platforms (i.e. using the mv643xx_eth driver).
>
> Until we manage to find what's causing this, this simple patch will make
> the TSO path disabled by default. This patch should be queued for stable,
> fixing the TSO feature introduced in v3.16.
>
> The corruption itself is very easy to reproduce: checking md5sum on a mounted
> NFS directory gives a different result each time. Same tests using the mvneta
> driver (Armada 370/38x/XP SoC) pass with no issues.
>
> Frankly, I'm a bit puzzled about this, and so any ideas or debugging hints
> are well received.
lack of barriers maybe ?
It seems you might need to populate all TX descriptors but delay the
first, like doing the populate in descending order.
If you take a look at txq_submit_skb(), you'll see the final
desc->cmd_sts = cmd_sts (line 959) is done _after_ frags were cooked by
txq_submit_frag_skb()
You should kick the nick only when all TX descriptors are ready and
committed to memory.
^ 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