Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tcp: populate inet->cork.fl.u.ip6 in tcp_v6_connect()

Instead of using private @fl6 and @final variables
use respectively inet->cork.fl.u.ip6 and np->final.

As explained in commit 85d05e281712 ("ipv6: change inet6_sk_rebuild_header()
to use inet->cork.fl.u.ip6"):

TCP v6 spends a good amount of time rebuilding a fresh fl6 at each
transmit in inet6_csk_xmit()/inet6_csk_route_socket().

TCP v4 caches the information in inet->cork.fl.u.ip4 instead.

After this patch, active TCP ipv6 flows have correctly initialized
inet->cork.fl.u.ip6 structure.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20260206173426.1638518-6-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
19bdb267 969a2019

+24 -23
+24 -23
net/ipv6/tcp_ipv6.c
··· 138 138 { 139 139 struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; 140 140 struct inet_connection_sock *icsk = inet_csk(sk); 141 - struct in6_addr *saddr = NULL, *final_p, final; 142 141 struct inet_timewait_death_row *tcp_death_row; 143 142 struct ipv6_pinfo *np = tcp_inet6_sk(sk); 143 + struct in6_addr *saddr = NULL, *final_p; 144 144 struct inet_sock *inet = inet_sk(sk); 145 145 struct tcp_sock *tp = tcp_sk(sk); 146 146 struct net *net = sock_net(sk); 147 147 struct ipv6_txoptions *opt; 148 148 struct dst_entry *dst; 149 - struct flowi6 fl6; 149 + struct flowi6 *fl6; 150 150 int addr_type; 151 151 int err; 152 152 ··· 156 156 if (usin->sin6_family != AF_INET6) 157 157 return -EAFNOSUPPORT; 158 158 159 - memset(&fl6, 0, sizeof(fl6)); 159 + fl6 = &inet_sk(sk)->cork.fl.u.ip6; 160 + memset(fl6, 0, sizeof(*fl6)); 160 161 161 162 if (inet6_test_bit(SNDFLOW, sk)) { 162 - fl6.flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK; 163 - IP6_ECN_flow_init(fl6.flowlabel); 164 - if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) { 163 + fl6->flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK; 164 + IP6_ECN_flow_init(fl6->flowlabel); 165 + if (fl6->flowlabel & IPV6_FLOWLABEL_MASK) { 165 166 struct ip6_flowlabel *flowlabel; 166 - flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); 167 + flowlabel = fl6_sock_lookup(sk, fl6->flowlabel); 167 168 if (IS_ERR(flowlabel)) 168 169 return -EINVAL; 169 170 fl6_sock_release(flowlabel); ··· 213 212 } 214 213 215 214 sk->sk_v6_daddr = usin->sin6_addr; 216 - np->flow_label = fl6.flowlabel; 215 + np->flow_label = fl6->flowlabel; 217 216 218 217 /* 219 218 * TCP over IPv4 ··· 261 260 if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) 262 261 saddr = &sk->sk_v6_rcv_saddr; 263 262 264 - fl6.flowi6_proto = IPPROTO_TCP; 265 - fl6.daddr = sk->sk_v6_daddr; 266 - fl6.saddr = saddr ? *saddr : np->saddr; 267 - fl6.flowlabel = ip6_make_flowinfo(np->tclass, np->flow_label); 268 - fl6.flowi6_oif = sk->sk_bound_dev_if; 269 - fl6.flowi6_mark = sk->sk_mark; 270 - fl6.fl6_dport = usin->sin6_port; 271 - fl6.fl6_sport = inet->inet_sport; 272 - if (IS_ENABLED(CONFIG_IP_ROUTE_MULTIPATH) && !fl6.fl6_sport) 273 - fl6.flowi6_flags = FLOWI_FLAG_ANY_SPORT; 274 - fl6.flowi6_uid = sk_uid(sk); 263 + fl6->flowi6_proto = IPPROTO_TCP; 264 + fl6->daddr = sk->sk_v6_daddr; 265 + fl6->saddr = saddr ? *saddr : np->saddr; 266 + fl6->flowlabel = ip6_make_flowinfo(np->tclass, np->flow_label); 267 + fl6->flowi6_oif = sk->sk_bound_dev_if; 268 + fl6->flowi6_mark = sk->sk_mark; 269 + fl6->fl6_dport = usin->sin6_port; 270 + fl6->fl6_sport = inet->inet_sport; 271 + if (IS_ENABLED(CONFIG_IP_ROUTE_MULTIPATH) && !fl6->fl6_sport) 272 + fl6->flowi6_flags = FLOWI_FLAG_ANY_SPORT; 273 + fl6->flowi6_uid = sk_uid(sk); 275 274 276 275 opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk)); 277 - final_p = fl6_update_dst(&fl6, opt, &final); 276 + final_p = fl6_update_dst(fl6, opt, &np->final); 278 277 279 - security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6)); 278 + security_sk_classify_flow(sk, flowi6_to_flowi_common(fl6)); 280 279 281 - dst = ip6_dst_lookup_flow(net, sk, &fl6, final_p); 280 + dst = ip6_dst_lookup_flow(net, sk, fl6, final_p); 282 281 if (IS_ERR(dst)) { 283 282 err = PTR_ERR(dst); 284 283 goto failure; ··· 288 287 tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row; 289 288 290 289 if (!saddr) { 291 - saddr = &fl6.saddr; 290 + saddr = &fl6->saddr; 292 291 293 292 err = inet_bhash2_update_saddr(sk, saddr, AF_INET6); 294 293 if (err)