Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2017-12-11 11:19:16 +0100
committerJiri Kosina <jkosina@suse.cz>2017-12-11 11:19:16 +0100
commit62cf71e0941c0b6f90ed219c0bea1fed7ad5c6cb (patch)
tree3ea78aa8cf35c126aa4f89e51f5e48604775f3bf
parent3ecb999be51f2fd327b07d3f26eb661fa868a804 (diff)
parent6e1c320dc6e366134bb150dae7dca498811b6f36 (diff)
Merge remote-tracking branch 'origin/users/mkubecek/SLE15/for-next' into SLE15
-rw-r--r--patches.fixes/net-Remove-unused-skb_shared_info-member.patch90
-rw-r--r--patches.fixes/net-accept-UFO-datagrams-from-tuntap-and-packet.patch546
-rw-r--r--patches.fixes/net-openvswitch-datapath-fix-data-type-in-queue_gso_.patch46
-rw-r--r--patches.fixes/netfilter-ebtables-fix-race-condition-in-frame_filte.patch146
-rw-r--r--series.conf16
5 files changed, 838 insertions, 6 deletions
diff --git a/patches.fixes/net-Remove-unused-skb_shared_info-member.patch b/patches.fixes/net-Remove-unused-skb_shared_info-member.patch
new file mode 100644
index 0000000000..d638e56cd9
--- /dev/null
+++ b/patches.fixes/net-Remove-unused-skb_shared_info-member.patch
@@ -0,0 +1,90 @@
+From: Mat Martineau <mathew.j.martineau@linux.intel.com>
+Date: Fri, 10 Nov 2017 14:03:51 -0800
+Subject: net: Remove unused skb_shared_info member
+Patch-mainline: v4.15-rc1
+Git-commit: 39b175211053c7a6a4d794c42e225994f1c069c2
+References: bsc#1066757
+
+ip6_frag_id was only used by UFO, which has been removed.
+ipv6_proxy_select_ident() only existed to set ip6_frag_id and has no
+in-tree callers.
+
+Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Acked-by: Michal Kubecek <mkubecek@suse.cz>
+
+---
+ include/linux/skbuff.h | 1 -
+ include/net/ipv6.h | 1 -
+ net/ipv6/output_core.c | 31 -------------------------------
+ 3 files changed, 33 deletions(-)
+
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index a6162fba327b..b20e4dcbcda1 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -425,7 +425,6 @@ struct skb_shared_info {
+ struct skb_shared_hwtstamps hwtstamps;
+ unsigned int gso_type;
+ u32 tskey;
+- __be32 ip6_frag_id;
+
+ /*
+ * Warning : all fields before dataref are cleared in __alloc_skb()
+diff --git a/include/net/ipv6.h b/include/net/ipv6.h
+index 3e505bbff8ca..305b136ccfcf 100644
+--- a/include/net/ipv6.h
++++ b/include/net/ipv6.h
+@@ -726,7 +726,6 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add
+ __be32 ipv6_select_ident(struct net *net,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr);
+-void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb);
+
+ int ip6_dst_hoplimit(struct dst_entry *dst);
+
+diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
+index a338bbc33cf3..4a7e5ffa5108 100644
+--- a/net/ipv6/output_core.c
++++ b/net/ipv6/output_core.c
+@@ -31,37 +31,6 @@ static u32 __ipv6_select_ident(struct net *net, u32 hashrnd,
+ return id;
+ }
+
+-/* This function exists only for tap drivers that must support broken
+- * clients requesting UFO without specifying an IPv6 fragment ID.
+- *
+- * This is similar to ipv6_select_ident() but we use an independent hash
+- * seed to limit information leakage.
+- *
+- * The network header must be set before calling this.
+- */
+-void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
+-{
+- static u32 ip6_proxy_idents_hashrnd __read_mostly;
+- struct in6_addr buf[2];
+- struct in6_addr *addrs;
+- u32 id;
+-
+- addrs = skb_header_pointer(skb,
+- skb_network_offset(skb) +
+- offsetof(struct ipv6hdr, saddr),
+- sizeof(buf), buf);
+- if (!addrs)
+- return;
+-
+- net_get_random_once(&ip6_proxy_idents_hashrnd,
+- sizeof(ip6_proxy_idents_hashrnd));
+-
+- id = __ipv6_select_ident(net, ip6_proxy_idents_hashrnd,
+- &addrs[1], &addrs[0]);
+- skb_shinfo(skb)->ip6_frag_id = htonl(id);
+-}
+-EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
+-
+ __be32 ipv6_select_ident(struct net *net,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr)
+--
+2.15.1
+
diff --git a/patches.fixes/net-accept-UFO-datagrams-from-tuntap-and-packet.patch b/patches.fixes/net-accept-UFO-datagrams-from-tuntap-and-packet.patch
new file mode 100644
index 0000000000..d86a125a4a
--- /dev/null
+++ b/patches.fixes/net-accept-UFO-datagrams-from-tuntap-and-packet.patch
@@ -0,0 +1,546 @@
+From: Willem de Bruijn <willemb@google.com>
+Date: Tue, 21 Nov 2017 10:22:25 -0500
+Subject: net: accept UFO datagrams from tuntap and packet
+Patch-mainline: v4.15-rc1
+Git-commit: 0c19f846d582af919db66a5914a0189f9f92c936
+References: bsc#1066757
+
+Tuntap and similar devices can inject GSO packets. Accept type
+VIRTIO_NET_HDR_GSO_UDP, even though not generating UFO natively.
+
+Processes are expected to use feature negotiation such as TUNSETOFFLOAD
+to detect supported offload types and refrain from injecting other
+packets. This process breaks down with live migration: guest kernels
+do not renegotiate flags, so destination hosts need to expose all
+features that the source host does.
+
+Partially revert the UFO removal from 182e0b6b5846~1..d9d30adf5677.
+This patch introduces nearly(*) no new code to simplify verification.
+It brings back verbatim tuntap UFO negotiation, VIRTIO_NET_HDR_GSO_UDP
+insertion and software UFO segmentation.
+
+It does not reinstate protocol stack support, hardware offload
+(NETIF_F_UFO), SKB_GSO_UDP tunneling in SKB_GSO_SOFTWARE or reception
+of VIRTIO_NET_HDR_GSO_UDP packets in tuntap.
+
+To support SKB_GSO_UDP reappearing in the stack, also reinstate
+logic in act_csum and openvswitch. Achieve equivalence with v4.13 HEAD
+by squashing in commit 939912216fa8 ("net: skb_needs_check() removes
+CHECKSUM_UNNECESSARY check for tx.") and reverting commit 8d63bee643f1
+("net: avoid skb_warn_bad_offload false positives on UFO").
+
+(*) To avoid having to bring back skb_shinfo(skb)->ip6_frag_id,
+ipv6_proxy_select_ident is changed to return a __be32 and this is
+assigned directly to the frag_hdr. Also, SKB_GSO_UDP is inserted
+at the end of the enum to minimize code churn.
+
+Tested
+ Booted a v4.13 guest kernel with QEMU. On a host kernel before this
+ patch `ethtool -k eth0` shows UFO disabled. After the patch, it is
+ enabled, same as on a v4.13 host kernel.
+
+ A UFO packet sent from the guest appears on the tap device:
+ host:
+ nc -l -p -u 8000 &
+ tcpdump -n -i tap0
+
+ guest:
+ dd if=/dev/zero of=payload.txt bs=1 count=2000
+ nc -u 192.16.1.1 8000 < payload.txt
+
+ Direct tap to tap transmission of VIRTIO_NET_HDR_GSO_UDP succeeds,
+ packets arriving fragmented:
+
+ ./with_tap_pair.sh ./tap_send_ufo tap0 tap1
+ (from https://github.com/wdebruij/kerneltools/tree/master/tests)
+
+Changes
+ v1 -> v2
+ - simplified set_offload change (review comment)
+ - documented test procedure
+
+Link: http://lkml.kernel.org/r/<CAF=yD-LuUeDuL9YWPJD9ykOZ0QCjNeznPDr6whqZ9NGMNF12Mw@mail.gmail.com>
+Fixes: fb652fdfe837 ("macvlan/macvtap: Remove NETIF_F_UFO advertisement.")
+Reported-by: Michal Kubecek <mkubecek@suse.cz>
+Signed-off-by: Willem de Bruijn <willemb@google.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Acked-by: Michal Kubecek <mkubecek@suse.cz>
+
+---
+ drivers/net/tap.c | 2 +-
+ drivers/net/tun.c | 2 +
+ include/linux/netdev_features.h | 4 +-
+ include/linux/netdevice.h | 1 +
+ include/linux/skbuff.h | 2 +
+ include/linux/virtio_net.h | 5 ++-
+ include/net/ipv6.h | 1 +
+ net/ipv4/af_inet.c | 12 +++++-
+ net/ipv4/udp_offload.c | 49 ++++++++++++++++++++++--
+ net/ipv6/output_core.c | 31 +++++++++++++++
+ net/ipv6/udp_offload.c | 85 +++++++++++++++++++++++++++++++++++++++--
+ net/openvswitch/datapath.c | 14 +++++++
+ net/openvswitch/flow.c | 6 ++-
+ net/sched/act_csum.c | 6 +++
+ 14 files changed, 207 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/tap.c b/drivers/net/tap.c
+index 46015c984d09..7ba9b3eaa29e 100644
+--- a/drivers/net/tap.c
++++ b/drivers/net/tap.c
+@@ -1072,7 +1072,7 @@ static long tap_ioctl(struct file *file, unsigned int cmd,
+ case TUNSETOFFLOAD:
+ /* let the user check for future flags */
+ if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
+- TUN_F_TSO_ECN))
++ TUN_F_TSO_ECN | TUN_F_UFO))
+ return -EINVAL;
+
+ rtnl_lock();
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index e662e575766a..b89ac3de8195 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -1921,6 +1921,8 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
+ features |= NETIF_F_TSO6;
+ arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
+ }
++
++ arg &= ~TUN_F_UFO;
+ }
+
+ /* This gives the user a way to test for new features in future by
+diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
+index ebd273627334..d96aa944ef4d 100644
+--- a/include/linux/netdev_features.h
++++ b/include/linux/netdev_features.h
+@@ -54,8 +54,9 @@ enum {
+ NETIF_F_GSO_TUNNEL_REMCSUM_BIT, /* ... TUNNEL with TSO & REMCSUM */
+ NETIF_F_GSO_SCTP_BIT, /* ... SCTP fragmentation */
+ NETIF_F_GSO_ESP_BIT, /* ... ESP with TSO */
++ NETIF_F_GSO_UDP_BIT, /* ... UFO, deprecated except tuntap */
+ /**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */
+- NETIF_F_GSO_ESP_BIT,
++ NETIF_F_GSO_UDP_BIT,
+
+ NETIF_F_FCOE_CRC_BIT, /* FCoE CRC32 */
+ NETIF_F_SCTP_CRC_BIT, /* SCTP checksum offload */
+@@ -131,6 +132,7 @@ enum {
+ #define NETIF_F_GSO_TUNNEL_REMCSUM __NETIF_F(GSO_TUNNEL_REMCSUM)
+ #define NETIF_F_GSO_SCTP __NETIF_F(GSO_SCTP)
+ #define NETIF_F_GSO_ESP __NETIF_F(GSO_ESP)
++#define NETIF_F_GSO_UDP __NETIF_F(GSO_UDP)
+ #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 bb78bfe517b7..8d9d2f1e0e67 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -4096,6 +4096,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
+ BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != (NETIF_F_GSO_TUNNEL_REMCSUM >> NETIF_F_GSO_SHIFT));
+ BUILD_BUG_ON(SKB_GSO_SCTP != (NETIF_F_GSO_SCTP >> NETIF_F_GSO_SHIFT));
+ BUILD_BUG_ON(SKB_GSO_ESP != (NETIF_F_GSO_ESP >> NETIF_F_GSO_SHIFT));
++ BUILD_BUG_ON(SKB_GSO_UDP != (NETIF_F_GSO_UDP >> NETIF_F_GSO_SHIFT));
+
+ return (features & feature) == feature;
+ }
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index b20e4dcbcda1..4aba51863fd4 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -494,6 +494,8 @@ enum {
+ SKB_GSO_SCTP = 1 << 14,
+
+ SKB_GSO_ESP = 1 << 15,
++
++ SKB_GSO_UDP = 1 << 16,
+ };
+
+ #if BITS_PER_LONG > 32
+diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
+index 32fb046f2173..3d88769c32e4 100644
+--- a/include/linux/virtio_net.h
++++ b/include/linux/virtio_net.h
+@@ -8,7 +8,7 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
+ const struct virtio_net_hdr *hdr,
+ bool little_endian)
+ {
+- unsigned short gso_type = 0;
++ unsigned int gso_type = 0;
+
+ if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
+ switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
+@@ -18,6 +18,9 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
+ case VIRTIO_NET_HDR_GSO_TCPV6:
+ gso_type = SKB_GSO_TCPV6;
+ break;
++ case VIRTIO_NET_HDR_GSO_UDP:
++ gso_type = SKB_GSO_UDP;
++ break;
+ default:
+ return -EINVAL;
+ }
+diff --git a/include/net/ipv6.h b/include/net/ipv6.h
+index 305b136ccfcf..6366b0399025 100644
+--- a/include/net/ipv6.h
++++ b/include/net/ipv6.h
+@@ -726,6 +726,7 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add
+ __be32 ipv6_select_ident(struct net *net,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr);
++__be32 ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb);
+
+ int ip6_dst_hoplimit(struct dst_entry *dst);
+
+diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
+index eca25b9587f0..ab8ebd440423 100644
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -1219,9 +1219,10 @@ EXPORT_SYMBOL(inet_sk_rebuild_header);
+ struct sk_buff *inet_gso_segment(struct sk_buff *skb,
+ netdev_features_t features)
+ {
+- bool fixedid = false, gso_partial, encap;
++ bool udpfrag = false, fixedid = false, gso_partial, encap;
+ struct sk_buff *segs = ERR_PTR(-EINVAL);
+ const struct net_offload *ops;
++ unsigned int offset = 0;
+ struct iphdr *iph;
+ int proto, tot_len;
+ int nhoff;
+@@ -1256,6 +1257,7 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb,
+ segs = ERR_PTR(-EPROTONOSUPPORT);
+
+ if (!skb->encapsulation || encap) {
++ udpfrag = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP);
+ fixedid = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TCP_FIXEDID);
+
+ /* fixed ID is invalid if DF bit is not set */
+@@ -1275,7 +1277,13 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb,
+ skb = segs;
+ do {
+ iph = (struct iphdr *)(skb_mac_header(skb) + nhoff);
+- if (skb_is_gso(skb)) {
++ if (udpfrag) {
++ iph->frag_off = htons(offset >> 3);
++ if (skb->next)
++ iph->frag_off |= htons(IP_MF);
++ offset += skb->len - nhoff - ihl;
++ tot_len = skb->len - nhoff;
++ } else if (skb_is_gso(skb)) {
+ if (!fixedid) {
+ iph->id = htons(id);
+ id += skb_shinfo(skb)->gso_segs;
+diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
+index e360d55be555..01801b77bd0d 100644
+--- a/net/ipv4/udp_offload.c
++++ b/net/ipv4/udp_offload.c
+@@ -187,16 +187,57 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
+ }
+ EXPORT_SYMBOL(skb_udp_tunnel_segment);
+
+-static struct sk_buff *udp4_tunnel_segment(struct sk_buff *skb,
+- netdev_features_t features)
++static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
++ netdev_features_t features)
+ {
+ struct sk_buff *segs = ERR_PTR(-EINVAL);
++ unsigned int mss;
++ __wsum csum;
++ struct udphdr *uh;
++ struct iphdr *iph;
+
+ if (skb->encapsulation &&
+ (skb_shinfo(skb)->gso_type &
+- (SKB_GSO_UDP_TUNNEL|SKB_GSO_UDP_TUNNEL_CSUM)))
++ (SKB_GSO_UDP_TUNNEL|SKB_GSO_UDP_TUNNEL_CSUM))) {
+ segs = skb_udp_tunnel_segment(skb, features, false);
++ goto out;
++ }
++
++ if (!pskb_may_pull(skb, sizeof(struct udphdr)))
++ goto out;
++
++ mss = skb_shinfo(skb)->gso_size;
++ if (unlikely(skb->len <= mss))
++ goto out;
++
++ /* Do software UFO. Complete and fill in the UDP checksum as
++ * HW cannot do checksum of UDP packets sent as multiple
++ * IP fragments.
++ */
+
++ uh = udp_hdr(skb);
++ iph = ip_hdr(skb);
++
++ uh->check = 0;
++ csum = skb_checksum(skb, 0, skb->len, 0);
++ uh->check = udp_v4_check(skb->len, iph->saddr, iph->daddr, csum);
++ if (uh->check == 0)
++ uh->check = CSUM_MANGLED_0;
++
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++ /* If there is no outer header we can fake a checksum offload
++ * due to the fact that we have already done the checksum in
++ * software prior to segmenting the frame.
++ */
++ if (!skb->encap_hdr_csum)
++ features |= NETIF_F_HW_CSUM;
++
++ /* Fragment the skb. IP headers of the fragments are updated in
++ * inet_gso_segment()
++ */
++ segs = skb_segment(skb, features);
++out:
+ return segs;
+ }
+
+@@ -330,7 +371,7 @@ static int udp4_gro_complete(struct sk_buff *skb, int nhoff)
+
+ static const struct net_offload udpv4_offload = {
+ .callbacks = {
+- .gso_segment = udp4_tunnel_segment,
++ .gso_segment = udp4_ufo_fragment,
+ .gro_receive = udp4_gro_receive,
+ .gro_complete = udp4_gro_complete,
+ },
+diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
+index 4a7e5ffa5108..4fe7c90962dd 100644
+--- a/net/ipv6/output_core.c
++++ b/net/ipv6/output_core.c
+@@ -31,6 +31,37 @@ static u32 __ipv6_select_ident(struct net *net, u32 hashrnd,
+ return id;
+ }
+
++/* This function exists only for tap drivers that must support broken
++ * clients requesting UFO without specifying an IPv6 fragment ID.
++ *
++ * This is similar to ipv6_select_ident() but we use an independent hash
++ * seed to limit information leakage.
++ *
++ * The network header must be set before calling this.
++ */
++__be32 ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
++{
++ static u32 ip6_proxy_idents_hashrnd __read_mostly;
++ struct in6_addr buf[2];
++ struct in6_addr *addrs;
++ u32 id;
++
++ addrs = skb_header_pointer(skb,
++ skb_network_offset(skb) +
++ offsetof(struct ipv6hdr, saddr),
++ sizeof(buf), buf);
++ if (!addrs)
++ return 0;
++
++ net_get_random_once(&ip6_proxy_idents_hashrnd,
++ sizeof(ip6_proxy_idents_hashrnd));
++
++ id = __ipv6_select_ident(net, ip6_proxy_idents_hashrnd,
++ &addrs[1], &addrs[0]);
++ return htonl(id);
++}
++EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
++
+ __be32 ipv6_select_ident(struct net *net,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr)
+diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
+index 455fd4e39333..a0f89ad76f9d 100644
+--- a/net/ipv6/udp_offload.c
++++ b/net/ipv6/udp_offload.c
+@@ -17,15 +17,94 @@
+ #include <net/ip6_checksum.h>
+ #include "ip6_offload.h"
+
+-static struct sk_buff *udp6_tunnel_segment(struct sk_buff *skb,
+- netdev_features_t features)
++static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
++ netdev_features_t features)
+ {
+ struct sk_buff *segs = ERR_PTR(-EINVAL);
++ unsigned int mss;
++ unsigned int unfrag_ip6hlen, unfrag_len;
++ struct frag_hdr *fptr;
++ u8 *packet_start, *prevhdr;
++ u8 nexthdr;
++ u8 frag_hdr_sz = sizeof(struct frag_hdr);
++ __wsum csum;
++ int tnl_hlen;
++ int err;
++
++ mss = skb_shinfo(skb)->gso_size;
++ if (unlikely(skb->len <= mss))
++ goto out;
+
+ if (skb->encapsulation && skb_shinfo(skb)->gso_type &
+ (SKB_GSO_UDP_TUNNEL|SKB_GSO_UDP_TUNNEL_CSUM))
+ segs = skb_udp_tunnel_segment(skb, features, true);
++ else {
++ const struct ipv6hdr *ipv6h;
++ struct udphdr *uh;
++
++ if (!pskb_may_pull(skb, sizeof(struct udphdr)))
++ goto out;
++
++ /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
++ * do checksum of UDP packets sent as multiple IP fragments.
++ */
++
++ uh = udp_hdr(skb);
++ ipv6h = ipv6_hdr(skb);
++
++ uh->check = 0;
++ csum = skb_checksum(skb, 0, skb->len, 0);
++ uh->check = udp_v6_check(skb->len, &ipv6h->saddr,
++ &ipv6h->daddr, csum);
++ if (uh->check == 0)
++ uh->check = CSUM_MANGLED_0;
++
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++ /* If there is no outer header we can fake a checksum offload
++ * due to the fact that we have already done the checksum in
++ * software prior to segmenting the frame.
++ */
++ if (!skb->encap_hdr_csum)
++ features |= NETIF_F_HW_CSUM;
++
++ /* Check if there is enough headroom to insert fragment header. */
++ tnl_hlen = skb_tnl_header_len(skb);
++ if (skb->mac_header < (tnl_hlen + frag_hdr_sz)) {
++ if (gso_pskb_expand_head(skb, tnl_hlen + frag_hdr_sz))
++ goto out;
++ }
++
++ /* Find the unfragmentable header and shift it left by frag_hdr_sz
++ * bytes to insert fragment header.
++ */
++ err = ip6_find_1stfragopt(skb, &prevhdr);
++ if (err < 0)
++ return ERR_PTR(err);
++ unfrag_ip6hlen = err;
++ nexthdr = *prevhdr;
++ *prevhdr = NEXTHDR_FRAGMENT;
++ unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) +
++ unfrag_ip6hlen + tnl_hlen;
++ packet_start = (u8 *) skb->head + SKB_GSO_CB(skb)->mac_offset;
++ memmove(packet_start-frag_hdr_sz, packet_start, unfrag_len);
++
++ SKB_GSO_CB(skb)->mac_offset -= frag_hdr_sz;
++ skb->mac_header -= frag_hdr_sz;
++ skb->network_header -= frag_hdr_sz;
++
++ fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
++ fptr->nexthdr = nexthdr;
++ fptr->reserved = 0;
++ fptr->identification = ipv6_proxy_select_ident(dev_net(skb->dev), skb);
++
++ /* Fragment the skb. ipv6 header and the remaining fields of the
++ * fragment header are updated in ipv6_gso_segment()
++ */
++ segs = skb_segment(skb, features);
++ }
+
++out:
+ return segs;
+ }
+
+@@ -75,7 +154,7 @@ static int udp6_gro_complete(struct sk_buff *skb, int nhoff)
+
+ static const struct net_offload udpv6_offload = {
+ .callbacks = {
+- .gso_segment = udp6_tunnel_segment,
++ .gso_segment = udp6_ufo_fragment,
+ .gro_receive = udp6_gro_receive,
+ .gro_complete = udp6_gro_complete,
+ },
+diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
+index 9c4866641aa1..3c06600612b8 100644
+--- a/net/openvswitch/datapath.c
++++ b/net/openvswitch/datapath.c
+@@ -335,6 +335,8 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
+ const struct dp_upcall_info *upcall_info,
+ uint32_t cutlen)
+ {
++ unsigned short gso_type = skb_shinfo(skb)->gso_type;
++ struct sw_flow_key later_key;
+ struct sk_buff *segs, *nskb;
+ int err;
+
+@@ -345,9 +347,21 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
+ if (segs == NULL)
+ return -EINVAL;
+
++ if (gso_type & SKB_GSO_UDP) {
++ /* The initial flow key extracted by ovs_flow_key_extract()
++ * in this case is for a first fragment, so we need to
++ * properly mark later fragments.
++ */
++ later_key = *key;
++ later_key.ip.frag = OVS_FRAG_TYPE_LATER;
++ }
++
+ /* Queue all of the segments. */
+ skb = segs;
+ do {
++ if (gso_type & SKB_GSO_UDP && skb != segs)
++ key = &later_key;
++
+ err = queue_userspace_packet(dp, skb, key, upcall_info, cutlen);
+ if (err)
+ break;
+diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
+index 597d96faca45..3f76cb765e5b 100644
+--- a/net/openvswitch/flow.c
++++ b/net/openvswitch/flow.c
+@@ -584,7 +584,8 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+ key->ip.frag = OVS_FRAG_TYPE_LATER;
+ return 0;
+ }
+- if (nh->frag_off & htons(IP_MF))
++ if (nh->frag_off & htons(IP_MF) ||
++ skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
+ key->ip.frag = OVS_FRAG_TYPE_FIRST;
+ else
+ key->ip.frag = OVS_FRAG_TYPE_NONE;
+@@ -700,6 +701,9 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+
+ if (key->ip.frag == OVS_FRAG_TYPE_LATER)
+ return 0;
++ if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
++ key->ip.frag = OVS_FRAG_TYPE_FIRST;
++
+ /* Transport layer. */
+ if (key->ip.proto == NEXTHDR_TCP) {
+ if (tcphdr_ok(skb)) {
+diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
+index 67afc12df88b..3317a2f579da 100644
+--- a/net/sched/act_csum.c
++++ b/net/sched/act_csum.c
+@@ -231,6 +231,9 @@ static int tcf_csum_ipv4_udp(struct sk_buff *skb, unsigned int ihl,
+ const struct iphdr *iph;
+ u16 ul;
+
++ if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
++ return 1;
++
+ /*
+ * Support both UDP and UDPLITE checksum algorithms, Don't use
+ * udph->len to get the real length without any protocol check,
+@@ -284,6 +287,9 @@ static int tcf_csum_ipv6_udp(struct sk_buff *skb, unsigned int ihl,
+ const struct ipv6hdr *ip6h;
+ u16 ul;
+
++ if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
++ return 1;
++
+ /*
+ * Support both UDP and UDPLITE checksum algorithms, Don't use
+ * udph->len to get the real length without any protocol check,
+--
+2.15.1
+
diff --git a/patches.fixes/net-openvswitch-datapath-fix-data-type-in-queue_gso_.patch b/patches.fixes/net-openvswitch-datapath-fix-data-type-in-queue_gso_.patch
new file mode 100644
index 0000000000..6471dc3e23
--- /dev/null
+++ b/patches.fixes/net-openvswitch-datapath-fix-data-type-in-queue_gso_.patch
@@ -0,0 +1,46 @@
+From: "Gustavo A. R. Silva" <garsilva@embeddedor.com>
+Date: Sat, 25 Nov 2017 13:14:40 -0600
+Subject: net: openvswitch: datapath: fix data type in queue_gso_packets
+Patch-mainline: v4.15-rc2
+Git-commit: 2734166e89639c973c6e125ac8bcfc2d9db72b70
+References: bsc#1066757
+
+gso_type is being used in binary AND operations together with SKB_GSO_UDP.
+The issue is that variable gso_type is of type unsigned short and
+SKB_GSO_UDP expands to more than 16 bits:
+
+SKB_GSO_UDP = 1 << 16
+
+this makes any binary AND operation between gso_type and SKB_GSO_UDP to
+be always zero, hence making some code unreachable and likely causing
+undesired behavior.
+
+Fix this by changing the data type of variable gso_type to unsigned int.
+
+Addresses-Coverity-ID: 1462223
+Fixes: 0c19f846d582 ("net: accept UFO datagrams from tuntap and packet")
+Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
+Acked-by: Willem de Bruijn <willemb@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Acked-by: Michal Kubecek <mkubecek@suse.cz>
+
+---
+ net/openvswitch/datapath.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
+index 3c06600612b8..b26f37ef234b 100644
+--- a/net/openvswitch/datapath.c
++++ b/net/openvswitch/datapath.c
+@@ -335,7 +335,7 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
+ const struct dp_upcall_info *upcall_info,
+ uint32_t cutlen)
+ {
+- unsigned short gso_type = skb_shinfo(skb)->gso_type;
++ unsigned int gso_type = skb_shinfo(skb)->gso_type;
+ struct sw_flow_key later_key;
+ struct sk_buff *segs, *nskb;
+ int err;
+--
+2.15.1
+
diff --git a/patches.fixes/netfilter-ebtables-fix-race-condition-in-frame_filte.patch b/patches.fixes/netfilter-ebtables-fix-race-condition-in-frame_filte.patch
new file mode 100644
index 0000000000..ba136ce5b9
--- /dev/null
+++ b/patches.fixes/netfilter-ebtables-fix-race-condition-in-frame_filte.patch
@@ -0,0 +1,146 @@
+From: Artem Savkov <asavkov@redhat.com>
+Date: Tue, 26 Sep 2017 18:35:45 +0200
+Subject: netfilter: ebtables: fix race condition in frame_filter_net_init()
+Patch-mainline: v4.14-rc5
+Git-commit: e6b72ee88a56bcfe63f72e9c30766484c45bec72
+References: bsc#1071929
+
+It is possible for ebt_in_hook to be triggered before ebt_table is assigned
+resulting in a NULL-pointer dereference. Make sure hooks are
+registered as the last step.
+
+Fixes: aee12a0a3727 ("ebtables: remove nf_hook_register usage")
+Signed-off-by: Artem Savkov <asavkov@redhat.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Acked-by: Michal Kubecek <mkubecek@suse.cz>
+
+---
+ include/linux/netfilter_bridge/ebtables.h | 7 ++++---
+ net/bridge/netfilter/ebtable_broute.c | 4 ++--
+ net/bridge/netfilter/ebtable_filter.c | 4 ++--
+ net/bridge/netfilter/ebtable_nat.c | 4 ++--
+ net/bridge/netfilter/ebtables.c | 17 +++++++++--------
+ 5 files changed, 19 insertions(+), 17 deletions(-)
+
+diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h
+index e0cbf17af780..87e1caf81f04 100644
+--- a/include/linux/netfilter_bridge/ebtables.h
++++ b/include/linux/netfilter_bridge/ebtables.h
+@@ -108,9 +108,10 @@ struct ebt_table {
+
+ #define EBT_ALIGN(s) (((s) + (__alignof__(struct _xt_align)-1)) & \
+ ~(__alignof__(struct _xt_align)-1))
+-extern struct ebt_table *ebt_register_table(struct net *net,
+- const struct ebt_table *table,
+- const struct nf_hook_ops *);
++extern int ebt_register_table(struct net *net,
++ const struct ebt_table *table,
++ const struct nf_hook_ops *ops,
++ struct ebt_table **res);
+ extern void ebt_unregister_table(struct net *net, struct ebt_table *table,
+ const struct nf_hook_ops *);
+ extern unsigned int ebt_do_table(struct sk_buff *skb,
+diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
+index 2585b100ebbb..276b60262981 100644
+--- a/net/bridge/netfilter/ebtable_broute.c
++++ b/net/bridge/netfilter/ebtable_broute.c
+@@ -65,8 +65,8 @@ static int ebt_broute(struct sk_buff *skb)
+
+ static int __net_init broute_net_init(struct net *net)
+ {
+- net->xt.broute_table = ebt_register_table(net, &broute_table, NULL);
+- return PTR_ERR_OR_ZERO(net->xt.broute_table);
++ return ebt_register_table(net, &broute_table, NULL,
++ &net->xt.broute_table);
+ }
+
+ static void __net_exit broute_net_exit(struct net *net)
+diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
+index f22ef7c21913..f29d9a424d2b 100644
+--- a/net/bridge/netfilter/ebtable_filter.c
++++ b/net/bridge/netfilter/ebtable_filter.c
+@@ -93,8 +93,8 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
+
+ static int __net_init frame_filter_net_init(struct net *net)
+ {
+- net->xt.frame_filter = ebt_register_table(net, &frame_filter, ebt_ops_filter);
+- return PTR_ERR_OR_ZERO(net->xt.frame_filter);
++ return ebt_register_table(net, &frame_filter, ebt_ops_filter,
++ &net->xt.frame_filter);
+ }
+
+ static void __net_exit frame_filter_net_exit(struct net *net)
+diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
+index 2f7a4f314406..b5f96d56c5b6 100644
+--- a/net/bridge/netfilter/ebtable_nat.c
++++ b/net/bridge/netfilter/ebtable_nat.c
+@@ -93,8 +93,8 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
+
+ static int __net_init frame_nat_net_init(struct net *net)
+ {
+- net->xt.frame_nat = ebt_register_table(net, &frame_nat, ebt_ops_nat);
+- return PTR_ERR_OR_ZERO(net->xt.frame_nat);
++ return ebt_register_table(net, &frame_nat, ebt_ops_nat,
++ &net->xt.frame_nat);
+ }
+
+ static void __net_exit frame_nat_net_exit(struct net *net)
+diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
+index 9c6e619f452b..621f75976dbd 100644
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -1178,9 +1178,8 @@ static void __ebt_unregister_table(struct net *net, struct ebt_table *table)
+ kfree(table);
+ }
+
+-struct ebt_table *
+-ebt_register_table(struct net *net, const struct ebt_table *input_table,
+- const struct nf_hook_ops *ops)
++int ebt_register_table(struct net *net, const struct ebt_table *input_table,
++ const struct nf_hook_ops *ops, struct ebt_table **res)
+ {
+ struct ebt_table_info *newinfo;
+ struct ebt_table *t, *table;
+@@ -1192,7 +1191,7 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table,
+ repl->entries == NULL || repl->entries_size == 0 ||
+ repl->counters != NULL || input_table->private != NULL) {
+ BUGPRINT("Bad table data for ebt_register_table!!!\n");
+- return ERR_PTR(-EINVAL);
++ return -EINVAL;
+ }
+
+ /* Don't add one table to multiple lists. */
+@@ -1261,16 +1260,18 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table,
+ list_add(&table->list, &net->xt.tables[NFPROTO_BRIDGE]);
+ mutex_unlock(&ebt_mutex);
+
++ WRITE_ONCE(*res, table);
++
+ if (!ops)
+- return table;
++ return 0;
+
+ ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks));
+ if (ret) {
+ __ebt_unregister_table(net, table);
+- return ERR_PTR(ret);
++ *res = NULL;
+ }
+
+- return table;
++ return ret;
+ free_unlock:
+ mutex_unlock(&ebt_mutex);
+ free_chainstack:
+@@ -1285,7 +1286,7 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table,
+ free_table:
+ kfree(table);
+ out:
+- return ERR_PTR(ret);
++ return ret;
+ }
+
+ void ebt_unregister_table(struct net *net, struct ebt_table *table,
+--
+2.15.1
+
diff --git a/series.conf b/series.conf
index ec85a48ae9..21b93df0dd 100644
--- a/series.conf
+++ b/series.conf
@@ -5397,6 +5397,7 @@
patches.drivers/0008-Revert-commit-1a8b6d76dc5b-net-add-one-common-config.patch
patches.drivers/0009-ixgbe-Use-new-PCI_DEV_FLAGS_NO_RELAXED_ORDERING-flag.patch
patches.drivers/ixgbe-incorrect-XDP-ring-accounting-in-ethtool-tx_fr.patch
+ patches.fixes/netfilter-ebtables-fix-race-condition-in-frame_filte.patch
patches.fixes/fix-mpage_writepage-for-pages-with-buffers.patch
patches.drivers/scsi-libfc-fix-a-deadlock-in-fc_rport_work.patch
patches.arch/s390-sles15-01-10-s390_cputime_fix_stat_after_CPU_hotplug.patch
@@ -5732,6 +5733,7 @@
patches.drivers/ibmvnic-115-Enable-scatter-gather-support.patch
patches.drivers/ibmvnic-116-Enable-TSO-support.patch
patches.drivers/ibmvnic-117-Let-users-change-net-device-features.patch
+ patches.drivers/0001-iwlwifi-fix-wrong-struct-for-a000-device.patch
patches.drivers/cxgb4-add-tc-flower-match-support-for-TOS.patch
patches.drivers/cxgb4-add-tc-flower-match-support-for-vlan.patch
patches.drivers/cxgb4-add-tc-flower-support-for-action-PASS.patch
@@ -5740,7 +5742,6 @@
patches.drivers/cxgb4-add-tc-flower-support-for-ETH-SMAC-rewrite.patch
patches.drivers/cxgb4-introduce-fw_filter2_wr-to-prepare-for-L3-L4-r.patch
patches.drivers/cxgb4-add-tc-flower-support-for-L3-L4-rewrite.patch
- patches.drivers/0001-iwlwifi-fix-wrong-struct-for-a000-device.patch
patches.drivers/Bluetooth-hci_bcm-Add-support-for-BCM2E7E
patches.drivers/cxgb4-fix-overflow-in-collecting-IBQ-and-OBQ-dump.patch
patches.drivers/cxgb4-collect-hardware-LA-dumps.patch
@@ -5767,6 +5768,7 @@
patches.drivers/net-mlx5e-Add-rollback-on-add-VLAN-failure.patch
patches.drivers/ibmvnic-120-Add-vnic-client-data-to-login-buffer.patch
patches.drivers/cxgb4-collect-vpd-info-directly-from-hardware.patch
+ patches.fixes/net-Remove-unused-skb_shared_info-member.patch
patches.drivers/iwlwifi-mvm-reset-seq-num-after-restart.patch
patches.drivers/iwlwifi-fix-multi-queue-notification-for-a000-device.patch
patches.drivers/cxgb4-collect-LE-TCAM-dump.patch
@@ -5855,8 +5857,6 @@
patches.drivers/iw_cxgb4-Fix-possible-circular-dependency-locking-wa.patch
patches.drivers/iw_cxgb4-only-call-the-cq-comp_handler-when-the-cq-i.patch
patches.drivers/iw_cxgb4-atomically-flush-the-qp.patch
- patches.suse/bio-ensure-__bio_clone_fast-copies-bi_partno.patch
- patches.drivers/0001-iwlwifi-mvm-support-version-7-of-the-SCAN_REQ_UMAC-F.patch
patches.suse/mm-Handle-0-flags-in-_calc_vm_trans-macro.patch
patches.suse/mm-introduce-MAP_SHARED_VALIDATE-a-mechanism-to-safe.patch
patches.suse/mm-Remove-VM_FAULT_HWPOISON_LARGE_MASK.patch
@@ -5880,25 +5880,29 @@
patches.fixes/dax-fix-PMD-faults-on-zero-length-files.patch
patches.fixes/dax-fix-general-protection-fault-in-dax_alloc_inode.patch
patches.drivers/nvmet_fc-fix-better-length-checking.patch
+ patches.suse/bio-ensure-__bio_clone_fast-copies-bi_partno.patch
patches.drivers/nfp-fix-flower-offload-metadata-flag-usage.patch
patches.drivers/nfp-fix-vlan-receive-MAC-statistics-typo.patch
patches.drivers/nfp-inherit-the-max_mtu-from-the-PF-netdev.patch
patches.drivers/ibmvnic-122-fix-dma_mapping_error-call.patch
patches.drivers/mac80211_hwsim-Fix-memory-leak-in-hwsim_new_radio_nl
+ patches.fixes/net-accept-UFO-datagrams-from-tuntap-and-packet.patch
+ patches.drivers/0001-iwlwifi-mvm-support-version-7-of-the-SCAN_REQ_UMAC-F.patch
patches.fixes/target-move-a-declaration-of-a-global-variable-into-a-header-file
+ patches.drivers/net-thunderx-Fix-TCP-UDP-checksum-offload-for-IPv6-p.patch
+ patches.fixes/net-openvswitch-datapath-fix-data-type-in-queue_gso_.patch
patches.fixes/mm-hugetlbfs-introduce-split-to-vm_operations_struct.patch
patches.fixes/device-dax-implement-split-to-catch-invalid-munmap-a.patch
patches.fixes/mm-introduce-get_user_pages_longterm.patch
patches.fixes/mm-fail-get_vaddr_frames-for-filesystem-dax-mappings.patch
patches.fixes/v4l2-disable-filesystem-dax-mapping-support.patch
patches.fixes/IB-core-disable-memory-registration-of-filesystem-da.patch
+ patches.drivers/mmc-core-prepend-0x-to-pre_eol_info-entry-in-sysfs
+ patches.drivers/mmc-core-prepend-0x-to-OCR-entry-in-sysfs
# jejb/scsi for-next
patches.fixes/scsi-scsi_devinfo-handle-non-terminated-strings.patch
patches.fixes/scsi-scsi_devinfo-cleanly-zero-pad-devinfo-strings.patch
- patches.drivers/net-thunderx-Fix-TCP-UDP-checksum-offload-for-IPv6-p.patch
- patches.drivers/mmc-core-prepend-0x-to-pre_eol_info-entry-in-sysfs
- patches.drivers/mmc-core-prepend-0x-to-OCR-entry-in-sysfs
# out-of-tree patches
patches.drivers/s390-sles15-00-04-04-kmsg-add-VNIC-Characteristics-msg-documentation.patch