[RFC PATCH 13/30] net: Prepare tcp_get_md5sig_pool() for handling softirq mask

From: Frederic Weisbecker
Date: Wed Oct 10 2018 - 19:13:16 EST


This pair of function is implemented on top of local_bh_disable() that
is going to handle a softirq mask in order to apply finegrained vector
disablement. The lock function is going to return the previous vectors
enabled mask prior to the last call to local_bh_disable(), following a
similar model to that of local_irq_save/restore. Subsequent calls to
local_bh_disable() and friends can then stack up:

bh = local_bh_disable(vec_mask);
tcp_get_md5sig_pool(&bh2) {
*bh2 = local_bh_disable(...)
}
...
tcp_put_md5sig_pool(bh2) {
local_bh_enable(bh2);
}
local_bh_enable(bh);

To prepare for that, make tcp_get_md5sig_pool() able to return a saved
vector enabled mask and pass it back to rcu_read_unlock_bh(). We'll plug
it to local_bh_disable() in a subsequent patch.

Signed-off-by: Frederic Weisbecker <frederic@xxxxxxxxxx>
Cc: Ingo Molnar <mingo@xxxxxxxxxx>
Cc: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Cc: David S. Miller <davem@xxxxxxxxxxxxx>
Cc: Mauro Carvalho Chehab <mchehab@xxxxxxxxxxxxxxxx>
Cc: Paul E. McKenney <paulmck@xxxxxxxxxxxxxxxxxx>
---
include/net/tcp.h | 4 ++--
net/ipv4/tcp.c | 5 ++++-
net/ipv4/tcp_ipv4.c | 14 ++++++++------
net/ipv6/tcp_ipv6.c | 14 ++++++++------
4 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 770917d..7fe357a 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1553,8 +1553,8 @@ static inline struct tcp_md5sig_key *tcp_md5_do_lookup(const struct sock *sk,

bool tcp_alloc_md5sig_pool(void);

-struct tcp_md5sig_pool *tcp_get_md5sig_pool(void);
-static inline void tcp_put_md5sig_pool(void)
+struct tcp_md5sig_pool *tcp_get_md5sig_pool(unsigned int *bh);
+static inline void tcp_put_md5sig_pool(unsigned int bh)
{
local_bh_enable();
}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 10c6246..dfd9bae 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -3665,16 +3665,19 @@ EXPORT_SYMBOL(tcp_alloc_md5sig_pool);
* and BH disabled, to make sure another thread or softirq handling
* wont try to get same context.
*/
-struct tcp_md5sig_pool *tcp_get_md5sig_pool(void)
+struct tcp_md5sig_pool *tcp_get_md5sig_pool(unsigned int *bh)
{
local_bh_disable();
+ *bh = 0;

if (tcp_md5sig_pool_populated) {
/* coupled with smp_wmb() in __tcp_alloc_md5sig_pool() */
smp_rmb();
return this_cpu_ptr(&tcp_md5sig_pool);
}
+
local_bh_enable();
+
return NULL;
}
EXPORT_SYMBOL(tcp_get_md5sig_pool);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 44c09ed..0378e77 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1194,8 +1194,9 @@ static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
{
struct tcp_md5sig_pool *hp;
struct ahash_request *req;
+ unsigned int bh;

- hp = tcp_get_md5sig_pool();
+ hp = tcp_get_md5sig_pool(&bh);
if (!hp)
goto clear_hash_noput;
req = hp->md5_req;
@@ -1210,11 +1211,11 @@ static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
if (crypto_ahash_final(req))
goto clear_hash;

- tcp_put_md5sig_pool();
+ tcp_put_md5sig_pool(bh);
return 0;

clear_hash:
- tcp_put_md5sig_pool();
+ tcp_put_md5sig_pool(bh);
clear_hash_noput:
memset(md5_hash, 0, 16);
return 1;
@@ -1228,6 +1229,7 @@ int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key,
struct ahash_request *req;
const struct tcphdr *th = tcp_hdr(skb);
__be32 saddr, daddr;
+ unsigned int bh;

if (sk) { /* valid for establish/request sockets */
saddr = sk->sk_rcv_saddr;
@@ -1238,7 +1240,7 @@ int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key,
daddr = iph->daddr;
}

- hp = tcp_get_md5sig_pool();
+ hp = tcp_get_md5sig_pool(&bh);
if (!hp)
goto clear_hash_noput;
req = hp->md5_req;
@@ -1256,11 +1258,11 @@ int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key,
if (crypto_ahash_final(req))
goto clear_hash;

- tcp_put_md5sig_pool();
+ tcp_put_md5sig_pool(bh);
return 0;

clear_hash:
- tcp_put_md5sig_pool();
+ tcp_put_md5sig_pool(bh);
clear_hash_noput:
memset(md5_hash, 0, 16);
return 1;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 03e6b7a..360efc3 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -610,8 +610,9 @@ static int tcp_v6_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
{
struct tcp_md5sig_pool *hp;
struct ahash_request *req;
+ unsigned int bh;

- hp = tcp_get_md5sig_pool();
+ hp = tcp_get_md5sig_pool(&bh);
if (!hp)
goto clear_hash_noput;
req = hp->md5_req;
@@ -626,11 +627,11 @@ static int tcp_v6_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
if (crypto_ahash_final(req))
goto clear_hash;

- tcp_put_md5sig_pool();
+ tcp_put_md5sig_pool(bh);
return 0;

clear_hash:
- tcp_put_md5sig_pool();
+ tcp_put_md5sig_pool(bh);
clear_hash_noput:
memset(md5_hash, 0, 16);
return 1;
@@ -645,6 +646,7 @@ static int tcp_v6_md5_hash_skb(char *md5_hash,
struct tcp_md5sig_pool *hp;
struct ahash_request *req;
const struct tcphdr *th = tcp_hdr(skb);
+ unsigned int bh;

if (sk) { /* valid for establish/request sockets */
saddr = &sk->sk_v6_rcv_saddr;
@@ -655,7 +657,7 @@ static int tcp_v6_md5_hash_skb(char *md5_hash,
daddr = &ip6h->daddr;
}

- hp = tcp_get_md5sig_pool();
+ hp = tcp_get_md5sig_pool(&bh);
if (!hp)
goto clear_hash_noput;
req = hp->md5_req;
@@ -673,11 +675,11 @@ static int tcp_v6_md5_hash_skb(char *md5_hash,
if (crypto_ahash_final(req))
goto clear_hash;

- tcp_put_md5sig_pool();
+ tcp_put_md5sig_pool(bh);
return 0;

clear_hash:
- tcp_put_md5sig_pool();
+ tcp_put_md5sig_pool(bh);
clear_hash_noput:
memset(md5_hash, 0, 16);
return 1;
--
2.7.4