18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <kunit/test.h>
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include "protocol.h"
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_cistatic struct mptcp_subflow_request_sock *build_req_sock(struct kunit *test)
78c2ecf20Sopenharmony_ci{
88c2ecf20Sopenharmony_ci	struct mptcp_subflow_request_sock *req;
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci	req = kunit_kzalloc(test, sizeof(struct mptcp_subflow_request_sock),
118c2ecf20Sopenharmony_ci			    GFP_USER);
128c2ecf20Sopenharmony_ci	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, req);
138c2ecf20Sopenharmony_ci	mptcp_token_init_request((struct request_sock *)req);
148c2ecf20Sopenharmony_ci	sock_net_set((struct sock *)req, &init_net);
158c2ecf20Sopenharmony_ci	return req;
168c2ecf20Sopenharmony_ci}
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistatic void mptcp_token_test_req_basic(struct kunit *test)
198c2ecf20Sopenharmony_ci{
208c2ecf20Sopenharmony_ci	struct mptcp_subflow_request_sock *req = build_req_sock(test);
218c2ecf20Sopenharmony_ci	struct mptcp_sock *null_msk = NULL;
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	KUNIT_ASSERT_EQ(test, 0,
248c2ecf20Sopenharmony_ci			mptcp_token_new_request((struct request_sock *)req));
258c2ecf20Sopenharmony_ci	KUNIT_EXPECT_NE(test, 0, (int)req->token);
268c2ecf20Sopenharmony_ci	KUNIT_EXPECT_PTR_EQ(test, null_msk, mptcp_token_get_sock(&init_net, req->token));
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	/* cleanup */
298c2ecf20Sopenharmony_ci	mptcp_token_destroy_request((struct request_sock *)req);
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic struct inet_connection_sock *build_icsk(struct kunit *test)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	struct inet_connection_sock *icsk;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	icsk = kunit_kzalloc(test, sizeof(struct inet_connection_sock),
378c2ecf20Sopenharmony_ci			     GFP_USER);
388c2ecf20Sopenharmony_ci	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, icsk);
398c2ecf20Sopenharmony_ci	return icsk;
408c2ecf20Sopenharmony_ci}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic struct mptcp_subflow_context *build_ctx(struct kunit *test)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	struct mptcp_subflow_context *ctx;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	ctx = kunit_kzalloc(test, sizeof(struct mptcp_subflow_context),
478c2ecf20Sopenharmony_ci			    GFP_USER);
488c2ecf20Sopenharmony_ci	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, ctx);
498c2ecf20Sopenharmony_ci	return ctx;
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic struct mptcp_sock *build_msk(struct kunit *test)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	struct mptcp_sock *msk;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	msk = kunit_kzalloc(test, sizeof(struct mptcp_sock), GFP_USER);
578c2ecf20Sopenharmony_ci	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, msk);
588c2ecf20Sopenharmony_ci	refcount_set(&((struct sock *)msk)->sk_refcnt, 1);
598c2ecf20Sopenharmony_ci	sock_net_set((struct sock *)msk, &init_net);
608c2ecf20Sopenharmony_ci	return msk;
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic void mptcp_token_test_msk_basic(struct kunit *test)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	struct inet_connection_sock *icsk = build_icsk(test);
668c2ecf20Sopenharmony_ci	struct mptcp_subflow_context *ctx = build_ctx(test);
678c2ecf20Sopenharmony_ci	struct mptcp_sock *msk = build_msk(test);
688c2ecf20Sopenharmony_ci	struct mptcp_sock *null_msk = NULL;
698c2ecf20Sopenharmony_ci	struct sock *sk;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	rcu_assign_pointer(icsk->icsk_ulp_data, ctx);
728c2ecf20Sopenharmony_ci	ctx->conn = (struct sock *)msk;
738c2ecf20Sopenharmony_ci	sk = (struct sock *)msk;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	KUNIT_ASSERT_EQ(test, 0,
768c2ecf20Sopenharmony_ci			mptcp_token_new_connect((struct sock *)icsk));
778c2ecf20Sopenharmony_ci	KUNIT_EXPECT_NE(test, 0, (int)ctx->token);
788c2ecf20Sopenharmony_ci	KUNIT_EXPECT_EQ(test, ctx->token, msk->token);
798c2ecf20Sopenharmony_ci	KUNIT_EXPECT_PTR_EQ(test, msk, mptcp_token_get_sock(&init_net, ctx->token));
808c2ecf20Sopenharmony_ci	KUNIT_EXPECT_EQ(test, 2, (int)refcount_read(&sk->sk_refcnt));
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	mptcp_token_destroy(msk);
838c2ecf20Sopenharmony_ci	KUNIT_EXPECT_PTR_EQ(test, null_msk, mptcp_token_get_sock(&init_net, ctx->token));
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic void mptcp_token_test_accept(struct kunit *test)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	struct mptcp_subflow_request_sock *req = build_req_sock(test);
898c2ecf20Sopenharmony_ci	struct mptcp_sock *msk = build_msk(test);
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	KUNIT_ASSERT_EQ(test, 0,
928c2ecf20Sopenharmony_ci			mptcp_token_new_request((struct request_sock *)req));
938c2ecf20Sopenharmony_ci	msk->token = req->token;
948c2ecf20Sopenharmony_ci	mptcp_token_accept(req, msk);
958c2ecf20Sopenharmony_ci	KUNIT_EXPECT_PTR_EQ(test, msk, mptcp_token_get_sock(&init_net, msk->token));
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	/* this is now a no-op */
988c2ecf20Sopenharmony_ci	mptcp_token_destroy_request((struct request_sock *)req);
998c2ecf20Sopenharmony_ci	KUNIT_EXPECT_PTR_EQ(test, msk, mptcp_token_get_sock(&init_net, msk->token));
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	/* cleanup */
1028c2ecf20Sopenharmony_ci	mptcp_token_destroy(msk);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistatic void mptcp_token_test_destroyed(struct kunit *test)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	struct mptcp_subflow_request_sock *req = build_req_sock(test);
1088c2ecf20Sopenharmony_ci	struct mptcp_sock *msk = build_msk(test);
1098c2ecf20Sopenharmony_ci	struct mptcp_sock *null_msk = NULL;
1108c2ecf20Sopenharmony_ci	struct sock *sk;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	sk = (struct sock *)msk;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	KUNIT_ASSERT_EQ(test, 0,
1158c2ecf20Sopenharmony_ci			mptcp_token_new_request((struct request_sock *)req));
1168c2ecf20Sopenharmony_ci	msk->token = req->token;
1178c2ecf20Sopenharmony_ci	mptcp_token_accept(req, msk);
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	/* simulate race on removal */
1208c2ecf20Sopenharmony_ci	refcount_set(&sk->sk_refcnt, 0);
1218c2ecf20Sopenharmony_ci	KUNIT_EXPECT_PTR_EQ(test, null_msk, mptcp_token_get_sock(&init_net, msk->token));
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	/* cleanup */
1248c2ecf20Sopenharmony_ci	mptcp_token_destroy(msk);
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic struct kunit_case mptcp_token_test_cases[] = {
1288c2ecf20Sopenharmony_ci	KUNIT_CASE(mptcp_token_test_req_basic),
1298c2ecf20Sopenharmony_ci	KUNIT_CASE(mptcp_token_test_msk_basic),
1308c2ecf20Sopenharmony_ci	KUNIT_CASE(mptcp_token_test_accept),
1318c2ecf20Sopenharmony_ci	KUNIT_CASE(mptcp_token_test_destroyed),
1328c2ecf20Sopenharmony_ci	{}
1338c2ecf20Sopenharmony_ci};
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic struct kunit_suite mptcp_token_suite = {
1368c2ecf20Sopenharmony_ci	.name = "mptcp-token",
1378c2ecf20Sopenharmony_ci	.test_cases = mptcp_token_test_cases,
1388c2ecf20Sopenharmony_ci};
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cikunit_test_suite(mptcp_token_suite);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
143