]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
xdp: load bpf program exactly once at knotd start
authorpeltan <peltan@localhost.localdomain>
Mon, 6 Jan 2020 17:28:01 +0000 (18:28 +0100)
committerDaniel Salzman <daniel.salzman@nic.cz>
Tue, 21 Apr 2020 16:43:10 +0000 (18:43 +0200)
src/knot/server/server.c
src/libknot/xdp/af_xdp.c
src/libknot/xdp/af_xdp.h
src/libknot/xdp/bpf-user.c
src/libknot/xdp/bpf-user.h

index 847dac4a2ab316ce47d5075f5b9d350d6cb23bd7..a121508d1712e1835e76b102befb70ab29ab4193 100644 (file)
@@ -361,7 +361,7 @@ static iface_t *server_init_iface(struct sockaddr_storage *addr,
                }
 
                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));
index d6d25f12f5f87df85c4eb18b1272caf22bb2f00a..437349c30e45362abdf3293287ed679079eb7168 100644 (file)
@@ -163,7 +163,7 @@ void knot_xsk_deinit(struct knot_xsk_socket *socket)
        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);
 }
 
@@ -599,13 +599,13 @@ void knot_xsk_free_recvd(struct knot_xsk_socket *socket, const knot_xsk_msg_t *m
 
 _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;
        }
@@ -614,14 +614,14 @@ int knot_xsk_init(struct knot_xsk_socket **socket, const char *ifname, int if_qu
        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;
        }
 
@@ -629,7 +629,7 @@ int knot_xsk_init(struct knot_xsk_socket **socket, const char *ifname, int if_qu
        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;
index 6a21380c4812f9b22aebc007476d6fd86e8b5d73..c3b2fa171d035c7f247daea362dd34387c46b023 100644 (file)
@@ -32,7 +32,7 @@ typedef struct {
 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);
 
index 520b1bd09a9b8f48d1563b1f732461082cdede4b..902acc63a13e7723e29c79d946309f3e28eff8c0 100644 (file)
 
 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));
@@ -54,7 +45,7 @@ static int ensure_udp_prog(struct kxsk_iface *iface, const char *prog_fname)
                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;
@@ -199,9 +190,9 @@ int kxsk_socket_stop(const struct kxsk_iface *iface, int queue_id)
        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;
@@ -214,7 +205,17 @@ struct kxsk_iface * kxsk_iface_new(const char *ifname)
        }
        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);
 
@@ -227,15 +228,14 @@ struct kxsk_iface * kxsk_iface_new(const char *ifname)
        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);
 }
index da12f702369ff0b9cdae9ce7a39d6bbe3af14691..5293462e9fec5a8e8e615f34d304a9abb9b95f12 100644 (file)
@@ -96,14 +96,14 @@ typedef struct knot_xsk_socket {
  * 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,