Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libbpf: Add a support for getting xdp prog id on ifindex

Since we have a dedicated netlink attributes for xdp setup on a
particular interface, it is now possible to retrieve the program id that
is currently attached to the interface. The use case is targeted for
sample xdp programs, which will store the program id just after loading
bpf program onto iface. On shutdown, the sample will make sure that it
can unload the program by querying again the iface and verifying that
both program id's matches.

Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

authored by

Maciej Fijalkowski and committed by
Daniel Borkmann
50db9f07 743e568c

+87
+1
tools/lib/bpf/libbpf.h
··· 317 317 struct bpf_object **pobj, int *prog_fd); 318 318 319 319 LIBBPF_API int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags); 320 + LIBBPF_API int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags); 320 321 321 322 enum bpf_perf_event_ret { 322 323 LIBBPF_PERF_EVENT_DONE = 0,
+1
tools/lib/bpf/libbpf.map
··· 132 132 bpf_probe_prog_type; 133 133 bpf_map_lookup_elem_flags; 134 134 bpf_object__find_map_fd_by_name; 135 + bpf_get_link_xdp_id; 135 136 } LIBBPF_0.0.1;
+85
tools/lib/bpf/netlink.c
··· 21 21 typedef int (*__dump_nlmsg_t)(struct nlmsghdr *nlmsg, libbpf_dump_nlmsg_t, 22 22 void *cookie); 23 23 24 + struct xdp_id_md { 25 + int ifindex; 26 + __u32 flags; 27 + __u32 id; 28 + }; 29 + 24 30 int libbpf_netlink_open(__u32 *nl_pid) 25 31 { 26 32 struct sockaddr_nl sa; ··· 200 194 return -LIBBPF_ERRNO__NLPARSE; 201 195 202 196 return dump_link_nlmsg(cookie, ifi, tb); 197 + } 198 + 199 + static unsigned char get_xdp_id_attr(unsigned char mode, __u32 flags) 200 + { 201 + if (mode != XDP_ATTACHED_MULTI) 202 + return IFLA_XDP_PROG_ID; 203 + if (flags & XDP_FLAGS_DRV_MODE) 204 + return IFLA_XDP_DRV_PROG_ID; 205 + if (flags & XDP_FLAGS_HW_MODE) 206 + return IFLA_XDP_HW_PROG_ID; 207 + if (flags & XDP_FLAGS_SKB_MODE) 208 + return IFLA_XDP_SKB_PROG_ID; 209 + 210 + return IFLA_XDP_UNSPEC; 211 + } 212 + 213 + static int get_xdp_id(void *cookie, void *msg, struct nlattr **tb) 214 + { 215 + struct nlattr *xdp_tb[IFLA_XDP_MAX + 1]; 216 + struct xdp_id_md *xdp_id = cookie; 217 + struct ifinfomsg *ifinfo = msg; 218 + unsigned char mode, xdp_attr; 219 + int ret; 220 + 221 + if (xdp_id->ifindex && xdp_id->ifindex != ifinfo->ifi_index) 222 + return 0; 223 + 224 + if (!tb[IFLA_XDP]) 225 + return 0; 226 + 227 + ret = libbpf_nla_parse_nested(xdp_tb, IFLA_XDP_MAX, tb[IFLA_XDP], NULL); 228 + if (ret) 229 + return ret; 230 + 231 + if (!xdp_tb[IFLA_XDP_ATTACHED]) 232 + return 0; 233 + 234 + mode = libbpf_nla_getattr_u8(xdp_tb[IFLA_XDP_ATTACHED]); 235 + if (mode == XDP_ATTACHED_NONE) 236 + return 0; 237 + 238 + xdp_attr = get_xdp_id_attr(mode, xdp_id->flags); 239 + if (!xdp_attr || !xdp_tb[xdp_attr]) 240 + return 0; 241 + 242 + xdp_id->id = libbpf_nla_getattr_u32(xdp_tb[xdp_attr]); 243 + 244 + return 0; 245 + } 246 + 247 + int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags) 248 + { 249 + struct xdp_id_md xdp_id = {}; 250 + int sock, ret; 251 + __u32 nl_pid; 252 + __u32 mask; 253 + 254 + if (flags & ~XDP_FLAGS_MASK) 255 + return -EINVAL; 256 + 257 + /* Check whether the single {HW,DRV,SKB} mode is set */ 258 + flags &= (XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE); 259 + mask = flags - 1; 260 + if (flags && flags & mask) 261 + return -EINVAL; 262 + 263 + sock = libbpf_netlink_open(&nl_pid); 264 + if (sock < 0) 265 + return sock; 266 + 267 + xdp_id.ifindex = ifindex; 268 + xdp_id.flags = flags; 269 + 270 + ret = libbpf_nl_get_link(sock, nl_pid, get_xdp_id, &xdp_id); 271 + if (!ret) 272 + *prog_id = xdp_id.id; 273 + 274 + close(sock); 275 + return ret; 203 276 } 204 277 205 278 int libbpf_nl_get_link(int sock, unsigned int nl_pid,