1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 // Copyright (C) 2018 Facebook
6 #include <bpf/libbpf.h>
7 #include <linux/rtnetlink.h>
8 #include <linux/tc_act/tc_bpf.h>
10 #include "bpf/nlattr.h"
12 #include "netlink_dumper.h"
14 static void xdp_dump_prog_id(struct nlattr
**tb
, int attr
,
23 NET_DUMP_STR("mode", " %s", mode
);
24 NET_DUMP_UINT("id", " id %u", libbpf_nla_getattr_u32(tb
[attr
]))
29 static int do_xdp_dump_one(struct nlattr
*attr
, unsigned int ifindex
,
32 struct nlattr
*tb
[IFLA_XDP_MAX
+ 1];
35 if (libbpf_nla_parse_nested(tb
, IFLA_XDP_MAX
, attr
, NULL
) < 0)
38 if (!tb
[IFLA_XDP_ATTACHED
])
41 mode
= libbpf_nla_getattr_u8(tb
[IFLA_XDP_ATTACHED
]);
42 if (mode
== XDP_ATTACHED_NONE
)
47 NET_DUMP_STR("devname", "%s", name
);
48 NET_DUMP_UINT("ifindex", "(%d)", ifindex
);
50 if (mode
== XDP_ATTACHED_MULTI
) {
52 jsonw_name(json_wtr
, "multi_attachments");
53 jsonw_start_array(json_wtr
);
55 xdp_dump_prog_id(tb
, IFLA_XDP_SKB_PROG_ID
, "generic", true);
56 xdp_dump_prog_id(tb
, IFLA_XDP_DRV_PROG_ID
, "driver", true);
57 xdp_dump_prog_id(tb
, IFLA_XDP_HW_PROG_ID
, "offload", true);
59 jsonw_end_array(json_wtr
);
60 } else if (mode
== XDP_ATTACHED_DRV
) {
61 xdp_dump_prog_id(tb
, IFLA_XDP_PROG_ID
, "driver", false);
62 } else if (mode
== XDP_ATTACHED_SKB
) {
63 xdp_dump_prog_id(tb
, IFLA_XDP_PROG_ID
, "generic", false);
64 } else if (mode
== XDP_ATTACHED_HW
) {
65 xdp_dump_prog_id(tb
, IFLA_XDP_PROG_ID
, "offload", false);
72 int do_xdp_dump(struct ifinfomsg
*ifinfo
, struct nlattr
**tb
)
77 return do_xdp_dump_one(tb
[IFLA_XDP
], ifinfo
->ifi_index
,
78 libbpf_nla_getattr_str(tb
[IFLA_IFNAME
]));
81 static int do_bpf_dump_one_act(struct nlattr
*attr
)
83 struct nlattr
*tb
[TCA_ACT_BPF_MAX
+ 1];
85 if (libbpf_nla_parse_nested(tb
, TCA_ACT_BPF_MAX
, attr
, NULL
) < 0)
86 return -LIBBPF_ERRNO__NLPARSE
;
88 if (!tb
[TCA_ACT_BPF_PARMS
])
89 return -LIBBPF_ERRNO__NLPARSE
;
91 NET_START_OBJECT_NESTED2
;
92 if (tb
[TCA_ACT_BPF_NAME
])
93 NET_DUMP_STR("name", "%s",
94 libbpf_nla_getattr_str(tb
[TCA_ACT_BPF_NAME
]));
95 if (tb
[TCA_ACT_BPF_ID
])
96 NET_DUMP_UINT("id", " id %u",
97 libbpf_nla_getattr_u32(tb
[TCA_ACT_BPF_ID
]));
98 NET_END_OBJECT_NESTED
;
102 static int do_dump_one_act(struct nlattr
*attr
)
104 struct nlattr
*tb
[TCA_ACT_MAX
+ 1];
109 if (libbpf_nla_parse_nested(tb
, TCA_ACT_MAX
, attr
, NULL
) < 0)
110 return -LIBBPF_ERRNO__NLPARSE
;
112 if (tb
[TCA_ACT_KIND
] &&
113 strcmp(libbpf_nla_data(tb
[TCA_ACT_KIND
]), "bpf") == 0)
114 return do_bpf_dump_one_act(tb
[TCA_ACT_OPTIONS
]);
119 static int do_bpf_act_dump(struct nlattr
*attr
)
121 struct nlattr
*tb
[TCA_ACT_MAX_PRIO
+ 1];
124 if (libbpf_nla_parse_nested(tb
, TCA_ACT_MAX_PRIO
, attr
, NULL
) < 0)
125 return -LIBBPF_ERRNO__NLPARSE
;
127 NET_START_ARRAY("act", " %s [");
128 for (act
= 0; act
<= TCA_ACT_MAX_PRIO
; act
++) {
129 ret
= do_dump_one_act(tb
[act
]);
138 static int do_bpf_filter_dump(struct nlattr
*attr
)
140 struct nlattr
*tb
[TCA_BPF_MAX
+ 1];
143 if (libbpf_nla_parse_nested(tb
, TCA_BPF_MAX
, attr
, NULL
) < 0)
144 return -LIBBPF_ERRNO__NLPARSE
;
146 if (tb
[TCA_BPF_NAME
])
147 NET_DUMP_STR("name", " %s",
148 libbpf_nla_getattr_str(tb
[TCA_BPF_NAME
]));
150 NET_DUMP_UINT("id", " id %u",
151 libbpf_nla_getattr_u32(tb
[TCA_BPF_ID
]));
152 if (tb
[TCA_BPF_ACT
]) {
153 ret
= do_bpf_act_dump(tb
[TCA_BPF_ACT
]);
161 int do_filter_dump(struct tcmsg
*info
, struct nlattr
**tb
, const char *kind
,
162 const char *devname
, int ifindex
)
166 if (tb
[TCA_OPTIONS
] &&
167 strcmp(libbpf_nla_data(tb
[TCA_KIND
]), "bpf") == 0) {
169 if (devname
[0] != '\0')
170 NET_DUMP_STR("devname", "%s", devname
);
171 NET_DUMP_UINT("ifindex", "(%u)", ifindex
);
172 NET_DUMP_STR("kind", " %s", kind
);
173 ret
= do_bpf_filter_dump(tb
[TCA_OPTIONS
]);
174 NET_END_OBJECT_FINAL
;