From: Leo Stone <leocstone@gmail.com>
To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, shuah@kernel.org, 0x7f454c46@gmail.com
Cc: Leo Stone <leocstone@gmail.com>,
rdunlap@infradead.org, mnassiri@ciena.com,
jiapeng.chong@linux.alibaba.com, colin.i.king@gmail.com,
netdev@vger.kernel.org, linux-kselftest@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH v2] selftest/tcp-ao: Add filter tests
Date: Tue, 15 Oct 2024 22:51:52 -0700 [thread overview]
Message-ID: <20241016055823.21299-1-leocstone@gmail.com> (raw)
Add tests that check if getsockopt(TCP_AO_GET_KEYS) returns the right
keys when using different filters.
Sample output:
> # ok 114 filter keys: by sndid, rcvid, address
> # ok 115 filter keys: by is_current
> # ok 116 filter keys: by is_rnext
> # ok 117 filter keys: by sndid, rcvid
> # ok 118 filter keys: correct nkeys when in.nkeys < matched_keys
Signed-off-by: Leo Stone <leocstone@gmail.com>
---
Changes in v2:
- Changed 2 unnecessary test_error calls to test_fail
- Added another test to make sure getsockopt returns the right nkeys
value when the input nkeys is smaller than the number of matching keys
- Removed the TODO that this patch addresses
Thank you for your feedback.
---
.../selftests/net/tcp_ao/setsockopt-closed.c | 180 +++++++++++++++++-
1 file changed, 175 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/net/tcp_ao/setsockopt-closed.c b/tools/testing/selftests/net/tcp_ao/setsockopt-closed.c
index 084db4ecdff6..4bfa76c28e4e 100644
--- a/tools/testing/selftests/net/tcp_ao/setsockopt-closed.c
+++ b/tools/testing/selftests/net/tcp_ao/setsockopt-closed.c
@@ -6,6 +6,8 @@
static union tcp_addr tcp_md5_client;
+#define FILTER_TEST_NKEYS 16
+
static int test_port = 7788;
static void make_listen(int sk)
{
@@ -813,23 +815,191 @@ static void duplicate_tests(void)
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: SendID differs");
}
+
+static void fetch_all_keys(int sk, struct tcp_ao_getsockopt *keys)
+{
+ socklen_t optlen = sizeof(struct tcp_ao_getsockopt);
+
+ memset(keys, 0, sizeof(struct tcp_ao_getsockopt) * FILTER_TEST_NKEYS);
+ keys[0].get_all = 1;
+ keys[0].nkeys = FILTER_TEST_NKEYS;
+ if (getsockopt(sk, IPPROTO_TCP, TCP_AO_GET_KEYS, &keys[0], &optlen))
+ test_error("getsockopt");
+}
+
+static int prepare_test_keys(struct tcp_ao_getsockopt *keys)
+{
+ struct tcp_ao_add test_ao[FILTER_TEST_NKEYS];
+ u8 rcvid = 100, sndid = 100;
+ const char *test_password = "Test password number ";
+ char test_password_scratch[64] = {};
+ int sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
+
+ if (sk < 0)
+ test_error("socket()");
+
+ for (int i = 0; i < FILTER_TEST_NKEYS; i++) {
+ snprintf(test_password_scratch, 64, "%s %d", test_password, i);
+ test_prepare_key(&test_ao[i], DEFAULT_TEST_ALGO, this_ip_dest, false, false,
+ DEFAULT_TEST_PREFIX, 0, sndid++, rcvid++, 0, 0,
+ strlen(test_password_scratch), test_password_scratch);
+ }
+ test_ao[0].set_current = 1;
+ test_ao[1].set_rnext = 1;
+ /* One key with a different addr and overlapping sndid, rcvid */
+ tcp_addr_to_sockaddr_in(&test_ao[2].addr, &this_ip_addr, 0);
+ test_ao[2].sndid = 100;
+ test_ao[2].rcvid = 100;
+
+ /* Add keys in a random order */
+ for (int i = 0; i < FILTER_TEST_NKEYS; i++) {
+ int randidx = rand() % (FILTER_TEST_NKEYS - i);
+
+ if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &test_ao[randidx],
+ sizeof(struct tcp_ao_add)))
+ test_error("setsockopt()");
+ memcpy(&test_ao[randidx], &test_ao[FILTER_TEST_NKEYS - 1 - i],
+ sizeof(struct tcp_ao_add));
+ }
+
+ fetch_all_keys(sk, keys);
+
+ return sk;
+}
+
+/* Assumes passwords are unique */
+static int compare_mkts(struct tcp_ao_getsockopt *expected, int nexpected,
+ struct tcp_ao_getsockopt *actual, int nactual)
+{
+ int matches = 0;
+
+ for (int i = 0; i < nexpected; i++) {
+ for (int j = 0; j < nactual; j++) {
+ if (memcmp(expected[i].key, actual[j].key, TCP_AO_MAXKEYLEN) == 0)
+ matches++;
+ }
+ }
+ return nexpected - matches;
+}
+
+static void filter_keys_checked(int sk, struct tcp_ao_getsockopt *filter,
+ struct tcp_ao_getsockopt *expected,
+ unsigned int nexpected, const char *tst)
+{
+ struct tcp_ao_getsockopt all_keys[FILTER_TEST_NKEYS] = {};
+ struct tcp_ao_getsockopt filtered_keys[FILTER_TEST_NKEYS] = {};
+ socklen_t len = sizeof(struct tcp_ao_getsockopt);
+
+ fetch_all_keys(sk, all_keys);
+ memcpy(&filtered_keys[0], filter, sizeof(struct tcp_ao_getsockopt));
+ filtered_keys[0].nkeys = FILTER_TEST_NKEYS;
+ if (getsockopt(sk, IPPROTO_TCP, TCP_AO_GET_KEYS, filtered_keys, &len))
+ test_error("getsockopt");
+ if (filtered_keys[0].nkeys != nexpected) {
+ test_fail("wrong nr of keys, expected %u got %u", nexpected,
+ filtered_keys[0].nkeys);
+ goto out_close;
+ }
+ if (compare_mkts(expected, nexpected, filtered_keys, filtered_keys[0].nkeys)) {
+ test_fail("got wrong keys back");
+ goto out_close;
+ }
+ test_ok("filter keys: %s", tst);
+
+out_close:
+ close(sk);
+ memset(filter, 0, sizeof(struct tcp_ao_getsockopt));
+}
+
+static void filter_tests(void)
+{
+ struct tcp_ao_getsockopt original_keys[FILTER_TEST_NKEYS];
+ struct tcp_ao_getsockopt expected_keys[FILTER_TEST_NKEYS];
+ struct tcp_ao_getsockopt filter = {};
+ int sk, f, nmatches;
+ socklen_t len;
+
+ f = 2;
+ sk = prepare_test_keys(original_keys);
+ filter.rcvid = original_keys[f].rcvid;
+ filter.sndid = original_keys[f].sndid;
+ memcpy(&filter.addr, &original_keys[f].addr, sizeof(original_keys[f].addr));
+ filter.prefix = original_keys[f].prefix;
+ filter_keys_checked(sk, &filter, &original_keys[f], 1, "by sndid, rcvid, address");
+
+ f = -1;
+ sk = prepare_test_keys(original_keys);
+ for (int i = 0; i < original_keys[0].nkeys; i++) {
+ if (original_keys[i].is_current) {
+ f = i;
+ break;
+ }
+ }
+ if (f < 0)
+ test_error("No current key after adding one");
+ filter.is_current = 1;
+ filter_keys_checked(sk, &filter, &original_keys[f], 1, "by is_current");
+
+ f = -1;
+ sk = prepare_test_keys(original_keys);
+ for (int i = 0; i < original_keys[0].nkeys; i++) {
+ if (original_keys[i].is_rnext) {
+ f = i;
+ break;
+ }
+ }
+ if (f < 0)
+ test_error("No rnext key after adding one");
+ filter.is_rnext = 1;
+ filter_keys_checked(sk, &filter, &original_keys[f], 1, "by is_rnext");
+
+ f = -1;
+ nmatches = 0;
+ sk = prepare_test_keys(original_keys);
+ for (int i = 0; i < original_keys[0].nkeys; i++) {
+ if (original_keys[i].sndid == 100) {
+ f = i;
+ memcpy(&expected_keys[nmatches], &original_keys[i],
+ sizeof(struct tcp_ao_getsockopt));
+ nmatches++;
+ }
+ }
+ if (f < 0)
+ test_error("No key for sndid 100");
+ if (nmatches != 2)
+ test_error("Should have 2 keys with sndid 100");
+ filter.rcvid = original_keys[f].rcvid;
+ filter.sndid = original_keys[f].sndid;
+ filter.addr.ss_family = test_family;
+ filter_keys_checked(sk, &filter, expected_keys, nmatches, "by sndid, rcvid");
+
+ sk = prepare_test_keys(original_keys);
+ filter.get_all = 1;
+ filter.nkeys = FILTER_TEST_NKEYS / 2;
+ len = sizeof(struct tcp_ao_getsockopt);
+ if (getsockopt(sk, IPPROTO_TCP, TCP_AO_GET_KEYS, &filter, &len))
+ test_error("getsockopt");
+ if (filter.nkeys == FILTER_TEST_NKEYS)
+ test_ok("filter keys: correct nkeys when in.nkeys < matched_keys");
+ else
+ test_fail("filter keys: wrong nkeys, expected %u got %u",
+ FILTER_TEST_NKEYS, filter.nkeys);
+}
+
static void *client_fn(void *arg)
{
if (inet_pton(TEST_FAMILY, __TEST_CLIENT_IP(2), &tcp_md5_client) != 1)
test_error("Can't convert ip address");
extend_tests();
einval_tests();
+ filter_tests();
duplicate_tests();
- /*
- * TODO: check getsockopt(TCP_AO_GET_KEYS) with different filters
- * returning proper nr & keys;
- */
return NULL;
}
int main(int argc, char *argv[])
{
- test_init(121, client_fn, NULL);
+ test_init(126, client_fn, NULL);
return 0;
}
--
2.43.0
next reply other threads:[~2024-10-16 5:59 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-16 5:51 Leo Stone [this message]
2024-10-17 1:04 ` [PATCH v2] selftest/tcp-ao: Add filter tests Dmitry Safonov
2024-10-18 9:32 ` Simon Horman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241016055823.21299-1-leocstone@gmail.com \
--to=leocstone@gmail.com \
--cc=0x7f454c46@gmail.com \
--cc=colin.i.king@gmail.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=jiapeng.chong@linux.alibaba.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=mnassiri@ciena.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=rdunlap@infradead.org \
--cc=shuah@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.