After cleaning the rust and dust off, I'm happy to see my tech skills remain intact.
It still feels good :)
Nowadays, I'm working on a novel network threat detection engine for my new startup. I'll be sharing some stuff that I think would be of value to people out there.
Here's the first one:
We've decided to utilize FreeBSD's netmap fast packet I/O API for managing packet input/output at high speeds. Since the documentation is quite limited, it's hard to find a minimal working sample code demonstrating netmap functionality.
Below is a simple packet receiver code which just counts the number of packet received off the wire:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <poll.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <net/netmap_user.h>
int
main(int argc, char **argv)
{
        struct  netmap_if *nifp;
        struct  netmap_ring *ring;
        struct  nmreq nmr;
        struct  pollfd fds;
        int fd = 0;
        void *p = NULL;
        int i = 0;
        void *buf = NULL;
        int tot = 0;
        int nret = 0;
        if (argc < 2) {
                printf("%s int\n", argv[0]);
                return(1);
        }
        if ((fd = open("/dev/netmap", O_RDWR)) < 0) {
                perror("open");
                return(1);
        }
        bzero(&nmr, sizeof(nmr));
        strcpy(nmr.nr_name, argv[1]);
        nmr.nr_version  = NETMAP_API;
/* Register interface for Netmap mode, bypass OS stack */
        if (ioctl(fd, NIOCREGIF, &nmr) != 0) {
                perror("ioctl");
                return(1);
        }
/* MAP kernerl ring buffers to userspace */
/* MAP kernerl ring buffers to userspace */
        if ((p = mmap(0, nmr.nr_memsize, PROT_READ | PROT_WRITE, MAP_SHARED , fd, 0)) == NULL) {
                perror("mmap");
                return(1);
        }
        nifp =  NETMAP_IF(p, nmr.nr_offset);
        ring =  NETMAP_RXRING(nifp, 0);
        fds.fd  = fd;
        fds.events = POLLIN;
        for (;;) {
                poll(&fds, 1, 1000);
                while (!nm_ring_empty(ring)) {
                        i = ring->cur;
                        buf = NETMAP_BUF(ring,  ring->slot[i].buf_idx);
                        /* Insert your cool stuff here */
                        ring->head = ring->cur  = nm_ring_next(ring, i);
                        nret++;
                }
                if (ioctl(fd, NIOCRXSYNC, NULL) != 0)
                        perror("sync ioctl");
                tot += nret;
                printf("recv'd %d packets, total: %d\n", nret, tot);
                nret = 0;
        }
        return 0;
}
