Home | History | Annotate | Line # | Download | only in shmif_pcapin
      1  1.1  ozaki /*	$NetBSD: shmif_pcapin.c,v 1.1 2024/09/02 05:14:45 ozaki-r Exp $	*/
      2  1.1  ozaki 
      3  1.1  ozaki /*-
      4  1.1  ozaki  * Copyright (c) 2017-2018 Internet Initiative Japan Inc.
      5  1.1  ozaki  * Copyright (c) 2010 Antti Kantee.
      6  1.1  ozaki  * All Rights Reserved.
      7  1.1  ozaki  *
      8  1.1  ozaki  * Redistribution and use in source and binary forms, with or without
      9  1.1  ozaki  * modification, are permitted provided that the following conditions
     10  1.1  ozaki  * are met:
     11  1.1  ozaki  * 1. Redistributions of source code must retain the above copyright
     12  1.1  ozaki  *    notice, this list of conditions and the following disclaimer.
     13  1.1  ozaki  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.1  ozaki  *    notice, this list of conditions and the following disclaimer in the
     15  1.1  ozaki  *    documentation and/or other materials provided with the distribution.
     16  1.1  ozaki  *
     17  1.1  ozaki  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     18  1.1  ozaki  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  1.1  ozaki  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  1.1  ozaki  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     21  1.1  ozaki  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  1.1  ozaki  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     23  1.1  ozaki  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  1.1  ozaki  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  1.1  ozaki  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  1.1  ozaki  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  1.1  ozaki  * SUCH DAMAGE.
     28  1.1  ozaki  */
     29  1.1  ozaki 
     30  1.1  ozaki #include <rump/rumpuser_port.h>
     31  1.1  ozaki 
     32  1.1  ozaki #ifndef lint
     33  1.1  ozaki __RCSID("$NetBSD: shmif_pcapin.c,v 1.1 2024/09/02 05:14:45 ozaki-r Exp $");
     34  1.1  ozaki #endif /* !lint */
     35  1.1  ozaki 
     36  1.1  ozaki #include <stddef.h>
     37  1.1  ozaki #include <sys/types.h>
     38  1.1  ozaki #include <sys/mman.h>
     39  1.1  ozaki #include <sys/stat.h>
     40  1.1  ozaki #include <sys/atomic.h>
     41  1.1  ozaki #include <sys/bswap.h>
     42  1.1  ozaki 
     43  1.1  ozaki #include <assert.h>
     44  1.1  ozaki #include <err.h>
     45  1.1  ozaki #include <fcntl.h>
     46  1.1  ozaki #include <inttypes.h>
     47  1.1  ozaki #include <pcap.h>
     48  1.1  ozaki #include <stdbool.h>
     49  1.1  ozaki #include <stdio.h>
     50  1.1  ozaki #include <stdlib.h>
     51  1.1  ozaki #include <string.h>
     52  1.1  ozaki #include <unistd.h>
     53  1.1  ozaki 
     54  1.1  ozaki #include "shmifvar.h"
     55  1.1  ozaki 
     56  1.1  ozaki __dead static void
     57  1.1  ozaki usage(void)
     58  1.1  ozaki {
     59  1.1  ozaki 
     60  1.1  ozaki #ifndef HAVE_GETPROGNAME
     61  1.1  ozaki #define getprogname() "shmif_pcapin"
     62  1.1  ozaki #endif
     63  1.1  ozaki 
     64  1.1  ozaki 	fprintf(stderr, "usage: %s pcap-file-path bus-path\n", getprogname());
     65  1.1  ozaki 	exit(1);
     66  1.1  ozaki }
     67  1.1  ozaki 
     68  1.1  ozaki /*
     69  1.1  ozaki  * The BUFSIZE come from shmif_dumpbus.c because there're not any experiences to
     70  1.1  ozaki  * make a decision about best size.
     71  1.1  ozaki  */
     72  1.1  ozaki #define BUFSIZE 64*1024
     73  1.1  ozaki 
     74  1.1  ozaki /*
     75  1.1  ozaki  * dowakeup, shmif_lockbus and shmif_unlockbus copy from
     76  1.1  ozaki  * sys/rump/net/lib/libshimif/if_shmem.c. So if you have to understood locking
     77  1.1  ozaki  * mechanism, you also see that.
     78  1.1  ozaki  */
     79  1.1  ozaki static int
     80  1.1  ozaki dowakeup(int memfd)
     81  1.1  ozaki {
     82  1.1  ozaki 	struct iovec iov;
     83  1.1  ozaki 	uint32_t ver = SHMIF_VERSION;
     84  1.1  ozaki 
     85  1.1  ozaki 	iov.iov_base = &ver;
     86  1.1  ozaki 	iov.iov_len = sizeof(ver);
     87  1.1  ozaki 
     88  1.1  ozaki 	if (lseek(memfd, IFMEM_WAKEUP, SEEK_SET) == IFMEM_WAKEUP)
     89  1.1  ozaki 		return writev(memfd, &iov, 1);
     90  1.1  ozaki 	else
     91  1.1  ozaki 		return -1;
     92  1.1  ozaki }
     93  1.1  ozaki 
     94  1.1  ozaki /*
     95  1.1  ozaki  * This locking needs work and will misbehave severely if:
     96  1.1  ozaki  * 1) the backing memory has to be paged in
     97  1.1  ozaki  * 2) some lockholder exits while holding the lock
     98  1.1  ozaki  */
     99  1.1  ozaki static void
    100  1.1  ozaki shmif_lockbus(struct shmif_mem *busmem)
    101  1.1  ozaki {
    102  1.1  ozaki 	int i = 0;
    103  1.1  ozaki 
    104  1.1  ozaki 	while (__predict_false(atomic_cas_32(&busmem->shm_lock,
    105  1.1  ozaki 	    LOCK_UNLOCKED, LOCK_LOCKED) == LOCK_LOCKED)) {
    106  1.1  ozaki 		if (__predict_false(++i > LOCK_COOLDOWN)) {
    107  1.1  ozaki 			usleep(1000);
    108  1.1  ozaki 			i = 0;
    109  1.1  ozaki 		}
    110  1.1  ozaki 		continue;
    111  1.1  ozaki 	}
    112  1.1  ozaki 	membar_enter();
    113  1.1  ozaki }
    114  1.1  ozaki 
    115  1.1  ozaki static void
    116  1.1  ozaki shmif_unlockbus(struct shmif_mem *busmem)
    117  1.1  ozaki {
    118  1.1  ozaki 	unsigned int old __diagused;
    119  1.1  ozaki 
    120  1.1  ozaki 	membar_exit();
    121  1.1  ozaki 	old = atomic_swap_32(&busmem->shm_lock, LOCK_UNLOCKED);
    122  1.1  ozaki 	assert(old == LOCK_LOCKED);
    123  1.1  ozaki }
    124  1.1  ozaki 
    125  1.1  ozaki 
    126  1.1  ozaki int
    127  1.1  ozaki main(int argc, char *argv[])
    128  1.1  ozaki {
    129  1.1  ozaki 	struct stat sb;
    130  1.1  ozaki 	void *busmem;
    131  1.1  ozaki 	struct shmif_mem *bmem;
    132  1.1  ozaki 	int fd;
    133  1.1  ozaki 	const u_char *pkt;
    134  1.1  ozaki 	char *buf;
    135  1.1  ozaki 	char pcap_errbuf[PCAP_ERRBUF_SIZE];
    136  1.1  ozaki 	pcap_t *pcap;
    137  1.1  ozaki 	struct pcap_pkthdr pcaphdr;
    138  1.1  ozaki 
    139  1.1  ozaki 	argc -= optind;
    140  1.1  ozaki 	argv += optind;
    141  1.1  ozaki 
    142  1.1  ozaki 	if (argc != 2)
    143  1.1  ozaki 		usage();
    144  1.1  ozaki 
    145  1.1  ozaki 	buf = malloc(BUFSIZE);
    146  1.1  ozaki 	if (buf == NULL)
    147  1.1  ozaki 		err(EXIT_FAILURE, "malloc");
    148  1.1  ozaki 
    149  1.1  ozaki 	fd = open(argv[1], O_RDWR);
    150  1.1  ozaki 	if (fd == -1)
    151  1.1  ozaki 		err(EXIT_FAILURE, "open bus");
    152  1.1  ozaki 
    153  1.1  ozaki 	if (fstat(fd, &sb) == -1)
    154  1.1  ozaki 		err(EXIT_FAILURE, "stat");
    155  1.1  ozaki 
    156  1.1  ozaki 	busmem = mmap(NULL, sb.st_size, PROT_WRITE|PROT_READ,
    157  1.1  ozaki 	    MAP_FILE|MAP_SHARED, fd, 0);
    158  1.1  ozaki 	if (busmem == MAP_FAILED)
    159  1.1  ozaki 		err(EXIT_FAILURE, "mmap");
    160  1.1  ozaki 	bmem = busmem;
    161  1.1  ozaki 
    162  1.1  ozaki 	if (bmem->shm_magic != SHMIF_MAGIC)
    163  1.1  ozaki 		errx(EXIT_FAILURE, "%s not a shmif bus", argv[1]);
    164  1.1  ozaki 
    165  1.1  ozaki 	/*
    166  1.1  ozaki 	 * if bmem->shm_version is 0, it indicates to not write any packets
    167  1.1  ozaki 	 * by anyone.
    168  1.1  ozaki 	 */
    169  1.1  ozaki 	if (bmem->shm_version != SHMIF_VERSION && bmem->shm_version != 0)
    170  1.1  ozaki 		errx(EXIT_FAILURE, "bus version %d, program %d",
    171  1.1  ozaki 		    bmem->shm_version, SHMIF_VERSION);
    172  1.1  ozaki 
    173  1.1  ozaki 	fprintf(stdout, "bus version %d, lock: %d, generation: %" PRIu64
    174  1.1  ozaki 	    ", firstoff: 0x%04x, lastoff: 0x%04x\n", bmem->shm_version,
    175  1.1  ozaki 	    bmem->shm_lock, bmem->shm_gen, bmem->shm_first, bmem->shm_last);
    176  1.1  ozaki 
    177  1.1  ozaki 	pcap = pcap_open_offline(argv[0], pcap_errbuf);
    178  1.1  ozaki 	if (pcap == NULL)
    179  1.1  ozaki 		err(EXIT_FAILURE, "cannot open pcap file: %s", pcap_errbuf);
    180  1.1  ozaki 
    181  1.1  ozaki 	while ((pkt = pcap_next(pcap, &pcaphdr))) {
    182  1.1  ozaki 		struct shmif_pkthdr sp;
    183  1.1  ozaki 		uint32_t dataoff;
    184  1.1  ozaki 		struct timeval tv;
    185  1.1  ozaki 		bool wrap;
    186  1.1  ozaki 
    187  1.1  ozaki 		gettimeofday(&tv, NULL);
    188  1.1  ozaki 		sp.sp_len = pcaphdr.len;
    189  1.1  ozaki 		sp.sp_sec = tv.tv_sec;
    190  1.1  ozaki 		sp.sp_usec = tv.tv_usec;
    191  1.1  ozaki 		memcpy(buf, pkt, pcaphdr.len);
    192  1.1  ozaki 
    193  1.1  ozaki 		shmif_lockbus(bmem);
    194  1.1  ozaki 
    195  1.1  ozaki 		bmem->shm_last = shmif_nextpktoff(bmem, bmem->shm_last);
    196  1.1  ozaki 		wrap = false;
    197  1.1  ozaki 
    198  1.1  ozaki 		dataoff = shmif_buswrite(bmem, bmem->shm_last, &sp,
    199  1.1  ozaki 		    sizeof(sp), &wrap);
    200  1.1  ozaki 		dataoff = shmif_buswrite(bmem, dataoff, buf, pcaphdr.len, &wrap);
    201  1.1  ozaki 
    202  1.1  ozaki 		if (wrap)
    203  1.1  ozaki 			bmem->shm_gen++;
    204  1.1  ozaki 
    205  1.1  ozaki 		shmif_unlockbus(bmem);
    206  1.1  ozaki 	}
    207  1.1  ozaki 
    208  1.1  ozaki 	if (dowakeup(fd) == -1)
    209  1.1  ozaki 		errx(EXIT_FAILURE, "writev for wakeup");
    210  1.1  ozaki 
    211  1.1  ozaki 	return 0;
    212  1.1  ozaki }
    213