}
ret = knot_xsk_init(new_if->sock_xdp + i, dev, i,
- sockaddr_port(addr));
+ sockaddr_port(addr), i == 0);
free(dev);
if (ret != KNOT_EOK) {
log_warning("failed to init XDP (%s)", knot_strerror(ret));
xsk_socket__delete(socket->xsk);
xsk_umem__delete(socket->umem->umem);
- kxsk_iface_free((struct kxsk_iface *)/*const-cast*/socket->iface, true);
+ kxsk_iface_free((struct kxsk_iface *)/*const-cast*/socket->iface);
free(socket);
}
_public_
int knot_xsk_init(struct knot_xsk_socket **socket, const char *ifname, int if_queue,
- int listen_port)
+ int listen_port, bool load_bpf)
{
if (socket == NULL || *socket != NULL) {
return KNOT_EINVAL;
}
- struct kxsk_iface *iface = kxsk_iface_new(ifname);
+ struct kxsk_iface *iface = kxsk_iface_new(ifname, load_bpf);
if (!iface) {
return KNOT_EINVAL;
}
struct xsk_umem_info *umem =
configure_xsk_umem(&global_umem_config, UMEM_FRAME_COUNT);
if (umem == NULL) {
- kxsk_iface_free(iface, false);
+ kxsk_iface_free(iface);
return KNOT_ENOMEM;
}
*socket = xsk_configure_socket(umem, iface, if_queue);
if (!*socket) {
xsk_umem__delete(umem->umem);
- kxsk_iface_free(iface, false);
+ kxsk_iface_free(iface);
return KNOT_NET_ESOCKET;
}
if (ret != KNOT_EOK) {
xsk_socket__delete((*socket)->xsk);
xsk_umem__delete((*socket)->umem->umem);
- kxsk_iface_free(iface, false);
+ kxsk_iface_free(iface);
free(*socket);
*socket = NULL;
return ret;
struct knot_xsk_socket;
int knot_xsk_init(struct knot_xsk_socket **socket, const char *ifname, int if_queue,
- int listen_port);
+ int listen_port, bool load_bpf);
void knot_xsk_deinit(struct knot_xsk_socket *socket);
static int ensure_udp_prog(struct kxsk_iface *iface, const char *prog_fname)
{
- int ret;
-
- uint32_t prog_id;
- ret = bpf_get_link_xdp_id(iface->ifindex, &prog_id, 0);
- if (ret)
- return -abs(ret);
- if (prog_id)
- return bpf_prog_get_fd_by_id(prog_id);
-
/* Use libbpf for extracting BPF byte-code from BPF-ELF object, and
* loading this into the kernel via bpf-syscall */
int prog_fd;
- ret = bpf_prog_load(prog_fname, BPF_PROG_TYPE_XDP, &iface->prog_obj, &prog_fd);
+ int ret = bpf_prog_load(prog_fname, BPF_PROG_TYPE_XDP, &iface->prog_obj, &prog_fd);
if (ret) {
fprintf(stderr, "[kxsk] failed loading BPF program (%s) (%d): %s\n",
prog_fname, ret, strerror(-ret));
fprintf(stderr, "bpf_set_link_xdp_fd() == %d\n", ret);
return -abs(ret);
} else {
- fprintf(stderr, "[kxsk] loaded BPF program\n");
+ fprintf(stderr, "[kxsk] loaded BPF program %d %d\n", iface->ifindex, prog_fd);
}
return prog_fd;
return err;
}
-struct kxsk_iface * kxsk_iface_new(const char *ifname)
+struct kxsk_iface * kxsk_iface_new(const char *ifname, bool load_bpf)
{
- struct kxsk_iface *iface = malloc(sizeof(*iface));
+ struct kxsk_iface *iface = calloc(1, sizeof(*iface));
if (!iface) {
errno = ENOMEM;
return NULL;
}
iface->qidconf_map_fd = iface->xsks_map_fd = -1;
- int ret = ensure_udp_prog_builtin(iface);
+ int ret;
+ if (load_bpf) {
+ ret = ensure_udp_prog_builtin(iface);
+ } else {
+ uint32_t prog_id = 0;
+ ret = bpf_get_link_xdp_id(iface->ifindex, &prog_id, 0);
+ if (!ret && prog_id) {
+ ret = bpf_prog_get_fd_by_id(prog_id);
+ }
+ }
+
if (ret >= 0)
ret = get_bpf_maps(ret, iface);
iface->ifname = strdup(iface->ifname);
return iface;
}
-void kxsk_iface_free(struct kxsk_iface *iface, bool unload_bpf)
+void kxsk_iface_free(struct kxsk_iface *iface)
{
unget_bpf_maps(iface);
- if (unload_bpf) {
- int ret = bpf_set_link_xdp_fd(iface->ifindex, -1, 0);
- printf("set link fd %d (%s) %d\n", ret, strerror(errno), iface->ifindex);
+ if (iface->prog_obj != NULL) {
(void)bpf_object__close(iface->prog_obj);
}
+
free((char *)/*const-cast*/iface->ifname);
free(iface);
}
* Note: if one is loaded on the interface already, we assume it's ours.
* LATER: it might be possible to check, e.g. by naming our maps unusually.
*/
-struct kxsk_iface * kxsk_iface_new(const char *ifname);
+struct kxsk_iface * kxsk_iface_new(const char *ifname, bool load_bpf);
/** Undo kxsk_iface_new(). It's always freed, even if some problems happen.
*
* Unloading the BPF program is optional, as keeping it only adds some overhead,
* and in case of multi-process it isn't easy to find that we're the last instance.
*/
-void kxsk_iface_free(struct kxsk_iface *iface, bool unload_bpf);
+void kxsk_iface_free(struct kxsk_iface *iface);
/** Activate this AF_XDP socket through the BPF maps. */
int kxsk_socket_start(const struct kxsk_iface *iface, int queue_id,