&xsk->fd, 0);
 }
 
-static int xsk_setup_xdp_prog(struct xsk_socket *xsk)
+static int xsk_create_xsk_struct(int ifindex, struct xsk_socket *xsk)
 {
+       char ifname[IFNAMSIZ];
+       struct xsk_ctx *ctx;
+       char *interface;
+
+       ctx = calloc(1, sizeof(*ctx));
+       if (!ctx)
+               return -ENOMEM;
+
+       interface = if_indextoname(ifindex, &ifname[0]);
+       if (!interface) {
+               free(ctx);
+               return -errno;
+       }
+
+       ctx->ifindex = ifindex;
+       strncpy(ctx->ifname, ifname, IFNAMSIZ - 1);
+       ctx->ifname[IFNAMSIZ - 1] = 0;
+
+       xsk->ctx = ctx;
+
+       return 0;
+}
+
+static int __xsk_setup_xdp_prog(struct xsk_socket *_xdp,
+                               int *xsks_map_fd)
+{
+       struct xsk_socket *xsk = _xdp;
        struct xsk_ctx *ctx = xsk->ctx;
        __u32 prog_id = 0;
        int err;
 
                err = xsk_load_xdp_prog(xsk);
                if (err) {
-                       xsk_delete_bpf_maps(xsk);
-                       return err;
+                       goto err_load_xdp_prog;
                }
        } else {
                ctx->prog_fd = bpf_prog_get_fd_by_id(prog_id);
                }
        }
 
-       if (xsk->rx)
+       if (xsk->rx) {
                err = xsk_set_bpf_maps(xsk);
-       if (err) {
-               xsk_delete_bpf_maps(xsk);
-               close(ctx->prog_fd);
-               return err;
+               if (err) {
+                       if (!prog_id) {
+                               goto err_set_bpf_maps;
+                       } else {
+                               close(ctx->prog_fd);
+                               return err;
+                       }
+               }
        }
+       if (xsks_map_fd)
+               *xsks_map_fd = ctx->xsks_map_fd;
 
        return 0;
+
+err_set_bpf_maps:
+       close(ctx->prog_fd);
+       bpf_set_link_xdp_fd(ctx->ifindex, -1, 0);
+err_load_xdp_prog:
+       xsk_delete_bpf_maps(xsk);
+
+       return err;
 }
 
 static struct xsk_ctx *xsk_get_ctx(struct xsk_umem *umem, int ifindex,
        return ctx;
 }
 
+static void xsk_destroy_xsk_struct(struct xsk_socket *xsk)
+{
+       free(xsk->ctx);
+       free(xsk);
+}
+
+int xsk_socket__update_xskmap(struct xsk_socket *xsk, int fd)
+{
+       xsk->ctx->xsks_map_fd = fd;
+       return xsk_set_bpf_maps(xsk);
+}
+
+int xsk_setup_xdp_prog(int ifindex, int *xsks_map_fd)
+{
+       struct xsk_socket *xsk;
+       int res;
+
+       xsk = calloc(1, sizeof(*xsk));
+       if (!xsk)
+               return -ENOMEM;
+
+       res = xsk_create_xsk_struct(ifindex, xsk);
+       if (res) {
+               free(xsk);
+               return -EINVAL;
+       }
+
+       res = __xsk_setup_xdp_prog(xsk, xsks_map_fd);
+
+       xsk_destroy_xsk_struct(xsk);
+
+       return res;
+}
+
 int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
                              const char *ifname,
                              __u32 queue_id, struct xsk_umem *umem,
        ctx->prog_fd = -1;
 
        if (!(xsk->config.libbpf_flags & XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) {
-               err = xsk_setup_xdp_prog(xsk);
+               err = __xsk_setup_xdp_prog(xsk, NULL);
                if (err)
                        goto out_mmap_tx;
        }