tools/testing/selftests/net/msg_zerocopy.c

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/net/msg_zerocopy.c
Extension
.c
Size
19908 bytes
Lines
828
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

if (domain == PF_RDS) {
			memset(&msg->msg_control, 0, sizeof(msg->msg_control));
			msg->msg_controllen = CMSG_SPACE(sizeof(cookie));
			msg->msg_control = (struct cmsghdr *)ckbuf;
			add_zcopy_cookie(msg, ++cookie);
		}
	}

	ret = sendmsg(fd, msg, flags);
	if (ret == -1 && errno == EAGAIN)
		return false;
	if (ret == -1)
		error(1, errno, "send");
	if (cfg_verbose && ret != len)
		fprintf(stderr, "send: ret=%u != %u\n", ret, len);
	sends_since_notify++;

	if (len) {
		packets++;
		bytes += ret;
		if (do_zerocopy && ret)
			expected_completions++;
	}
	if (do_zerocopy && domain == PF_RDS) {
		msg->msg_control = NULL;
		msg->msg_controllen = 0;
	}

	return true;
}

static void do_sendmsg_corked(int fd, struct msghdr *msg)
{
	bool do_zerocopy = cfg_zerocopy;
	int i, payload_len, extra_len;

	/* split up the packet. for non-multiple, make first buffer longer */
	payload_len = cfg_payload_len / cfg_cork;
	extra_len = cfg_payload_len - (cfg_cork * payload_len);

	do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 1);

	for (i = 0; i < cfg_cork; i++) {

		/* in mixed-frags mode, alternate zerocopy and copy frags
		 * start with non-zerocopy, to ensure attach later works
		 */
		if (cfg_cork_mixed)
			do_zerocopy = (i & 1);

		msg->msg_iov[0].iov_len = payload_len + extra_len;
		extra_len = 0;

		do_sendmsg(fd, msg, do_zerocopy,
			   (cfg_dst_addr.ss_family == AF_INET ?
			    PF_INET : PF_INET6));
	}

	do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 0);
}

static int setup_iph(struct iphdr *iph, uint16_t payload_len)
{
	struct sockaddr_in *daddr = (void *) &cfg_dst_addr;
	struct sockaddr_in *saddr = (void *) &cfg_src_addr;

	memset(iph, 0, sizeof(*iph));

	iph->version	= 4;
	iph->tos	= 0;
	iph->ihl	= 5;
	iph->ttl	= 2;
	iph->saddr	= saddr->sin_addr.s_addr;
	iph->daddr	= daddr->sin_addr.s_addr;
	iph->protocol	= IPPROTO_EGP;
	iph->tot_len	= htons(sizeof(*iph) + payload_len);
	iph->check	= get_ip_csum((void *) iph, iph->ihl << 1);

	return sizeof(*iph);
}

static int setup_ip6h(struct ipv6hdr *ip6h, uint16_t payload_len)
{
	struct sockaddr_in6 *daddr = (void *) &cfg_dst_addr;
	struct sockaddr_in6 *saddr = (void *) &cfg_src_addr;

	memset(ip6h, 0, sizeof(*ip6h));

	ip6h->version		= 6;
	ip6h->payload_len	= htons(payload_len);

Annotation

Implementation Notes