Out-of-band packet support

The EVL network stack implements a raw packet interface, for exchanging raw frames directly with the network device driver (OSI Layer 2). This is the EVL equivalent of the AF_PACKET protocol family with raw sockets (SOCK_RAW) available wih the in-band network stack. Using out-of-band packet sockets with EVL is very similar to using its in-band counterpart, as illustrated by the oob-net-icmp demo program. This boils down to:

  1. creating a socket with the SOCK_OOB flag set, which extends the associated protocol support to out-of-band handling, in this case AF_PACKET.
#include <sys/socket.h>

	/* Get a raw socket with out-of-band capabilities. */
	s = socket(AF_PACKET, SOCK_RAW | SOCK_OOB, 0);
  1. fetching the interface index (aka ifindex) of the network device to use, typically by issuing the ioctl(SIOCGIFINDEX) request to the socket. An out-of-band port must be enabled for this device.
#include <net/if.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

	struct ifreq ifr;

	/* Retrieve the interface index for 'eth0.42'. */
	memset(&ifr, 0, sizeof(ifr));
	strncpy(ifr.ifr_name, "eth0.42", IFNAMSIZ - 1);
	ret = ioctl(s, SIOCGIFINDEX, &ifr);
	if (ret < 0)
		  error(1, errno, "ioctl(SIOCGIFINDEX)");
  1. binding the socket to its address (struct sockaddr_ll) which specifies the interface index, the address family set to AF_PACKET and a valid packet type to filter ingress packets in.
#include <sys/socket.h>
#include <linux/if_packet.h>

	struct sockaddr_ll addr;

	/* Bind the socket to its address, receiving all (ethernet) packet types. */
	memset(&addr, 0, sizeof(addr));
	addr.sll_ifindex = ifr.ifr_ifindex;
	addr.sll_family = AF_PACKET;
	addr.sll_protocol = htons(ETH_P_ALL);	/* All Ethernet packet types accepted. */
	ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
	if (ret)
		  error(1, errno, "cannot bind packet socket");
  1. sending and/or receiving packets via the socket using the oob_recvmsg() and oob_sendmsg() calls respectively.
	struct oob_msghdr msghdr;
	struct sockaddr_ll addr;
	struct iovec iov;
	ssize_t count;

	/* INPUT */
	iov.iov_base = input_packet;
	iov.iov_len = sizeof(input_packet);
	msghdr.msg_iov = &iov;
	msghdr.msg_iovlen = 1;
	msghdr.msg_control = NULL;
	msghdr.msg_controllen = 0;
	msghdr.msg_name = &addr;	/* or NULL, optional */
	msghdr.msg_namelen = sizeof(addr); /* or zero, optional */
	msghdr.msg_flags = 0;
	count = oob_recvmsg(s, &msghdr, NULL, 0);
	if (count < 0)
		  error(1, errno, "oob_recvmsg() failed");

	/* OUTPUT */
	iov.iov_base = output_packet;
	iov.iov_len = sizeof(output_packet);
	msghdr.msg_iov = &iov;
	msghdr.msg_iovlen = 1;
	msghdr.msg_control = NULL;
	msghdr.msg_controllen = 0;
	msghdr.msg_name = NULL; /* Optional, use bound device if NULL. */
	msghdr.msg_namelen = 0;
	msghdr.msg_flags = 0;
	count = oob_sendmsg(s, &msghdr, NULL, 0);
	if (count < 0)
	      error(1, errno, "oob_sendmsg() failed");

Threads issuing the oob_recvmsg() and/or oob_sendmsg() calls must be attached to the EVL core.


Last modified: Thu, 03 Jul 2025 16:39:27 +0200