Skip to content

Commit

Permalink
Merge branch 'listener-refactoring-preparations'
Browse files Browse the repository at this point in the history
Eric Dumazet says:

====================
tcp: listener refactoring preparations

This patch series makes changes to TCP/DCCP stacks so that
we can switch listener code to lockless mode.

This is done by marking const the listener socket in all
appropriate paths.

FastOpen code had to be changed to not dynamically allocate
a very small structure to make code simpler for following changes.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 29, 2015
2 parents 4c7e622 + 0536fcc commit e6934f3
Showing 24 changed files with 118 additions and 151 deletions.
22 changes: 4 additions & 18 deletions include/linux/tcp.h
Original file line number Diff line number Diff line change
@@ -382,25 +382,11 @@ static inline bool tcp_passive_fastopen(const struct sock *sk)
tcp_sk(sk)->fastopen_rsk != NULL);
}

extern void tcp_sock_destruct(struct sock *sk);

static inline int fastopen_init_queue(struct sock *sk, int backlog)
static inline void fastopen_queue_tune(struct sock *sk, int backlog)
{
struct request_sock_queue *queue =
&inet_csk(sk)->icsk_accept_queue;

if (queue->fastopenq == NULL) {
queue->fastopenq = kzalloc(
sizeof(struct fastopen_queue),
sk->sk_allocation);
if (queue->fastopenq == NULL)
return -ENOMEM;

sk->sk_destruct = tcp_sock_destruct;
spin_lock_init(&queue->fastopenq->lock);
}
queue->fastopenq->max_qlen = backlog;
return 0;
struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;

queue->fastopenq.max_qlen = backlog;
}

static inline void tcp_saved_syn_free(struct tcp_sock *tp)
2 changes: 1 addition & 1 deletion include/net/inet6_connection_sock.h
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ int inet6_csk_bind_conflict(const struct sock *sk,
const struct inet_bind_bucket *tb, bool relax);

struct dst_entry *inet6_csk_route_req(const struct sock *sk, struct flowi6 *fl6,
const struct request_sock *req);
const struct request_sock *req, u8 proto);

struct request_sock *inet6_csk_search_req(struct sock *sk,
const __be16 rport,
5 changes: 3 additions & 2 deletions include/net/inet_connection_sock.h
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ struct inet_connection_sock_af_ops {
int (*rebuild_header)(struct sock *sk);
void (*sk_rx_dst_set)(struct sock *sk, const struct sk_buff *skb);
int (*conn_request)(struct sock *sk, struct sk_buff *skb);
struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb,
struct sock *(*syn_recv_sock)(const struct sock *sk, struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst);
u16 net_header_len;
@@ -268,7 +268,8 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum);

struct dst_entry *inet_csk_route_req(const struct sock *sk, struct flowi4 *fl4,
const struct request_sock *req);
struct dst_entry *inet_csk_route_child_sock(struct sock *sk, struct sock *newsk,
struct dst_entry *inet_csk_route_child_sock(const struct sock *sk,
struct sock *newsk,
const struct request_sock *req);

static inline void inet_csk_reqsk_queue_add(struct sock *sk,
2 changes: 1 addition & 1 deletion include/net/inet_hashtables.h
Original file line number Diff line number Diff line change
@@ -199,7 +199,7 @@ static inline int inet_sk_listen_hashfn(const struct sock *sk)
}

/* Caller must disable local BH processing. */
int __inet_inherit_port(struct sock *sk, struct sock *child);
int __inet_inherit_port(const struct sock *sk, struct sock *child);

void inet_put_port(struct sock *sk);

16 changes: 6 additions & 10 deletions include/net/request_sock.h
Original file line number Diff line number Diff line change
@@ -34,9 +34,9 @@ struct request_sock_ops {
char *slab_name;
int (*rtx_syn_ack)(const struct sock *sk,
struct request_sock *req);
void (*send_ack)(struct sock *sk, struct sk_buff *skb,
void (*send_ack)(const struct sock *sk, struct sk_buff *skb,
struct request_sock *req);
void (*send_reset)(struct sock *sk,
void (*send_reset)(const struct sock *sk,
struct sk_buff *skb);
void (*destructor)(struct request_sock *req);
void (*syn_ack_timeout)(const struct request_sock *req);
@@ -129,9 +129,8 @@ struct listen_sock {
atomic_t qlen_dec; /* qlen = qlen_inc - qlen_dec */
atomic_t young_dec;

u8 max_qlen_log ____cacheline_aligned_in_smp;
u8 synflood_warned;
/* 2 bytes hole, try to use */
u32 max_qlen_log ____cacheline_aligned_in_smp;
u32 synflood_warned;
u32 hash_rnd;
u32 nr_table_entries;
struct request_sock *syn_table[0];
@@ -181,11 +180,8 @@ struct request_sock_queue {
struct request_sock *rskq_accept_tail;
u8 rskq_defer_accept;
struct listen_sock *listen_opt;
struct fastopen_queue *fastopenq; /* This is non-NULL iff TFO has been
* enabled on this listener. Check
* max_qlen != 0 in fastopen_queue
* to determine if TFO is enabled
* right at this moment.
struct fastopen_queue fastopenq; /* Check max_qlen != 0 to determine
* if TFO is enabled.
*/

/* temporary alignment, our goal is to get rid of this lock */
2 changes: 1 addition & 1 deletion include/net/sock.h
Original file line number Diff line number Diff line change
@@ -759,7 +759,7 @@ static inline int sk_memalloc_socks(void)

#endif

static inline gfp_t sk_gfp_atomic(struct sock *sk, gfp_t gfp_mask)
static inline gfp_t sk_gfp_atomic(const struct sock *sk, gfp_t gfp_mask)
{
return GFP_ATOMIC | (sk->sk_allocation & __GFP_MEMALLOC);
}
28 changes: 14 additions & 14 deletions include/net/tcp.h
Original file line number Diff line number Diff line change
@@ -365,8 +365,7 @@ void tcp_wfree(struct sk_buff *skb);
void tcp_write_timer_handler(struct sock *sk);
void tcp_delack_timer_handler(struct sock *sk);
int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg);
int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
const struct tcphdr *th, unsigned int len);
int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb);
void tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
const struct tcphdr *th, unsigned int len);
void tcp_rcv_space_adjust(struct sock *sk);
@@ -451,11 +450,11 @@ void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb);
void tcp_v4_mtu_reduced(struct sock *sk);
void tcp_req_err(struct sock *sk, u32 seq);
int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
struct sock *tcp_create_openreq_child(struct sock *sk,
struct sock *tcp_create_openreq_child(const struct sock *sk,
struct request_sock *req,
struct sk_buff *skb);
void tcp_ca_openreq_child(struct sock *sk, const struct dst_entry *dst);
struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst);
int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb);
@@ -492,8 +491,9 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb);

/* syncookies: remember time of last synqueue overflow
* But do not dirty this field too often (once per second is enough)
* It is racy as we do not hold a lock, but race is very minor.
*/
static inline void tcp_synq_overflow(struct sock *sk)
static inline void tcp_synq_overflow(const struct sock *sk)
{
unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp;
unsigned long now = jiffies;
@@ -520,8 +520,7 @@ static inline u32 tcp_cookie_time(void)

u32 __cookie_v4_init_sequence(const struct iphdr *iph, const struct tcphdr *th,
u16 *mssp);
__u32 cookie_v4_init_sequence(struct sock *sk, const struct sk_buff *skb,
__u16 *mss);
__u32 cookie_v4_init_sequence(const struct sk_buff *skb, __u16 *mss);
__u32 cookie_init_timestamp(struct request_sock *req);
bool cookie_timestamp_decode(struct tcp_options_received *opt);
bool cookie_ecn_ok(const struct tcp_options_received *opt,
@@ -534,8 +533,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb);

u32 __cookie_v6_init_sequence(const struct ipv6hdr *iph,
const struct tcphdr *th, u16 *mssp);
__u32 cookie_v6_init_sequence(struct sock *sk, const struct sk_buff *skb,
__u16 *mss);
__u32 cookie_v6_init_sequence(const struct sk_buff *skb, __u16 *mss);
#endif
/* tcp_output.c */

@@ -1710,10 +1708,10 @@ struct tcp_request_sock_ops {
const struct sock *sk_listener,
struct sk_buff *skb);
#ifdef CONFIG_SYN_COOKIES
__u32 (*cookie_init_seq)(struct sock *sk, const struct sk_buff *skb,
__u32 (*cookie_init_seq)(const struct sk_buff *skb,
__u16 *mss);
#endif
struct dst_entry *(*route_req)(struct sock *sk, struct flowi *fl,
struct dst_entry *(*route_req)(const struct sock *sk, struct flowi *fl,
const struct request_sock *req,
bool *strict);
__u32 (*init_seq)(const struct sk_buff *skb);
@@ -1726,14 +1724,16 @@ struct tcp_request_sock_ops {

#ifdef CONFIG_SYN_COOKIES
static inline __u32 cookie_init_sequence(const struct tcp_request_sock_ops *ops,
struct sock *sk, struct sk_buff *skb,
const struct sock *sk, struct sk_buff *skb,
__u16 *mss)
{
return ops->cookie_init_seq(sk, skb, mss);
tcp_synq_overflow(sk);
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESSENT);
return ops->cookie_init_seq(skb, mss);
}
#else
static inline __u32 cookie_init_sequence(const struct tcp_request_sock_ops *ops,
struct sock *sk, struct sk_buff *skb,
const struct sock *sk, struct sk_buff *skb,
__u16 *mss)
{
return 0;
9 changes: 8 additions & 1 deletion net/core/request_sock.c
Original file line number Diff line number Diff line change
@@ -59,6 +59,13 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,

get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd));
spin_lock_init(&queue->syn_wait_lock);

spin_lock_init(&queue->fastopenq.lock);
queue->fastopenq.rskq_rst_head = NULL;
queue->fastopenq.rskq_rst_tail = NULL;
queue->fastopenq.qlen = 0;
queue->fastopenq.max_qlen = 0;

queue->rskq_accept_head = NULL;
lopt->nr_table_entries = nr_table_entries;
lopt->max_qlen_log = ilog2(nr_table_entries);
@@ -174,7 +181,7 @@ void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req,
struct sock *lsk = req->rsk_listener;
struct fastopen_queue *fastopenq;

fastopenq = inet_csk(lsk)->icsk_accept_queue.fastopenq;
fastopenq = &inet_csk(lsk)->icsk_accept_queue.fastopenq;

tcp_sk(sk)->fastopen_rsk = NULL;
spin_lock_bh(&fastopenq->lock);
6 changes: 3 additions & 3 deletions net/dccp/dccp.h
Original file line number Diff line number Diff line change
@@ -229,7 +229,7 @@ void dccp_v4_send_check(struct sock *sk, struct sk_buff *skb);
int dccp_retransmit_skb(struct sock *sk);

void dccp_send_ack(struct sock *sk);
void dccp_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
void dccp_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
struct request_sock *rsk);

void dccp_send_sync(struct sock *sk, const u64 seq,
@@ -270,13 +270,13 @@ int dccp_reqsk_init(struct request_sock *rq, struct dccp_sock const *dp,

int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb);

struct sock *dccp_create_openreq_child(struct sock *sk,
struct sock *dccp_create_openreq_child(const struct sock *sk,
const struct request_sock *req,
const struct sk_buff *skb);

int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb);

struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,
struct sock *dccp_v4_request_recv_sock(const struct sock *sk, struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst);
struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
5 changes: 3 additions & 2 deletions net/dccp/ipv4.c
Original file line number Diff line number Diff line change
@@ -390,7 +390,8 @@ static inline u64 dccp_v4_init_sequence(const struct sk_buff *skb)
*
* This is the equivalent of TCP's tcp_v4_syn_recv_sock
*/
struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,
struct sock *dccp_v4_request_recv_sock(const struct sock *sk,
struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst)
{
@@ -527,7 +528,7 @@ static int dccp_v4_send_response(const struct sock *sk, struct request_sock *req
return err;
}

static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
static void dccp_v4_ctl_send_reset(const struct sock *sk, struct sk_buff *rxskb)
{
int err;
const struct iphdr *rxiph;
24 changes: 7 additions & 17 deletions net/dccp/ipv6.c
Original file line number Diff line number Diff line change
@@ -234,7 +234,7 @@ static void dccp_v6_reqsk_destructor(struct request_sock *req)
kfree_skb(inet_rsk(req)->pktopts);
}

static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
static void dccp_v6_ctl_send_reset(const struct sock *sk, struct sk_buff *rxskb)
{
const struct ipv6hdr *rxip6h;
struct sk_buff *skb;
@@ -408,13 +408,14 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
return -1;
}

static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst)
{
struct inet_request_sock *ireq = inet_rsk(req);
struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
struct ipv6_pinfo *newnp;
const struct ipv6_pinfo *np = inet6_sk(sk);
struct inet_sock *newinet;
struct dccp6_sock *newdp6;
struct sock *newsk;
@@ -462,22 +463,11 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
if (sk_acceptq_is_full(sk))
goto out_overflow;

if (dst == NULL) {
struct in6_addr *final_p, final;
if (!dst) {
struct flowi6 fl6;

memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_proto = IPPROTO_DCCP;
fl6.daddr = ireq->ir_v6_rmt_addr;
final_p = fl6_update_dst(&fl6, np->opt, &final);
fl6.saddr = ireq->ir_v6_loc_addr;
fl6.flowi6_oif = sk->sk_bound_dev_if;
fl6.fl6_dport = ireq->ir_rmt_port;
fl6.fl6_sport = htons(ireq->ir_num);
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));

dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
if (IS_ERR(dst))
dst = inet6_csk_route_req(sk, &fl6, req, IPPROTO_DCCP);
if (!dst)
goto out;
}

4 changes: 2 additions & 2 deletions net/dccp/minisocks.c
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@ void dccp_time_wait(struct sock *sk, int state, int timeo)
dccp_done(sk);
}

struct sock *dccp_create_openreq_child(struct sock *sk,
struct sock *dccp_create_openreq_child(const struct sock *sk,
const struct request_sock *req,
const struct sk_buff *skb)
{
@@ -236,7 +236,7 @@ int dccp_child_process(struct sock *parent, struct sock *child,

EXPORT_SYMBOL_GPL(dccp_child_process);

void dccp_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
void dccp_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
struct request_sock *rsk)
{
DCCP_BUG("DCCP-ACK packets are never sent in LISTEN/RESPOND state");
10 changes: 3 additions & 7 deletions net/ipv4/af_inet.c
Original file line number Diff line number Diff line change
@@ -219,17 +219,13 @@ int inet_listen(struct socket *sock, int backlog)
* shutdown() (rather than close()).
*/
if ((sysctl_tcp_fastopen & TFO_SERVER_ENABLE) != 0 &&
!inet_csk(sk)->icsk_accept_queue.fastopenq) {
!inet_csk(sk)->icsk_accept_queue.fastopenq.max_qlen) {
if ((sysctl_tcp_fastopen & TFO_SERVER_WO_SOCKOPT1) != 0)
err = fastopen_init_queue(sk, backlog);
fastopen_queue_tune(sk, backlog);
else if ((sysctl_tcp_fastopen &
TFO_SERVER_WO_SOCKOPT2) != 0)
err = fastopen_init_queue(sk,
fastopen_queue_tune(sk,
((uint)sysctl_tcp_fastopen) >> 16);
else
err = 0;
if (err)
goto out;

tcp_fastopen_init_key_once(true);
}
Loading

0 comments on commit e6934f3

Please sign in to comment.