hc
2024-05-11 04dd17822334871b23ea2862f7798fb0e0007777
kernel/scripts/bpf_helpers_doc.py
....@@ -1,7 +1,7 @@
1
-#!/usr/bin/python3
1
+#!/usr/bin/env python3
22 # SPDX-License-Identifier: GPL-2.0-only
33 #
4
-# Copyright (C) 2018 Netronome Systems, Inc.
4
+# Copyright (C) 2018-2019 Netronome Systems, Inc.
55
66 # In case user attempts to run with Python 2.
77 from __future__ import print_function
....@@ -39,7 +39,7 @@
3939 Break down helper function protocol into smaller chunks: return type,
4040 name, distincts arguments.
4141 """
42
- arg_re = re.compile('((const )?(struct )?(\w+|...))( (\**)(\w+))?$')
42
+ arg_re = re.compile('((\w+ )*?(\w+|...))( (\**)(\w+))?$')
4343 res = {}
4444 proto_re = re.compile('(.+) (\**)(\w+)\(((([^,]+)(, )?){1,5})\)$')
4545
....@@ -54,8 +54,8 @@
5454 capture = arg_re.match(a)
5555 res['args'].append({
5656 'type' : capture.group(1),
57
- 'star' : capture.group(6),
58
- 'name' : capture.group(7)
57
+ 'star' : capture.group(5),
58
+ 'name' : capture.group(6)
5959 })
6060
6161 return res
....@@ -158,8 +158,6 @@
158158 break
159159
160160 self.reader.close()
161
- print('Parsed description of %d helper function(s)' % len(self.helpers),
162
- file=sys.stderr)
163161
164162 ###############################################################################
165163
....@@ -320,6 +318,11 @@
320318 of eBPF maps are used with a given helper function.
321319 * *kernel/bpf/* directory contains other files in which additional helpers are
322320 defined (for cgroups, sockmaps, etc.).
321
+* The bpftool utility can be used to probe the availability of helper functions
322
+ on the system (as well as supported program and map types, and a number of
323
+ other parameters). To do so, run **bpftool feature probe** (see
324
+ **bpftool-feature**\ (8) for details). Add the **unprivileged** keyword to
325
+ list features available to unprivileged users.
323326
324327 Compatibility between helper functions and program types can generally be found
325328 in the files where helper functions are defined. Look for the **struct
....@@ -340,6 +343,7 @@
340343 ========
341344
342345 **bpf**\ (2),
346
+**bpftool**\ (8),
343347 **cgroups**\ (7),
344348 **ip**\ (8),
345349 **perf_event_open**\ (2),
....@@ -391,6 +395,183 @@
391395
392396 print('')
393397
398
+class PrinterHelpers(Printer):
399
+ """
400
+ A printer for dumping collected information about helpers as C header to
401
+ be included from BPF program.
402
+ @helpers: array of Helper objects to print to standard output
403
+ """
404
+
405
+ type_fwds = [
406
+ 'struct bpf_fib_lookup',
407
+ 'struct bpf_sk_lookup',
408
+ 'struct bpf_perf_event_data',
409
+ 'struct bpf_perf_event_value',
410
+ 'struct bpf_pidns_info',
411
+ 'struct bpf_redir_neigh',
412
+ 'struct bpf_sock',
413
+ 'struct bpf_sock_addr',
414
+ 'struct bpf_sock_ops',
415
+ 'struct bpf_sock_tuple',
416
+ 'struct bpf_spin_lock',
417
+ 'struct bpf_sysctl',
418
+ 'struct bpf_tcp_sock',
419
+ 'struct bpf_tunnel_key',
420
+ 'struct bpf_xfrm_state',
421
+ 'struct pt_regs',
422
+ 'struct sk_reuseport_md',
423
+ 'struct sockaddr',
424
+ 'struct tcphdr',
425
+ 'struct seq_file',
426
+ 'struct tcp6_sock',
427
+ 'struct tcp_sock',
428
+ 'struct tcp_timewait_sock',
429
+ 'struct tcp_request_sock',
430
+ 'struct udp6_sock',
431
+ 'struct task_struct',
432
+
433
+ 'struct __sk_buff',
434
+ 'struct sk_msg_md',
435
+ 'struct xdp_md',
436
+ 'struct path',
437
+ 'struct btf_ptr',
438
+ ]
439
+ known_types = {
440
+ '...',
441
+ 'void',
442
+ 'const void',
443
+ 'char',
444
+ 'const char',
445
+ 'int',
446
+ 'long',
447
+ 'unsigned long',
448
+
449
+ '__be16',
450
+ '__be32',
451
+ '__wsum',
452
+
453
+ 'struct bpf_fib_lookup',
454
+ 'struct bpf_perf_event_data',
455
+ 'struct bpf_perf_event_value',
456
+ 'struct bpf_pidns_info',
457
+ 'struct bpf_redir_neigh',
458
+ 'struct bpf_sk_lookup',
459
+ 'struct bpf_sock',
460
+ 'struct bpf_sock_addr',
461
+ 'struct bpf_sock_ops',
462
+ 'struct bpf_sock_tuple',
463
+ 'struct bpf_spin_lock',
464
+ 'struct bpf_sysctl',
465
+ 'struct bpf_tcp_sock',
466
+ 'struct bpf_tunnel_key',
467
+ 'struct bpf_xfrm_state',
468
+ 'struct pt_regs',
469
+ 'struct sk_reuseport_md',
470
+ 'struct sockaddr',
471
+ 'struct tcphdr',
472
+ 'struct seq_file',
473
+ 'struct tcp6_sock',
474
+ 'struct tcp_sock',
475
+ 'struct tcp_timewait_sock',
476
+ 'struct tcp_request_sock',
477
+ 'struct udp6_sock',
478
+ 'struct task_struct',
479
+ 'struct path',
480
+ 'struct btf_ptr',
481
+ }
482
+ mapped_types = {
483
+ 'u8': '__u8',
484
+ 'u16': '__u16',
485
+ 'u32': '__u32',
486
+ 'u64': '__u64',
487
+ 's8': '__s8',
488
+ 's16': '__s16',
489
+ 's32': '__s32',
490
+ 's64': '__s64',
491
+ 'size_t': 'unsigned long',
492
+ 'struct bpf_map': 'void',
493
+ 'struct sk_buff': 'struct __sk_buff',
494
+ 'const struct sk_buff': 'const struct __sk_buff',
495
+ 'struct sk_msg_buff': 'struct sk_msg_md',
496
+ 'struct xdp_buff': 'struct xdp_md',
497
+ }
498
+ # Helpers overloaded for different context types.
499
+ overloaded_helpers = [
500
+ 'bpf_get_socket_cookie',
501
+ 'bpf_sk_assign',
502
+ ]
503
+
504
+ def print_header(self):
505
+ header = '''\
506
+/* This is auto-generated file. See bpf_helpers_doc.py for details. */
507
+
508
+/* Forward declarations of BPF structs */'''
509
+
510
+ print(header)
511
+ for fwd in self.type_fwds:
512
+ print('%s;' % fwd)
513
+ print('')
514
+
515
+ def print_footer(self):
516
+ footer = ''
517
+ print(footer)
518
+
519
+ def map_type(self, t):
520
+ if t in self.known_types:
521
+ return t
522
+ if t in self.mapped_types:
523
+ return self.mapped_types[t]
524
+ print("Unrecognized type '%s', please add it to known types!" % t,
525
+ file=sys.stderr)
526
+ sys.exit(1)
527
+
528
+ seen_helpers = set()
529
+
530
+ def print_one(self, helper):
531
+ proto = helper.proto_break_down()
532
+
533
+ if proto['name'] in self.seen_helpers:
534
+ return
535
+ self.seen_helpers.add(proto['name'])
536
+
537
+ print('/*')
538
+ print(" * %s" % proto['name'])
539
+ print(" *")
540
+ if (helper.desc):
541
+ # Do not strip all newline characters: formatted code at the end of
542
+ # a section must be followed by a blank line.
543
+ for line in re.sub('\n$', '', helper.desc, count=1).split('\n'):
544
+ print(' *{}{}'.format(' \t' if line else '', line))
545
+
546
+ if (helper.ret):
547
+ print(' *')
548
+ print(' * Returns')
549
+ for line in helper.ret.rstrip().split('\n'):
550
+ print(' *{}{}'.format(' \t' if line else '', line))
551
+
552
+ print(' */')
553
+ print('static %s %s(*%s)(' % (self.map_type(proto['ret_type']),
554
+ proto['ret_star'], proto['name']), end='')
555
+ comma = ''
556
+ for i, a in enumerate(proto['args']):
557
+ t = a['type']
558
+ n = a['name']
559
+ if proto['name'] in self.overloaded_helpers and i == 0:
560
+ t = 'void'
561
+ n = 'ctx'
562
+ one_arg = '{}{}'.format(comma, self.map_type(t))
563
+ if n:
564
+ if a['star']:
565
+ one_arg += ' {}'.format(a['star'])
566
+ else:
567
+ one_arg += ' '
568
+ one_arg += '{}'.format(n)
569
+ comma = ', '
570
+ print(one_arg, end='')
571
+
572
+ print(') = (void *) %d;' % len(self.seen_helpers))
573
+ print('')
574
+
394575 ###############################################################################
395576
396577 # If script is launched from scripts/ from kernel tree and can access
....@@ -405,6 +586,8 @@
405586 The RST-formatted output produced can be turned into a manual page with the
406587 rst2man utility.
407588 """)
589
+argParser.add_argument('--header', action='store_true',
590
+ help='generate C header file')
408591 if (os.path.isfile(bpfh)):
409592 argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h',
410593 default=bpfh)
....@@ -417,5 +600,8 @@
417600 headerParser.run()
418601
419602 # Print formatted output to standard output.
420
-printer = PrinterRST(headerParser.helpers)
603
+if args.header:
604
+ printer = PrinterHelpers(headerParser.helpers)
605
+else:
606
+ printer = PrinterRST(headerParser.helpers)
421607 printer.print_all()