mirror of
https://github.com/torvalds/linux.git
synced 2024-10-23 21:50:43 +00:00
tcp: metrics: Handle v6/v4-mapped sockets in tcp-metrics
A socket may be v6/v4-mapped. In that case sk->sk_family is AF_INET6, but the IP being used is actually an IPv4-address. Current's tcp-metrics will thus represent it as an IPv6-address: root@server:~# ip tcp_metrics ::ffff:10.1.1.2 age 22.920sec rtt 18750us rttvar 15000us cwnd 10 10.1.1.2 age 47.970sec rtt 16250us rttvar 10000us cwnd 10 This patch modifies the tcp-metrics so that they are able to handle the v6/v4-mapped sockets correctly. Signed-off-by: Christoph Paasch <christoph.paasch@uclouvain.be> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5ae5e991ee
commit
3ad88cf70a
|
@ -274,24 +274,32 @@ static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock
|
||||||
unsigned int hash;
|
unsigned int hash;
|
||||||
struct net *net;
|
struct net *net;
|
||||||
|
|
||||||
saddr.family = tw->tw_family;
|
if (tw->tw_family == AF_INET) {
|
||||||
daddr.family = tw->tw_family;
|
saddr.family = AF_INET;
|
||||||
switch (daddr.family) {
|
|
||||||
case AF_INET:
|
|
||||||
saddr.addr.a4 = tw->tw_rcv_saddr;
|
saddr.addr.a4 = tw->tw_rcv_saddr;
|
||||||
|
daddr.family = AF_INET;
|
||||||
daddr.addr.a4 = tw->tw_daddr;
|
daddr.addr.a4 = tw->tw_daddr;
|
||||||
hash = (__force unsigned int) daddr.addr.a4;
|
hash = (__force unsigned int) daddr.addr.a4;
|
||||||
break;
|
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
|
||||||
case AF_INET6:
|
|
||||||
*(struct in6_addr *)saddr.addr.a6 = tw->tw_v6_rcv_saddr;
|
|
||||||
*(struct in6_addr *)daddr.addr.a6 = tw->tw_v6_daddr;
|
|
||||||
hash = ipv6_addr_hash(&tw->tw_v6_daddr);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
else if (tw->tw_family == AF_INET6) {
|
||||||
|
if (ipv6_addr_v4mapped(&tw->tw_v6_daddr)) {
|
||||||
|
saddr.family = AF_INET;
|
||||||
|
saddr.addr.a4 = tw->tw_rcv_saddr;
|
||||||
|
daddr.family = AF_INET;
|
||||||
|
daddr.addr.a4 = tw->tw_daddr;
|
||||||
|
hash = (__force unsigned int) daddr.addr.a4;
|
||||||
|
} else {
|
||||||
|
saddr.family = AF_INET6;
|
||||||
|
*(struct in6_addr *)saddr.addr.a6 = tw->tw_v6_rcv_saddr;
|
||||||
|
daddr.family = AF_INET6;
|
||||||
|
*(struct in6_addr *)daddr.addr.a6 = tw->tw_v6_daddr;
|
||||||
|
hash = ipv6_addr_hash(&tw->tw_v6_daddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
net = twsk_net(tw);
|
net = twsk_net(tw);
|
||||||
hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log);
|
hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log);
|
||||||
|
@ -314,24 +322,32 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
|
||||||
unsigned int hash;
|
unsigned int hash;
|
||||||
struct net *net;
|
struct net *net;
|
||||||
|
|
||||||
saddr.family = sk->sk_family;
|
if (sk->sk_family == AF_INET) {
|
||||||
daddr.family = sk->sk_family;
|
saddr.family = AF_INET;
|
||||||
switch (daddr.family) {
|
|
||||||
case AF_INET:
|
|
||||||
saddr.addr.a4 = inet_sk(sk)->inet_saddr;
|
saddr.addr.a4 = inet_sk(sk)->inet_saddr;
|
||||||
|
daddr.family = AF_INET;
|
||||||
daddr.addr.a4 = inet_sk(sk)->inet_daddr;
|
daddr.addr.a4 = inet_sk(sk)->inet_daddr;
|
||||||
hash = (__force unsigned int) daddr.addr.a4;
|
hash = (__force unsigned int) daddr.addr.a4;
|
||||||
break;
|
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
|
||||||
case AF_INET6:
|
|
||||||
*(struct in6_addr *)saddr.addr.a6 = sk->sk_v6_rcv_saddr;
|
|
||||||
*(struct in6_addr *)daddr.addr.a6 = sk->sk_v6_daddr;
|
|
||||||
hash = ipv6_addr_hash(&sk->sk_v6_daddr);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
else if (sk->sk_family == AF_INET6) {
|
||||||
|
if (ipv6_addr_v4mapped(&sk->sk_v6_daddr)) {
|
||||||
|
saddr.family = AF_INET;
|
||||||
|
saddr.addr.a4 = inet_sk(sk)->inet_saddr;
|
||||||
|
daddr.family = AF_INET;
|
||||||
|
daddr.addr.a4 = inet_sk(sk)->inet_daddr;
|
||||||
|
hash = (__force unsigned int) daddr.addr.a4;
|
||||||
|
} else {
|
||||||
|
saddr.family = AF_INET6;
|
||||||
|
*(struct in6_addr *)saddr.addr.a6 = sk->sk_v6_rcv_saddr;
|
||||||
|
daddr.family = AF_INET6;
|
||||||
|
*(struct in6_addr *)daddr.addr.a6 = sk->sk_v6_daddr;
|
||||||
|
hash = ipv6_addr_hash(&sk->sk_v6_daddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
net = dev_net(dst->dev);
|
net = dev_net(dst->dev);
|
||||||
hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log);
|
hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user