1272343Sngie/* $NetBSD: t_recvmmsg.c,v 1.1 2012/06/22 18:45:23 christos Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2012 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * This code is derived from software contributed to The NetBSD Foundation 8272343Sngie * by Jared McNeill and Christos Zoulas. 9272343Sngie * 10272343Sngie * Redistribution and use in source and binary forms, with or without 11272343Sngie * modification, are permitted provided that the following conditions 12272343Sngie * are met: 13272343Sngie * 1. Redistributions of source code must retain the above copyright 14272343Sngie * notice, this list of conditions and the following disclaimer. 15272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 16272343Sngie * notice, this list of conditions and the following disclaimer in the 17272343Sngie * documentation and/or other materials provided with the distribution. 18272343Sngie * 3. All advertising materials mentioning features or use of this software 19272343Sngie * must display the following acknowledgement: 20272343Sngie * This product includes software developed by the NetBSD 21272343Sngie * Foundation, Inc. and its contributors. 22272343Sngie * 4. Neither the name of The NetBSD Foundation nor the names of its 23272343Sngie * contributors may be used to endorse or promote products derived 24272343Sngie * from this software without specific prior written permission. 25272343Sngie * 26272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36272343Sngie * POSSIBILITY OF SUCH DAMAGE. 37272343Sngie */ 38272343Sngie#include <sys/cdefs.h> 39272343Sngie__RCSID("$NetBSD: t_recvmmsg.c,v 1.1 2012/06/22 18:45:23 christos Exp $"); 40272343Sngie 41272343Sngie#include <atf-c.h> 42272343Sngie#include <sys/types.h> 43272343Sngie#include <sys/socket.h> 44272343Sngie#include <sys/wait.h> 45272343Sngie 46272343Sngie#include <string.h> 47272343Sngie#include <time.h> 48272343Sngie#include <stdint.h> 49272343Sngie#include <errno.h> 50272343Sngie#include <stdio.h> 51272343Sngie#include <stdlib.h> 52272343Sngie#include <unistd.h> 53272343Sngie#include <sched.h> 54272343Sngie 55272343Sngie#define BUFSIZE 65536 56272343Sngie#define NPKTS 50 57272343Sngie 58272343Sngie#define min(a, b) ((a) < (b) ? (a) : (b)) 59272343Sngiestatic int debug; 60272343Sngie 61272343Sngie 62272343SngieATF_TC(recvmmsg_basic); 63272343SngieATF_TC_HEAD(recvmmsg_basic, tc) 64272343Sngie{ 65272343Sngie atf_tc_set_md_var(tc, "descr", "A basic test of recvmmsg(2)"); 66272343Sngie} 67272343Sngie 68272343SngieATF_TC_BODY(recvmmsg_basic, tc) 69272343Sngie{ 70272343Sngie int fd[2], error, i, cnt; 71272343Sngie uint8_t *buf; 72272343Sngie struct mmsghdr *mmsghdr; 73272343Sngie struct iovec *iov; 74272343Sngie unsigned int mmsgcnt, n; 75272343Sngie int status; 76272343Sngie off_t off; 77272343Sngie uint8_t DGRAM[1316] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, }; 78272343Sngie 79272343Sngie error = socketpair(AF_UNIX, SOCK_DGRAM, 0, fd); 80272343Sngie ATF_REQUIRE_MSG(error != -1, "socketpair failed (%s)", strerror(errno)); 81272343Sngie 82272343Sngie buf = malloc(BUFSIZE); 83272343Sngie ATF_REQUIRE_MSG(buf != NULL, "malloc failed (%s)", strerror(errno)); 84272343Sngie 85272343Sngie mmsgcnt = BUFSIZE / sizeof(DGRAM); 86272343Sngie mmsghdr = malloc(sizeof(*mmsghdr) * mmsgcnt); 87272343Sngie ATF_REQUIRE_MSG(mmsghdr != NULL, "malloc failed (%s)", strerror(errno)); 88272343Sngie iov = malloc(sizeof(*iov) * mmsgcnt); 89272343Sngie ATF_REQUIRE_MSG(iov != NULL, "malloc failed (%s)", strerror(errno)); 90272343Sngie 91272343Sngie for (off = 0, n = 0; n < mmsgcnt; n++) { 92272343Sngie iov[n].iov_base = buf + off; 93272343Sngie iov[n].iov_len = sizeof(DGRAM); 94272343Sngie off += iov[n].iov_len; 95272343Sngie mmsghdr[n].msg_hdr.msg_iov = &iov[n]; 96272343Sngie mmsghdr[n].msg_hdr.msg_iovlen = 1; 97272343Sngie mmsghdr[n].msg_hdr.msg_name = NULL; 98272343Sngie mmsghdr[n].msg_hdr.msg_namelen = 0; 99272343Sngie } 100272343Sngie 101272343Sngie switch (fork()) { 102272343Sngie case -1: 103272343Sngie ATF_REQUIRE_MSG(0, "fork failed (%s)", strerror(errno)); 104272343Sngie break; 105272343Sngie 106272343Sngie case 0: 107272343Sngie n = NPKTS; 108272343Sngie if (debug) 109272343Sngie printf("waiting for %u messages (max %u per syscall)\n", n, 110272343Sngie mmsgcnt); 111272343Sngie while (n > 0) { 112272343Sngie struct timespec ts = { 1, 0 }; 113272343Sngie cnt = recvmmsg(fd[1], mmsghdr, min(mmsgcnt, n), 114272343Sngie MSG_WAITALL, &ts); 115272343Sngie ATF_REQUIRE_MSG(cnt != -1, "recvmmsg failed (%s)", 116272343Sngie strerror(errno)); 117272343Sngie ATF_REQUIRE_MSG(cnt != 0, "recvmmsg timeout"); 118272343Sngie if (debug) 119272343Sngie printf("recvmmsg: got %u messages\n", cnt); 120272343Sngie for (i = 0; i < cnt; i++) { 121272343Sngie ATF_CHECK_EQ_MSG(mmsghdr[i].msg_len, 122272343Sngie sizeof(DGRAM), "packet length"); 123272343Sngie ATF_CHECK_EQ_MSG( 124272343Sngie ((uint8_t *)iov[i].iov_base)[0], 125272343Sngie NPKTS - n + i, "packet contents"); 126272343Sngie } 127272343Sngie n -= cnt; 128272343Sngie } 129272343Sngie if (debug) 130272343Sngie printf("done!\n"); 131272343Sngie exit(0); 132272343Sngie /*NOTREACHED*/ 133272343Sngie default: 134272343Sngie sched_yield(); 135272343Sngie 136272343Sngie for (n = 0; n < NPKTS; n++) { 137272343Sngie if (debug) 138272343Sngie printf("sending packet %u/%u...\n", (n+1), 139272343Sngie NPKTS); 140272343Sngie do { 141272343Sngie DGRAM[0] = n; 142272343Sngie error = send(fd[0], DGRAM, sizeof(DGRAM), 0); 143272343Sngie } while (error == -1 && errno == ENOBUFS); 144272343Sngie if (error == -1) 145272343Sngie ATF_REQUIRE_MSG(error != -1, "send failed (%s)", 146272343Sngie strerror(errno)); 147272343Sngie } 148272343Sngie error = wait(&status); 149272343Sngie ATF_REQUIRE_MSG(error != -1, "wait failed (%s)", 150272343Sngie strerror(errno)); 151272343Sngie break; 152272343Sngie } 153272343Sngie} 154272343Sngie 155272343SngieATF_TP_ADD_TCS(tp) 156272343Sngie{ 157272343Sngie 158272343Sngie ATF_TP_ADD_TC(tp, recvmmsg_basic); 159272343Sngie 160272343Sngie return atf_no_error(); 161272343Sngie} 162