]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/iplink_xdp.c
json: move json printer to common library
[mirror_iproute2.git] / ip / iplink_xdp.c
CommitLineData
c7272ca7
DB
1/*
2 * iplink_xdp.c XDP program loader
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Daniel Borkmann <daniel@iogearbox.net>
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14
15#include <linux/bpf.h>
16
17#include "xdp.h"
18#include "bpf_util.h"
2f26065e 19#include "ip_common.h"
c7272ca7
DB
20
21extern int force;
22
a872b870
DB
23struct xdp_req {
24 struct iplink_req *req;
25 __u32 flags;
26};
27
c7272ca7
DB
28static void xdp_ebpf_cb(void *raw, int fd, const char *annotation)
29{
a872b870
DB
30 struct xdp_req *xdp = raw;
31 struct iplink_req *req = xdp->req;
32 struct rtattr *xdp_attr;
c7272ca7 33
a872b870 34 xdp_attr = addattr_nest(&req->n, sizeof(*req), IFLA_XDP);
c7272ca7 35 addattr32(&req->n, sizeof(*req), IFLA_XDP_FD, fd);
a872b870
DB
36 if (xdp->flags)
37 addattr32(&req->n, sizeof(*req), IFLA_XDP_FLAGS, xdp->flags);
38 addattr_nest_end(&req->n, xdp_attr);
c7272ca7
DB
39}
40
41static const struct bpf_cfg_ops bpf_cb_ops = {
42 .ebpf_cb = xdp_ebpf_cb,
43};
44
a872b870 45static int xdp_delete(struct xdp_req *xdp)
c7272ca7 46{
a872b870 47 xdp_ebpf_cb(xdp, -1, NULL);
c7272ca7
DB
48 return 0;
49}
50
14683814 51int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
1b5e8094 52 bool drv, bool offload)
c7272ca7
DB
53{
54 struct bpf_cfg_in cfg = {
55 .argc = *argc,
56 .argv = *argv,
57 };
a872b870
DB
58 struct xdp_req xdp = {
59 .req = req,
60 };
61
62 if (!force)
63 xdp.flags |= XDP_FLAGS_UPDATE_IF_NOEXIST;
64 if (generic)
65 xdp.flags |= XDP_FLAGS_SKB_MODE;
14683814
JK
66 if (drv)
67 xdp.flags |= XDP_FLAGS_DRV_MODE;
1b5e8094
JK
68 if (offload)
69 xdp.flags |= XDP_FLAGS_HW_MODE;
c7272ca7
DB
70
71 if (*argc == 1) {
72 if (strcmp(**argv, "none") == 0 ||
73 strcmp(**argv, "off") == 0)
a872b870 74 return xdp_delete(&xdp);
c7272ca7 75 }
a872b870
DB
76
77 if (bpf_parse_common(BPF_PROG_TYPE_XDP, &cfg, &bpf_cb_ops, &xdp))
c7272ca7
DB
78 return -1;
79
80 *argc = cfg.argc;
81 *argv = cfg.argv;
82 return 0;
83}
84
a0b5b7cf 85void xdp_dump(FILE *fp, struct rtattr *xdp, bool link, bool details)
c7272ca7
DB
86{
87 struct rtattr *tb[IFLA_XDP_MAX + 1];
a0b5b7cf 88 __u32 prog_id = 0;
077bb180 89 __u8 mode;
c7272ca7
DB
90
91 parse_rtattr_nested(tb, IFLA_XDP_MAX, xdp);
a872b870 92
077bb180 93 if (!tb[IFLA_XDP_ATTACHED])
c7272ca7
DB
94 return;
95
077bb180 96 mode = rta_getattr_u8(tb[IFLA_XDP_ATTACHED]);
2f26065e
JF
97 if (is_json_context()) {
98 print_uint(PRINT_JSON, "attached", NULL, mode);
99 } else {
100 if (mode == XDP_ATTACHED_NONE)
101 return;
a17a0114
SH
102 else if (details && link)
103 fprintf(fp, "%s prog/xdp", _SL_);
2f26065e
JF
104 else if (mode == XDP_ATTACHED_DRV)
105 fprintf(fp, "xdp");
106 else if (mode == XDP_ATTACHED_SKB)
107 fprintf(fp, "xdpgeneric");
108 else if (mode == XDP_ATTACHED_HW)
109 fprintf(fp, "xdpoffload");
110 else
111 fprintf(fp, "xdp[%u]", mode);
0b4ea60b 112
a17a0114
SH
113 if (tb[IFLA_XDP_PROG_ID])
114 prog_id = rta_getattr_u32(tb[IFLA_XDP_PROG_ID]);
115 if (!details) {
116 if (prog_id && !link)
117 fprintf(fp, "/id:%u", prog_id);
118 fprintf(fp, " ");
119 return;
120 }
0b4ea60b 121
a17a0114
SH
122 if (prog_id) {
123 fprintf(fp, " ");
124 bpf_dump_prog_info(fp, prog_id);
125 }
a0b5b7cf 126 }
c7272ca7 127}