Skip to content

Commit

Permalink
tcp: prepare CC get_info() access from getsockopt()
Browse files Browse the repository at this point in the history
We would like that optional info provided by Congestion Control
modules using netlink can also be read using getsockopt()

This patch changes get_info() to put this information in a buffer,
instead of skb, like tcp_get_info(), so that following patch
can reuse this common infrastructure.

Signed-off-by: Eric Dumazet <[email protected]>
Cc: Yuchung Cheng <[email protected]>
Cc: Neal Cardwell <[email protected]>
Acked-by: Neal Cardwell <[email protected]>
Acked-by: Daniel Borkmann <[email protected]>
Acked-by: Yuchung Cheng <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Eric Dumazet authored and davem330 committed Apr 29, 2015
1 parent bdd1f9e commit 64f40ff
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 34 deletions.
5 changes: 4 additions & 1 deletion include/net/tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,8 @@ enum tcp_ca_ack_event_flags {
/* Requires ECN/ECT set on all packets */
#define TCP_CONG_NEEDS_ECN 0x2

union tcp_cc_info;

struct tcp_congestion_ops {
struct list_head list;
u32 key;
Expand All @@ -829,7 +831,8 @@ struct tcp_congestion_ops {
/* hook for packet ack accounting (optional) */
void (*pkts_acked)(struct sock *sk, u32 num_acked, s32 rtt_us);
/* get info for inet_diag (optional) */
int (*get_info)(struct sock *sk, u32 ext, struct sk_buff *skb);
size_t (*get_info)(struct sock *sk, u32 ext, int *attr,
union tcp_cc_info *info);

char name[TCP_CA_NAME_MAX];
struct module *owner;
Expand Down
4 changes: 4 additions & 0 deletions include/uapi/linux/inet_diag.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,8 @@ struct tcp_dctcp_info {
__u32 dctcp_ab_tot;
};

union tcp_cc_info {
struct tcpvegas_info vegas;
struct tcp_dctcp_info dctcp;
};
#endif /* _UAPI_INET_DIAG_H_ */
8 changes: 5 additions & 3 deletions net/ipv4/inet_diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,14 +224,16 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
handler->idiag_get_info(sk, r, info);

if (sk->sk_state < TCP_TIME_WAIT) {
int err = 0;
union tcp_cc_info info;
size_t sz = 0;
int attr;

rcu_read_lock();
ca_ops = READ_ONCE(icsk->icsk_ca_ops);
if (ca_ops && ca_ops->get_info)
err = ca_ops->get_info(sk, ext, skb);
sz = ca_ops->get_info(sk, ext, &attr, &info);
rcu_read_unlock();
if (err < 0)
if (sz && nla_put(skb, attr, sz, &info) < 0)
goto errout;
}

Expand Down
20 changes: 10 additions & 10 deletions net/ipv4/tcp_dctcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,8 @@ static void dctcp_cwnd_event(struct sock *sk, enum tcp_ca_event ev)
}
}

static int dctcp_get_info(struct sock *sk, u32 ext, struct sk_buff *skb)
static size_t dctcp_get_info(struct sock *sk, u32 ext, int *attr,
union tcp_cc_info *info)
{
const struct dctcp *ca = inet_csk_ca(sk);

Expand All @@ -286,18 +287,17 @@ static int dctcp_get_info(struct sock *sk, u32 ext, struct sk_buff *skb)
*/
if (ext & (1 << (INET_DIAG_DCTCPINFO - 1)) ||
ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
struct tcp_dctcp_info info;

memset(&info, 0, sizeof(info));
memset(info, 0, sizeof(struct tcp_dctcp_info));
if (inet_csk(sk)->icsk_ca_ops != &dctcp_reno) {
info.dctcp_enabled = 1;
info.dctcp_ce_state = (u16) ca->ce_state;
info.dctcp_alpha = ca->dctcp_alpha;
info.dctcp_ab_ecn = ca->acked_bytes_ecn;
info.dctcp_ab_tot = ca->acked_bytes_total;
info->dctcp.dctcp_enabled = 1;
info->dctcp.dctcp_ce_state = (u16) ca->ce_state;
info->dctcp.dctcp_alpha = ca->dctcp_alpha;
info->dctcp.dctcp_ab_ecn = ca->acked_bytes_ecn;
info->dctcp.dctcp_ab_tot = ca->acked_bytes_total;
}

return nla_put(skb, INET_DIAG_DCTCPINFO, sizeof(info), &info);
*attr = INET_DIAG_DCTCPINFO;
return sizeof(*info);
}
return 0;
}
Expand Down
21 changes: 11 additions & 10 deletions net/ipv4/tcp_illinois.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,24 +300,25 @@ static u32 tcp_illinois_ssthresh(struct sock *sk)
}

/* Extract info for Tcp socket info provided via netlink. */
static int tcp_illinois_info(struct sock *sk, u32 ext, struct sk_buff *skb)
static size_t tcp_illinois_info(struct sock *sk, u32 ext, int *attr,
union tcp_cc_info *info)
{
const struct illinois *ca = inet_csk_ca(sk);

if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
struct tcpvegas_info info = {
.tcpv_enabled = 1,
.tcpv_rttcnt = ca->cnt_rtt,
.tcpv_minrtt = ca->base_rtt,
};
info->vegas.tcpv_enabled = 1;
info->vegas.tcpv_rttcnt = ca->cnt_rtt;
info->vegas.tcpv_minrtt = ca->base_rtt;
info->vegas.tcpv_rtt = 0;

if (info.tcpv_rttcnt > 0) {
if (info->vegas.tcpv_rttcnt > 0) {
u64 t = ca->sum_rtt;

do_div(t, info.tcpv_rttcnt);
info.tcpv_rtt = t;
do_div(t, info->vegas.tcpv_rttcnt);
info->vegas.tcpv_rtt = t;
}
return nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info);
*attr = INET_DIAG_VEGASINFO;
return sizeof(struct tcpvegas_info);
}
return 0;
}
Expand Down
19 changes: 10 additions & 9 deletions net/ipv4/tcp_vegas.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,18 +286,19 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 acked)
}

/* Extract info for Tcp socket info provided via netlink. */
int tcp_vegas_get_info(struct sock *sk, u32 ext, struct sk_buff *skb)
size_t tcp_vegas_get_info(struct sock *sk, u32 ext, int *attr,
union tcp_cc_info *info)
{
const struct vegas *ca = inet_csk_ca(sk);

if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
struct tcpvegas_info info = {
.tcpv_enabled = ca->doing_vegas_now,
.tcpv_rttcnt = ca->cntRTT,
.tcpv_rtt = ca->baseRTT,
.tcpv_minrtt = ca->minRTT,
};

return nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info);
info->vegas.tcpv_enabled = ca->doing_vegas_now,
info->vegas.tcpv_rttcnt = ca->cntRTT,
info->vegas.tcpv_rtt = ca->baseRTT,
info->vegas.tcpv_minrtt = ca->minRTT,

*attr = INET_DIAG_VEGASINFO;
return sizeof(struct tcpvegas_info);
}
return 0;
}
Expand Down
3 changes: 2 additions & 1 deletion net/ipv4/tcp_vegas.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ void tcp_vegas_init(struct sock *sk);
void tcp_vegas_state(struct sock *sk, u8 ca_state);
void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, s32 rtt_us);
void tcp_vegas_cwnd_event(struct sock *sk, enum tcp_ca_event event);
int tcp_vegas_get_info(struct sock *sk, u32 ext, struct sk_buff *skb);
size_t tcp_vegas_get_info(struct sock *sk, u32 ext, int *attr,
union tcp_cc_info *info);

#endif /* __TCP_VEGAS_H */

0 comments on commit 64f40ff

Please sign in to comment.