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-cleanups'

Matthieu Baerts says:

====================
mptcp: a couple of cleanups and improvements

Patch 1 removes an unneeded address copy in subflow_syn_recv_sock().

Patch 2 simplifies subflow_syn_recv_sock() to postpone some actions and
to avoid a bunch of conditionals.

Patch 3 stops reporting limits that are not taken into account when the
userspace PM is used.

Patch 4 adds a new test to validate that the 'subflows' field reported
by the kernel is correct. Such info can be retrieved via Netlink (e.g.
with ss) or getsockopt(SOL_MPTCP, MPTCP_INFO).

---
Changes in v2:
- Patch 3/4's commit message has been updated to use the correct SHA
- Rebased on latest net-next
- Link to v1: https://lore.kernel.org/r/20230324-upstream-net-next-20230324-misc-features-v1-0-5a29154592bd@tessares.net
====================

Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

+72 -38
+13 -7
net/mptcp/sockopt.c
··· 885 885 void mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info) 886 886 { 887 887 u32 flags = 0; 888 - u8 val; 889 888 890 889 memset(info, 0, sizeof(*info)); 891 890 ··· 892 893 info->mptcpi_add_addr_signal = READ_ONCE(msk->pm.add_addr_signaled); 893 894 info->mptcpi_add_addr_accepted = READ_ONCE(msk->pm.add_addr_accepted); 894 895 info->mptcpi_local_addr_used = READ_ONCE(msk->pm.local_addr_used); 895 - info->mptcpi_subflows_max = mptcp_pm_get_subflows_max(msk); 896 - val = mptcp_pm_get_add_addr_signal_max(msk); 897 - info->mptcpi_add_addr_signal_max = val; 898 - val = mptcp_pm_get_add_addr_accept_max(msk); 899 - info->mptcpi_add_addr_accepted_max = val; 900 - info->mptcpi_local_addr_max = mptcp_pm_get_local_addr_max(msk); 896 + 897 + /* The following limits only make sense for the in-kernel PM */ 898 + if (mptcp_pm_is_kernel(msk)) { 899 + info->mptcpi_subflows_max = 900 + mptcp_pm_get_subflows_max(msk); 901 + info->mptcpi_add_addr_signal_max = 902 + mptcp_pm_get_add_addr_signal_max(msk); 903 + info->mptcpi_add_addr_accepted_max = 904 + mptcp_pm_get_add_addr_accept_max(msk); 905 + info->mptcpi_local_addr_max = 906 + mptcp_pm_get_local_addr_max(msk); 907 + } 908 + 901 909 if (test_bit(MPTCP_FALLBACK_DONE, &msk->flags)) 902 910 flags |= MPTCP_INFO_FLAG_FALLBACK; 903 911 if (READ_ONCE(msk->can_ack))
+13 -30
net/mptcp/subflow.c
··· 696 696 return !crypto_memneq(hmac, mp_opt->hmac, MPTCPOPT_HMAC_LEN); 697 697 } 698 698 699 - static void mptcp_force_close(struct sock *sk) 700 - { 701 - /* the msk is not yet exposed to user-space, and refcount is 2 */ 702 - inet_sk_state_store(sk, TCP_CLOSE); 703 - sk_common_release(sk); 704 - sock_put(sk); 705 - } 706 - 707 699 static void subflow_ulp_fallback(struct sock *sk, 708 700 struct mptcp_subflow_context *old_ctx) 709 701 { ··· 747 755 struct mptcp_subflow_request_sock *subflow_req; 748 756 struct mptcp_options_received mp_opt; 749 757 bool fallback, fallback_is_fatal; 750 - struct sock *new_msk = NULL; 751 758 struct mptcp_sock *owner; 752 759 struct sock *child; 753 760 ··· 775 784 * options. 776 785 */ 777 786 mptcp_get_options(skb, &mp_opt); 778 - if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPC)) { 787 + if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPC)) 779 788 fallback = true; 780 - goto create_child; 781 - } 782 789 783 - new_msk = mptcp_sk_clone(listener->conn, &mp_opt, req); 784 - if (!new_msk) 785 - fallback = true; 786 790 } else if (subflow_req->mp_join) { 787 791 mptcp_get_options(skb, &mp_opt); 788 792 if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ) || ··· 806 820 subflow_add_reset_reason(skb, MPTCP_RST_EMPTCP); 807 821 goto dispose_child; 808 822 } 809 - 810 - if (new_msk) 811 - mptcp_copy_inaddrs(new_msk, child); 812 - mptcp_subflow_drop_ctx(child); 813 - goto out; 823 + goto fallback; 814 824 } 815 825 816 826 /* ssk inherits options of listener sk */ 817 827 ctx->setsockopt_seq = listener->setsockopt_seq; 818 828 819 829 if (ctx->mp_capable) { 820 - owner = mptcp_sk(new_msk); 830 + ctx->conn = mptcp_sk_clone(listener->conn, &mp_opt, req); 831 + if (!ctx->conn) 832 + goto fallback; 833 + 834 + owner = mptcp_sk(ctx->conn); 821 835 822 836 /* this can't race with mptcp_close(), as the msk is 823 837 * not yet exposted to user-space 824 838 */ 825 - inet_sk_state_store((void *)new_msk, TCP_ESTABLISHED); 839 + inet_sk_state_store(ctx->conn, TCP_ESTABLISHED); 826 840 827 841 /* record the newly created socket as the first msk 828 842 * subflow, but don't link it yet into conn_list ··· 832 846 /* new mpc subflow takes ownership of the newly 833 847 * created mptcp socket 834 848 */ 835 - mptcp_sk(new_msk)->setsockopt_seq = ctx->setsockopt_seq; 849 + owner->setsockopt_seq = ctx->setsockopt_seq; 836 850 mptcp_pm_new_connection(owner, child, 1); 837 851 mptcp_token_accept(subflow_req, owner); 838 - ctx->conn = new_msk; 839 - new_msk = NULL; 840 852 841 853 /* set msk addresses early to ensure mptcp_pm_get_local_id() 842 854 * uses the correct data ··· 884 900 } 885 901 } 886 902 887 - out: 888 - /* dispose of the left over mptcp master, if any */ 889 - if (unlikely(new_msk)) 890 - mptcp_force_close(new_msk); 891 - 892 903 /* check for expected invariant - should never trigger, just help 893 904 * catching eariler subtle bugs 894 905 */ ··· 900 921 req->rsk_ops->send_reset(sk, skb); 901 922 902 923 /* The last child reference will be released by the caller */ 924 + return child; 925 + 926 + fallback: 927 + mptcp_subflow_drop_ctx(child); 903 928 return child; 904 929 } 905 930
+46 -1
tools/testing/selftests/net/mptcp/mptcp_join.sh
··· 1719 1719 fi 1720 1720 } 1721 1721 1722 + chk_mptcp_info() 1723 + { 1724 + local nr_info=$1 1725 + local info 1726 + local cnt1 1727 + local cnt2 1728 + local dump_stats 1729 + 1730 + if [[ $nr_info = "subflows_"* ]]; then 1731 + info="subflows" 1732 + nr_info=${nr_info:9} 1733 + else 1734 + echo "[fail] unsupported argument: $nr_info" 1735 + fail_test 1736 + return 1 1737 + fi 1738 + 1739 + printf "%-${nr_blank}s %-30s" " " "mptcp_info $info=$nr_info" 1740 + 1741 + cnt1=$(ss -N $ns1 -inmHM | grep "$info:" | 1742 + sed -n 's/.*\('"$info"':\)\([[:digit:]]*\).*$/\2/p;q') 1743 + [ -z "$cnt1" ] && cnt1=0 1744 + cnt2=$(ss -N $ns2 -inmHM | grep "$info:" | 1745 + sed -n 's/.*\('"$info"':\)\([[:digit:]]*\).*$/\2/p;q') 1746 + [ -z "$cnt2" ] && cnt2=0 1747 + if [ "$cnt1" != "$nr_info" ] || [ "$cnt2" != "$nr_info" ]; then 1748 + echo "[fail] got $cnt1:$cnt2 $info expected $nr_info" 1749 + fail_test 1750 + dump_stats=1 1751 + else 1752 + echo "[ ok ]" 1753 + fi 1754 + 1755 + if [ "$dump_stats" = 1 ]; then 1756 + ss -N $ns1 -inmHM 1757 + ss -N $ns2 -inmHM 1758 + dump_stats 1759 + fi 1760 + } 1761 + 1722 1762 chk_link_usage() 1723 1763 { 1724 1764 local ns=$1 ··· 3158 3118 run_tests $ns1 $ns2 10.0.1.1 4 0 0 speed_20 2>/dev/null & 3159 3119 3160 3120 wait_mpj $ns2 3121 + chk_subflow_nr needtitle "before delete" 2 3122 + chk_mptcp_info subflows_1 3123 + 3161 3124 pm_nl_del_endpoint $ns2 2 10.0.2.2 3162 3125 sleep 0.5 3163 - chk_subflow_nr needtitle "after delete" 1 3126 + chk_subflow_nr "" "after delete" 1 3127 + chk_mptcp_info subflows_0 3164 3128 3165 3129 pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow 3166 3130 wait_mpj $ns2 3167 3131 chk_subflow_nr "" "after re-add" 2 3132 + chk_mptcp_info subflows_1 3168 3133 kill_tests_wait 3169 3134 fi 3170 3135 }