diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/tcp_metrics.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 1a115b665792..d02ff3777785 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c | |||
@@ -30,6 +30,11 @@ enum tcp_metric_index { | |||
30 | TCP_METRIC_MAX, | 30 | TCP_METRIC_MAX, |
31 | }; | 31 | }; |
32 | 32 | ||
33 | struct tcp_fastopen_metrics { | ||
34 | u16 mss; | ||
35 | struct tcp_fastopen_cookie cookie; | ||
36 | }; | ||
37 | |||
33 | struct tcp_metrics_block { | 38 | struct tcp_metrics_block { |
34 | struct tcp_metrics_block __rcu *tcpm_next; | 39 | struct tcp_metrics_block __rcu *tcpm_next; |
35 | struct inetpeer_addr tcpm_addr; | 40 | struct inetpeer_addr tcpm_addr; |
@@ -38,6 +43,7 @@ struct tcp_metrics_block { | |||
38 | u32 tcpm_ts_stamp; | 43 | u32 tcpm_ts_stamp; |
39 | u32 tcpm_lock; | 44 | u32 tcpm_lock; |
40 | u32 tcpm_vals[TCP_METRIC_MAX]; | 45 | u32 tcpm_vals[TCP_METRIC_MAX]; |
46 | struct tcp_fastopen_metrics tcpm_fastopen; | ||
41 | }; | 47 | }; |
42 | 48 | ||
43 | static bool tcp_metric_locked(struct tcp_metrics_block *tm, | 49 | static bool tcp_metric_locked(struct tcp_metrics_block *tm, |
@@ -118,6 +124,8 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst) | |||
118 | tm->tcpm_vals[TCP_METRIC_REORDERING] = dst_metric_raw(dst, RTAX_REORDERING); | 124 | tm->tcpm_vals[TCP_METRIC_REORDERING] = dst_metric_raw(dst, RTAX_REORDERING); |
119 | tm->tcpm_ts = 0; | 125 | tm->tcpm_ts = 0; |
120 | tm->tcpm_ts_stamp = 0; | 126 | tm->tcpm_ts_stamp = 0; |
127 | tm->tcpm_fastopen.mss = 0; | ||
128 | tm->tcpm_fastopen.cookie.len = 0; | ||
121 | } | 129 | } |
122 | 130 | ||
123 | static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, | 131 | static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, |
@@ -633,6 +641,49 @@ bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw) | |||
633 | return ret; | 641 | return ret; |
634 | } | 642 | } |
635 | 643 | ||
644 | static DEFINE_SEQLOCK(fastopen_seqlock); | ||
645 | |||
646 | void tcp_fastopen_cache_get(struct sock *sk, u16 *mss, | ||
647 | struct tcp_fastopen_cookie *cookie) | ||
648 | { | ||
649 | struct tcp_metrics_block *tm; | ||
650 | |||
651 | rcu_read_lock(); | ||
652 | tm = tcp_get_metrics(sk, __sk_dst_get(sk), false); | ||
653 | if (tm) { | ||
654 | struct tcp_fastopen_metrics *tfom = &tm->tcpm_fastopen; | ||
655 | unsigned int seq; | ||
656 | |||
657 | do { | ||
658 | seq = read_seqbegin(&fastopen_seqlock); | ||
659 | if (tfom->mss) | ||
660 | *mss = tfom->mss; | ||
661 | *cookie = tfom->cookie; | ||
662 | } while (read_seqretry(&fastopen_seqlock, seq)); | ||
663 | } | ||
664 | rcu_read_unlock(); | ||
665 | } | ||
666 | |||
667 | |||
668 | void tcp_fastopen_cache_set(struct sock *sk, u16 mss, | ||
669 | struct tcp_fastopen_cookie *cookie) | ||
670 | { | ||
671 | struct tcp_metrics_block *tm; | ||
672 | |||
673 | rcu_read_lock(); | ||
674 | tm = tcp_get_metrics(sk, __sk_dst_get(sk), true); | ||
675 | if (tm) { | ||
676 | struct tcp_fastopen_metrics *tfom = &tm->tcpm_fastopen; | ||
677 | |||
678 | write_seqlock_bh(&fastopen_seqlock); | ||
679 | tfom->mss = mss; | ||
680 | if (cookie->len > 0) | ||
681 | tfom->cookie = *cookie; | ||
682 | write_sequnlock_bh(&fastopen_seqlock); | ||
683 | } | ||
684 | rcu_read_unlock(); | ||
685 | } | ||
686 | |||
636 | static unsigned long tcpmhash_entries; | 687 | static unsigned long tcpmhash_entries; |
637 | static int __init set_tcpmhash_entries(char *str) | 688 | static int __init set_tcpmhash_entries(char *str) |
638 | { | 689 | { |