diff options
| -rw-r--r-- | net/dccp/ccid.h | 18 | ||||
| -rw-r--r-- | net/dccp/ccids/ccid3.c | 27 | ||||
| -rw-r--r-- | net/dccp/diag.c | 26 | 
3 files changed, 70 insertions, 1 deletions
| diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index c6767b282244..962f1e9e2f7e 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -50,6 +50,10 @@ struct ccid {  						  struct sk_buff *skb, int len);  	void		(*ccid_hc_tx_packet_sent)(struct sock *sk, int more,  						  int len); +	void		(*ccid_hc_rx_get_info)(struct sock *sk, +					       struct tcp_info *info); +	void		(*ccid_hc_tx_get_info)(struct sock *sk, +					       struct tcp_info *info);  };  extern int	   ccid_register(struct ccid *ccid); @@ -159,4 +163,18 @@ static inline void ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,  	if (ccid->ccid_hc_rx_insert_options != NULL)  		ccid->ccid_hc_rx_insert_options(sk, skb);  } + +static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk, +				       struct tcp_info *info) +{ +	if (ccid->ccid_hc_rx_get_info != NULL) +		ccid->ccid_hc_rx_get_info(sk, info); +} + +static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk, +				       struct tcp_info *info) +{ +	if (ccid->ccid_hc_tx_get_info != NULL) +		ccid->ccid_hc_tx_get_info(sk, info); +}  #endif /* _CCID_H */ diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 48c36afa4934..fe4cc85f5bcc 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -2020,6 +2020,31 @@ static void ccid3_hc_rx_exit(struct sock *sk)  	dp->dccps_hc_rx_ccid_private = NULL;  } +static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info) +{ +	const struct dccp_sock *dp = dccp_sk(sk); +	const struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; + +	if (hcrx == NULL) +		return; + +	info->tcpi_ca_state	= hcrx->ccid3hcrx_state; +	info->tcpi_options	|= TCPI_OPT_TIMESTAMPS; +	info->tcpi_rcv_rtt	= hcrx->ccid3hcrx_rtt; +} + +static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info) +{ +	const struct dccp_sock *dp = dccp_sk(sk); +	const struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; + +	if (hctx == NULL) +		return; + +	info->tcpi_rto = hctx->ccid3hctx_t_rto; +	info->tcpi_rtt = hctx->ccid3hctx_rtt; +} +  static struct ccid ccid3 = {  	.ccid_id		   = 3,  	.ccid_name		   = "ccid3", @@ -2037,6 +2062,8 @@ static struct ccid ccid3 = {  	.ccid_hc_rx_exit	   = ccid3_hc_rx_exit,  	.ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options,  	.ccid_hc_rx_packet_recv	   = ccid3_hc_rx_packet_recv, +	.ccid_hc_rx_get_info	   = ccid3_hc_rx_get_info, +	.ccid_hc_tx_get_info	   = ccid3_hc_tx_get_info,  };  module_param(ccid3_debug, int, 0444); diff --git a/net/dccp/diag.c b/net/dccp/diag.c index 0b10c176c35a..f675d8e642d3 100644 --- a/net/dccp/diag.c +++ b/net/dccp/diag.c @@ -14,19 +14,43 @@  #include <linux/module.h>  #include <linux/inet_diag.h> +#include "ccid.h"  #include "dccp.h" +static void dccp_get_info(struct sock *sk, struct tcp_info *info) +{ +	struct dccp_sock *dp = dccp_sk(sk); +	const struct inet_connection_sock *icsk = inet_csk(sk); + +	memset(info, 0, sizeof(*info)); + +	info->tcpi_state	= sk->sk_state; +	info->tcpi_retransmits	= icsk->icsk_retransmits; +	info->tcpi_probes	= icsk->icsk_probes_out; +	info->tcpi_backoff	= icsk->icsk_backoff; +	info->tcpi_pmtu		= dp->dccps_pmtu_cookie; + +	if (dp->dccps_options.dccpo_send_ack_vector) +		info->tcpi_options |= TCPI_OPT_SACK; + +	ccid_hc_rx_get_info(dp->dccps_hc_rx_ccid, sk, info); +	ccid_hc_tx_get_info(dp->dccps_hc_tx_ccid, sk, info); +} +  static void dccp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,  			       void *_info)  {  	r->idiag_rqueue = r->idiag_wqueue = 0; + +	if (_info != NULL) +		dccp_get_info(sk, _info);  }  static struct inet_diag_handler dccp_diag_handler = {  	.idiag_hashinfo	 = &dccp_hashinfo,  	.idiag_get_info	 = dccp_diag_get_info,  	.idiag_type	 = DCCPDIAG_GETSOCK, -	.idiag_info_size = 0, +	.idiag_info_size = sizeof(struct tcp_info),  };  static int __init dccp_diag_init(void) | 
