iovisor / iovisor/bcc

I want to use xdpsock to do the following things:

Open
#2,409 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C
Stars
22.7k
Forks
4.1k
Avg merge
10d 4h
Merged PRs (30d)
3

Description

I want use xdpsock receive packets from a network interface, then encapsulation header, then send to another network interface.
I want use on umem between this two socket to reduce copy..
I refer to the samples in kernel code:
samples\bpf\xdpsock_user.c
samples\bpf\xdpsock_kern.c

the following function in the user.c i modified like this:
static struct xdpsock *xsk_configure(struct xdp_umem *umem,int opt_ifindex, int opt_queue)
{
struct sockaddr_xdp sxdp = {};
struct xdp_mmap_offsets off;
int sfd, ndescs = NUM_DESCS;
struct xdpsock *xsk;
bool shared = true;
socklen_t optlen;
u64 i;

sfd = socket(PF_XDP, SOCK_RAW, 0);
lassert(sfd >= 0);

xsk = calloc(1, sizeof(*xsk));
lassert(xsk);

xsk->sfd = sfd;
xsk->outstanding_tx = 0;

if (!umem) {
shared = false;
xsk->umem = xdp_umem_configure(sfd);
} else {
xsk->umem = umem;
}

lassert(setsockopt(sfd, SOL_XDP, XDP_RX_RING,
&ndescs, sizeof(int)) == 0);
lassert(setsockopt(sfd, SOL_XDP, XDP_TX_RING,
&ndescs, sizeof(int)) == 0);
optlen = sizeof(off);
lassert(getsockopt(sfd, SOL_XDP, XDP_MMAP_OFFSETS, &off,
&optlen) == 0);

/* Rx */
xsk->rx.map = mmap(NULL,
off.rx.desc +
NUM_DESCS * sizeof(struct xdp_desc),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE, sfd,
XDP_PGOFF_RX_RING);
lassert(xsk->rx.map != MAP_FAILED);

if (!shared) {
for (i = 0; i < NUM_DESCS * FRAME_SIZE; i += FRAME_SIZE)
lassert(umem_fill_to_kernel(&xsk->umem->fq, &i, 1)
== 0);
}

/* Tx */
xsk->tx.map = mmap(NULL,
off.tx.desc +
NUM_DESCS * sizeof(struct xdp_desc),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE, sfd,
XDP_PGOFF_TX_RING);
lassert(xsk->tx.map != MAP_FAILED);

xsk->rx.mask = NUM_DESCS - 1;
xsk->rx.size = NUM_DESCS;
xsk->rx.producer = xsk->rx.map + off.rx.producer;
xsk->rx.consumer = xsk->rx.map + off.rx.consumer;
xsk->rx.ring = xsk->rx.map + off.rx.desc;

xsk->tx.mask = NUM_DESCS - 1;
xsk->tx.size = NUM_DESCS;
xsk->tx.producer = xsk->tx.map + off.tx.producer;
xsk->tx.consumer = xsk->tx.map + off.tx.consumer;
xsk->tx.ring = xsk->tx.map + off.tx.desc;
xsk->tx.cached_cons = NUM_DESCS;

sxdp.sxdp_family = PF_XDP;
sxdp.sxdp_ifindex = opt_ifindex; // If I try to create two socket share the same umem , this ifindex must be the same, otherwise the bind() will be failed
sxdp.sxdp_queue_id = opt_queue;

if (shared) {
sxdp.sxdp_flags = XDP_SHARED_UMEM;
sxdp.sxdp_shared_umem_fd = umem->fd;
} else {
sxdp.sxdp_flags = opt_xdp_bind_flags;
}

lassert(bind(sfd, (struct sockaddr *)&sxdp, sizeof(sxdp)) == 0);

return xsk;
}

static struct xdp_umem *xdp_umem_configure(int sfd)
{
int fq_size = FQ_NUM_DESCS, cq_size = CQ_NUM_DESCS;
struct xdp_mmap_offsets off;
struct xdp_umem_reg mr;
struct xdp_umem *umem;
socklen_t optlen;
void *bufs;

umem = calloc(1, sizeof(*umem));
lassert(umem);

lassert(posix_memalign(&bufs, getpagesize(), /* PAGE_SIZE aligned */
NUM_FRAMES * FRAME_SIZE) == 0);

mr.addr = (__u64)bufs;
mr.len = NUM_FRAMES * FRAME_SIZE;
mr.chunk_size = FRAME_SIZE;
mr.headroom = FRAME_HEADROOM; // Is this is the head reserved bytes?

Question:
1、 If I try to create two socket share the same umem , this ifindex must be the same, otherwise the bind() will be failed。How can I realize the following scense?
2、I want to encapsulate header, how to adjust the header postion?

![image](https://user-images.githubusercontent.com/22912347/59366611-27313a00-8d6d-11e9-83b8-0161859bf624.png)

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.