Examples
The following examples illustrate how to send & receive a batch of 30 frames using
the xdpiface
lib.
#include <sys/socket.h>
#include "xdpiface_classes.h"
static void hex_dump(void *pkt, size_t length)
{
const unsigned char *address = (unsigned char *)pkt;
const unsigned char *line = address;
size_t line_size = 32;
unsigned char c;
char buf[32];
int i = 0;
printf("length = %zu\n", length);
printf("%s | ", buf);
while (length-- > 0) {
printf("%02X ", *address++);
if (!(++i % line_size) || (length == 0 && i % line_size)) {
if (length == 0) {
while (i++ % line_size)
printf("__ ");
}
printf(" | "); /* right close */
while (line < address) {
c = *line++;
printf("%c", (c < 33 || c == 255) ? 0x2E : c);
}
printf("\n");
if (length > 0)
printf("%s | ", buf);
}
}
printf("\n");
}
int main (int argc, char *argv [])
{
int i = 0;
int ret = 0;
uint32_t batch_size = 30;
uint32_t frames_rcvd = 0;
const char *xdp_prog_path = "./xdp_sock_bpf.o";
char i_buffer[9000];
size_t i_buffer_size = 0;
size_t o_buffer_size = 1000;
char o_buffer[9000];
memset(o_buffer, 0x55, o_buffer_size);
xdp_iface_t *xdp_iface = xdp_iface_new ("lo");
ret = xdp_iface_load_program(xdp_iface, xdp_prog_path);
if (0 != ret) {
printf( "Failed to load program (%s)!", xdp_prog_path);
goto exit;
}
xdp_sock_t *xdp_sock = xdp_sock_new (xdp_iface);
xdp_sock_lookup_bpf_map(xdp_sock, xdp_iface, "xsks_map", 4, 4);
xdp_sock_set_sockopt(xdp_sock, SO_PREFER_BUSY_POLL, 1);
xdp_sock_set_sockopt(xdp_sock, SO_BUSY_POLL, 20);
xdp_sock_set_sockopt(xdp_sock, SO_BUSY_POLL_BUDGET, batch_size);
xdp_sock_tx_batch_set_size(xdp_sock, batch_size);
for (i = 0; i < batch_size; i++)
xdp_sock_send (xdp_sock, o_buffer, o_buffer_size);
xdp_sock_tx_batch_release(xdp_sock, batch_size);
xdp_sock_rx_batch_get_size (xdp_sock, &frames_rcvd, batch_size);
for (i = 0; i < frames_rcvd; i ++)
{
xdp_sock_recv (xdp_sock, i_buffer, &i_buffer_size);
hex_dump(i_buffer, i_buffer_size);
}
xdp_sock_rx_batch_release(xdp_sock, frames_rcvd);
xdp_sock_destroy (&xdp_sock);
xdp_iface_unload_program(xdp_iface);
exit:
xdp_iface_destroy (&xdp_iface);
return 0;
}
#include <sys/socket.h>
#include <cstring>
#include <iostream>
#include "xdpiface.hpp"
static void hexdump(void *ptr, int buflen) {
unsigned char *buf = (unsigned char*)ptr;
int i, j;
for (i=0; i<buflen; i+=16) {
printf("%06x: ", i);
for (j=0; j<16; j++)
if (i+j < buflen)
printf("%02x ", buf[i+j]);
else
printf(" ");
printf(" ");
for (j=0; j<16; j++)
if (i+j < buflen)
printf("%c", isprint(buf[i+j]) ? buf[i+j] : '.');
printf("\n");
}
}
int main (int argc, char *argv [])
{
uint32_t batch_size = 30;
uint32_t frames_rcvd = 0;
size_t o_buffer_size = 1000;
char o_buffer[9000];
memset(o_buffer, 0x55, o_buffer_size);
char i_buffer[9000];
size_t i_buffer_size = 0;
const std::string xdp_prog_path = "./xdp_sock_bpf.o";
const std::string interface = "lo";
XdpIface xdp_iface(interface);
xdp_iface.loadProgram(xdp_prog_path);
XdpSock xdp_sock(&xdp_iface);
xdp_sock.lookupBpfMap(&xdp_iface, "xsks_map", 4, 4);
xdp_sock.setSockopt(SO_PREFER_BUSY_POLL, 1);
xdp_sock.setSockopt(SO_BUSY_POLL, 20);
xdp_sock.setSockopt(SO_BUSY_POLL_BUDGET, batch_size);
xdp_sock.txBatchSetSize(batch_size);
for (int i = 0; i < batch_size; i++)
xdp_sock.send (o_buffer, o_buffer_size);
xdp_sock.txBatchRelease(batch_size);
xdp_sock.rxBatchGetSize (&frames_rcvd, batch_size);
for (int i = 0; i < frames_rcvd; i ++)
{
xdp_sock.recv (i_buffer, &i_buffer_size);
hexdump(i_buffer, i_buffer_size);
}
xdp_sock.rxBatchRelease(frames_rcvd);
std::cout << "Frames received: " << frames_rcvd << std::endl;
xdp_iface.unloadProgram();
return 0;
}
import xdpiface
from ctypes import c_int, create_string_buffer, c_size_t
def main():
batch_size = 30
xdp_iface = xdpiface.XdpIface("lo")
xdp_iface.load_program("./xdp_sock_bpf.o")
xdp_sock = xdpiface.XdpSock(xdp_iface)
xdp_sock.lookup_bpf_map(xdp_iface, b"xsks_map", 4, 4)
xdp_sock.set_sockopt(xdpiface.SO_PREFER_BUSY_POLL, 1)
xdp_sock.set_sockopt(xdpiface.SO_BUSY_POLL, 20)
xdp_sock.set_sockopt(xdpiface.SO_BUSY_POLL_BUDGET, batch_size)
frames_recd = c_int(0)
i_buffer = create_string_buffer(9000)
i_buffer_size = c_size_t(0)
frames_received = 0
o_buffer = create_string_buffer(1500)
o_buffer.raw = bytearray([0x55] * 1500)
o_buffer_size = c_size_t(1500)
xdp_sock.tx_batch_set_size(batch_size);
for i in range(batch_size):
xdp_sock.send (o_buffer, o_buffer_size);
xdp_sock.tx_batch_release(batch_size);
xdp_sock.rx_batch_get_size (frames_recd, batch_size);
for i in range(frames_recd.value):
xdp_sock.recv (i_buffer, i_buffer_size)
print(hexdump(i_buffer.raw[:i_buffer_size.value]))
xdp_sock.rx_batch_release(frames_recd.value);
xdp_iface.unload_program()
class hexdump:
def __init__(self, buf, off=0):
self.buf = buf
self.off = off
def __iter__(self):
last_bs, last_line = None, None
for i in range(0, len(self.buf), 16):
bs = bytearray(self.buf[i : i + 16])
line = "{:08x} {:23} {:23} |{:16}|".format(
self.off + i,
" ".join(("{:02x}".format(x) for x in bs[:8])),
" ".join(("{:02x}".format(x) for x in bs[8:])),
"".join((chr(x) if 32 <= x < 127 else "." for x in bs)),
)
if bs == last_bs:
line = "*"
if bs != last_bs or line != last_line:
yield line
last_bs, last_line = bs, line
yield "{:08x}".format(self.off + len(self.buf))
def __str__(self):
return "\n".join(self)
def __repr__(self):
return "\n".join(self)
if __name__ == '__main__':
main()
package main
import (
"testing"
"encoding/hex"
"bytes"
"fmt"
"xdpiface" // This may vary
)
func main() {
batch_size := uint32(30)
var frames_rcvd uint32 = 0
var oBufferSize int = 1000
oBuffer := bytes.Repeat([]byte{0x55}, oBufferSize)
var iBufferSize int = 0
iBuffer := make([]byte, 9000)
xdp_iface, err := XdpIfaceNew("lo")
if err != nil {
t.Errorf("Failed to create XDP iface")
}
defer xdp_iface.Destroy()
xdp_iface.LoadProgram("./xdp_sock_bpf.o")
xdp_sock, err := XdpSockNew(xdp_iface)
if err != nil {
t.Errorf("Failed to create XDP sock")
}
defer xdp_sock.Destroy()
xdp_sock.LoopUpBpfMap(xdp_iface, "xsks_map", 4, 4)
xdp_sock.SetSockopt(SO_PREFER_BUSY_POLL, 1)
xdp_sock.SetSockopt(SO_BUSY_POLL, 20)
xdp_sock.SetSockopt(SO_BUSY_POLL_BUDGET, int(batch_size))
xdp_sock.TxBatchSetSize(batch_size);
for i := 1; i <= int(batch_size); i++ {
xdp_sock.Send (oBuffer, oBufferSize)
}
xdp_sock.TxBatchRelease(batch_size);
xdp_sock.RxBatchGetSize (&frames_rcvd, batch_size);
for i := 1; i <= int(frames_rcvd); i ++ {
xdp_sock.Recv (iBuffer, &iBufferSize)
fmt.Println(hex.Dump(iBuffer[:iBufferSize]))
}
xdp_sock.RxBatchRelease(frames_rcvd)
xdp_iface.UnloadProgram()
}