tools/testing/selftests/net/rds/getsockopt.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/net/rds/getsockopt.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/net/rds/getsockopt.c
Extension
.c
Size
5641 bytes
Lines
209
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * Exercise the RDS getsockopt() paths that were converted to the
 * getsockopt_iter() / sockopt_t callback.
 *
 * Three distinct paths are covered:
 *
 *   - RDS_RECVERR and SO_RDS_TRANSPORT, which now return their int value
 *     through copy_to_iter() and report the written length in opt->optlen.
 *
 *   - RDS_INFO_*, which pins the userspace buffer with
 *     iov_iter_extract_pages() (including a non-zero starting page offset)
 *     and lets the info producers memcpy the snapshot in under a spinlock.
 *
 * The kvec (in-kernel buffer) -> -EOPNOTSUPP path of rds_info_getsockopt()
 * is not reachable from a userspace getsockopt() and so is not tested here.
 */
#include <errno.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <linux/rds.h>

#include "../../kselftest_harness.h"

#ifndef AF_RDS
#define AF_RDS 21
#endif

FIXTURE(rds) {
	int fd;
};

FIXTURE_SETUP(rds)
{
	self->fd = socket(AF_RDS, SOCK_SEQPACKET, 0);
	if (self->fd < 0)
		SKIP(return, "AF_RDS unavailable (errno %d) - load the rds module",
		     errno);
}

FIXTURE_TEARDOWN(rds)
{
	if (self->fd >= 0)
		close(self->fd);
}

/* RDS_RECVERR defaults to 0 and is reported back as a 4-byte int. */
TEST_F(rds, recverr_default)
{
	socklen_t len = sizeof(int);
	int val = 0xdeadbeef;

	ASSERT_EQ(0, getsockopt(self->fd, SOL_RDS, RDS_RECVERR, &val, &len));
	EXPECT_EQ(sizeof(int), len);
	EXPECT_EQ(0, val);
}

/* A value set via setsockopt() must be readable back unchanged. */
TEST_F(rds, recverr_set_get)
{
	socklen_t len = sizeof(int);
	int val = 1;

	ASSERT_EQ(0, setsockopt(self->fd, SOL_RDS, RDS_RECVERR, &val, len));

	val = 0;
	ASSERT_EQ(0, getsockopt(self->fd, SOL_RDS, RDS_RECVERR, &val, &len));
	EXPECT_EQ(sizeof(int), len);
	EXPECT_EQ(1, val);
}

/* A buffer smaller than an int is rejected with EINVAL, not silently. */
TEST_F(rds, recverr_short_buffer)
{
	socklen_t len = sizeof(int) - 1;
	char buf[sizeof(int)];

	EXPECT_EQ(-1, getsockopt(self->fd, SOL_RDS, RDS_RECVERR, buf, &len));
	EXPECT_EQ(EINVAL, errno);
}

/* An unbound socket reports RDS_TRANS_NONE for SO_RDS_TRANSPORT. */
TEST_F(rds, transport_unbound)
{
	socklen_t len = sizeof(int);
	int val = 0;

Annotation

Implementation Notes