--- /dev/null
+From a504b703bb1da526a01593da0e4be2af9d9f5fa8 Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Mon, 10 Dec 2018 17:18:46 +0100
+Subject: netfilter: nat: limit port clash resolution attempts
+
+From: Florian Westphal <fw@strlen.de>
+
+commit a504b703bb1da526a01593da0e4be2af9d9f5fa8 upstream.
+
+In case almost or all available ports are taken, clash resolution can
+take a very long time, resulting in soft lockup.
+
+This can happen when many to-be-natted hosts connect to same
+destination:port (e.g. a proxy) and all connections pass the same SNAT.
+
+Pick a random offset in the acceptable range, then try ever smaller
+number of adjacent port numbers, until either the limit is reached or a
+useable port was found. This results in at most 248 attempts
+(128 + 64 + 32 + 16 + 8, i.e. 4 restarts with new search offset)
+instead of 64000+,
+
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/netfilter/nf_nat_proto_common.c | 29 +++++++++++++++++++++++------
+ 1 file changed, 23 insertions(+), 6 deletions(-)
+
+--- a/net/netfilter/nf_nat_proto_common.c
++++ b/net/netfilter/nf_nat_proto_common.c
+@@ -40,9 +40,10 @@ void nf_nat_l4proto_unique_tuple(const s
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct)
+ {
+- unsigned int range_size, min, max, i;
++ unsigned int range_size, min, max, i, attempts;
+ __be16 *portptr;
+- u_int16_t off;
++ u16 off;
++ static const unsigned int max_attempts = 128;
+
+ if (maniptype == NF_NAT_MANIP_SRC)
+ portptr = &tuple->src.u.all;
+@@ -88,12 +89,28 @@ void nf_nat_l4proto_unique_tuple(const s
+ off = prandom_u32();
+ }
+
+- for (i = 0; ; ++off) {
++ attempts = range_size;
++ if (attempts > max_attempts)
++ attempts = max_attempts;
++
++ /* We are in softirq; doing a search of the entire range risks
++ * soft lockup when all tuples are already used.
++ *
++ * If we can't find any free port from first offset, pick a new
++ * one and try again, with ever smaller search window.
++ */
++another_round:
++ for (i = 0; i < attempts; i++, off++) {
+ *portptr = htons(min + off % range_size);
+- if (++i != range_size && nf_nat_used_tuple(tuple, ct))
+- continue;
+- return;
++ if (!nf_nat_used_tuple(tuple, ct))
++ return;
+ }
++
++ if (attempts >= range_size || attempts < 16)
++ return;
++ attempts /= 2;
++ off = prandom_u32();
++ goto another_round;
+ }
+ EXPORT_SYMBOL_GPL(nf_nat_l4proto_unique_tuple);
+
--- /dev/null
+From 6ed5943f8735e2b778d92ea4d9805c0a1d89bc2b Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Thu, 15 Nov 2018 10:22:59 +0100
+Subject: netfilter: nat: remove l4 protocol port rovers
+
+From: Florian Westphal <fw@strlen.de>
+
+commit 6ed5943f8735e2b778d92ea4d9805c0a1d89bc2b upstream.
+
+This is a leftover from days where single-cpu systems were common:
+Store last port used to resolve a clash to use it as a starting point when
+the next conflict needs to be resolved.
+
+When we have parallel attempt to connect to same address:port pair,
+its likely that both cores end up computing the same "available" port,
+as both use same starting port, and newly used ports won't become
+visible to other cores until the conntrack gets confirmed later.
+
+One of the cores then has to drop the packet at insertion time because
+the chosen new tuple turns out to be in use after all.
+
+Lets simplify this: remove port rover and use a pseudo-random starting
+point.
+
+Note that this doesn't make netfilter default to 'fully random' mode;
+the 'rover' was only used if NAT could not reuse source port as-is.
+
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/netfilter/nf_nat_l4proto.h | 2 +-
+ net/netfilter/nf_nat_proto_common.c | 8 ++------
+ net/netfilter/nf_nat_proto_dccp.c | 5 +----
+ net/netfilter/nf_nat_proto_sctp.c | 5 +----
+ net/netfilter/nf_nat_proto_tcp.c | 5 +----
+ net/netfilter/nf_nat_proto_udp.c | 10 ++--------
+ 6 files changed, 8 insertions(+), 27 deletions(-)
+
+--- a/include/net/netfilter/nf_nat_l4proto.h
++++ b/include/net/netfilter/nf_nat_l4proto.h
+@@ -74,7 +74,7 @@ void nf_nat_l4proto_unique_tuple(const s
+ struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range2 *range,
+ enum nf_nat_manip_type maniptype,
+- const struct nf_conn *ct, u16 *rover);
++ const struct nf_conn *ct);
+
+ int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[],
+ struct nf_nat_range2 *range);
+--- a/net/netfilter/nf_nat_proto_common.c
++++ b/net/netfilter/nf_nat_proto_common.c
+@@ -38,8 +38,7 @@ void nf_nat_l4proto_unique_tuple(const s
+ struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range2 *range,
+ enum nf_nat_manip_type maniptype,
+- const struct nf_conn *ct,
+- u16 *rover)
++ const struct nf_conn *ct)
+ {
+ unsigned int range_size, min, max, i;
+ __be16 *portptr;
+@@ -86,16 +85,13 @@ void nf_nat_l4proto_unique_tuple(const s
+ } else if (range->flags & NF_NAT_RANGE_PROTO_OFFSET) {
+ off = (ntohs(*portptr) - ntohs(range->base_proto.all));
+ } else {
+- off = *rover;
++ off = prandom_u32();
+ }
+
+ for (i = 0; ; ++off) {
+ *portptr = htons(min + off % range_size);
+ if (++i != range_size && nf_nat_used_tuple(tuple, ct))
+ continue;
+- if (!(range->flags & (NF_NAT_RANGE_PROTO_RANDOM_ALL|
+- NF_NAT_RANGE_PROTO_OFFSET)))
+- *rover = off;
+ return;
+ }
+ }
+--- a/net/netfilter/nf_nat_proto_dccp.c
++++ b/net/netfilter/nf_nat_proto_dccp.c
+@@ -18,8 +18,6 @@
+ #include <net/netfilter/nf_nat_l3proto.h>
+ #include <net/netfilter/nf_nat_l4proto.h>
+
+-static u_int16_t dccp_port_rover;
+-
+ static void
+ dccp_unique_tuple(const struct nf_nat_l3proto *l3proto,
+ struct nf_conntrack_tuple *tuple,
+@@ -27,8 +25,7 @@ dccp_unique_tuple(const struct nf_nat_l3
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct)
+ {
+- nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct,
+- &dccp_port_rover);
++ nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct);
+ }
+
+ static bool
+--- a/net/netfilter/nf_nat_proto_sctp.c
++++ b/net/netfilter/nf_nat_proto_sctp.c
+@@ -12,8 +12,6 @@
+
+ #include <net/netfilter/nf_nat_l4proto.h>
+
+-static u_int16_t nf_sctp_port_rover;
+-
+ static void
+ sctp_unique_tuple(const struct nf_nat_l3proto *l3proto,
+ struct nf_conntrack_tuple *tuple,
+@@ -21,8 +19,7 @@ sctp_unique_tuple(const struct nf_nat_l3
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct)
+ {
+- nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct,
+- &nf_sctp_port_rover);
++ nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct);
+ }
+
+ static bool
+--- a/net/netfilter/nf_nat_proto_tcp.c
++++ b/net/netfilter/nf_nat_proto_tcp.c
+@@ -18,8 +18,6 @@
+ #include <net/netfilter/nf_nat_l4proto.h>
+ #include <net/netfilter/nf_nat_core.h>
+
+-static u16 tcp_port_rover;
+-
+ static void
+ tcp_unique_tuple(const struct nf_nat_l3proto *l3proto,
+ struct nf_conntrack_tuple *tuple,
+@@ -27,8 +25,7 @@ tcp_unique_tuple(const struct nf_nat_l3p
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct)
+ {
+- nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct,
+- &tcp_port_rover);
++ nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct);
+ }
+
+ static bool
+--- a/net/netfilter/nf_nat_proto_udp.c
++++ b/net/netfilter/nf_nat_proto_udp.c
+@@ -17,8 +17,6 @@
+ #include <net/netfilter/nf_nat_l3proto.h>
+ #include <net/netfilter/nf_nat_l4proto.h>
+
+-static u16 udp_port_rover;
+-
+ static void
+ udp_unique_tuple(const struct nf_nat_l3proto *l3proto,
+ struct nf_conntrack_tuple *tuple,
+@@ -26,8 +24,7 @@ udp_unique_tuple(const struct nf_nat_l3p
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct)
+ {
+- nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct,
+- &udp_port_rover);
++ nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct);
+ }
+
+ static void
+@@ -78,8 +75,6 @@ static bool udp_manip_pkt(struct sk_buff
+ }
+
+ #ifdef CONFIG_NF_NAT_PROTO_UDPLITE
+-static u16 udplite_port_rover;
+-
+ static bool udplite_manip_pkt(struct sk_buff *skb,
+ const struct nf_nat_l3proto *l3proto,
+ unsigned int iphdroff, unsigned int hdroff,
+@@ -103,8 +98,7 @@ udplite_unique_tuple(const struct nf_nat
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct)
+ {
+- nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct,
+- &udplite_port_rover);
++ nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct);
+ }
+
+ const struct nf_nat_l4proto nf_nat_l4proto_udplite = {