Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
0002 // Copyright (C) 2018 Facebook
0003 
0004 #include <stdlib.h>
0005 #include <string.h>
0006 #include <bpf/libbpf.h>
0007 #include <linux/rtnetlink.h>
0008 #include <linux/tc_act/tc_bpf.h>
0009 
0010 #include "bpf/nlattr.h"
0011 #include "main.h"
0012 #include "netlink_dumper.h"
0013 
0014 static void xdp_dump_prog_id(struct nlattr **tb, int attr,
0015                  const char *mode,
0016                  bool new_json_object)
0017 {
0018     if (!tb[attr])
0019         return;
0020 
0021     if (new_json_object)
0022         NET_START_OBJECT
0023     NET_DUMP_STR("mode", " %s", mode);
0024     NET_DUMP_UINT("id", " id %u", libbpf_nla_getattr_u32(tb[attr]))
0025     if (new_json_object)
0026         NET_END_OBJECT
0027 }
0028 
0029 static int do_xdp_dump_one(struct nlattr *attr, unsigned int ifindex,
0030                const char *name)
0031 {
0032     struct nlattr *tb[IFLA_XDP_MAX + 1];
0033     unsigned char mode;
0034 
0035     if (libbpf_nla_parse_nested(tb, IFLA_XDP_MAX, attr, NULL) < 0)
0036         return -1;
0037 
0038     if (!tb[IFLA_XDP_ATTACHED])
0039         return 0;
0040 
0041     mode = libbpf_nla_getattr_u8(tb[IFLA_XDP_ATTACHED]);
0042     if (mode == XDP_ATTACHED_NONE)
0043         return 0;
0044 
0045     NET_START_OBJECT;
0046     if (name)
0047         NET_DUMP_STR("devname", "%s", name);
0048     NET_DUMP_UINT("ifindex", "(%d)", ifindex);
0049 
0050     if (mode == XDP_ATTACHED_MULTI) {
0051         if (json_output) {
0052             jsonw_name(json_wtr, "multi_attachments");
0053             jsonw_start_array(json_wtr);
0054         }
0055         xdp_dump_prog_id(tb, IFLA_XDP_SKB_PROG_ID, "generic", true);
0056         xdp_dump_prog_id(tb, IFLA_XDP_DRV_PROG_ID, "driver", true);
0057         xdp_dump_prog_id(tb, IFLA_XDP_HW_PROG_ID, "offload", true);
0058         if (json_output)
0059             jsonw_end_array(json_wtr);
0060     } else if (mode == XDP_ATTACHED_DRV) {
0061         xdp_dump_prog_id(tb, IFLA_XDP_PROG_ID, "driver", false);
0062     } else if (mode == XDP_ATTACHED_SKB) {
0063         xdp_dump_prog_id(tb, IFLA_XDP_PROG_ID, "generic", false);
0064     } else if (mode == XDP_ATTACHED_HW) {
0065         xdp_dump_prog_id(tb, IFLA_XDP_PROG_ID, "offload", false);
0066     }
0067 
0068     NET_END_OBJECT_FINAL;
0069     return 0;
0070 }
0071 
0072 int do_xdp_dump(struct ifinfomsg *ifinfo, struct nlattr **tb)
0073 {
0074     if (!tb[IFLA_XDP])
0075         return 0;
0076 
0077     return do_xdp_dump_one(tb[IFLA_XDP], ifinfo->ifi_index,
0078                    libbpf_nla_getattr_str(tb[IFLA_IFNAME]));
0079 }
0080 
0081 static int do_bpf_dump_one_act(struct nlattr *attr)
0082 {
0083     struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
0084 
0085     if (libbpf_nla_parse_nested(tb, TCA_ACT_BPF_MAX, attr, NULL) < 0)
0086         return -LIBBPF_ERRNO__NLPARSE;
0087 
0088     if (!tb[TCA_ACT_BPF_PARMS])
0089         return -LIBBPF_ERRNO__NLPARSE;
0090 
0091     NET_START_OBJECT_NESTED2;
0092     if (tb[TCA_ACT_BPF_NAME])
0093         NET_DUMP_STR("name", "%s",
0094                  libbpf_nla_getattr_str(tb[TCA_ACT_BPF_NAME]));
0095     if (tb[TCA_ACT_BPF_ID])
0096         NET_DUMP_UINT("id", " id %u",
0097                   libbpf_nla_getattr_u32(tb[TCA_ACT_BPF_ID]));
0098     NET_END_OBJECT_NESTED;
0099     return 0;
0100 }
0101 
0102 static int do_dump_one_act(struct nlattr *attr)
0103 {
0104     struct nlattr *tb[TCA_ACT_MAX + 1];
0105 
0106     if (!attr)
0107         return 0;
0108 
0109     if (libbpf_nla_parse_nested(tb, TCA_ACT_MAX, attr, NULL) < 0)
0110         return -LIBBPF_ERRNO__NLPARSE;
0111 
0112     if (tb[TCA_ACT_KIND] &&
0113         strcmp(libbpf_nla_data(tb[TCA_ACT_KIND]), "bpf") == 0)
0114         return do_bpf_dump_one_act(tb[TCA_ACT_OPTIONS]);
0115 
0116     return 0;
0117 }
0118 
0119 static int do_bpf_act_dump(struct nlattr *attr)
0120 {
0121     struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
0122     int act, ret;
0123 
0124     if (libbpf_nla_parse_nested(tb, TCA_ACT_MAX_PRIO, attr, NULL) < 0)
0125         return -LIBBPF_ERRNO__NLPARSE;
0126 
0127     NET_START_ARRAY("act", " %s [");
0128     for (act = 0; act <= TCA_ACT_MAX_PRIO; act++) {
0129         ret = do_dump_one_act(tb[act]);
0130         if (ret)
0131             break;
0132     }
0133     NET_END_ARRAY("] ");
0134 
0135     return ret;
0136 }
0137 
0138 static int do_bpf_filter_dump(struct nlattr *attr)
0139 {
0140     struct nlattr *tb[TCA_BPF_MAX + 1];
0141     int ret;
0142 
0143     if (libbpf_nla_parse_nested(tb, TCA_BPF_MAX, attr, NULL) < 0)
0144         return -LIBBPF_ERRNO__NLPARSE;
0145 
0146     if (tb[TCA_BPF_NAME])
0147         NET_DUMP_STR("name", " %s",
0148                  libbpf_nla_getattr_str(tb[TCA_BPF_NAME]));
0149     if (tb[TCA_BPF_ID])
0150         NET_DUMP_UINT("id", " id %u",
0151                   libbpf_nla_getattr_u32(tb[TCA_BPF_ID]));
0152     if (tb[TCA_BPF_ACT]) {
0153         ret = do_bpf_act_dump(tb[TCA_BPF_ACT]);
0154         if (ret)
0155             return ret;
0156     }
0157 
0158     return 0;
0159 }
0160 
0161 int do_filter_dump(struct tcmsg *info, struct nlattr **tb, const char *kind,
0162            const char *devname, int ifindex)
0163 {
0164     int ret = 0;
0165 
0166     if (tb[TCA_OPTIONS] &&
0167         strcmp(libbpf_nla_data(tb[TCA_KIND]), "bpf") == 0) {
0168         NET_START_OBJECT;
0169         if (devname[0] != '\0')
0170             NET_DUMP_STR("devname", "%s", devname);
0171         NET_DUMP_UINT("ifindex", "(%u)", ifindex);
0172         NET_DUMP_STR("kind", " %s", kind);
0173         ret = do_bpf_filter_dump(tb[TCA_OPTIONS]);
0174         NET_END_OBJECT_FINAL;
0175     }
0176 
0177     return ret;
0178 }