2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 09:58:01 +00:00
ovs/lib/netdev-afxdp-pool.c
Ilya Maximets 1dcc490d44 netdev-afxdp: Allow building with libxdp and newer libbpf.
AF_XDP functions was deprecated in libbpf 0.7 and moved to libxdp.
Functions bpf_get/set_link_xdp_id() was deprecated in libbpf 0.8
and replaced with bpf_xdp_query_id() and bpf_xdp_attach/detach().

Updating configuration and source code to accommodate above changes
and allow building OVS with AF_XDP support on newer systems:

 - Checking the version of libbpf by detecting availability
   of bpf_xdp_detach.

 - Checking availability of the libxdp in a system by looking
   for a library providing libxdp_strerror(), if libbpf is
   newer than 0.6.  And checking for xsk.h header provided by
   libxdp-dev[el].

 - Use xsk.h from libbpf if it is older than 0.7 and not linking
   with libxdp in this case as there are known incompatible
   versions of libxdp in distributions.

 - Check for the NEED_WAKEUP feature replaced with direct checking
   in the source code if XDP_USE_NEED_WAKEUP is defined.

 - Checking availability of bpf_xdp_query_id and bpf_xdp_detach
   and using them instead of deprecated APIs.  Fall back to old
   functions if not found.

 - Dropped LIBBPF_LDADD variable as it makes library and function
   detection much harder without providing any actual benefits.
   AC_SEARCH_LIBS is used instead and it allows use of AC_CHECK_FUNCS.

 - Header includes moved around to files where they are actually used.

 - Removed libelf dependency as it is not really used.

With these changes it should be possible to build OVS with either:

 - libbpf built from the kernel sources (5.19 or older).
 - libbpf < 0.7 provided in distributions.
 - libxdp and libbpf >= 0.7 provided in newer distributions.

While it is technically possible to build with libbpf 0.7+ without
libxdp at the moment we're not allowing that for a few reasons.
First, required functions in libbpf are deprecated and can be removed
in future releases.  Second, support for all these combinations makes
the detection code fairly complex.
AFAIK, most of the distributions packaging libbpf 0.7+ do package
libxdp as well.

libxdp added as a build dependency for Fedora build since all
supported versions of Fedora are packaging this library.

Acked-by: Eelco Chaudron <echaudro@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2023-01-03 16:06:21 +01:00

170 lines
3.5 KiB
C

/*
* Copyright (c) 2018, 2019 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <config.h>
#include <errno.h>
#include "dp-packet.h"
#include "netdev-afxdp-pool.h"
#include "openvswitch/util.h"
/* Note:
* umem_elem_push* shouldn't overflow because we always pop
* elem first, then push back to the stack.
*/
static inline void
umem_elem_push_n__(struct umem_pool *umemp, int n, void **addrs)
{
void *ptr;
ovs_assert(umemp->index + n <= umemp->size);
ptr = &umemp->array[umemp->index];
memcpy(ptr, addrs, n * sizeof(void *));
umemp->index += n;
}
void umem_elem_push_n(struct umem_pool *umemp, int n, void **addrs)
{
ovs_spin_lock(&umemp->lock);
umem_elem_push_n__(umemp, n, addrs);
ovs_spin_unlock(&umemp->lock);
}
static inline void
umem_elem_push__(struct umem_pool *umemp, void *addr)
{
ovs_assert(umemp->index + 1 <= umemp->size);
umemp->array[umemp->index++] = addr;
}
void
umem_elem_push(struct umem_pool *umemp, void *addr)
{
ovs_spin_lock(&umemp->lock);
umem_elem_push__(umemp, addr);
ovs_spin_unlock(&umemp->lock);
}
static inline int
umem_elem_pop_n__(struct umem_pool *umemp, int n, void **addrs)
{
void *ptr;
if (OVS_UNLIKELY(umemp->index - n < 0)) {
return -ENOMEM;
}
umemp->index -= n;
ptr = &umemp->array[umemp->index];
memcpy(addrs, ptr, n * sizeof(void *));
return 0;
}
int
umem_elem_pop_n(struct umem_pool *umemp, int n, void **addrs)
{
int ret;
ovs_spin_lock(&umemp->lock);
ret = umem_elem_pop_n__(umemp, n, addrs);
ovs_spin_unlock(&umemp->lock);
return ret;
}
static inline void *
umem_elem_pop__(struct umem_pool *umemp)
{
if (OVS_UNLIKELY(umemp->index - 1 < 0)) {
return NULL;
}
return umemp->array[--umemp->index];
}
void *
umem_elem_pop(struct umem_pool *umemp)
{
void *ptr;
ovs_spin_lock(&umemp->lock);
ptr = umem_elem_pop__(umemp);
ovs_spin_unlock(&umemp->lock);
return ptr;
}
static void **
umem_pool_alloc__(unsigned int size)
{
void **bufs;
bufs = xmalloc_pagealign(size * sizeof *bufs);
memset(bufs, 0, size * sizeof *bufs);
return bufs;
}
int
umem_pool_init(struct umem_pool *umemp, unsigned int size)
{
umemp->array = umem_pool_alloc__(size);
if (!umemp->array) {
return -ENOMEM;
}
umemp->size = size;
umemp->index = 0;
ovs_spin_init(&umemp->lock);
return 0;
}
void
umem_pool_cleanup(struct umem_pool *umemp)
{
free_pagealign(umemp->array);
umemp->array = NULL;
ovs_spin_destroy(&umemp->lock);
}
unsigned int
umem_pool_count(struct umem_pool *umemp)
{
return umemp->index;
}
/* AF_XDP metadata init/destroy. */
int
xpacket_pool_init(struct xpacket_pool *xp, unsigned int size)
{
xp->array = xmalloc_pagealign(size * sizeof *xp->array);
xp->size = size;
memset(xp->array, 0, size * sizeof *xp->array);
return 0;
}
void
xpacket_pool_cleanup(struct xpacket_pool *xp)
{
free_pagealign(xp->array);
xp->array = NULL;
}