aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-03 17:04:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-03 17:04:18 -0400
commit5bb053bef82523a8fd78d650bca81c9f114fa276 (patch)
tree58c2fe47f60bb69230bb05d57a6c9e3f47f7b1fe /tools/lib
parentbb2407a7219760926760f0448fddf00d625e5aec (diff)
parent159f02977b2feb18a4bece5e586c838a6d26d44b (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: 1) Support offloading wireless authentication to userspace via NL80211_CMD_EXTERNAL_AUTH, from Srinivas Dasari. 2) A lot of work on network namespace setup/teardown from Kirill Tkhai. Setup and cleanup of namespaces now all run asynchronously and thus performance is significantly increased. 3) Add rx/tx timestamping support to mv88e6xxx driver, from Brandon Streiff. 4) Support zerocopy on RDS sockets, from Sowmini Varadhan. 5) Use denser instruction encoding in x86 eBPF JIT, from Daniel Borkmann. 6) Support hw offload of vlan filtering in mvpp2 dreiver, from Maxime Chevallier. 7) Support grafting of child qdiscs in mlxsw driver, from Nogah Frankel. 8) Add packet forwarding tests to selftests, from Ido Schimmel. 9) Deal with sub-optimal GSO packets better in BBR congestion control, from Eric Dumazet. 10) Support 5-tuple hashing in ipv6 multipath routing, from David Ahern. 11) Add path MTU tests to selftests, from Stefano Brivio. 12) Various bits of IPSEC offloading support for mlx5, from Aviad Yehezkel, Yossi Kuperman, and Saeed Mahameed. 13) Support RSS spreading on ntuple filters in SFC driver, from Edward Cree. 14) Lots of sockmap work from John Fastabend. Applications can use eBPF to filter sendmsg and sendpage operations. 15) In-kernel receive TLS support, from Dave Watson. 16) Add XDP support to ixgbevf, this is significant because it should allow optimized XDP usage in various cloud environments. From Tony Nguyen. 17) Add new Intel E800 series "ice" ethernet driver, from Anirudh Venkataramanan et al. 18) IP fragmentation match offload support in nfp driver, from Pieter Jansen van Vuuren. 19) Support XDP redirect in i40e driver, from Björn Töpel. 20) Add BPF_RAW_TRACEPOINT program type for accessing the arguments of tracepoints in their raw form, from Alexei Starovoitov. 21) Lots of striding RQ improvements to mlx5 driver with many performance improvements, from Tariq Toukan. 22) Use rhashtable for inet frag reassembly, from Eric Dumazet. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1678 commits) net: mvneta: improve suspend/resume net: mvneta: split rxq/txq init and txq deinit into SW and HW parts ipv6: frags: fix /proc/sys/net/ipv6/ip6frag_low_thresh net: bgmac: Fix endian access in bgmac_dma_tx_ring_free() net: bgmac: Correctly annotate register space route: check sysctl_fib_multipath_use_neigh earlier than hash fix typo in command value in drivers/net/phy/mdio-bitbang. sky2: Increase D3 delay to sky2 stops working after suspend net/mlx5e: Set EQE based as default TX interrupt moderation mode ibmvnic: Disable irqs before exiting reset from closed state net: sched: do not emit messages while holding spinlock vlan: also check phy_driver ts_info for vlan's real device Bluetooth: Mark expected switch fall-throughs Bluetooth: Set HCI_QUIRK_SIMULTANEOUS_DISCOVERY for BTUSB_QCA_ROME Bluetooth: btrsi: remove unused including <linux/version.h> Bluetooth: hci_bcm: Remove DMI quirk for the MINIX Z83-4 sh_eth: kill useless check in __sh_eth_get_regs() sh_eth: add sh_eth_cpu_data::no_xdfar flag ipv6: factorize sk_wmem_alloc updates done by __ip6_append_data() ipv4: factorize sk_wmem_alloc updates done by __ip_append_data() ...
Diffstat (limited to 'tools/lib')
-rw-r--r--tools/lib/bpf/bpf.c55
-rw-r--r--tools/lib/bpf/bpf.h18
-rw-r--r--tools/lib/bpf/libbpf.c114
-rw-r--r--tools/lib/bpf/libbpf.h8
4 files changed, 149 insertions, 46 deletions
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 592a58a2b681..acbb3f8b3bec 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -146,26 +146,30 @@ int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
146 -1); 146 -1);
147} 147}
148 148
149int bpf_load_program_name(enum bpf_prog_type type, const char *name, 149int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
150 const struct bpf_insn *insns, 150 char *log_buf, size_t log_buf_sz)
151 size_t insns_cnt, const char *license,
152 __u32 kern_version, char *log_buf,
153 size_t log_buf_sz)
154{ 151{
155 int fd;
156 union bpf_attr attr; 152 union bpf_attr attr;
157 __u32 name_len = name ? strlen(name) : 0; 153 __u32 name_len;
154 int fd;
155
156 if (!load_attr)
157 return -EINVAL;
158
159 name_len = load_attr->name ? strlen(load_attr->name) : 0;
158 160
159 bzero(&attr, sizeof(attr)); 161 bzero(&attr, sizeof(attr));
160 attr.prog_type = type; 162 attr.prog_type = load_attr->prog_type;
161 attr.insn_cnt = (__u32)insns_cnt; 163 attr.expected_attach_type = load_attr->expected_attach_type;
162 attr.insns = ptr_to_u64(insns); 164 attr.insn_cnt = (__u32)load_attr->insns_cnt;
163 attr.license = ptr_to_u64(license); 165 attr.insns = ptr_to_u64(load_attr->insns);
166 attr.license = ptr_to_u64(load_attr->license);
164 attr.log_buf = ptr_to_u64(NULL); 167 attr.log_buf = ptr_to_u64(NULL);
165 attr.log_size = 0; 168 attr.log_size = 0;
166 attr.log_level = 0; 169 attr.log_level = 0;
167 attr.kern_version = kern_version; 170 attr.kern_version = load_attr->kern_version;
168 memcpy(attr.prog_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1)); 171 memcpy(attr.prog_name, load_attr->name,
172 min(name_len, BPF_OBJ_NAME_LEN - 1));
169 173
170 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 174 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
171 if (fd >= 0 || !log_buf || !log_buf_sz) 175 if (fd >= 0 || !log_buf || !log_buf_sz)
@@ -184,8 +188,18 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
184 __u32 kern_version, char *log_buf, 188 __u32 kern_version, char *log_buf,
185 size_t log_buf_sz) 189 size_t log_buf_sz)
186{ 190{
187 return bpf_load_program_name(type, NULL, insns, insns_cnt, license, 191 struct bpf_load_program_attr load_attr;
188 kern_version, log_buf, log_buf_sz); 192
193 memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
194 load_attr.prog_type = type;
195 load_attr.expected_attach_type = 0;
196 load_attr.name = NULL;
197 load_attr.insns = insns;
198 load_attr.insns_cnt = insns_cnt;
199 load_attr.license = license;
200 load_attr.kern_version = kern_version;
201
202 return bpf_load_program_xattr(&load_attr, log_buf, log_buf_sz);
189} 203}
190 204
191int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, 205int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
@@ -428,6 +442,17 @@ int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len)
428 return err; 442 return err;
429} 443}
430 444
445int bpf_raw_tracepoint_open(const char *name, int prog_fd)
446{
447 union bpf_attr attr;
448
449 bzero(&attr, sizeof(attr));
450 attr.raw_tracepoint.name = ptr_to_u64(name);
451 attr.raw_tracepoint.prog_fd = prog_fd;
452
453 return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
454}
455
431int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags) 456int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
432{ 457{
433 struct sockaddr_nl sa; 458 struct sockaddr_nl sa;
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 8d18fb73d7fb..39f6a0d64a3b 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -41,13 +41,20 @@ int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
41 int key_size, int inner_map_fd, int max_entries, 41 int key_size, int inner_map_fd, int max_entries,
42 __u32 map_flags); 42 __u32 map_flags);
43 43
44struct bpf_load_program_attr {
45 enum bpf_prog_type prog_type;
46 enum bpf_attach_type expected_attach_type;
47 const char *name;
48 const struct bpf_insn *insns;
49 size_t insns_cnt;
50 const char *license;
51 __u32 kern_version;
52};
53
44/* Recommend log buffer size */ 54/* Recommend log buffer size */
45#define BPF_LOG_BUF_SIZE (256 * 1024) 55#define BPF_LOG_BUF_SIZE (256 * 1024)
46int bpf_load_program_name(enum bpf_prog_type type, const char *name, 56int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
47 const struct bpf_insn *insns, 57 char *log_buf, size_t log_buf_sz);
48 size_t insns_cnt, const char *license,
49 __u32 kern_version, char *log_buf,
50 size_t log_buf_sz);
51int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, 58int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
52 size_t insns_cnt, const char *license, 59 size_t insns_cnt, const char *license,
53 __u32 kern_version, char *log_buf, 60 __u32 kern_version, char *log_buf,
@@ -79,4 +86,5 @@ int bpf_map_get_fd_by_id(__u32 id);
79int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len); 86int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len);
80int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags, 87int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
81 __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt); 88 __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt);
89int bpf_raw_tracepoint_open(const char *name, int prog_fd);
82#endif 90#endif
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 5bbbf285af74..5922443063f0 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -203,6 +203,8 @@ struct bpf_program {
203 struct bpf_object *obj; 203 struct bpf_object *obj;
204 void *priv; 204 void *priv;
205 bpf_program_clear_priv_t clear_priv; 205 bpf_program_clear_priv_t clear_priv;
206
207 enum bpf_attach_type expected_attach_type;
206}; 208};
207 209
208struct bpf_map { 210struct bpf_map {
@@ -1162,21 +1164,31 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
1162} 1164}
1163 1165
1164static int 1166static int
1165load_program(enum bpf_prog_type type, const char *name, struct bpf_insn *insns, 1167load_program(enum bpf_prog_type type, enum bpf_attach_type expected_attach_type,
1166 int insns_cnt, char *license, u32 kern_version, int *pfd) 1168 const char *name, struct bpf_insn *insns, int insns_cnt,
1169 char *license, u32 kern_version, int *pfd)
1167{ 1170{
1168 int ret; 1171 struct bpf_load_program_attr load_attr;
1169 char *log_buf; 1172 char *log_buf;
1173 int ret;
1170 1174
1171 if (!insns || !insns_cnt) 1175 memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
1176 load_attr.prog_type = type;
1177 load_attr.expected_attach_type = expected_attach_type;
1178 load_attr.name = name;
1179 load_attr.insns = insns;
1180 load_attr.insns_cnt = insns_cnt;
1181 load_attr.license = license;
1182 load_attr.kern_version = kern_version;
1183
1184 if (!load_attr.insns || !load_attr.insns_cnt)
1172 return -EINVAL; 1185 return -EINVAL;
1173 1186
1174 log_buf = malloc(BPF_LOG_BUF_SIZE); 1187 log_buf = malloc(BPF_LOG_BUF_SIZE);
1175 if (!log_buf) 1188 if (!log_buf)
1176 pr_warning("Alloc log buffer for bpf loader error, continue without log\n"); 1189 pr_warning("Alloc log buffer for bpf loader error, continue without log\n");
1177 1190
1178 ret = bpf_load_program_name(type, name, insns, insns_cnt, license, 1191 ret = bpf_load_program_xattr(&load_attr, log_buf, BPF_LOG_BUF_SIZE);
1179 kern_version, log_buf, BPF_LOG_BUF_SIZE);
1180 1192
1181 if (ret >= 0) { 1193 if (ret >= 0) {
1182 *pfd = ret; 1194 *pfd = ret;
@@ -1192,18 +1204,18 @@ load_program(enum bpf_prog_type type, const char *name, struct bpf_insn *insns,
1192 pr_warning("-- BEGIN DUMP LOG ---\n"); 1204 pr_warning("-- BEGIN DUMP LOG ---\n");
1193 pr_warning("\n%s\n", log_buf); 1205 pr_warning("\n%s\n", log_buf);
1194 pr_warning("-- END LOG --\n"); 1206 pr_warning("-- END LOG --\n");
1195 } else if (insns_cnt >= BPF_MAXINSNS) { 1207 } else if (load_attr.insns_cnt >= BPF_MAXINSNS) {
1196 pr_warning("Program too large (%d insns), at most %d insns\n", 1208 pr_warning("Program too large (%zu insns), at most %d insns\n",
1197 insns_cnt, BPF_MAXINSNS); 1209 load_attr.insns_cnt, BPF_MAXINSNS);
1198 ret = -LIBBPF_ERRNO__PROG2BIG; 1210 ret = -LIBBPF_ERRNO__PROG2BIG;
1199 } else { 1211 } else {
1200 /* Wrong program type? */ 1212 /* Wrong program type? */
1201 if (type != BPF_PROG_TYPE_KPROBE) { 1213 if (load_attr.prog_type != BPF_PROG_TYPE_KPROBE) {
1202 int fd; 1214 int fd;
1203 1215
1204 fd = bpf_load_program_name(BPF_PROG_TYPE_KPROBE, name, 1216 load_attr.prog_type = BPF_PROG_TYPE_KPROBE;
1205 insns, insns_cnt, license, 1217 load_attr.expected_attach_type = 0;
1206 kern_version, NULL, 0); 1218 fd = bpf_load_program_xattr(&load_attr, NULL, 0);
1207 if (fd >= 0) { 1219 if (fd >= 0) {
1208 close(fd); 1220 close(fd);
1209 ret = -LIBBPF_ERRNO__PROGTYPE; 1221 ret = -LIBBPF_ERRNO__PROGTYPE;
@@ -1247,8 +1259,9 @@ bpf_program__load(struct bpf_program *prog,
1247 pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n", 1259 pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n",
1248 prog->section_name, prog->instances.nr); 1260 prog->section_name, prog->instances.nr);
1249 } 1261 }
1250 err = load_program(prog->type, prog->name, prog->insns, 1262 err = load_program(prog->type, prog->expected_attach_type,
1251 prog->insns_cnt, license, kern_version, &fd); 1263 prog->name, prog->insns, prog->insns_cnt,
1264 license, kern_version, &fd);
1252 if (!err) 1265 if (!err)
1253 prog->instances.fds[0] = fd; 1266 prog->instances.fds[0] = fd;
1254 goto out; 1267 goto out;
@@ -1276,8 +1289,8 @@ bpf_program__load(struct bpf_program *prog,
1276 continue; 1289 continue;
1277 } 1290 }
1278 1291
1279 err = load_program(prog->type, prog->name, 1292 err = load_program(prog->type, prog->expected_attach_type,
1280 result.new_insn_ptr, 1293 prog->name, result.new_insn_ptr,
1281 result.new_insn_cnt, 1294 result.new_insn_cnt,
1282 license, kern_version, &fd); 1295 license, kern_version, &fd);
1283 1296
@@ -1835,11 +1848,25 @@ BPF_PROG_TYPE_FNS(tracepoint, BPF_PROG_TYPE_TRACEPOINT);
1835BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP); 1848BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP);
1836BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT); 1849BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT);
1837 1850
1838#define BPF_PROG_SEC(string, type) { string, sizeof(string) - 1, type } 1851static void bpf_program__set_expected_attach_type(struct bpf_program *prog,
1852 enum bpf_attach_type type)
1853{
1854 prog->expected_attach_type = type;
1855}
1856
1857#define BPF_PROG_SEC_FULL(string, ptype, atype) \
1858 { string, sizeof(string) - 1, ptype, atype }
1859
1860#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_FULL(string, ptype, 0)
1861
1862#define BPF_SA_PROG_SEC(string, ptype) \
1863 BPF_PROG_SEC_FULL(string, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, ptype)
1864
1839static const struct { 1865static const struct {
1840 const char *sec; 1866 const char *sec;
1841 size_t len; 1867 size_t len;
1842 enum bpf_prog_type prog_type; 1868 enum bpf_prog_type prog_type;
1869 enum bpf_attach_type expected_attach_type;
1843} section_names[] = { 1870} section_names[] = {
1844 BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER), 1871 BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER),
1845 BPF_PROG_SEC("kprobe/", BPF_PROG_TYPE_KPROBE), 1872 BPF_PROG_SEC("kprobe/", BPF_PROG_TYPE_KPROBE),
@@ -1857,10 +1884,18 @@ static const struct {
1857 BPF_PROG_SEC("lwt_xmit", BPF_PROG_TYPE_LWT_XMIT), 1884 BPF_PROG_SEC("lwt_xmit", BPF_PROG_TYPE_LWT_XMIT),
1858 BPF_PROG_SEC("sockops", BPF_PROG_TYPE_SOCK_OPS), 1885 BPF_PROG_SEC("sockops", BPF_PROG_TYPE_SOCK_OPS),
1859 BPF_PROG_SEC("sk_skb", BPF_PROG_TYPE_SK_SKB), 1886 BPF_PROG_SEC("sk_skb", BPF_PROG_TYPE_SK_SKB),
1887 BPF_PROG_SEC("sk_msg", BPF_PROG_TYPE_SK_MSG),
1888 BPF_SA_PROG_SEC("cgroup/bind4", BPF_CGROUP_INET4_BIND),
1889 BPF_SA_PROG_SEC("cgroup/bind6", BPF_CGROUP_INET6_BIND),
1890 BPF_SA_PROG_SEC("cgroup/connect4", BPF_CGROUP_INET4_CONNECT),
1891 BPF_SA_PROG_SEC("cgroup/connect6", BPF_CGROUP_INET6_CONNECT),
1860}; 1892};
1893
1861#undef BPF_PROG_SEC 1894#undef BPF_PROG_SEC
1895#undef BPF_PROG_SEC_FULL
1896#undef BPF_SA_PROG_SEC
1862 1897
1863static enum bpf_prog_type bpf_program__guess_type(struct bpf_program *prog) 1898static int bpf_program__identify_section(struct bpf_program *prog)
1864{ 1899{
1865 int i; 1900 int i;
1866 1901
@@ -1870,13 +1905,13 @@ static enum bpf_prog_type bpf_program__guess_type(struct bpf_program *prog)
1870 for (i = 0; i < ARRAY_SIZE(section_names); i++) 1905 for (i = 0; i < ARRAY_SIZE(section_names); i++)
1871 if (strncmp(prog->section_name, section_names[i].sec, 1906 if (strncmp(prog->section_name, section_names[i].sec,
1872 section_names[i].len) == 0) 1907 section_names[i].len) == 0)
1873 return section_names[i].prog_type; 1908 return i;
1874 1909
1875err: 1910err:
1876 pr_warning("failed to guess program type based on section name %s\n", 1911 pr_warning("failed to guess program type based on section name %s\n",
1877 prog->section_name); 1912 prog->section_name);
1878 1913
1879 return BPF_PROG_TYPE_UNSPEC; 1914 return -1;
1880} 1915}
1881 1916
1882int bpf_map__fd(struct bpf_map *map) 1917int bpf_map__fd(struct bpf_map *map)
@@ -1976,11 +2011,30 @@ long libbpf_get_error(const void *ptr)
1976int bpf_prog_load(const char *file, enum bpf_prog_type type, 2011int bpf_prog_load(const char *file, enum bpf_prog_type type,
1977 struct bpf_object **pobj, int *prog_fd) 2012 struct bpf_object **pobj, int *prog_fd)
1978{ 2013{
2014 struct bpf_prog_load_attr attr;
2015
2016 memset(&attr, 0, sizeof(struct bpf_prog_load_attr));
2017 attr.file = file;
2018 attr.prog_type = type;
2019 attr.expected_attach_type = 0;
2020
2021 return bpf_prog_load_xattr(&attr, pobj, prog_fd);
2022}
2023
2024int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
2025 struct bpf_object **pobj, int *prog_fd)
2026{
1979 struct bpf_program *prog, *first_prog = NULL; 2027 struct bpf_program *prog, *first_prog = NULL;
2028 enum bpf_attach_type expected_attach_type;
2029 enum bpf_prog_type prog_type;
1980 struct bpf_object *obj; 2030 struct bpf_object *obj;
2031 int section_idx;
1981 int err; 2032 int err;
1982 2033
1983 obj = bpf_object__open(file); 2034 if (!attr)
2035 return -EINVAL;
2036
2037 obj = bpf_object__open(attr->file);
1984 if (IS_ERR(obj)) 2038 if (IS_ERR(obj))
1985 return -ENOENT; 2039 return -ENOENT;
1986 2040
@@ -1989,15 +2043,23 @@ int bpf_prog_load(const char *file, enum bpf_prog_type type,
1989 * If type is not specified, try to guess it based on 2043 * If type is not specified, try to guess it based on
1990 * section name. 2044 * section name.
1991 */ 2045 */
1992 if (type == BPF_PROG_TYPE_UNSPEC) { 2046 prog_type = attr->prog_type;
1993 type = bpf_program__guess_type(prog); 2047 expected_attach_type = attr->expected_attach_type;
1994 if (type == BPF_PROG_TYPE_UNSPEC) { 2048 if (prog_type == BPF_PROG_TYPE_UNSPEC) {
2049 section_idx = bpf_program__identify_section(prog);
2050 if (section_idx < 0) {
1995 bpf_object__close(obj); 2051 bpf_object__close(obj);
1996 return -EINVAL; 2052 return -EINVAL;
1997 } 2053 }
2054 prog_type = section_names[section_idx].prog_type;
2055 expected_attach_type =
2056 section_names[section_idx].expected_attach_type;
1998 } 2057 }
1999 2058
2000 bpf_program__set_type(prog, type); 2059 bpf_program__set_type(prog, prog_type);
2060 bpf_program__set_expected_attach_type(prog,
2061 expected_attach_type);
2062
2001 if (prog->idx != obj->efile.text_shndx && !first_prog) 2063 if (prog->idx != obj->efile.text_shndx && !first_prog)
2002 first_prog = prog; 2064 first_prog = prog;
2003 } 2065 }
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index f85906533cdd..a3a62a583f27 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -248,6 +248,14 @@ int bpf_map__pin(struct bpf_map *map, const char *path);
248 248
249long libbpf_get_error(const void *ptr); 249long libbpf_get_error(const void *ptr);
250 250
251struct bpf_prog_load_attr {
252 const char *file;
253 enum bpf_prog_type prog_type;
254 enum bpf_attach_type expected_attach_type;
255};
256
257int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
258 struct bpf_object **pobj, int *prog_fd);
251int bpf_prog_load(const char *file, enum bpf_prog_type type, 259int bpf_prog_load(const char *file, enum bpf_prog_type type,
252 struct bpf_object **pobj, int *prog_fd); 260 struct bpf_object **pobj, int *prog_fd);
253 261