tools/testing/selftests/net/forwarding/ipmr.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/net/forwarding/ipmr.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/net/forwarding/ipmr.c
Extension
.c
Size
12371 bytes
Lines
511
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

struct mfc_attr {
	int table;
	__u32 origin;
	__u32 group;
	int ifindex;
	bool proxy;
};

static struct rtattr *nl_add_rtattr(struct nlmsghdr *nlmsg, struct rtattr *rta,
				    int type, const void *data, int len)
{
	int unused = 0;

	rta->rta_type = type;
	rta->rta_len = RTA_LENGTH(len);
	memcpy(RTA_DATA(rta), data, len);

	nlmsg->nlmsg_len += NLMSG_ALIGN(rta->rta_len);

	return RTA_NEXT(rta, unused);
}

static int nl_sendmsg_mfc(struct __test_metadata *_metadata,
			  FIXTURE_DATA(ipmr) *self,
			  const FIXTURE_VARIANT(ipmr) *variant,
			  __u16 nlmsg_type, struct mfc_attr *mfc_attr)
{
	struct {
		struct nlmsghdr nlmsg;
		struct rtmsg rtm;
		char buf[4096];
	} req = {
		.nlmsg = {
			.nlmsg_len = NLMSG_LENGTH(sizeof(req.rtm)),
			/* ipmr does not care about NLM_F_CREATE and NLM_F_EXCL ... */
			.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
			.nlmsg_type = nlmsg_type,
		},
		.rtm = {
			/* hard requirements in rtm_to_ipmr_mfcc() */
			.rtm_family = variant->rtm_family,
			.rtm_dst_len = 32,
			.rtm_type = RTN_MULTICAST,
			.rtm_scope = RT_SCOPE_UNIVERSE,
			.rtm_protocol = RTPROT_MROUTED,
		},
	};
	struct nlmsghdr *nlmsg = &req.nlmsg;
	struct nlmsgerr *errmsg;
	struct rtattr *rta;
	int err;

	rta = (struct rtattr *)&req.buf;
	rta = nl_add_rtattr(nlmsg, rta, RTA_TABLE, &mfc_attr->table, sizeof(mfc_attr->table));
	rta = nl_add_rtattr(nlmsg, rta, RTA_SRC, &mfc_attr->origin, sizeof(mfc_attr->origin));
	rta = nl_add_rtattr(nlmsg, rta, RTA_DST, &mfc_attr->group, sizeof(mfc_attr->group));
	if (mfc_attr->ifindex)
		rta = nl_add_rtattr(nlmsg, rta, RTA_IIF, &mfc_attr->ifindex, sizeof(mfc_attr->ifindex));
	if (mfc_attr->proxy)
		rta = nl_add_rtattr(nlmsg, rta, RTA_PREFSRC, NULL, 0);

	err = send(self->netlink_sk, &req, req.nlmsg.nlmsg_len, 0);
	ASSERT_EQ(err, req.nlmsg.nlmsg_len);

	memset(&req, 0, sizeof(req));

	err = recv(self->netlink_sk, &req, sizeof(req), 0);
	ASSERT_TRUE(NLMSG_OK(nlmsg, err));
	ASSERT_EQ(NLMSG_ERROR, nlmsg->nlmsg_type);

	errmsg = (struct nlmsgerr *)NLMSG_DATA(nlmsg);
	return errmsg->error;
}

FIXTURE_SETUP(ipmr)
{
	struct ifreq ifr = {
		.ifr_name = "veth0",
	};
	int err;

	err = unshare(CLONE_NEWNET);
	ASSERT_EQ(0, err);

	self->netlink_sk = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
	ASSERT_LE(0, self->netlink_sk);

	self->raw_sk = socket(variant->family, SOCK_RAW, variant->protocol);
	ASSERT_LT(0, self->raw_sk);

Annotation

Implementation Notes