|
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;
|
@@ -196,6 +202,85 @@ static int __dump_link_nlmsg(struct nlmsghdr *nlh,
|
196 | 202 | return dump_link_nlmsg(cookie, ifi, tb);
|
197 | 203 | }
|
198 | 204 |
|
| 205 | +static unsigned char get_xdp_id_attr(unsigned char mode, __u32 flags) |
| 206 | +{ |
| 207 | + if (mode != XDP_ATTACHED_MULTI) |
| 208 | + return IFLA_XDP_PROG_ID; |
| 209 | + if (flags & XDP_FLAGS_DRV_MODE) |
| 210 | + return IFLA_XDP_DRV_PROG_ID; |
| 211 | + if (flags & XDP_FLAGS_HW_MODE) |
| 212 | + return IFLA_XDP_HW_PROG_ID; |
| 213 | + if (flags & XDP_FLAGS_SKB_MODE) |
| 214 | + return IFLA_XDP_SKB_PROG_ID; |
| 215 | + |
| 216 | + return IFLA_XDP_UNSPEC; |
| 217 | +} |
| 218 | + |
| 219 | +static int get_xdp_id(void *cookie, void *msg, struct nlattr **tb) |
| 220 | +{ |
| 221 | + struct nlattr *xdp_tb[IFLA_XDP_MAX + 1]; |
| 222 | + struct xdp_id_md *xdp_id = cookie; |
| 223 | + struct ifinfomsg *ifinfo = msg; |
| 224 | + unsigned char mode, xdp_attr; |
| 225 | + int ret; |
| 226 | + |
| 227 | + if (xdp_id->ifindex && xdp_id->ifindex != ifinfo->ifi_index) |
| 228 | + return 0; |
| 229 | + |
| 230 | + if (!tb[IFLA_XDP]) |
| 231 | + return 0; |
| 232 | + |
| 233 | + ret = libbpf_nla_parse_nested(xdp_tb, IFLA_XDP_MAX, tb[IFLA_XDP], NULL); |
| 234 | + if (ret) |
| 235 | + return ret; |
| 236 | + |
| 237 | + if (!xdp_tb[IFLA_XDP_ATTACHED]) |
| 238 | + return 0; |
| 239 | + |
| 240 | + mode = libbpf_nla_getattr_u8(xdp_tb[IFLA_XDP_ATTACHED]); |
| 241 | + if (mode == XDP_ATTACHED_NONE) |
| 242 | + return 0; |
| 243 | + |
| 244 | + xdp_attr = get_xdp_id_attr(mode, xdp_id->flags); |
| 245 | + if (!xdp_attr || !xdp_tb[xdp_attr]) |
| 246 | + return 0; |
| 247 | + |
| 248 | + xdp_id->id = libbpf_nla_getattr_u32(xdp_tb[xdp_attr]); |
| 249 | + |
| 250 | + return 0; |
| 251 | +} |
| 252 | + |
| 253 | +int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags) |
| 254 | +{ |
| 255 | + struct xdp_id_md xdp_id = {}; |
| 256 | + int sock, ret; |
| 257 | + __u32 nl_pid; |
| 258 | + __u32 mask; |
| 259 | + |
| 260 | + if (flags & ~XDP_FLAGS_MASK) |
| 261 | + return -EINVAL; |
| 262 | + |
| 263 | + /* Check whether the single {HW,DRV,SKB} mode is set */ |
| 264 | + flags &= (XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE); |
| 265 | + mask = flags - 1; |
| 266 | + if (flags && flags & mask) |
| 267 | + return -EINVAL; |
| 268 | + |
| 269 | + sock = libbpf_netlink_open(&nl_pid); |
| 270 | + if (sock < 0) |
| 271 | + return sock; |
| 272 | + |
| 273 | + xdp_id.ifindex = ifindex; |
| 274 | + xdp_id.flags = flags; |
| 275 | + |
| 276 | + ret = libbpf_nl_get_link(sock, nl_pid, get_xdp_id, &xdp_id); |
| 277 | + if (!ret) |
| 278 | + *prog_id = xdp_id.id; |
| 279 | + |
| 280 | + close(sock); |
| 281 | + return ret; |
| 282 | +} |
| 283 | + |
199 | 284 | int libbpf_nl_get_link(int sock, unsigned int nl_pid,
|
200 | 285 | libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie)
|
201 | 286 | {
|
|
0 commit comments