On Tue, Apr 30, 2019 at 5:46 AM Björn Töpel <bjorn.to...@gmail.com> wrote: > > From: Björn Töpel <bjorn.to...@intel.com> > > The bpf_map_update_elem() function, when used on an XSKMAP, will fail > if not a valid AF_XDP socket is passed as value. Therefore, this is > function cannot be used to clear the XSKMAP. Instead, the > bpf_map_delete_elem() function should be used for that. > > This patch also simplifies the code by breaking up > xsk_update_bpf_maps() into three smaller functions. > > Reported-by: William Tu <u9012...@gmail.com> > Fixes: 1cad07884239 ("libbpf: add support for using AF_XDP sockets") > Signed-off-by: Björn Töpel <bjorn.to...@intel.com> > ---
Thank you. Tested-by: William Tu <u9012...@gmail.com> > tools/lib/bpf/xsk.c | 115 +++++++++++++++++++++++--------------------- > 1 file changed, 60 insertions(+), 55 deletions(-) > > diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c > index af5f310ecca1..c2e6da464504 100644 > --- a/tools/lib/bpf/xsk.c > +++ b/tools/lib/bpf/xsk.c > @@ -386,21 +386,17 @@ static void xsk_delete_bpf_maps(struct xsk_socket *xsk) > { > close(xsk->qidconf_map_fd); > close(xsk->xsks_map_fd); > + xsk->qidconf_map_fd = -1; > + xsk->xsks_map_fd = -1; > } > > -static int xsk_update_bpf_maps(struct xsk_socket *xsk, int qidconf_value, > - int xsks_value) > +static int xsk_lookup_bpf_maps(struct xsk_socket *xsk) > { > - bool qidconf_map_updated = false, xsks_map_updated = false; > + __u32 i, *map_ids, num_maps, prog_len = sizeof(struct bpf_prog_info); > + __u32 map_len = sizeof(struct bpf_map_info); > struct bpf_prog_info prog_info = {}; > - __u32 prog_len = sizeof(prog_info); > struct bpf_map_info map_info; > - __u32 map_len = sizeof(map_info); > - __u32 *map_ids; > - int reset_value = 0; > - __u32 num_maps; > - unsigned int i; > - int err; > + int fd, err; > > err = bpf_obj_get_info_by_fd(xsk->prog_fd, &prog_info, &prog_len); > if (err) > @@ -421,66 +417,71 @@ static int xsk_update_bpf_maps(struct xsk_socket *xsk, > int qidconf_value, > goto out_map_ids; > > for (i = 0; i < prog_info.nr_map_ids; i++) { > - int fd; > + if (xsk->qidconf_map_fd != -1 && xsk->xsks_map_fd != -1) > + break; > > fd = bpf_map_get_fd_by_id(map_ids[i]); > - if (fd < 0) { > - err = -errno; > - goto out_maps; > - } > + if (fd < 0) > + continue; > > err = bpf_obj_get_info_by_fd(fd, &map_info, &map_len); > - if (err) > - goto out_maps; > + if (err) { > + close(fd); > + continue; > + } > > if (!strcmp(map_info.name, "qidconf_map")) { > - err = bpf_map_update_elem(fd, &xsk->queue_id, > - &qidconf_value, 0); > - if (err) > - goto out_maps; > - qidconf_map_updated = true; > xsk->qidconf_map_fd = fd; > - } else if (!strcmp(map_info.name, "xsks_map")) { > - err = bpf_map_update_elem(fd, &xsk->queue_id, > - &xsks_value, 0); > - if (err) > - goto out_maps; > - xsks_map_updated = true; > + continue; > + } > + > + if (!strcmp(map_info.name, "xsks_map")) { > xsk->xsks_map_fd = fd; > + continue; > } > > - if (qidconf_map_updated && xsks_map_updated) > - break; > + close(fd); > } > > - if (!(qidconf_map_updated && xsks_map_updated)) { > + err = 0; > + if (xsk->qidconf_map_fd < 0 || xsk->xsks_map_fd < 0) { > err = -ENOENT; > - goto out_maps; > + xsk_delete_bpf_maps(xsk); > } > > - err = 0; > - goto out_success; > - > -out_maps: > - if (qidconf_map_updated) > - (void)bpf_map_update_elem(xsk->qidconf_map_fd, &xsk->queue_id, > - &reset_value, 0); > - if (xsks_map_updated) > - (void)bpf_map_update_elem(xsk->xsks_map_fd, &xsk->queue_id, > - &reset_value, 0); > -out_success: > - if (qidconf_map_updated) > - close(xsk->qidconf_map_fd); > - if (xsks_map_updated) > - close(xsk->xsks_map_fd); > out_map_ids: > free(map_ids); > return err; > } > > +static void xsk_clear_bpf_maps(struct xsk_socket *xsk) > +{ > + int qid = false; > + > + (void)bpf_map_update_elem(xsk->qidconf_map_fd, &xsk->queue_id, &qid, > 0); > + (void)bpf_map_delete_elem(xsk->xsks_map_fd, &xsk->queue_id); > +} > + > +static int xsk_set_bpf_maps(struct xsk_socket *xsk) > +{ > + int qid = true, fd = xsk->fd, err; > + > + err = bpf_map_update_elem(xsk->qidconf_map_fd, &xsk->queue_id, &qid, > 0); > + if (err) > + goto out; > + > + err = bpf_map_update_elem(xsk->xsks_map_fd, &xsk->queue_id, &fd, 0); > + if (err) > + goto out; > + > + return 0; > +out: > + xsk_clear_bpf_maps(xsk); > + return err; > +} > + > static int xsk_setup_xdp_prog(struct xsk_socket *xsk) > { > - bool prog_attached = false; > __u32 prog_id = 0; > int err; > > @@ -490,7 +491,6 @@ static int xsk_setup_xdp_prog(struct xsk_socket *xsk) > return err; > > if (!prog_id) { > - prog_attached = true; > err = xsk_create_bpf_maps(xsk); > if (err) > return err; > @@ -500,20 +500,21 @@ static int xsk_setup_xdp_prog(struct xsk_socket *xsk) > goto out_maps; > } else { > xsk->prog_fd = bpf_prog_get_fd_by_id(prog_id); > + err = xsk_lookup_bpf_maps(xsk); > + if (err) > + goto out_load; > } > > - err = xsk_update_bpf_maps(xsk, true, xsk->fd); > + err = xsk_set_bpf_maps(xsk); > if (err) > goto out_load; > > return 0; > > out_load: > - if (prog_attached) > - close(xsk->prog_fd); > + close(xsk->prog_fd); > out_maps: > - if (prog_attached) > - xsk_delete_bpf_maps(xsk); > + xsk_delete_bpf_maps(xsk); > return err; > } > > @@ -641,6 +642,9 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const > char *ifname, > goto out_mmap_tx; > } > > + xsk->qidconf_map_fd = -1; > + xsk->xsks_map_fd = -1; > + > if (!(xsk->config.libbpf_flags & > XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) { > err = xsk_setup_xdp_prog(xsk); > if (err) > @@ -705,7 +709,8 @@ void xsk_socket__delete(struct xsk_socket *xsk) > if (!xsk) > return; > > - (void)xsk_update_bpf_maps(xsk, 0, 0); > + xsk_clear_bpf_maps(xsk); > + xsk_delete_bpf_maps(xsk); > > optlen = sizeof(off); > err = getsockopt(xsk->fd, SOL_XDP, XDP_MMAP_OFFSETS, &off, &optlen); > -- > 2.20.1 >