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.

Merge branch 'mptcp-mib-counters'

Matthieu Baerts says:

====================
mptcp: add CurrEstab MIB counter

This MIB counter is similar to the one of TCP -- CurrEstab -- available
in /proc/net/snmp. This is useful to quickly list the number of MPTCP
connections without having to iterate over all of them.

Patch 1 prepares its support by adding new helper functions:

- MPTCP_DEC_STATS(): similar to MPTCP_INC_STATS(), but this time to
decrement a counter.

- mptcp_set_state(): similar to tcp_set_state(), to change the state of
an MPTCP socket, and to inc/decrement the new counter when needed.

Patch 2 uses mptcp_set_state() instead of directly calling
inet_sk_state_store() to change the state of MPTCP sockets.

Patch 3 and 4 validate the new feature in MPTCP "join" and "diag"
selftests.
====================

Signed-off-by: Matthieu Baerts <matttbe@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

+110 -26
+1
net/mptcp/mib.c
··· 66 66 SNMP_MIB_ITEM("RcvWndShared", MPTCP_MIB_RCVWNDSHARED), 67 67 SNMP_MIB_ITEM("RcvWndConflictUpdate", MPTCP_MIB_RCVWNDCONFLICTUPDATE), 68 68 SNMP_MIB_ITEM("RcvWndConflict", MPTCP_MIB_RCVWNDCONFLICT), 69 + SNMP_MIB_ITEM("MPCurrEstab", MPTCP_MIB_CURRESTAB), 69 70 SNMP_MIB_SENTINEL 70 71 }; 71 72
+8
net/mptcp/mib.h
··· 65 65 * conflict with another subflow while updating msk rcv wnd 66 66 */ 67 67 MPTCP_MIB_RCVWNDCONFLICT, /* Conflict with while updating msk rcv wnd */ 68 + MPTCP_MIB_CURRESTAB, /* Current established MPTCP connections */ 68 69 __MPTCP_MIB_MAX 69 70 }; 70 71 ··· 94 93 { 95 94 if (likely(net->mib.mptcp_statistics)) 96 95 __SNMP_INC_STATS(net->mib.mptcp_statistics, field); 96 + } 97 + 98 + static inline void MPTCP_DEC_STATS(struct net *net, 99 + enum linux_mptcp_mib_field field) 100 + { 101 + if (likely(net->mib.mptcp_statistics)) 102 + SNMP_DEC_STATS(net->mib.mptcp_statistics, field); 97 103 } 98 104 99 105 bool mptcp_mib_alloc(struct net *net);
+5
net/mptcp/pm_netlink.c
··· 1048 1048 if (err) 1049 1049 return err; 1050 1050 1051 + /* We don't use mptcp_set_state() here because it needs to be called 1052 + * under the msk socket lock. For the moment, that will not bring 1053 + * anything more than only calling inet_sk_state_store(), because the 1054 + * old status is known (TCP_CLOSE). 1055 + */ 1051 1056 inet_sk_state_store(newsk, TCP_LISTEN); 1052 1057 lock_sock(ssk); 1053 1058 err = __inet_listen_sk(ssk, backlog);
+37 -19
net/mptcp/protocol.c
··· 429 429 430 430 switch (sk->sk_state) { 431 431 case TCP_FIN_WAIT1: 432 - inet_sk_state_store(sk, TCP_FIN_WAIT2); 432 + mptcp_set_state(sk, TCP_FIN_WAIT2); 433 433 break; 434 434 case TCP_CLOSING: 435 435 case TCP_LAST_ACK: 436 - inet_sk_state_store(sk, TCP_CLOSE); 436 + mptcp_set_state(sk, TCP_CLOSE); 437 437 break; 438 438 } 439 439 ··· 594 594 595 595 switch (sk->sk_state) { 596 596 case TCP_ESTABLISHED: 597 - inet_sk_state_store(sk, TCP_CLOSE_WAIT); 597 + mptcp_set_state(sk, TCP_CLOSE_WAIT); 598 598 break; 599 599 case TCP_FIN_WAIT1: 600 - inet_sk_state_store(sk, TCP_CLOSING); 600 + mptcp_set_state(sk, TCP_CLOSING); 601 601 break; 602 602 case TCP_FIN_WAIT2: 603 - inet_sk_state_store(sk, TCP_CLOSE); 603 + mptcp_set_state(sk, TCP_CLOSE); 604 604 break; 605 605 default: 606 606 /* Other states not expected */ ··· 775 775 */ 776 776 ssk_state = inet_sk_state_load(ssk); 777 777 if (ssk_state == TCP_CLOSE && !sock_flag(sk, SOCK_DEAD)) 778 - inet_sk_state_store(sk, ssk_state); 778 + mptcp_set_state(sk, ssk_state); 779 779 WRITE_ONCE(sk->sk_err, -err); 780 780 781 781 /* This barrier is coupled with smp_rmb() in mptcp_poll() */ ··· 2463 2463 inet_sk_state_load(msk->first) == TCP_CLOSE) { 2464 2464 if (sk->sk_state != TCP_ESTABLISHED || 2465 2465 msk->in_accept_queue || sock_flag(sk, SOCK_DEAD)) { 2466 - inet_sk_state_store(sk, TCP_CLOSE); 2466 + mptcp_set_state(sk, TCP_CLOSE); 2467 2467 mptcp_close_wake_up(sk); 2468 2468 } else { 2469 2469 mptcp_start_tout_timer(sk); ··· 2558 2558 WRITE_ONCE(sk->sk_err, ECONNRESET); 2559 2559 } 2560 2560 2561 - inet_sk_state_store(sk, TCP_CLOSE); 2561 + mptcp_set_state(sk, TCP_CLOSE); 2562 2562 WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK); 2563 2563 smp_mb__before_atomic(); /* SHUTDOWN must be visible first */ 2564 2564 set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags); ··· 2693 2693 struct mptcp_subflow_context *subflow, *tmp; 2694 2694 struct mptcp_sock *msk = mptcp_sk(sk); 2695 2695 2696 - inet_sk_state_store(sk, TCP_CLOSE); 2696 + mptcp_set_state(sk, TCP_CLOSE); 2697 2697 mptcp_for_each_subflow_safe(msk, subflow, tmp) 2698 2698 __mptcp_close_ssk(sk, mptcp_subflow_tcp_sock(subflow), 2699 2699 subflow, MPTCP_CF_FASTCLOSE); ··· 2871 2871 release_sock(ssk); 2872 2872 } 2873 2873 2874 + void mptcp_set_state(struct sock *sk, int state) 2875 + { 2876 + int oldstate = sk->sk_state; 2877 + 2878 + switch (state) { 2879 + case TCP_ESTABLISHED: 2880 + if (oldstate != TCP_ESTABLISHED) 2881 + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_CURRESTAB); 2882 + break; 2883 + 2884 + default: 2885 + if (oldstate == TCP_ESTABLISHED) 2886 + MPTCP_DEC_STATS(sock_net(sk), MPTCP_MIB_CURRESTAB); 2887 + } 2888 + 2889 + inet_sk_state_store(sk, state); 2890 + } 2891 + 2874 2892 static const unsigned char new_state[16] = { 2875 2893 /* current state: new state: action: */ 2876 2894 [0 /* (Invalid) */] = TCP_CLOSE, ··· 2911 2893 int next = (int)new_state[sk->sk_state]; 2912 2894 int ns = next & TCP_STATE_MASK; 2913 2895 2914 - inet_sk_state_store(sk, ns); 2896 + mptcp_set_state(sk, ns); 2915 2897 2916 2898 return next & TCP_ACTION_FIN; 2917 2899 } ··· 3022 3004 3023 3005 if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) { 3024 3006 mptcp_check_listen_stop(sk); 3025 - inet_sk_state_store(sk, TCP_CLOSE); 3007 + mptcp_set_state(sk, TCP_CLOSE); 3026 3008 goto cleanup; 3027 3009 } 3028 3010 ··· 3065 3047 * state, let's not keep resources busy for no reasons 3066 3048 */ 3067 3049 if (subflows_alive == 0) 3068 - inet_sk_state_store(sk, TCP_CLOSE); 3050 + mptcp_set_state(sk, TCP_CLOSE); 3069 3051 3070 3052 sock_hold(sk); 3071 3053 pr_debug("msk=%p state=%d", sk, sk->sk_state); ··· 3131 3113 return -EBUSY; 3132 3114 3133 3115 mptcp_check_listen_stop(sk); 3134 - inet_sk_state_store(sk, TCP_CLOSE); 3116 + mptcp_set_state(sk, TCP_CLOSE); 3135 3117 3136 3118 mptcp_stop_rtx_timer(sk); 3137 3119 mptcp_stop_tout_timer(sk); ··· 3219 3201 /* this can't race with mptcp_close(), as the msk is 3220 3202 * not yet exposted to user-space 3221 3203 */ 3222 - inet_sk_state_store(nsk, TCP_ESTABLISHED); 3204 + mptcp_set_state(nsk, TCP_ESTABLISHED); 3223 3205 3224 3206 /* The msk maintain a ref to each subflow in the connections list */ 3225 3207 WRITE_ONCE(msk->first, ssk); ··· 3640 3622 if (IS_ERR(ssk)) 3641 3623 return PTR_ERR(ssk); 3642 3624 3643 - inet_sk_state_store(sk, TCP_SYN_SENT); 3625 + mptcp_set_state(sk, TCP_SYN_SENT); 3644 3626 subflow = mptcp_subflow_ctx(ssk); 3645 3627 #ifdef CONFIG_TCP_MD5SIG 3646 3628 /* no MPTCP if MD5SIG is enabled on this socket or we may run out of ··· 3690 3672 if (unlikely(err)) { 3691 3673 /* avoid leaving a dangling token in an unconnected socket */ 3692 3674 mptcp_token_destroy(msk); 3693 - inet_sk_state_store(sk, TCP_CLOSE); 3675 + mptcp_set_state(sk, TCP_CLOSE); 3694 3676 return err; 3695 3677 } 3696 3678 ··· 3779 3761 goto unlock; 3780 3762 } 3781 3763 3782 - inet_sk_state_store(sk, TCP_LISTEN); 3764 + mptcp_set_state(sk, TCP_LISTEN); 3783 3765 sock_set_flag(sk, SOCK_RCU_FREE); 3784 3766 3785 3767 lock_sock(ssk); 3786 3768 err = __inet_listen_sk(ssk, backlog); 3787 3769 release_sock(ssk); 3788 - inet_sk_state_store(sk, inet_sk_state_load(ssk)); 3770 + mptcp_set_state(sk, inet_sk_state_load(ssk)); 3789 3771 3790 3772 if (!err) { 3791 3773 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); ··· 3863 3845 __mptcp_close_ssk(newsk, msk->first, 3864 3846 mptcp_subflow_ctx(msk->first), 0); 3865 3847 if (unlikely(list_is_singular(&msk->conn_list))) 3866 - inet_sk_state_store(newsk, TCP_CLOSE); 3848 + mptcp_set_state(newsk, TCP_CLOSE); 3867 3849 } 3868 3850 } else { 3869 3851 MPTCP_INC_STATS(sock_net(ssk),
+1
net/mptcp/protocol.h
··· 641 641 void mptcp_cancel_work(struct sock *sk); 642 642 void __mptcp_unaccepted_force_close(struct sock *sk); 643 643 void mptcp_set_owner_r(struct sk_buff *skb, struct sock *sk); 644 + void mptcp_set_state(struct sock *sk, int state); 644 645 645 646 bool mptcp_addresses_equal(const struct mptcp_addr_info *a, 646 647 const struct mptcp_addr_info *b, bool use_port);
+1 -1
net/mptcp/subflow.c
··· 425 425 426 426 __mptcp_propagate_sndbuf(sk, msk->first); 427 427 if (sk->sk_state == TCP_SYN_SENT) { 428 - inet_sk_state_store(sk, state); 428 + mptcp_set_state(sk, state); 429 429 sk->sk_state_change(sk); 430 430 } 431 431 }
+16 -1
tools/testing/selftests/net/mptcp/diag.sh
··· 56 56 local command="$1" 57 57 local expected=$2 58 58 local msg="$3" 59 - local skip="${4:-SKIP}" 59 + local skip="${4-SKIP}" 60 60 local nr 61 61 62 62 nr=$(eval $command) ··· 182 182 __chk_nr get_msk_inuse $expected "$msg" 0 183 183 } 184 184 185 + # $1: cestab nr 186 + chk_msk_cestab() 187 + { 188 + local cestab=$1 189 + 190 + __chk_nr "mptcp_lib_get_counter ${ns} MPTcpExtMPCurrEstab" \ 191 + "${cestab}" "....chk ${cestab} cestab" "" 192 + } 193 + 185 194 wait_connected() 186 195 { 187 196 local listener_ns="${1}" ··· 228 219 chk_msk_remote_key_nr 2 "....chk remote_key" 229 220 chk_msk_fallback_nr 0 "....chk no fallback" 230 221 chk_msk_inuse 2 "....chk 2 msk in use" 222 + chk_msk_cestab 2 231 223 flush_pids 232 224 233 225 chk_msk_inuse 0 "....chk 0 msk in use after flush" 226 + chk_msk_cestab 0 234 227 235 228 echo "a" | \ 236 229 timeout ${timeout_test} \ ··· 248 237 wait_connected $ns 10001 249 238 chk_msk_fallback_nr 1 "check fallback" 250 239 chk_msk_inuse 1 "....chk 1 msk in use" 240 + chk_msk_cestab 1 251 241 flush_pids 252 242 253 243 chk_msk_inuse 0 "....chk 0 msk in use after flush" 244 + chk_msk_cestab 0 254 245 255 246 NR_CLIENTS=100 256 247 for I in `seq 1 $NR_CLIENTS`; do ··· 274 261 275 262 wait_msk_nr $((NR_CLIENTS*2)) "many msk socket present" 276 263 chk_msk_inuse $((NR_CLIENTS*2)) "....chk many msk in use" 264 + chk_msk_cestab $((NR_CLIENTS*2)) 277 265 flush_pids 278 266 279 267 chk_msk_inuse 0 "....chk 0 msk in use after flush" 268 + chk_msk_cestab 0 280 269 281 270 mptcp_lib_result_print_all_tap 282 271 exit $ret
+41 -5
tools/testing/selftests/net/mptcp/mptcp_join.sh
··· 56 56 unset test_linkfail 57 57 unset addr_nr_ns1 58 58 unset addr_nr_ns2 59 + unset cestab_ns1 60 + unset cestab_ns2 59 61 unset sflags 60 62 unset fastclose 61 63 unset fullmesh ··· 978 976 fi 979 977 } 980 978 979 + chk_cestab_nr() 980 + { 981 + local ns=$1 982 + local cestab=$2 983 + local count 984 + 985 + print_check "cestab $cestab" 986 + count=$(mptcp_lib_get_counter ${ns} "MPTcpExtMPCurrEstab") 987 + if [ -z "$count" ]; then 988 + print_skip 989 + elif [ "$count" != "$cestab" ]; then 990 + fail_test "got $count current establish[s] expected $cestab" 991 + else 992 + print_ok 993 + fi 994 + } 995 + 996 + # $1 namespace 1, $2 namespace 2 997 + check_cestab() 998 + { 999 + if [ -n "${cestab_ns1}" ]; then 1000 + chk_cestab_nr ${1} ${cestab_ns1} 1001 + fi 1002 + if [ -n "${cestab_ns2}" ]; then 1003 + chk_cestab_nr ${2} ${cestab_ns2} 1004 + fi 1005 + } 1006 + 981 1007 do_transfer() 982 1008 { 983 1009 local listener_ns="$1" ··· 1119 1089 local cpid=$! 1120 1090 1121 1091 pm_nl_set_endpoint $listener_ns $connector_ns $connect_addr 1092 + check_cestab $listener_ns $connector_ns 1122 1093 1123 1094 wait $cpid 1124 1095 local retc=$? ··· 2508 2477 if reset "add single subflow"; then 2509 2478 pm_nl_set_limits $ns1 0 1 2510 2479 pm_nl_set_limits $ns2 0 1 2511 - addr_nr_ns2=1 speed=slow \ 2480 + addr_nr_ns2=1 speed=slow cestab_ns2=1 \ 2512 2481 run_tests $ns1 $ns2 10.0.1.1 2513 2482 chk_join_nr 1 1 1 2483 + chk_cestab_nr $ns2 0 2514 2484 fi 2515 2485 2516 2486 # add signal address 2517 2487 if reset "add signal address"; then 2518 2488 pm_nl_set_limits $ns1 0 1 2519 2489 pm_nl_set_limits $ns2 1 1 2520 - addr_nr_ns1=1 speed=slow \ 2490 + addr_nr_ns1=1 speed=slow cestab_ns1=1 \ 2521 2491 run_tests $ns1 $ns2 10.0.1.1 2522 2492 chk_join_nr 1 1 1 2523 2493 chk_add_nr 1 1 2494 + chk_cestab_nr $ns1 0 2524 2495 fi 2525 2496 2526 2497 # add multiple subflows 2527 2498 if reset "add multiple subflows"; then 2528 2499 pm_nl_set_limits $ns1 0 2 2529 2500 pm_nl_set_limits $ns2 0 2 2530 - addr_nr_ns2=2 speed=slow \ 2501 + addr_nr_ns2=2 speed=slow cestab_ns2=1 \ 2531 2502 run_tests $ns1 $ns2 10.0.1.1 2532 2503 chk_join_nr 2 2 2 2504 + chk_cestab_nr $ns2 0 2533 2505 fi 2534 2506 2535 2507 # add multiple subflows IPv6 2536 2508 if reset "add multiple subflows IPv6"; then 2537 2509 pm_nl_set_limits $ns1 0 2 2538 2510 pm_nl_set_limits $ns2 0 2 2539 - addr_nr_ns2=2 speed=slow \ 2511 + addr_nr_ns2=2 speed=slow cestab_ns2=1 \ 2540 2512 run_tests $ns1 $ns2 dead:beef:1::1 2541 2513 chk_join_nr 2 2 2 2514 + chk_cestab_nr $ns2 0 2542 2515 fi 2543 2516 2544 2517 # add multiple addresses IPv6 2545 2518 if reset "add multiple addresses IPv6"; then 2546 2519 pm_nl_set_limits $ns1 0 2 2547 2520 pm_nl_set_limits $ns2 2 2 2548 - addr_nr_ns1=2 speed=slow \ 2521 + addr_nr_ns1=2 speed=slow cestab_ns1=1 \ 2549 2522 run_tests $ns1 $ns2 dead:beef:1::1 2550 2523 chk_join_nr 2 2 2 2551 2524 chk_add_nr 2 2 2525 + chk_cestab_nr $ns1 0 2552 2526 fi 2553 2527 } 2554 2528