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.

net/tcp: Add static_key for TCP-AO

Similarly to TCP-MD5, add a static key to TCP-AO that is patched out
when there are no keys on a machine and dynamically enabled with the
first setsockopt(TCP_AO) adds a key on any socket. The static key is as
well dynamically disabled later when the socket is destructed.

The lifetime of enabled static key here is the same as ao_info: it is
enabled on allocation, passed over from full socket to twsk and
destructed when ao_info is scheduled for destruction.

Signed-off-by: Dmitry Safonov <dima@arista.com>
Acked-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Dmitry Safonov and committed by
David S. Miller
67fa83f7 d6732b95

+98 -46
+16 -8
include/net/tcp.h
··· 2288 2288 #if defined(CONFIG_TCP_AO) || defined(CONFIG_TCP_MD5SIG) 2289 2289 const struct tcp_sock *tp = tcp_sk(sk); 2290 2290 #endif 2291 - #ifdef CONFIG_TCP_AO 2292 - struct tcp_ao_info *ao; 2293 2291 2294 - ao = rcu_dereference_protected(tp->ao_info, lockdep_sock_is_held(sk)); 2295 - if (ao) { 2296 - out->ao_key = READ_ONCE(ao->current_key); 2297 - out->type = TCP_KEY_AO; 2298 - return; 2292 + #ifdef CONFIG_TCP_AO 2293 + if (static_branch_unlikely(&tcp_ao_needed.key)) { 2294 + struct tcp_ao_info *ao; 2295 + 2296 + ao = rcu_dereference_protected(tp->ao_info, 2297 + lockdep_sock_is_held(sk)); 2298 + if (ao) { 2299 + out->ao_key = READ_ONCE(ao->current_key); 2300 + out->type = TCP_KEY_AO; 2301 + return; 2302 + } 2299 2303 } 2300 2304 #endif 2301 2305 #ifdef CONFIG_TCP_MD5SIG ··· 2328 2324 static inline bool tcp_key_is_ao(const struct tcp_key *key) 2329 2325 { 2330 2326 #ifdef CONFIG_TCP_AO 2331 - if (key->type == TCP_KEY_AO) 2327 + if (static_branch_unlikely(&tcp_ao_needed.key) && 2328 + key->type == TCP_KEY_AO) 2332 2329 return true; 2333 2330 #endif 2334 2331 return false; ··· 2722 2717 #ifdef CONFIG_TCP_AO 2723 2718 struct tcp_ao_info *ao_info; 2724 2719 struct tcp_ao_key *ao_key; 2720 + 2721 + if (!static_branch_unlikely(&tcp_ao_needed.key)) 2722 + return false; 2725 2723 2726 2724 ao_info = rcu_dereference_check(tcp_sk(sk)->ao_info, 2727 2725 lockdep_sock_is_held(sk));
+2
include/net/tcp_ao.h
··· 151 151 152 152 #ifdef CONFIG_TCP_AO 153 153 /* TCP-AO structures and functions */ 154 + #include <linux/jump_label.h> 155 + extern struct static_key_false_deferred tcp_ao_needed; 154 156 155 157 struct tcp4_ao_context { 156 158 __be32 saddr;
+22
net/ipv4/tcp_ao.c
··· 17 17 #include <net/ipv6.h> 18 18 #include <net/icmp.h> 19 19 20 + DEFINE_STATIC_KEY_DEFERRED_FALSE(tcp_ao_needed, HZ); 21 + 20 22 int tcp_ao_calc_traffic_key(struct tcp_ao_key *mkt, u8 *key, void *ctx, 21 23 unsigned int len, struct tcp_sigpool *hp) 22 24 { ··· 51 49 { 52 50 bool ignore_icmp = false; 53 51 struct tcp_ao_info *ao; 52 + 53 + if (!static_branch_unlikely(&tcp_ao_needed.key)) 54 + return false; 54 55 55 56 /* RFC5925, 7.8: 56 57 * >> A TCP-AO implementation MUST default to ignore incoming ICMPv4 ··· 190 185 struct tcp_ao_key *key; 191 186 struct tcp_ao_info *ao; 192 187 188 + if (!static_branch_unlikely(&tcp_ao_needed.key)) 189 + return NULL; 190 + 193 191 ao = rcu_dereference_check(tcp_sk(sk)->ao_info, 194 192 lockdep_sock_is_held(sk)); 195 193 if (!ao) ··· 284 276 } 285 277 286 278 kfree_rcu(ao, rcu); 279 + static_branch_slow_dec_deferred(&tcp_ao_needed); 287 280 } 288 281 289 282 void tcp_ao_time_wait(struct tcp_timewait_sock *tcptw, struct tcp_sock *tp) ··· 1189 1180 goto free_and_exit; 1190 1181 } 1191 1182 1183 + if (!static_key_fast_inc_not_disabled(&tcp_ao_needed.key.key)) { 1184 + ret = -EUSERS; 1185 + goto free_and_exit; 1186 + } 1187 + 1192 1188 key_head = rcu_dereference(hlist_first_rcu(&new_ao->head)); 1193 1189 first_key = hlist_entry_safe(key_head, struct tcp_ao_key, node); 1194 1190 ··· 1621 1607 1622 1608 tcp_ao_link_mkt(ao_info, key); 1623 1609 if (first) { 1610 + if (!static_branch_inc(&tcp_ao_needed.key)) { 1611 + ret = -EUSERS; 1612 + goto err_free_sock; 1613 + } 1624 1614 sk_gso_disable(sk); 1625 1615 rcu_assign_pointer(tcp_sk(sk)->ao_info, ao_info); 1626 1616 } ··· 1893 1875 if (new_rnext) 1894 1876 WRITE_ONCE(ao_info->rnext_key, new_rnext); 1895 1877 if (first) { 1878 + if (!static_branch_inc(&tcp_ao_needed.key)) { 1879 + err = -EUSERS; 1880 + goto out; 1881 + } 1896 1882 sk_gso_disable(sk); 1897 1883 rcu_assign_pointer(tcp_sk(sk)->ao_info, ao_info); 1898 1884 }
+30 -16
net/ipv4/tcp_input.c
··· 3572 3572 (ack_seq == tp->snd_wl1 && (nwin > tp->snd_wnd || !nwin)); 3573 3573 } 3574 3574 3575 - /* If we update tp->snd_una, also update tp->bytes_acked */ 3576 - static void tcp_snd_una_update(struct tcp_sock *tp, u32 ack) 3575 + static void tcp_snd_sne_update(struct tcp_sock *tp, u32 ack) 3577 3576 { 3578 - u32 delta = ack - tp->snd_una; 3579 3577 #ifdef CONFIG_TCP_AO 3580 3578 struct tcp_ao_info *ao; 3581 - #endif 3582 3579 3583 - sock_owned_by_me((struct sock *)tp); 3584 - tp->bytes_acked += delta; 3585 - #ifdef CONFIG_TCP_AO 3580 + if (!static_branch_unlikely(&tcp_ao_needed.key)) 3581 + return; 3582 + 3586 3583 ao = rcu_dereference_protected(tp->ao_info, 3587 3584 lockdep_sock_is_held((struct sock *)tp)); 3588 3585 if (ao && ack < tp->snd_una) 3589 3586 ao->snd_sne++; 3590 3587 #endif 3588 + } 3589 + 3590 + /* If we update tp->snd_una, also update tp->bytes_acked */ 3591 + static void tcp_snd_una_update(struct tcp_sock *tp, u32 ack) 3592 + { 3593 + u32 delta = ack - tp->snd_una; 3594 + 3595 + sock_owned_by_me((struct sock *)tp); 3596 + tp->bytes_acked += delta; 3597 + tcp_snd_sne_update(tp, ack); 3591 3598 tp->snd_una = ack; 3599 + } 3600 + 3601 + static void tcp_rcv_sne_update(struct tcp_sock *tp, u32 seq) 3602 + { 3603 + #ifdef CONFIG_TCP_AO 3604 + struct tcp_ao_info *ao; 3605 + 3606 + if (!static_branch_unlikely(&tcp_ao_needed.key)) 3607 + return; 3608 + 3609 + ao = rcu_dereference_protected(tp->ao_info, 3610 + lockdep_sock_is_held((struct sock *)tp)); 3611 + if (ao && seq < tp->rcv_nxt) 3612 + ao->rcv_sne++; 3613 + #endif 3592 3614 } 3593 3615 3594 3616 /* If we update tp->rcv_nxt, also update tp->bytes_received */ 3595 3617 static void tcp_rcv_nxt_update(struct tcp_sock *tp, u32 seq) 3596 3618 { 3597 3619 u32 delta = seq - tp->rcv_nxt; 3598 - #ifdef CONFIG_TCP_AO 3599 - struct tcp_ao_info *ao; 3600 - #endif 3601 3620 3602 3621 sock_owned_by_me((struct sock *)tp); 3603 3622 tp->bytes_received += delta; 3604 - #ifdef CONFIG_TCP_AO 3605 - ao = rcu_dereference_protected(tp->ao_info, 3606 - lockdep_sock_is_held((struct sock *)tp)); 3607 - if (ao && seq < tp->rcv_nxt) 3608 - ao->rcv_sne++; 3609 - #endif 3623 + tcp_rcv_sne_update(tp, seq); 3610 3624 WRITE_ONCE(tp->rcv_nxt, seq); 3611 3625 } 3612 3626
+14 -11
net/ipv4/tcp_ipv4.c
··· 1024 1024 #ifdef CONFIG_TCP_AO 1025 1025 struct tcp_ao_info *ao_info; 1026 1026 1027 - /* FIXME: the segment to-be-acked is not verified yet */ 1028 - ao_info = rcu_dereference(tcptw->ao_info); 1029 - if (ao_info) { 1030 - const struct tcp_ao_hdr *aoh; 1027 + if (static_branch_unlikely(&tcp_ao_needed.key)) { 1028 + /* FIXME: the segment to-be-acked is not verified yet */ 1029 + ao_info = rcu_dereference(tcptw->ao_info); 1030 + if (ao_info) { 1031 + const struct tcp_ao_hdr *aoh; 1031 1032 1032 - if (tcp_parse_auth_options(tcp_hdr(skb), NULL, &aoh)) { 1033 - inet_twsk_put(tw); 1034 - return; 1033 + if (tcp_parse_auth_options(tcp_hdr(skb), NULL, &aoh)) { 1034 + inet_twsk_put(tw); 1035 + return; 1036 + } 1037 + 1038 + if (aoh) 1039 + key.ao_key = tcp_ao_established_key(ao_info, aoh->rnext_keyid, -1); 1035 1040 } 1036 - 1037 - if (aoh) 1038 - key.ao_key = tcp_ao_established_key(ao_info, aoh->rnext_keyid, -1); 1039 1041 } 1040 1042 if (key.ao_key) { 1041 1043 struct tcp_ao_key *rnext_key; ··· 1083 1081 tcp_sk(sk)->snd_nxt; 1084 1082 1085 1083 #ifdef CONFIG_TCP_AO 1086 - if (tcp_rsk_used_ao(req)) { 1084 + if (static_branch_unlikely(&tcp_ao_needed.key) && 1085 + tcp_rsk_used_ao(req)) { 1087 1086 const union tcp_md5_addr *addr; 1088 1087 const struct tcp_ao_hdr *aoh; 1089 1088
+14 -11
net/ipv6/tcp_ipv6.c
··· 1154 1154 #ifdef CONFIG_TCP_AO 1155 1155 struct tcp_ao_info *ao_info; 1156 1156 1157 - /* FIXME: the segment to-be-acked is not verified yet */ 1158 - ao_info = rcu_dereference(tcptw->ao_info); 1159 - if (ao_info) { 1160 - const struct tcp_ao_hdr *aoh; 1157 + if (static_branch_unlikely(&tcp_ao_needed.key)) { 1161 1158 1162 - /* Invalid TCP option size or twice included auth */ 1163 - if (tcp_parse_auth_options(tcp_hdr(skb), NULL, &aoh)) 1164 - goto out; 1165 - if (aoh) { 1166 - key.ao_key = tcp_ao_established_key(ao_info, 1167 - aoh->rnext_keyid, -1); 1159 + /* FIXME: the segment to-be-acked is not verified yet */ 1160 + ao_info = rcu_dereference(tcptw->ao_info); 1161 + if (ao_info) { 1162 + const struct tcp_ao_hdr *aoh; 1163 + 1164 + /* Invalid TCP option size or twice included auth */ 1165 + if (tcp_parse_auth_options(tcp_hdr(skb), NULL, &aoh)) 1166 + goto out; 1167 + if (aoh) 1168 + key.ao_key = tcp_ao_established_key(ao_info, 1169 + aoh->rnext_keyid, -1); 1168 1170 } 1169 1171 } 1170 1172 if (key.ao_key) { ··· 1208 1206 struct tcp_key key = {}; 1209 1207 1210 1208 #ifdef CONFIG_TCP_AO 1211 - if (tcp_rsk_used_ao(req)) { 1209 + if (static_branch_unlikely(&tcp_ao_needed.key) && 1210 + tcp_rsk_used_ao(req)) { 1212 1211 const struct in6_addr *addr = &ipv6_hdr(skb)->saddr; 1213 1212 const struct tcp_ao_hdr *aoh; 1214 1213 int l3index;