Deploying to gh-pages from @ eunomia-bpf/bpf-developer-tutorial@ab0d1eef08 🚀
1
third_party/libbpf/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
assets/** export-ignore
|
||||
22
third_party/libbpf/.readthedocs.yaml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# .readthedocs.yaml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
builder: html
|
||||
configuration: docs/conf.py
|
||||
|
||||
formats:
|
||||
- htmlzip
|
||||
- pdf
|
||||
- epub
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
version: 3.7
|
||||
install:
|
||||
- requirements: docs/sphinx/requirements.txt
|
||||
1
third_party/libbpf/BPF-CHECKPOINT-COMMIT
vendored
Normal file
@@ -0,0 +1 @@
|
||||
496720b7cfb6574a8f6f4d434f23e3d1e6cfaeb9
|
||||
1
third_party/libbpf/CHECKPOINT-COMMIT
vendored
Normal file
@@ -0,0 +1 @@
|
||||
a3e7e6b17946f48badce98d7ac360678a0ea7393
|
||||
1
third_party/libbpf/LICENSE
vendored
Normal file
@@ -0,0 +1 @@
|
||||
LGPL-2.1 OR BSD-2-Clause
|
||||
32
third_party/libbpf/LICENSE.BSD-2-Clause
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
Valid-License-Identifier: BSD-2-Clause
|
||||
SPDX-URL: https://spdx.org/licenses/BSD-2-Clause.html
|
||||
Usage-Guide:
|
||||
To use the BSD 2-clause "Simplified" License put the following SPDX
|
||||
tag/value pair into a comment according to the placement guidelines in
|
||||
the licensing rules documentation:
|
||||
SPDX-License-Identifier: BSD-2-Clause
|
||||
License-Text:
|
||||
|
||||
Copyright (c) 2015 The Libbpf Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
503
third_party/libbpf/LICENSE.LGPL-2.1
vendored
Normal file
@@ -0,0 +1,503 @@
|
||||
Valid-License-Identifier: LGPL-2.1
|
||||
Valid-License-Identifier: LGPL-2.1+
|
||||
SPDX-URL: https://spdx.org/licenses/LGPL-2.1.html
|
||||
Usage-Guide:
|
||||
To use this license in source code, put one of the following SPDX
|
||||
tag/value pairs into a comment according to the placement
|
||||
guidelines in the licensing rules documentation.
|
||||
For 'GNU Lesser General Public License (LGPL) version 2.1 only' use:
|
||||
SPDX-License-Identifier: LGPL-2.1
|
||||
For 'GNU Lesser General Public License (LGPL) version 2.1 or any later
|
||||
version' use:
|
||||
SPDX-License-Identifier: LGPL-2.1+
|
||||
License-Text:
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts as
|
||||
the successor of the GNU Library Public License, version 2, hence the
|
||||
version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your freedom to
|
||||
share and change it. By contrast, the GNU General Public Licenses are
|
||||
intended to guarantee your freedom to share and change free software--to
|
||||
make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some specially
|
||||
designated software packages--typically libraries--of the Free Software
|
||||
Foundation and other authors who decide to use it. You can use it too, but
|
||||
we suggest you first think carefully about whether this license or the
|
||||
ordinary General Public License is the better strategy to use in any
|
||||
particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use, not
|
||||
price. Our General Public Licenses are designed to make sure that you have
|
||||
the freedom to distribute copies of free software (and charge for this
|
||||
service if you wish); that you receive source code or can get it if you
|
||||
want it; that you can change the software and use pieces of it in new free
|
||||
programs; and that you are informed that you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis or for
|
||||
a fee, you must give the recipients all the rights that we gave you. You
|
||||
must make sure that they, too, receive or can get the source code. If you
|
||||
link other code with the library, you must provide complete object files to
|
||||
the recipients, so that they can relink them with the library after making
|
||||
changes to the library and recompiling it. And you must show them these
|
||||
terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that there is no
|
||||
warranty for the free library. Also, if the library is modified by someone
|
||||
else and passed on, the recipients should know that what they have is not
|
||||
the original version, so that the original author's reputation will not be
|
||||
affected by problems that might be introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of any
|
||||
free program. We wish to make sure that a company cannot effectively
|
||||
restrict the users of a free program by obtaining a restrictive license
|
||||
from a patent holder. Therefore, we insist that any patent license obtained
|
||||
for a version of the library must be consistent with the full freedom of
|
||||
use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary GNU
|
||||
General Public License. This license, the GNU Lesser General Public
|
||||
License, applies to certain designated libraries, and is quite different
|
||||
from the ordinary General Public License. We use this license for certain
|
||||
libraries in order to permit linking those libraries into non-free
|
||||
programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using a
|
||||
shared library, the combination of the two is legally speaking a combined
|
||||
work, a derivative of the original library. The ordinary General Public
|
||||
License therefore permits such linking only if the entire combination fits
|
||||
its criteria of freedom. The Lesser General Public License permits more lax
|
||||
criteria for linking other code with the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it does
|
||||
Less to protect the user's freedom than the ordinary General Public
|
||||
License. It also provides other free software developers Less of an
|
||||
advantage over competing non-free programs. These disadvantages are the
|
||||
reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to encourage
|
||||
the widest possible use of a certain library, so that it becomes a de-facto
|
||||
standard. To achieve this, non-free programs must be allowed to use the
|
||||
library. A more frequent case is that a free library does the same job as
|
||||
widely used non-free libraries. In this case, there is little to gain by
|
||||
limiting the free library to free software only, so we use the Lesser
|
||||
General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free programs
|
||||
enables a greater number of people to use a large body of free
|
||||
software. For example, permission to use the GNU C Library in non-free
|
||||
programs enables many more people to use the whole GNU operating system, as
|
||||
well as its variant, the GNU/Linux operating system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the users'
|
||||
freedom, it does ensure that the user of a program that is linked with the
|
||||
Library has the freedom and the wherewithal to run that program using a
|
||||
modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and modification
|
||||
follow. Pay close attention to the difference between a "work based on the
|
||||
library" and a "work that uses the library". The former contains code
|
||||
derived from the library, whereas the latter must be combined with the
|
||||
library in order to run.
|
||||
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other program
|
||||
which contains a notice placed by the copyright holder or other
|
||||
authorized party saying it may be distributed under the terms of this
|
||||
Lesser General Public License (also called "this License"). Each
|
||||
licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work which
|
||||
has been distributed under these terms. A "work based on the Library"
|
||||
means either the Library or any derivative work under copyright law:
|
||||
that is to say, a work containing the Library or a portion of it, either
|
||||
verbatim or with modifications and/or translated straightforwardly into
|
||||
another language. (Hereinafter, translation is included without
|
||||
limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for making
|
||||
modifications to it. For a library, complete source code means all the
|
||||
source code for all modules it contains, plus any associated interface
|
||||
definition files, plus the scripts used to control compilation and
|
||||
installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of running
|
||||
a program using the Library is not restricted, and output from such a
|
||||
program is covered only if its contents constitute a work based on the
|
||||
Library (independent of the use of the Library in a tool for writing
|
||||
it). Whether that is true depends on what the Library does and what the
|
||||
program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's complete
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the notices
|
||||
that refer to this License and to the absence of any warranty; and
|
||||
distribute a copy of this License along with the Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion of it,
|
||||
thus forming a work based on the Library, and copy and distribute such
|
||||
modifications or work under the terms of Section 1 above, provided that
|
||||
you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices stating
|
||||
that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no charge to
|
||||
all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a table
|
||||
of data to be supplied by an application program that uses the
|
||||
facility, other than as an argument passed when the facility is
|
||||
invoked, then you must make a good faith effort to ensure that, in
|
||||
the event an application does not supply such function or table, the
|
||||
facility still operates, and performs whatever part of its purpose
|
||||
remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has a
|
||||
purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must be
|
||||
optional: if the application does not supply it, the square root
|
||||
function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library, and
|
||||
can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based on
|
||||
the Library, the distribution of the whole must be on the terms of this
|
||||
License, whose permissions for other licensees extend to the entire
|
||||
whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of a
|
||||
storage or distribution medium does not bring the other work under the
|
||||
scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so that
|
||||
they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in these
|
||||
notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for that
|
||||
copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of the
|
||||
Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or derivative of
|
||||
it, under Section 2) in object code or executable form under the terms
|
||||
of Sections 1 and 2 above provided that you accompany it with the
|
||||
complete corresponding machine-readable source code, which must be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy from a
|
||||
designated place, then offering equivalent access to copy the source
|
||||
code from the same place satisfies the requirement to distribute the
|
||||
source code, even though third parties are not compelled to copy the
|
||||
source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the Library, but
|
||||
is designed to work with the Library by being compiled or linked with
|
||||
it, is called a "work that uses the Library". Such a work, in isolation,
|
||||
is not a derivative work of the Library, and therefore falls outside the
|
||||
scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library creates
|
||||
an executable that is a derivative of the Library (because it contains
|
||||
portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License. Section 6
|
||||
states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is
|
||||
not. Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data structure
|
||||
layouts and accessors, and small macros and small inline functions (ten
|
||||
lines or less in length), then the use of the object file is
|
||||
unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section
|
||||
6. Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or link a
|
||||
"work that uses the Library" with the Library to produce a work
|
||||
containing portions of the Library, and distribute that work under terms
|
||||
of your choice, provided that the terms permit modification of the work
|
||||
for the customer's own use and reverse engineering for debugging such
|
||||
modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work during
|
||||
execution displays copyright notices, you must include the copyright
|
||||
notice for the Library among them, as well as a reference directing the
|
||||
user to the copy of this License. Also, you must do one of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding machine-readable
|
||||
source code for the Library including whatever changes were used in
|
||||
the work (which must be distributed under Sections 1 and 2 above);
|
||||
and, if the work is an executable linked with the Library, with the
|
||||
complete machine-readable "work that uses the Library", as object
|
||||
code and/or source code, so that the user can modify the Library and
|
||||
then relink to produce a modified executable containing the modified
|
||||
Library. (It is understood that the user who changes the contents of
|
||||
definitions files in the Library will not necessarily be able to
|
||||
recompile the application to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a copy
|
||||
of the library already present on the user's computer system, rather
|
||||
than copying library functions into the executable, and (2) will
|
||||
operate properly with a modified version of the library, if the user
|
||||
installs one, as long as the modified version is interface-compatible
|
||||
with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at least three
|
||||
years, to give the same user the materials specified in Subsection
|
||||
6a, above, for a charge no more than the cost of performing this
|
||||
distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy from a
|
||||
designated place, offer equivalent access to copy the above specified
|
||||
materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these materials
|
||||
or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the Library"
|
||||
must include any data and utility programs needed for reproducing the
|
||||
executable from it. However, as a special exception, the materials to be
|
||||
distributed need not include anything that is normally distributed (in
|
||||
either source or binary form) with the major components (compiler,
|
||||
kernel, and so on) of the operating system on which the executable runs,
|
||||
unless that component itself accompanies the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license restrictions
|
||||
of other proprietary libraries that do not normally accompany the
|
||||
operating system. Such a contradiction means you cannot use both them
|
||||
and the Library together in an executable that you distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the Library
|
||||
side-by-side in a single library together with other library facilities
|
||||
not covered by this License, and distribute such a combined library,
|
||||
provided that the separate distribution of the work based on the Library
|
||||
and of the other library facilities is otherwise permitted, and provided
|
||||
that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based on
|
||||
the Library, uncombined with any other library facilities. This must
|
||||
be distributed under the terms of the Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact that part
|
||||
of it is a work based on the Library, and explaining where to find
|
||||
the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute the
|
||||
Library except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense, link with, or distribute the
|
||||
Library is void, and will automatically terminate your rights under this
|
||||
License. However, parties who have received copies, or rights, from you
|
||||
under this License will not have their licenses terminated so long as
|
||||
such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not signed
|
||||
it. However, nothing else grants you permission to modify or distribute
|
||||
the Library or its derivative works. These actions are prohibited by law
|
||||
if you do not accept this License. Therefore, by modifying or
|
||||
distributing the Library (or any work based on the Library), you
|
||||
indicate your acceptance of this License to do so, and all its terms and
|
||||
conditions for copying, distributing or modifying the Library or works
|
||||
based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted
|
||||
herein. You are not responsible for enforcing compliance by third
|
||||
parties with this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent license
|
||||
would not permit royalty-free redistribution of the Library by all
|
||||
those who receive copies directly or indirectly through you, then the
|
||||
only way you could satisfy both it and this License would be to refrain
|
||||
entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply, and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is implemented
|
||||
by public license practices. Many people have made generous
|
||||
contributions to the wide range of software distributed through that
|
||||
system in reliance on consistent application of that system; it is up
|
||||
to the author/donor to decide if he or she is willing to distribute
|
||||
software through any other system and a licensee cannot impose that
|
||||
choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in certain
|
||||
countries either by patents or by copyrighted interfaces, the original
|
||||
copyright holder who places the Library under this License may add an
|
||||
explicit geographical distribution limitation excluding those
|
||||
countries, so that distribution is permitted only in or among countries
|
||||
not thus excluded. In such case, this License incorporates the
|
||||
limitation as if written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new versions of
|
||||
the Lesser General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in
|
||||
detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a license
|
||||
version number, you may choose any version ever published by the Free
|
||||
Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free Software
|
||||
Foundation; we sometimes make exceptions for this. Our decision will be
|
||||
guided by the two goals of preserving the free status of all
|
||||
derivatives of our free software and of promoting the sharing and reuse
|
||||
of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
||||
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH
|
||||
YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
|
||||
NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
|
||||
DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
|
||||
DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY
|
||||
(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
|
||||
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
|
||||
THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR
|
||||
OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
one line to give the library's name and an idea of what it does.
|
||||
Copyright (C) year name of author
|
||||
|
||||
This library is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add
|
||||
information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in
|
||||
the library `Frob' (a library for tweaking knobs) written
|
||||
by James Random Hacker.
|
||||
|
||||
signature of Ty Coon, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
That's all there is to it!
|
||||
BIN
third_party/libbpf/assets/libbpf-logo-compact-darkbg.png
vendored
Normal file
|
After Width: | Height: | Size: 262 KiB |
BIN
third_party/libbpf/assets/libbpf-logo-compact-mono.png
vendored
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
third_party/libbpf/assets/libbpf-logo-compact.png
vendored
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
third_party/libbpf/assets/libbpf-logo-sideways-darkbg.png
vendored
Normal file
|
After Width: | Height: | Size: 284 KiB |
BIN
third_party/libbpf/assets/libbpf-logo-sideways-mono.png
vendored
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
third_party/libbpf/assets/libbpf-logo-sideways.png
vendored
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
third_party/libbpf/assets/libbpf-logo-sparse-darkbg.png
vendored
Normal file
|
After Width: | Height: | Size: 352 KiB |
BIN
third_party/libbpf/assets/libbpf-logo-sparse-mono.png
vendored
Normal file
|
After Width: | Height: | Size: 206 KiB |
BIN
third_party/libbpf/assets/libbpf-logo-sparse.png
vendored
Normal file
|
After Width: | Height: | Size: 236 KiB |
0
third_party/libbpf/ci/diffs/.keep
vendored
Normal file
70
third_party/libbpf/ci/diffs/0001-s390-define-RUNTIME_DISCARD_EXIT-to-fix-link-error-w.patch
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
From 6fba14e2ed9d159f76b23fa5c16f3ea99acbc003 Mon Sep 17 00:00:00 2001
|
||||
From: Masahiro Yamada <masahiroy@kernel.org>
|
||||
Date: Thu, 5 Jan 2023 12:13:06 +0900
|
||||
Subject: [PATCH] s390: define RUNTIME_DISCARD_EXIT to fix link error with GNU
|
||||
ld < 2.36
|
||||
|
||||
Nathan Chancellor reports that the s390 vmlinux fails to link with
|
||||
GNU ld < 2.36 since commit 99cb0d917ffa ("arch: fix broken BuildID
|
||||
for arm64 and riscv").
|
||||
|
||||
It happens for defconfig, or more specifically for CONFIG_EXPOLINE=y.
|
||||
|
||||
$ s390x-linux-gnu-ld --version | head -n1
|
||||
GNU ld (GNU Binutils for Debian) 2.35.2
|
||||
$ make -s ARCH=s390 CROSS_COMPILE=s390x-linux-gnu- allnoconfig
|
||||
$ ./scripts/config -e CONFIG_EXPOLINE
|
||||
$ make -s ARCH=s390 CROSS_COMPILE=s390x-linux-gnu- olddefconfig
|
||||
$ make -s ARCH=s390 CROSS_COMPILE=s390x-linux-gnu-
|
||||
`.exit.text' referenced in section `.s390_return_reg' of drivers/base/dd.o: defined in discarded section `.exit.text' of drivers/base/dd.o
|
||||
make[1]: *** [scripts/Makefile.vmlinux:34: vmlinux] Error 1
|
||||
make: *** [Makefile:1252: vmlinux] Error 2
|
||||
|
||||
arch/s390/kernel/vmlinux.lds.S wants to keep EXIT_TEXT:
|
||||
|
||||
.exit.text : {
|
||||
EXIT_TEXT
|
||||
}
|
||||
|
||||
But, at the same time, EXIT_TEXT is thrown away by DISCARD because
|
||||
s390 does not define RUNTIME_DISCARD_EXIT.
|
||||
|
||||
I still do not understand why the latter wins after 99cb0d917ffa,
|
||||
but defining RUNTIME_DISCARD_EXIT seems correct because the comment
|
||||
line in arch/s390/kernel/vmlinux.lds.S says:
|
||||
|
||||
/*
|
||||
* .exit.text is discarded at runtime, not link time,
|
||||
* to deal with references from __bug_table
|
||||
*/
|
||||
|
||||
Nathan also found that binutils commit 21401fc7bf67 ("Duplicate output
|
||||
sections in scripts") cured this issue, so we cannot reproduce it with
|
||||
binutils 2.36+, but it is better to not rely on it.
|
||||
|
||||
Fixes: 99cb0d917ffa ("arch: fix broken BuildID for arm64 and riscv")
|
||||
Link: https://lore.kernel.org/all/Y7Jal56f6UBh1abE@dev-arch.thelio-3990X/
|
||||
Reported-by: Nathan Chancellor <nathan@kernel.org>
|
||||
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20230105031306.1455409-1-masahiroy@kernel.org
|
||||
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
|
||||
---
|
||||
arch/s390/kernel/vmlinux.lds.S | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
|
||||
index 5ea3830af0cc..6e101e6f499d 100644
|
||||
--- a/arch/s390/kernel/vmlinux.lds.S
|
||||
+++ b/arch/s390/kernel/vmlinux.lds.S
|
||||
@@ -17,6 +17,8 @@
|
||||
/* Handle ro_after_init data on our own. */
|
||||
#define RO_AFTER_INIT_DATA
|
||||
|
||||
+#define RUNTIME_DISCARD_EXIT
|
||||
+
|
||||
#define EMITS_PT_NOTE
|
||||
|
||||
#include <asm-generic/vmlinux.lds.h>
|
||||
--
|
||||
2.30.2
|
||||
|
||||
37
third_party/libbpf/ci/diffs/0001-selftests-bpf-Check-whether-to-run-selftest.patch
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
From ff8be5401b359e23ec2b74184034082564bac7c5 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Daniel=20M=C3=BCller?= <deso@posteo.net>
|
||||
Date: Thu, 25 May 2023 16:04:20 -0700
|
||||
Subject: [PATCH] selftests/bpf: Check whether to run selftest
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The sockopt test invokes test__start_subtest and then unconditionally
|
||||
asserts the success. That means that even if deny-listed, any test will
|
||||
still run and potentially fail.
|
||||
Evaluate the return value of test__start_subtest() to achieve the
|
||||
desired behavior, as other tests do.
|
||||
|
||||
Signed-off-by: Daniel Müller <deso@posteo.net>
|
||||
---
|
||||
tools/testing/selftests/bpf/prog_tests/sockopt.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tools/testing/selftests/bpf/prog_tests/sockopt.c b/tools/testing/selftests/bpf/prog_tests/sockopt.c
|
||||
index 33dd45..9e6a5e 100644
|
||||
--- a/tools/testing/selftests/bpf/prog_tests/sockopt.c
|
||||
+++ b/tools/testing/selftests/bpf/prog_tests/sockopt.c
|
||||
@@ -1060,7 +1060,9 @@ void test_sockopt(void)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tests); i++) {
|
||||
- test__start_subtest(tests[i].descr);
|
||||
+ if (!test__start_subtest(tests[i].descr))
|
||||
+ continue;
|
||||
+
|
||||
ASSERT_OK(run_test(cgroup_fd, &tests[i]), tests[i].descr);
|
||||
}
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
||||
46
third_party/libbpf/ci/diffs/0001-selftests-bpf-Select-CONFIG_FUNCTION_ERROR_INJECTION.patch
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
From a8dfde09c90109e3a98af54847e91bde7dc2d5c2 Mon Sep 17 00:00:00 2001
|
||||
From: Song Liu <song@kernel.org>
|
||||
Date: Tue, 13 Dec 2022 14:05:00 -0800
|
||||
Subject: [PATCH] selftests/bpf: Select CONFIG_FUNCTION_ERROR_INJECTION
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
BPF selftests require CONFIG_FUNCTION_ERROR_INJECTION to work. However,
|
||||
CONFIG_FUNCTION_ERROR_INJECTION is no longer 'y' by default after recent
|
||||
changes. As a result, we are seeing errors like the following from BPF CI:
|
||||
|
||||
bpf_testmod_test_read() is not modifiable
|
||||
__x64_sys_setdomainname is not sleepable
|
||||
__x64_sys_getpgid is not sleepable
|
||||
|
||||
Fix this by explicitly selecting CONFIG_FUNCTION_ERROR_INJECTION in the
|
||||
selftest config.
|
||||
|
||||
Fixes: a4412fdd49dc ("error-injection: Add prompt for function error injection")
|
||||
Reported-by: Daniel Müller <deso@posteo.net>
|
||||
Signed-off-by: Song Liu <song@kernel.org>
|
||||
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
|
||||
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
|
||||
Acked-by: Daniel Müller <deso@posteo.net>
|
||||
Link: https://lore.kernel.org/bpf/20221213220500.3427947-1-song@kernel.org
|
||||
Signed-off-by: Daniel Müller <deso@posteo.net>
|
||||
---
|
||||
tools/testing/selftests/bpf/config | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config
|
||||
index 612f69..63cd4a 100644
|
||||
--- a/tools/testing/selftests/bpf/config
|
||||
+++ b/tools/testing/selftests/bpf/config
|
||||
@@ -16,6 +16,7 @@ CONFIG_CRYPTO_USER_API_HASH=y
|
||||
CONFIG_DYNAMIC_FTRACE=y
|
||||
CONFIG_FPROBE=y
|
||||
CONFIG_FTRACE_SYSCALLS=y
|
||||
+CONFIG_FUNCTION_ERROR_INJECTION=y
|
||||
CONFIG_FUNCTION_TRACER=y
|
||||
CONFIG_GENEVE=y
|
||||
CONFIG_IKCONFIG=y
|
||||
--
|
||||
2.30.2
|
||||
|
||||
68
third_party/libbpf/ci/diffs/0001-tracing-fprobe-Initialize-ret-valiable-to-fix-smatch.patch
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
From d3484f640bc82cff459beb85a00f7ebab20f0a41 Mon Sep 17 00:00:00 2001
|
||||
From: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>
|
||||
Date: Sun, 9 Apr 2023 11:28:31 +0900
|
||||
Subject: [PATCH] tracing: fprobe: Initialize ret valiable to fix smatch error
|
||||
|
||||
The commit 39d954200bf6 ("fprobe: Skip exit_handler if entry_handler returns
|
||||
!0") introduced a hidden dependency of 'ret' local variable in the
|
||||
fprobe_handler(), Smatch warns the `ret` can be accessed without
|
||||
initialization.
|
||||
|
||||
kernel/trace/fprobe.c:59 fprobe_handler()
|
||||
error: uninitialized symbol 'ret'.
|
||||
|
||||
kernel/trace/fprobe.c
|
||||
49 fpr->entry_ip = ip;
|
||||
50 if (fp->entry_data_size)
|
||||
51 entry_data = fpr->data;
|
||||
52 }
|
||||
53
|
||||
54 if (fp->entry_handler)
|
||||
55 ret = fp->entry_handler(fp, ip, ftrace_get_regs(fregs), entry_data);
|
||||
|
||||
ret is only initialized if there is an ->entry_handler
|
||||
|
||||
56
|
||||
57 /* If entry_handler returns !0, nmissed is not counted. */
|
||||
58 if (rh) {
|
||||
|
||||
rh is only true if there is an ->exit_handler. Presumably if you have
|
||||
and ->exit_handler that means you also have a ->entry_handler but Smatch
|
||||
is not smart enough to figure it out.
|
||||
|
||||
--> 59 if (ret)
|
||||
^^^
|
||||
Warning here.
|
||||
|
||||
60 rethook_recycle(rh);
|
||||
61 else
|
||||
62 rethook_hook(rh, ftrace_get_regs(fregs), true);
|
||||
63 }
|
||||
64 out:
|
||||
65 ftrace_test_recursion_unlock(bit);
|
||||
66 }
|
||||
|
||||
Reported-by: Dan Carpenter <error27@gmail.com>
|
||||
Link: https://lore.kernel.org/all/85429a5c-a4b9-499e-b6c0-cbd313291c49@kili.mountain
|
||||
Fixes: 39d954200bf6 ("fprobe: Skip exit_handler if entry_handler returns !0")
|
||||
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
||||
---
|
||||
kernel/trace/fprobe.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c
|
||||
index 9abb3905bc8e..293184227394 100644
|
||||
--- a/kernel/trace/fprobe.c
|
||||
+++ b/kernel/trace/fprobe.c
|
||||
@@ -27,7 +27,7 @@ static void fprobe_handler(unsigned long ip, unsigned long parent_ip,
|
||||
struct rethook_node *rh = NULL;
|
||||
struct fprobe *fp;
|
||||
void *entry_data = NULL;
|
||||
- int bit, ret;
|
||||
+ int bit, ret = 0;
|
||||
|
||||
fp = container_of(ops, struct fprobe, ops);
|
||||
if (fprobe_disabled(fp))
|
||||
--
|
||||
2.34.1
|
||||
|
||||
83
third_party/libbpf/ci/diffs/0001-veth-take-into-account-peer-device-for-NETDEV_XDP_AC.patch
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
From 8267fc71abb2dc47338570e56dd3473a58313fce Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Mon, 17 Apr 2023 23:53:22 +0200
|
||||
Subject: [PATCH] veth: take into account peer device for
|
||||
NETDEV_XDP_ACT_NDO_XMIT xdp_features flag
|
||||
|
||||
For veth pairs, NETDEV_XDP_ACT_NDO_XMIT is supported by the current
|
||||
device if the peer one is running a XDP program or if it has GRO enabled.
|
||||
Fix the xdp_features flags reporting considering peer device and not
|
||||
current one for NETDEV_XDP_ACT_NDO_XMIT.
|
||||
|
||||
Fixes: fccca038f300 ("veth: take into account device reconfiguration for xdp_features flag")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/4f1ca6f6f6b42ae125bfdb5c7782217c83968b2e.1681767806.git.lorenzo@kernel.org
|
||||
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
|
||||
---
|
||||
drivers/net/veth.c | 17 +++++++++++------
|
||||
1 file changed, 11 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
|
||||
index e1b38fbf1dd9..4b3c6647edc6 100644
|
||||
--- a/drivers/net/veth.c
|
||||
+++ b/drivers/net/veth.c
|
||||
@@ -1262,11 +1262,12 @@ static void veth_set_xdp_features(struct net_device *dev)
|
||||
|
||||
peer = rtnl_dereference(priv->peer);
|
||||
if (peer && peer->real_num_tx_queues <= dev->real_num_rx_queues) {
|
||||
+ struct veth_priv *priv_peer = netdev_priv(peer);
|
||||
xdp_features_t val = NETDEV_XDP_ACT_BASIC |
|
||||
NETDEV_XDP_ACT_REDIRECT |
|
||||
NETDEV_XDP_ACT_RX_SG;
|
||||
|
||||
- if (priv->_xdp_prog || veth_gro_requested(dev))
|
||||
+ if (priv_peer->_xdp_prog || veth_gro_requested(peer))
|
||||
val |= NETDEV_XDP_ACT_NDO_XMIT |
|
||||
NETDEV_XDP_ACT_NDO_XMIT_SG;
|
||||
xdp_set_features_flag(dev, val);
|
||||
@@ -1504,19 +1505,23 @@ static int veth_set_features(struct net_device *dev,
|
||||
{
|
||||
netdev_features_t changed = features ^ dev->features;
|
||||
struct veth_priv *priv = netdev_priv(dev);
|
||||
+ struct net_device *peer;
|
||||
int err;
|
||||
|
||||
if (!(changed & NETIF_F_GRO) || !(dev->flags & IFF_UP) || priv->_xdp_prog)
|
||||
return 0;
|
||||
|
||||
+ peer = rtnl_dereference(priv->peer);
|
||||
if (features & NETIF_F_GRO) {
|
||||
err = veth_napi_enable(dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- xdp_features_set_redirect_target(dev, true);
|
||||
+ if (peer)
|
||||
+ xdp_features_set_redirect_target(peer, true);
|
||||
} else {
|
||||
- xdp_features_clear_redirect_target(dev);
|
||||
+ if (peer)
|
||||
+ xdp_features_clear_redirect_target(peer);
|
||||
veth_napi_del(dev);
|
||||
}
|
||||
return 0;
|
||||
@@ -1598,13 +1603,13 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
|
||||
peer->max_mtu = max_mtu;
|
||||
}
|
||||
|
||||
- xdp_features_set_redirect_target(dev, true);
|
||||
+ xdp_features_set_redirect_target(peer, true);
|
||||
}
|
||||
|
||||
if (old_prog) {
|
||||
if (!prog) {
|
||||
- if (!veth_gro_requested(dev))
|
||||
- xdp_features_clear_redirect_target(dev);
|
||||
+ if (peer && !veth_gro_requested(dev))
|
||||
+ xdp_features_clear_redirect_target(peer);
|
||||
|
||||
if (dev->flags & IFF_UP)
|
||||
veth_disable_xdp(dev);
|
||||
--
|
||||
2.34.1
|
||||
|
||||
95
third_party/libbpf/ci/managers/debian.sh
vendored
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
|
||||
PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP})
|
||||
DEBIAN_RELEASE="${DEBIAN_RELEASE:-testing}"
|
||||
CONT_NAME="${CONT_NAME:-libbpf-debian-$DEBIAN_RELEASE}"
|
||||
ENV_VARS="${ENV_VARS:-}"
|
||||
DOCKER_RUN="${DOCKER_RUN:-docker run}"
|
||||
REPO_ROOT="${REPO_ROOT:-$PWD}"
|
||||
ADDITIONAL_DEPS=(pkgconf)
|
||||
EXTRA_CFLAGS=""
|
||||
EXTRA_LDFLAGS=""
|
||||
|
||||
function info() {
|
||||
echo -e "\033[33;1m$1\033[0m"
|
||||
}
|
||||
|
||||
function error() {
|
||||
echo -e "\033[31;1m$1\033[0m"
|
||||
}
|
||||
|
||||
function docker_exec() {
|
||||
docker exec $ENV_VARS $CONT_NAME "$@"
|
||||
}
|
||||
|
||||
set -eu
|
||||
|
||||
source "$(dirname $0)/travis_wait.bash"
|
||||
|
||||
for phase in "${PHASES[@]}"; do
|
||||
case $phase in
|
||||
SETUP)
|
||||
info "Setup phase"
|
||||
info "Using Debian $DEBIAN_RELEASE"
|
||||
|
||||
docker --version
|
||||
|
||||
docker pull debian:$DEBIAN_RELEASE
|
||||
info "Starting container $CONT_NAME"
|
||||
$DOCKER_RUN -v $REPO_ROOT:/build:rw \
|
||||
-w /build --privileged=true --name $CONT_NAME \
|
||||
-dit --net=host debian:$DEBIAN_RELEASE /bin/bash
|
||||
echo -e "::group::Build Env Setup"
|
||||
docker_exec bash -c "echo deb-src http://deb.debian.org/debian $DEBIAN_RELEASE main >>/etc/apt/sources.list"
|
||||
docker_exec apt-get -y update
|
||||
docker_exec apt-get -y install aptitude
|
||||
docker_exec aptitude -y install make libz-dev libelf-dev
|
||||
docker_exec aptitude -y install "${ADDITIONAL_DEPS[@]}"
|
||||
echo -e "::endgroup::"
|
||||
;;
|
||||
RUN|RUN_CLANG|RUN_CLANG14|RUN_CLANG15|RUN_CLANG16|RUN_GCC10|RUN_GCC11|RUN_GCC12|RUN_ASAN|RUN_CLANG_ASAN|RUN_GCC10_ASAN)
|
||||
CC="cc"
|
||||
if [[ "$phase" =~ "RUN_CLANG(\d+)(_ASAN)?" ]]; then
|
||||
ENV_VARS="-e CC=clang-${BASH_REMATCH[1]} -e CXX=clang++-${BASH_REMATCH[1]}"
|
||||
CC="clang-${BASH_REMATCH[1]}"
|
||||
elif [[ "$phase" = *"CLANG"* ]]; then
|
||||
ENV_VARS="-e CC=clang -e CXX=clang++"
|
||||
CC="clang"
|
||||
elif [[ "$phase" =~ "RUN_GCC(\d+)(_ASAN)?" ]]; then
|
||||
ENV_VARS="-e CC=gcc-${BASH_REMATCH[1]} -e CXX=g++-${BASH_REMATCH[1]}"
|
||||
CC="gcc-${BASH_REMATCH[1]}"
|
||||
fi
|
||||
if [[ "$phase" = *"ASAN"* ]]; then
|
||||
EXTRA_CFLAGS="${EXTRA_CFLAGS} -fsanitize=address,undefined"
|
||||
EXTRA_LDFLAGS="${EXTRA_LDFLAGS} -fsanitize=address,undefined"
|
||||
fi
|
||||
if [[ "$CC" != "cc" ]]; then
|
||||
docker_exec aptitude -y install "$CC"
|
||||
else
|
||||
docker_exec aptitude -y install gcc
|
||||
fi
|
||||
docker_exec mkdir build install
|
||||
docker_exec ${CC} --version
|
||||
info "build"
|
||||
docker_exec make -j$((4*$(nproc))) EXTRA_CFLAGS="${EXTRA_CFLAGS}" EXTRA_LDFLAGS="${EXTRA_LDFLAGS}" -C ./src -B OBJDIR=../build
|
||||
info "ldd build/libbpf.so:"
|
||||
docker_exec ldd build/libbpf.so
|
||||
if ! docker_exec ldd build/libbpf.so | grep -q libelf; then
|
||||
error "No reference to libelf.so in libbpf.so!"
|
||||
exit 1
|
||||
fi
|
||||
info "install"
|
||||
docker_exec make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install
|
||||
info "link binary"
|
||||
docker_exec bash -c "EXTRA_CFLAGS=\"${EXTRA_CFLAGS}\" EXTRA_LDFLAGS=\"${EXTRA_LDFLAGS}\" ./ci/managers/test_compile.sh"
|
||||
;;
|
||||
CLEANUP)
|
||||
info "Cleanup phase"
|
||||
docker stop $CONT_NAME
|
||||
docker rm -f $CONT_NAME
|
||||
;;
|
||||
*)
|
||||
echo >&2 "Unknown phase '$phase'"
|
||||
exit 1
|
||||
esac
|
||||
done
|
||||
15
third_party/libbpf/ci/managers/test_compile.sh
vendored
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
set -euox pipefail
|
||||
|
||||
EXTRA_CFLAGS=${EXTRA_CFLAGS:-}
|
||||
EXTRA_LDFLAGS=${EXTRA_LDFLAGS:-}
|
||||
|
||||
cat << EOF > main.c
|
||||
#include <bpf/libbpf.h>
|
||||
int main() {
|
||||
return bpf_object__open(0) < 0;
|
||||
}
|
||||
EOF
|
||||
|
||||
# static linking
|
||||
${CC:-cc} ${EXTRA_CFLAGS} ${EXTRA_LDFLAGS} -o main -I./include/uapi -I./install/usr/include main.c ./build/libbpf.a -lelf -lz
|
||||
61
third_party/libbpf/ci/managers/travis_wait.bash
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
# This was borrowed from https://github.com/travis-ci/travis-build/tree/master/lib/travis/build/bash
|
||||
# to get around https://github.com/travis-ci/travis-ci/issues/9979. It should probably be removed
|
||||
# as soon as Travis CI has started to provide an easy way to export the functions to bash scripts.
|
||||
|
||||
travis_jigger() {
|
||||
local cmd_pid="${1}"
|
||||
shift
|
||||
local timeout="${1}"
|
||||
shift
|
||||
local count=0
|
||||
|
||||
echo -e "\\n"
|
||||
|
||||
while [[ "${count}" -lt "${timeout}" ]]; do
|
||||
count="$((count + 1))"
|
||||
echo -ne "Still running (${count} of ${timeout}): ${*}\\r"
|
||||
sleep 60
|
||||
done
|
||||
|
||||
echo -e "\\n${ANSI_RED}Timeout (${timeout} minutes) reached. Terminating \"${*}\"${ANSI_RESET}\\n"
|
||||
kill -9 "${cmd_pid}"
|
||||
}
|
||||
|
||||
travis_wait() {
|
||||
local timeout="${1}"
|
||||
|
||||
if [[ "${timeout}" =~ ^[0-9]+$ ]]; then
|
||||
shift
|
||||
else
|
||||
timeout=20
|
||||
fi
|
||||
|
||||
local cmd=("${@}")
|
||||
local log_file="travis_wait_${$}.log"
|
||||
|
||||
"${cmd[@]}" &>"${log_file}" &
|
||||
local cmd_pid="${!}"
|
||||
|
||||
travis_jigger "${!}" "${timeout}" "${cmd[@]}" &
|
||||
local jigger_pid="${!}"
|
||||
local result
|
||||
|
||||
{
|
||||
set +e
|
||||
wait "${cmd_pid}" 2>/dev/null
|
||||
result="${?}"
|
||||
ps -p"${jigger_pid}" &>/dev/null && kill "${jigger_pid}"
|
||||
set -e
|
||||
}
|
||||
|
||||
if [[ "${result}" -eq 0 ]]; then
|
||||
echo -e "\\n${ANSI_GREEN}The command ${cmd[*]} exited with ${result}.${ANSI_RESET}"
|
||||
else
|
||||
echo -e "\\n${ANSI_RED}The command ${cmd[*]} exited with ${result}.${ANSI_RESET}"
|
||||
fi
|
||||
|
||||
echo -e "\\n${ANSI_GREEN}Log:${ANSI_RESET}\\n"
|
||||
cat "${log_file}"
|
||||
|
||||
return "${result}"
|
||||
}
|
||||
24
third_party/libbpf/ci/managers/ubuntu.sh
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
|
||||
RELEASE="focal"
|
||||
|
||||
apt-get update
|
||||
apt-get install -y pkg-config
|
||||
|
||||
source "$(dirname $0)/travis_wait.bash"
|
||||
|
||||
cd $REPO_ROOT
|
||||
|
||||
EXTRA_CFLAGS="-Werror -Wall -fsanitize=address,undefined"
|
||||
EXTRA_LDFLAGS="-Werror -Wall -fsanitize=address,undefined"
|
||||
mkdir build install
|
||||
cc --version
|
||||
make -j$((4*$(nproc))) EXTRA_CFLAGS="${EXTRA_CFLAGS}" EXTRA_LDFLAGS="${EXTRA_LDFLAGS}" -C ./src -B OBJDIR=../build
|
||||
ldd build/libbpf.so
|
||||
if ! ldd build/libbpf.so | grep -q libelf; then
|
||||
echo "FAIL: No reference to libelf.so in libbpf.so!"
|
||||
exit 1
|
||||
fi
|
||||
make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install
|
||||
EXTRA_CFLAGS=${EXTRA_CFLAGS} EXTRA_LDFLAGS=${EXTRA_LDFLAGS} $(dirname $0)/test_compile.sh
|
||||
8
third_party/libbpf/ci/vmtest/configs/ALLOWLIST-4.9.0
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# btf_dump -- need to disable data dump sub-tests
|
||||
core_retro
|
||||
cpu_mask
|
||||
hashmap
|
||||
legacy_printk
|
||||
perf_buffer
|
||||
section_names
|
||||
|
||||
51
third_party/libbpf/ci/vmtest/configs/ALLOWLIST-5.5.0
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
# attach_probe
|
||||
autoload
|
||||
bpf_verif_scale
|
||||
cgroup_attach_autodetach
|
||||
cgroup_attach_override
|
||||
core_autosize
|
||||
core_extern
|
||||
core_read_macros
|
||||
core_reloc
|
||||
core_retro
|
||||
cpu_mask
|
||||
endian
|
||||
get_branch_snapshot
|
||||
get_stackid_cannot_attach
|
||||
global_data
|
||||
global_data_init
|
||||
global_func_args
|
||||
hashmap
|
||||
legacy_printk
|
||||
linked_funcs
|
||||
linked_maps
|
||||
map_lock
|
||||
obj_name
|
||||
perf_buffer
|
||||
perf_event_stackmap
|
||||
pinning
|
||||
pkt_md_access
|
||||
probe_user
|
||||
queue_stack_map
|
||||
raw_tp_writable_reject_nbd_invalid
|
||||
raw_tp_writable_test_run
|
||||
rdonly_maps
|
||||
section_names
|
||||
signal_pending
|
||||
skeleton
|
||||
sockmap_ktls
|
||||
sockopt
|
||||
spinlock
|
||||
stacktrace_map
|
||||
stacktrace_map_raw_tp
|
||||
static_linked
|
||||
task_fd_query_rawtp
|
||||
task_fd_query_tp
|
||||
tc_bpf
|
||||
tcp_estats
|
||||
tcp_rtt
|
||||
tp_attach_query
|
||||
usdt/urand_pid_attach
|
||||
xdp
|
||||
xdp_noinline
|
||||
xdp_perf
|
||||
120
third_party/libbpf/ci/vmtest/configs/DENYLIST-5.5.0
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
# This file is not used and is there for historic purposes only.
|
||||
# See ALLOWLIST-5.5.0 instead.
|
||||
|
||||
# PERMANENTLY DISABLED
|
||||
align # verifier output format changed
|
||||
atomics # new atomic operations (v5.12+)
|
||||
atomic_bounds # new atomic operations (v5.12+)
|
||||
bind_perm # changed semantics of return values (v5.12+)
|
||||
bpf_cookie # 5.15+
|
||||
bpf_iter # bpf_iter support is missing
|
||||
bpf_obj_id # bpf_link support missing for GET_OBJ_INFO, GET_FD_BY_ID, etc
|
||||
bpf_tcp_ca # STRUCT_OPS is missing
|
||||
btf_map_in_map # inner map leak fixed in 5.8
|
||||
btf_skc_cls_ingress # v5.10+ functionality
|
||||
cg_storage_multi # v5.9+ functionality
|
||||
cgroup_attach_multi # BPF_F_REPLACE_PROG missing
|
||||
cgroup_link # LINK_CREATE is missing
|
||||
cgroup_skb_sk_lookup # bpf_sk_lookup_tcp() helper is missing
|
||||
check_mtu # missing BPF helper (v5.12+)
|
||||
cls_redirect # bpf_csum_level() helper is missing
|
||||
connect_force_port # cgroup/get{peer,sock}name{4,6} support is missing
|
||||
d_path # v5.10+ feature
|
||||
enable_stats # BPF_ENABLE_STATS support is missing
|
||||
fentry_fexit # bpf_prog_test_tracing missing
|
||||
fentry_test # bpf_prog_test_tracing missing
|
||||
fexit_bpf2bpf # freplace is missing
|
||||
fexit_sleep # relies on bpf_trampoline fix in 5.12+
|
||||
fexit_test # bpf_prog_test_tracing missing
|
||||
flow_dissector # bpf_link-based flow dissector is in 5.8+
|
||||
flow_dissector_reattach
|
||||
for_each # v5.12+
|
||||
get_func_ip_test # v5.15+
|
||||
get_stack_raw_tp # exercising BPF verifier bug causing infinite loop
|
||||
hash_large_key # v5.11+
|
||||
ima # v5.11+
|
||||
kfree_skb # 32-bit pointer arith in test_pkt_access
|
||||
ksyms # __start_BTF has different name
|
||||
kfunc_call # v5.13+
|
||||
link_pinning # bpf_link is missing
|
||||
linked_vars # v5.13+
|
||||
load_bytes_relative # new functionality in 5.8
|
||||
lookup_and_delete # v5.14+
|
||||
map_init # per-CPU LRU missing
|
||||
map_ptr # test uses BPF_MAP_TYPE_RINGBUF, added in 5.8
|
||||
metadata # v5.10+
|
||||
migrate_reuseport # v5.14+
|
||||
mmap # 5.5 kernel is too permissive with re-mmaping
|
||||
modify_return # fmod_ret support is missing
|
||||
module_attach # module BTF support missing (v5.11+)
|
||||
netcnt
|
||||
netns_cookie # v5.15+
|
||||
ns_current_pid_tgid # bpf_get_ns_current_pid_tgid() helper is missing
|
||||
pe_preserve_elems # v5.10+
|
||||
perf_branches # bpf_read_branch_records() helper is missing
|
||||
perf_link # v5.15+
|
||||
pkt_access # 32-bit pointer arith in test_pkt_access
|
||||
probe_read_user_str # kernel bug with garbage bytes at the end
|
||||
prog_run_xattr # 32-bit pointer arith in test_pkt_access
|
||||
raw_tp_test_run # v5.10+
|
||||
recursion # v5.12+
|
||||
ringbuf # BPF_MAP_TYPE_RINGBUF is supported in 5.8+
|
||||
|
||||
# bug in verifier w/ tracking references
|
||||
#reference_tracking/classifier/sk_lookup_success
|
||||
reference_tracking
|
||||
|
||||
select_reuseport # UDP support is missing
|
||||
send_signal # bpf_send_signal_thread() helper is missing
|
||||
sk_assign # bpf_sk_assign helper missing
|
||||
sk_lookup # v5.9+
|
||||
sk_storage_tracing # missing bpf_sk_storage_get() helper
|
||||
skb_ctx # ctx_{size, }_{in, out} in BPF_PROG_TEST_RUN is missing
|
||||
skb_helpers # helpers added in 5.8+
|
||||
skeleton # creates too big ARRAY map
|
||||
snprintf # v5.13+
|
||||
snprintf_btf # v5.10+
|
||||
sock_fields # v5.10+
|
||||
socket_cookie # v5.12+
|
||||
sockmap_basic # uses new socket fields, 5.8+
|
||||
sockmap_listen # no listen socket supportin SOCKMAP
|
||||
sockopt/getsockopt: ignore >PAGE_SIZE optlen
|
||||
sockopt/setsockopt: ignore >PAGE_SIZE optlen
|
||||
sockopt_sk
|
||||
sockopt_qos_to_cc # v5.15+
|
||||
stacktrace_build_id # v5.9+
|
||||
stack_var_off # v5.12+
|
||||
syscall # v5.14+
|
||||
task_local_storage # v5.12+
|
||||
task_pt_regs # v5.15+
|
||||
tcp_hdr_options # v5.10+, new TCP header options feature in BPF
|
||||
tcpbpf_user # LINK_CREATE is missing
|
||||
tc_redirect # v5.14+
|
||||
test_bpffs # v5.10+, new CONFIG_BPF_PRELOAD=y and CONFIG_BPF_PRELOAD_UMG=y|m
|
||||
test_bprm_opts # v5.11+
|
||||
test_global_funcs # kernel doesn't support BTF linkage=global on FUNCs
|
||||
test_local_storage # v5.10+ feature
|
||||
test_lsm # no BPF_LSM support
|
||||
test_overhead # no fmod_ret support
|
||||
test_profiler # needs verifier logic improvements from v5.10+
|
||||
test_skb_pkt_end # v5.11+
|
||||
timer # v5.15+
|
||||
timer_mim # v5.15+
|
||||
trace_ext # v5.10+
|
||||
trace_printk # v5.14+
|
||||
trampoline_count # v5.12+ have lower allowed limits
|
||||
udp_limit # no cgroup/sock_release BPF program type (5.9+)
|
||||
varlen # verifier bug fixed in later kernels
|
||||
vmlinux # hrtimer_nanosleep() signature changed incompatibly
|
||||
xdp_adjust_tail # new XDP functionality added in 5.8
|
||||
xdp_attach # IFLA_XDP_EXPECTED_FD support is missing
|
||||
xdp_bonding # v5.15+
|
||||
xdp_bpf2bpf # freplace is missing
|
||||
xdp_context_test_run # v5.15+
|
||||
xdp_cpumap_attach # v5.9+
|
||||
xdp_devmap_attach # new feature in 5.8
|
||||
xdp_link # v5.9+
|
||||
|
||||
# SUBTESTS FAILING (block entire test until blocking subtests works properly)
|
||||
btf # "size check test", "func (Non zero vlen)"
|
||||
tailcalls # tailcall_bpf2bpf_1, tailcall_bpf2bpf_2, tailcall_bpf2bpf_3
|
||||
4
third_party/libbpf/ci/vmtest/configs/DENYLIST-latest
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
decap_sanity # weird failure with decap_sanity_ns netns already existing, TBD
|
||||
bpf_nf/tc-bpf-ct # test consistently failing on x86: https://github.com/libbpf/libbpf/pull/698#issuecomment-1590341200
|
||||
bpf_nf/xdp-ct # test consistently failing on x86: https://github.com/libbpf/libbpf/pull/698#issuecomment-1590341200
|
||||
kprobe_multi_bench_attach # suspected to cause crashes in CI
|
||||
4
third_party/libbpf/ci/vmtest/configs/DENYLIST-latest.s390x
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# TEMPORARY
|
||||
sockmap_listen/sockhash VSOCK test_vsock_redir
|
||||
usdt/basic # failing verifier due to bounds check after LLVM update
|
||||
usdt/multispec # same as above
|
||||
38
third_party/libbpf/ci/vmtest/helpers.sh
vendored
Executable file
@@ -0,0 +1,38 @@
|
||||
# shellcheck shell=bash
|
||||
|
||||
# $1 - start or end
|
||||
# $2 - fold identifier, no spaces
|
||||
# $3 - fold section description
|
||||
foldable() {
|
||||
local YELLOW='\033[1;33m'
|
||||
local NOCOLOR='\033[0m'
|
||||
if [ $1 = "start" ]; then
|
||||
line="::group::$2"
|
||||
if [ ! -z "${3:-}" ]; then
|
||||
line="$line - ${YELLOW}$3${NOCOLOR}"
|
||||
fi
|
||||
else
|
||||
line="::endgroup::"
|
||||
fi
|
||||
echo -e "$line"
|
||||
}
|
||||
|
||||
__print() {
|
||||
local TITLE=""
|
||||
if [[ -n $2 ]]; then
|
||||
TITLE=" title=$2"
|
||||
fi
|
||||
echo "::$1${TITLE}::$3"
|
||||
}
|
||||
|
||||
# $1 - title
|
||||
# $2 - message
|
||||
print_error() {
|
||||
__print error $1 $2
|
||||
}
|
||||
|
||||
# $1 - title
|
||||
# $2 - message
|
||||
print_notice() {
|
||||
__print notice $1 $2
|
||||
}
|
||||
94
third_party/libbpf/ci/vmtest/run_selftests.sh
vendored
Executable file
@@ -0,0 +1,94 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
source $(cd $(dirname $0) && pwd)/helpers.sh
|
||||
|
||||
ARCH=$(uname -m)
|
||||
|
||||
STATUS_FILE=/exitstatus
|
||||
|
||||
read_lists() {
|
||||
(for path in "$@"; do
|
||||
if [[ -s "$path" ]]; then
|
||||
cat "$path"
|
||||
fi;
|
||||
done) | cut -d'#' -f1 | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | tr -s '\n' ','
|
||||
}
|
||||
|
||||
test_progs() {
|
||||
if [[ "${KERNEL}" != '4.9.0' ]]; then
|
||||
foldable start test_progs "Testing test_progs"
|
||||
# "&& true" does not change the return code (it is not executed
|
||||
# if the Python script fails), but it prevents exiting on a
|
||||
# failure due to the "set -e".
|
||||
./test_progs ${DENYLIST:+-d"$DENYLIST"} ${ALLOWLIST:+-a"$ALLOWLIST"} && true
|
||||
echo "test_progs:$?" >> "${STATUS_FILE}"
|
||||
foldable end test_progs
|
||||
fi
|
||||
}
|
||||
|
||||
test_progs_no_alu32() {
|
||||
foldable start test_progs-no_alu32 "Testing test_progs-no_alu32"
|
||||
./test_progs-no_alu32 ${DENYLIST:+-d"$DENYLIST"} ${ALLOWLIST:+-a"$ALLOWLIST"} && true
|
||||
echo "test_progs-no_alu32:$?" >> "${STATUS_FILE}"
|
||||
foldable end test_progs-no_alu32
|
||||
}
|
||||
|
||||
test_maps() {
|
||||
if [[ "${KERNEL}" == 'latest' ]]; then
|
||||
foldable start test_maps "Testing test_maps"
|
||||
./test_maps && true
|
||||
echo "test_maps:$?" >> "${STATUS_FILE}"
|
||||
foldable end test_maps
|
||||
fi
|
||||
}
|
||||
|
||||
test_verifier() {
|
||||
if [[ "${KERNEL}" == 'latest' ]]; then
|
||||
foldable start test_verifier "Testing test_verifier"
|
||||
./test_verifier && true
|
||||
echo "test_verifier:$?" >> "${STATUS_FILE}"
|
||||
foldable end test_verifier
|
||||
fi
|
||||
}
|
||||
|
||||
foldable end vm_init
|
||||
|
||||
foldable start kernel_config "Kconfig"
|
||||
|
||||
zcat /proc/config.gz
|
||||
|
||||
foldable end kernel_config
|
||||
|
||||
|
||||
configs_path=/${PROJECT_NAME}/selftests/bpf
|
||||
local_configs_path=${PROJECT_NAME}/vmtest/configs
|
||||
DENYLIST=$(read_lists \
|
||||
"$configs_path/DENYLIST" \
|
||||
"$configs_path/DENYLIST.${ARCH}" \
|
||||
"$local_configs_path/DENYLIST-${KERNEL}" \
|
||||
"$local_configs_path/DENYLIST-${KERNEL}.${ARCH}" \
|
||||
)
|
||||
ALLOWLIST=$(read_lists \
|
||||
"$configs_path/ALLOWLIST" \
|
||||
"$configs_path/ALLOWLIST.${ARCH}" \
|
||||
"$local_configs_path/ALLOWLIST-${KERNEL}" \
|
||||
"$local_configs_path/ALLOWLIST-${KERNEL}.${ARCH}" \
|
||||
)
|
||||
|
||||
echo "DENYLIST: ${DENYLIST}"
|
||||
echo "ALLOWLIST: ${ALLOWLIST}"
|
||||
|
||||
cd ${PROJECT_NAME}/selftests/bpf
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
test_progs
|
||||
test_progs_no_alu32
|
||||
# test_maps
|
||||
test_verifier
|
||||
else
|
||||
for test_name in "$@"; do
|
||||
"${test_name}"
|
||||
done
|
||||
fi
|
||||
2
third_party/libbpf/docs/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
sphinx/build
|
||||
sphinx/doxygen/build
|
||||
93
third_party/libbpf/docs/api.rst
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
|
||||
.. _api:
|
||||
|
||||
.. toctree:: Table of Contents
|
||||
|
||||
|
||||
LIBBPF API
|
||||
==========
|
||||
|
||||
Error Handling
|
||||
--------------
|
||||
|
||||
When libbpf is used in "libbpf 1.0 mode", API functions can return errors in one of two ways.
|
||||
|
||||
You can set "libbpf 1.0" mode with the following line:
|
||||
|
||||
.. code-block::
|
||||
|
||||
libbpf_set_strict_mode(LIBBPF_STRICT_DIRECT_ERRS | LIBBPF_STRICT_CLEAN_PTRS);
|
||||
|
||||
If the function returns an error code directly, it uses 0 to indicate success
|
||||
and a negative error code to indicate what caused the error. In this case the
|
||||
error code should be checked directly from the return, you do not need to check
|
||||
errno.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block::
|
||||
|
||||
err = some_libbpf_api_with_error_return(...);
|
||||
if (err < 0) {
|
||||
/* Handle error accordingly */
|
||||
}
|
||||
|
||||
If the function returns a pointer, it will return NULL to indicate there was
|
||||
an error. In this case errno should be checked for the error code.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block::
|
||||
|
||||
ptr = some_libbpf_api_returning_ptr();
|
||||
if (!ptr) {
|
||||
/* note no minus sign for EINVAL and E2BIG below */
|
||||
if (errno == EINVAL) {
|
||||
/* handle EINVAL error */
|
||||
} else if (errno == E2BIG) {
|
||||
/* handle E2BIG error */
|
||||
}
|
||||
}
|
||||
|
||||
libbpf.h
|
||||
--------
|
||||
.. doxygenfile:: libbpf.h
|
||||
:project: libbpf
|
||||
:sections: func define public-type enum
|
||||
|
||||
bpf.h
|
||||
-----
|
||||
.. doxygenfile:: bpf.h
|
||||
:project: libbpf
|
||||
:sections: func define public-type enum
|
||||
|
||||
btf.h
|
||||
-----
|
||||
.. doxygenfile:: btf.h
|
||||
:project: libbpf
|
||||
:sections: func define public-type enum
|
||||
|
||||
xsk.h
|
||||
-----
|
||||
.. doxygenfile:: xsk.h
|
||||
:project: libbpf
|
||||
:sections: func define public-type enum
|
||||
|
||||
bpf_tracing.h
|
||||
-------------
|
||||
.. doxygenfile:: bpf_tracing.h
|
||||
:project: libbpf
|
||||
:sections: func define public-type enum
|
||||
|
||||
bpf_core_read.h
|
||||
---------------
|
||||
.. doxygenfile:: bpf_core_read.h
|
||||
:project: libbpf
|
||||
:sections: func define public-type enum
|
||||
|
||||
bpf_endian.h
|
||||
------------
|
||||
.. doxygenfile:: bpf_endian.h
|
||||
:project: libbpf
|
||||
:sections: func define public-type enum
|
||||
40
third_party/libbpf/docs/conf.py
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
project = "libbpf"
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.doctest',
|
||||
'sphinx.ext.mathjax',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx.ext.imgmath',
|
||||
'sphinx.ext.todo',
|
||||
'breathe',
|
||||
]
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = []
|
||||
|
||||
read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
|
||||
if read_the_docs_build:
|
||||
subprocess.call('cd sphinx ; make clean', shell=True)
|
||||
subprocess.call('cd sphinx/doxygen ; doxygen', shell=True)
|
||||
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
breathe_projects = { "libbpf": "./sphinx/doxygen/build/xml/" }
|
||||
breathe_default_project = "libbpf"
|
||||
breathe_show_define_initializer = True
|
||||
breathe_show_enumvalue_initializer = True
|
||||
33
third_party/libbpf/docs/index.rst
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
|
||||
.. _libbpf:
|
||||
|
||||
======
|
||||
libbpf
|
||||
======
|
||||
|
||||
If you are looking to develop BPF applications using the libbpf library, this
|
||||
directory contains important documentation that you should read.
|
||||
|
||||
To get started, it is recommended to begin with the :doc:`libbpf Overview
|
||||
<libbpf_overview>` document, which provides a high-level understanding of the
|
||||
libbpf APIs and their usage. This will give you a solid foundation to start
|
||||
exploring and utilizing the various features of libbpf to develop your BPF
|
||||
applications.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
libbpf_overview
|
||||
API Documentation <https://libbpf.readthedocs.io/en/latest/api.html>
|
||||
program_types
|
||||
libbpf_naming_convention
|
||||
libbpf_build
|
||||
|
||||
|
||||
All general BPF questions, including kernel functionality, libbpf APIs and their
|
||||
application, should be sent to bpf@vger.kernel.org mailing list. You can
|
||||
`subscribe <http://vger.kernel.org/vger-lists.html#bpf>`_ to the mailing list
|
||||
search its `archive <https://lore.kernel.org/bpf/>`_. Please search the archive
|
||||
before asking new questions. It may be that this was already addressed or
|
||||
answered before.
|
||||
37
third_party/libbpf/docs/libbpf_build.rst
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
|
||||
Building libbpf
|
||||
===============
|
||||
|
||||
libelf and zlib are internal dependencies of libbpf and thus are required to link
|
||||
against and must be installed on the system for applications to work.
|
||||
pkg-config is used by default to find libelf, and the program called
|
||||
can be overridden with PKG_CONFIG.
|
||||
|
||||
If using pkg-config at build time is not desired, it can be disabled by
|
||||
setting NO_PKG_CONFIG=1 when calling make.
|
||||
|
||||
To build both static libbpf.a and shared libbpf.so:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ cd src
|
||||
$ make
|
||||
|
||||
To build only static libbpf.a library in directory build/ and install them
|
||||
together with libbpf headers in a staging directory root/:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ cd src
|
||||
$ mkdir build root
|
||||
$ BUILD_STATIC_ONLY=y OBJDIR=build DESTDIR=root make install
|
||||
|
||||
To build both static libbpf.a and shared libbpf.so against a custom libelf
|
||||
dependency installed in /build/root/ and install them together with libbpf
|
||||
headers in a build directory /build/root/:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ cd src
|
||||
$ PKG_CONFIG_PATH=/build/root/lib64/pkgconfig DESTDIR=/build/root make
|
||||
193
third_party/libbpf/docs/libbpf_naming_convention.rst
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
|
||||
API naming convention
|
||||
=====================
|
||||
|
||||
libbpf API provides access to a few logically separated groups of
|
||||
functions and types. Every group has its own naming convention
|
||||
described here. It's recommended to follow these conventions whenever a
|
||||
new function or type is added to keep libbpf API clean and consistent.
|
||||
|
||||
All types and functions provided by libbpf API should have one of the
|
||||
following prefixes: ``bpf_``, ``btf_``, ``libbpf_``, ``btf_dump_``,
|
||||
``ring_buffer_``, ``perf_buffer_``.
|
||||
|
||||
System call wrappers
|
||||
--------------------
|
||||
|
||||
System call wrappers are simple wrappers for commands supported by
|
||||
sys_bpf system call. These wrappers should go to ``bpf.h`` header file
|
||||
and map one to one to corresponding commands.
|
||||
|
||||
For example ``bpf_map_lookup_elem`` wraps ``BPF_MAP_LOOKUP_ELEM``
|
||||
command of sys_bpf, ``bpf_prog_attach`` wraps ``BPF_PROG_ATTACH``, etc.
|
||||
|
||||
Objects
|
||||
-------
|
||||
|
||||
Another class of types and functions provided by libbpf API is "objects"
|
||||
and functions to work with them. Objects are high-level abstractions
|
||||
such as BPF program or BPF map. They're represented by corresponding
|
||||
structures such as ``struct bpf_object``, ``struct bpf_program``,
|
||||
``struct bpf_map``, etc.
|
||||
|
||||
Structures are forward declared and access to their fields should be
|
||||
provided via corresponding getters and setters rather than directly.
|
||||
|
||||
These objects are associated with corresponding parts of ELF object that
|
||||
contains compiled BPF programs.
|
||||
|
||||
For example ``struct bpf_object`` represents ELF object itself created
|
||||
from an ELF file or from a buffer, ``struct bpf_program`` represents a
|
||||
program in ELF object and ``struct bpf_map`` is a map.
|
||||
|
||||
Functions that work with an object have names built from object name,
|
||||
double underscore and part that describes function purpose.
|
||||
|
||||
For example ``bpf_object__open`` consists of the name of corresponding
|
||||
object, ``bpf_object``, double underscore and ``open`` that defines the
|
||||
purpose of the function to open ELF file and create ``bpf_object`` from
|
||||
it.
|
||||
|
||||
All objects and corresponding functions other than BTF related should go
|
||||
to ``libbpf.h``. BTF types and functions should go to ``btf.h``.
|
||||
|
||||
Auxiliary functions
|
||||
-------------------
|
||||
|
||||
Auxiliary functions and types that don't fit well in any of categories
|
||||
described above should have ``libbpf_`` prefix, e.g.
|
||||
``libbpf_get_error`` or ``libbpf_prog_type_by_name``.
|
||||
|
||||
ABI
|
||||
---
|
||||
|
||||
libbpf can be both linked statically or used as DSO. To avoid possible
|
||||
conflicts with other libraries an application is linked with, all
|
||||
non-static libbpf symbols should have one of the prefixes mentioned in
|
||||
API documentation above. See API naming convention to choose the right
|
||||
name for a new symbol.
|
||||
|
||||
Symbol visibility
|
||||
-----------------
|
||||
|
||||
libbpf follow the model when all global symbols have visibility "hidden"
|
||||
by default and to make a symbol visible it has to be explicitly
|
||||
attributed with ``LIBBPF_API`` macro. For example:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id);
|
||||
|
||||
This prevents from accidentally exporting a symbol, that is not supposed
|
||||
to be a part of ABI what, in turn, improves both libbpf developer- and
|
||||
user-experiences.
|
||||
|
||||
ABI versioning
|
||||
--------------
|
||||
|
||||
To make future ABI extensions possible libbpf ABI is versioned.
|
||||
Versioning is implemented by ``libbpf.map`` version script that is
|
||||
passed to linker.
|
||||
|
||||
Version name is ``LIBBPF_`` prefix + three-component numeric version,
|
||||
starting from ``0.0.1``.
|
||||
|
||||
Every time ABI is being changed, e.g. because a new symbol is added or
|
||||
semantic of existing symbol is changed, ABI version should be bumped.
|
||||
This bump in ABI version is at most once per kernel development cycle.
|
||||
|
||||
For example, if current state of ``libbpf.map`` is:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
LIBBPF_0.0.1 {
|
||||
global:
|
||||
bpf_func_a;
|
||||
bpf_func_b;
|
||||
local:
|
||||
\*;
|
||||
};
|
||||
|
||||
, and a new symbol ``bpf_func_c`` is being introduced, then
|
||||
``libbpf.map`` should be changed like this:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
LIBBPF_0.0.1 {
|
||||
global:
|
||||
bpf_func_a;
|
||||
bpf_func_b;
|
||||
local:
|
||||
\*;
|
||||
};
|
||||
LIBBPF_0.0.2 {
|
||||
global:
|
||||
bpf_func_c;
|
||||
} LIBBPF_0.0.1;
|
||||
|
||||
, where new version ``LIBBPF_0.0.2`` depends on the previous
|
||||
``LIBBPF_0.0.1``.
|
||||
|
||||
Format of version script and ways to handle ABI changes, including
|
||||
incompatible ones, described in details in [1].
|
||||
|
||||
Stand-alone build
|
||||
-------------------
|
||||
|
||||
Under https://github.com/libbpf/libbpf there is a (semi-)automated
|
||||
mirror of the mainline's version of libbpf for a stand-alone build.
|
||||
|
||||
However, all changes to libbpf's code base must be upstreamed through
|
||||
the mainline kernel tree.
|
||||
|
||||
|
||||
API documentation convention
|
||||
============================
|
||||
|
||||
The libbpf API is documented via comments above definitions in
|
||||
header files. These comments can be rendered by doxygen and sphinx
|
||||
for well organized html output. This section describes the
|
||||
convention in which these comments should be formatted.
|
||||
|
||||
Here is an example from btf.h:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/**
|
||||
* @brief **btf__new()** creates a new instance of a BTF object from the raw
|
||||
* bytes of an ELF's BTF section
|
||||
* @param data raw bytes
|
||||
* @param size number of bytes passed in `data`
|
||||
* @return new BTF object instance which has to be eventually freed with
|
||||
* **btf__free()**
|
||||
*
|
||||
* On error, error-code-encoded-as-pointer is returned, not a NULL. To extract
|
||||
* error code from such a pointer `libbpf_get_error()` should be used. If
|
||||
* `libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS)` is enabled, NULL is
|
||||
* returned on error instead. In both cases thread-local `errno` variable is
|
||||
* always set to error code as well.
|
||||
*/
|
||||
|
||||
The comment must start with a block comment of the form '/\*\*'.
|
||||
|
||||
The documentation always starts with a @brief directive. This line is a short
|
||||
description about this API. It starts with the name of the API, denoted in bold
|
||||
like so: **api_name**. Please include an open and close parenthesis if this is a
|
||||
function. Follow with the short description of the API. A longer form description
|
||||
can be added below the last directive, at the bottom of the comment.
|
||||
|
||||
Parameters are denoted with the @param directive, there should be one for each
|
||||
parameter. If this is a function with a non-void return, use the @return directive
|
||||
to document it.
|
||||
|
||||
License
|
||||
-------------------
|
||||
|
||||
libbpf is dual-licensed under LGPL 2.1 and BSD 2-Clause.
|
||||
|
||||
Links
|
||||
-------------------
|
||||
|
||||
[1] https://www.akkadia.org/drepper/dsohowto.pdf
|
||||
(Chapter 3. Maintaining APIs and ABIs).
|
||||
228
third_party/libbpf/docs/libbpf_overview.rst
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
===============
|
||||
libbpf Overview
|
||||
===============
|
||||
|
||||
libbpf is a C-based library containing a BPF loader that takes compiled BPF
|
||||
object files and prepares and loads them into the Linux kernel. libbpf takes the
|
||||
heavy lifting of loading, verifying, and attaching BPF programs to various
|
||||
kernel hooks, allowing BPF application developers to focus only on BPF program
|
||||
correctness and performance.
|
||||
|
||||
The following are the high-level features supported by libbpf:
|
||||
|
||||
* Provides high-level and low-level APIs for user space programs to interact
|
||||
with BPF programs. The low-level APIs wrap all the bpf system call
|
||||
functionality, which is useful when users need more fine-grained control
|
||||
over the interactions between user space and BPF programs.
|
||||
* Provides overall support for the BPF object skeleton generated by bpftool.
|
||||
The skeleton file simplifies the process for the user space programs to access
|
||||
global variables and work with BPF programs.
|
||||
* Provides BPF-side APIS, including BPF helper definitions, BPF maps support,
|
||||
and tracing helpers, allowing developers to simplify BPF code writing.
|
||||
* Supports BPF CO-RE mechanism, enabling BPF developers to write portable
|
||||
BPF programs that can be compiled once and run across different kernel
|
||||
versions.
|
||||
|
||||
This document will delve into the above concepts in detail, providing a deeper
|
||||
understanding of the capabilities and advantages of libbpf and how it can help
|
||||
you develop BPF applications efficiently.
|
||||
|
||||
BPF App Lifecycle and libbpf APIs
|
||||
==================================
|
||||
|
||||
A BPF application consists of one or more BPF programs (either cooperating or
|
||||
completely independent), BPF maps, and global variables. The global
|
||||
variables are shared between all BPF programs, which allows them to cooperate on
|
||||
a common set of data. libbpf provides APIs that user space programs can use to
|
||||
manipulate the BPF programs by triggering different phases of a BPF application
|
||||
lifecycle.
|
||||
|
||||
The following section provides a brief overview of each phase in the BPF life
|
||||
cycle:
|
||||
|
||||
* **Open phase**: In this phase, libbpf parses the BPF
|
||||
object file and discovers BPF maps, BPF programs, and global variables. After
|
||||
a BPF app is opened, user space apps can make additional adjustments
|
||||
(setting BPF program types, if necessary; pre-setting initial values for
|
||||
global variables, etc.) before all the entities are created and loaded.
|
||||
|
||||
* **Load phase**: In the load phase, libbpf creates BPF
|
||||
maps, resolves various relocations, and verifies and loads BPF programs into
|
||||
the kernel. At this point, libbpf validates all the parts of a BPF application
|
||||
and loads the BPF program into the kernel, but no BPF program has yet been
|
||||
executed. After the load phase, it’s possible to set up the initial BPF map
|
||||
state without racing with the BPF program code execution.
|
||||
|
||||
* **Attachment phase**: In this phase, libbpf
|
||||
attaches BPF programs to various BPF hook points (e.g., tracepoints, kprobes,
|
||||
cgroup hooks, network packet processing pipeline, etc.). During this
|
||||
phase, BPF programs perform useful work such as processing
|
||||
packets, or updating BPF maps and global variables that can be read from user
|
||||
space.
|
||||
|
||||
* **Tear down phase**: In the tear down phase,
|
||||
libbpf detaches BPF programs and unloads them from the kernel. BPF maps are
|
||||
destroyed, and all the resources used by the BPF app are freed.
|
||||
|
||||
BPF Object Skeleton File
|
||||
========================
|
||||
|
||||
BPF skeleton is an alternative interface to libbpf APIs for working with BPF
|
||||
objects. Skeleton code abstract away generic libbpf APIs to significantly
|
||||
simplify code for manipulating BPF programs from user space. Skeleton code
|
||||
includes a bytecode representation of the BPF object file, simplifying the
|
||||
process of distributing your BPF code. With BPF bytecode embedded, there are no
|
||||
extra files to deploy along with your application binary.
|
||||
|
||||
You can generate the skeleton header file ``(.skel.h)`` for a specific object
|
||||
file by passing the BPF object to the bpftool. The generated BPF skeleton
|
||||
provides the following custom functions that correspond to the BPF lifecycle,
|
||||
each of them prefixed with the specific object name:
|
||||
|
||||
* ``<name>__open()`` – creates and opens BPF application (``<name>`` stands for
|
||||
the specific bpf object name)
|
||||
* ``<name>__load()`` – instantiates, loads,and verifies BPF application parts
|
||||
* ``<name>__attach()`` – attaches all auto-attachable BPF programs (it’s
|
||||
optional, you can have more control by using libbpf APIs directly)
|
||||
* ``<name>__destroy()`` – detaches all BPF programs and
|
||||
frees up all used resources
|
||||
|
||||
Using the skeleton code is the recommended way to work with bpf programs. Keep
|
||||
in mind, BPF skeleton provides access to the underlying BPF object, so whatever
|
||||
was possible to do with generic libbpf APIs is still possible even when the BPF
|
||||
skeleton is used. It's an additive convenience feature, with no syscalls, and no
|
||||
cumbersome code.
|
||||
|
||||
Other Advantages of Using Skeleton File
|
||||
---------------------------------------
|
||||
|
||||
* BPF skeleton provides an interface for user space programs to work with BPF
|
||||
global variables. The skeleton code memory maps global variables as a struct
|
||||
into user space. The struct interface allows user space programs to initialize
|
||||
BPF programs before the BPF load phase and fetch and update data from user
|
||||
space afterward.
|
||||
|
||||
* The ``skel.h`` file reflects the object file structure by listing out the
|
||||
available maps, programs, etc. BPF skeleton provides direct access to all the
|
||||
BPF maps and BPF programs as struct fields. This eliminates the need for
|
||||
string-based lookups with ``bpf_object_find_map_by_name()`` and
|
||||
``bpf_object_find_program_by_name()`` APIs, reducing errors due to BPF source
|
||||
code and user-space code getting out of sync.
|
||||
|
||||
* The embedded bytecode representation of the object file ensures that the
|
||||
skeleton and the BPF object file are always in sync.
|
||||
|
||||
BPF Helpers
|
||||
===========
|
||||
|
||||
libbpf provides BPF-side APIs that BPF programs can use to interact with the
|
||||
system. The BPF helpers definition allows developers to use them in BPF code as
|
||||
any other plain C function. For example, there are helper functions to print
|
||||
debugging messages, get the time since the system was booted, interact with BPF
|
||||
maps, manipulate network packets, etc.
|
||||
|
||||
For a complete description of what the helpers do, the arguments they take, and
|
||||
the return value, see the `bpf-helpers
|
||||
<https://man7.org/linux/man-pages/man7/bpf-helpers.7.html>`_ man page.
|
||||
|
||||
BPF CO-RE (Compile Once – Run Everywhere)
|
||||
=========================================
|
||||
|
||||
BPF programs work in the kernel space and have access to kernel memory and data
|
||||
structures. One limitation that BPF applications come across is the lack of
|
||||
portability across different kernel versions and configurations. `BCC
|
||||
<https://github.com/iovisor/bcc/>`_ is one of the solutions for BPF
|
||||
portability. However, it comes with runtime overhead and a large binary size
|
||||
from embedding the compiler with the application.
|
||||
|
||||
libbpf steps up the BPF program portability by supporting the BPF CO-RE concept.
|
||||
BPF CO-RE brings together BTF type information, libbpf, and the compiler to
|
||||
produce a single executable binary that you can run on multiple kernel versions
|
||||
and configurations.
|
||||
|
||||
To make BPF programs portable libbpf relies on the BTF type information of the
|
||||
running kernel. Kernel also exposes this self-describing authoritative BTF
|
||||
information through ``sysfs`` at ``/sys/kernel/btf/vmlinux``.
|
||||
|
||||
You can generate the BTF information for the running kernel with the following
|
||||
command:
|
||||
|
||||
::
|
||||
|
||||
$ bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
|
||||
|
||||
The command generates a ``vmlinux.h`` header file with all kernel types
|
||||
(:doc:`BTF types <../btf>`) that the running kernel uses. Including
|
||||
``vmlinux.h`` in your BPF program eliminates dependency on system-wide kernel
|
||||
headers.
|
||||
|
||||
libbpf enables portability of BPF programs by looking at the BPF program’s
|
||||
recorded BTF type and relocation information and matching them to BTF
|
||||
information (vmlinux) provided by the running kernel. libbpf then resolves and
|
||||
matches all the types and fields, and updates necessary offsets and other
|
||||
relocatable data to ensure that BPF program’s logic functions correctly for a
|
||||
specific kernel on the host. BPF CO-RE concept thus eliminates overhead
|
||||
associated with BPF development and allows developers to write portable BPF
|
||||
applications without modifications and runtime source code compilation on the
|
||||
target machine.
|
||||
|
||||
The following code snippet shows how to read the parent field of a kernel
|
||||
``task_struct`` using BPF CO-RE and libbf. The basic helper to read a field in a
|
||||
CO-RE relocatable manner is ``bpf_core_read(dst, sz, src)``, which will read
|
||||
``sz`` bytes from the field referenced by ``src`` into the memory pointed to by
|
||||
``dst``.
|
||||
|
||||
.. code-block:: C
|
||||
:emphasize-lines: 6
|
||||
|
||||
//...
|
||||
struct task_struct *task = (void *)bpf_get_current_task();
|
||||
struct task_struct *parent_task;
|
||||
int err;
|
||||
|
||||
err = bpf_core_read(&parent_task, sizeof(void *), &task->parent);
|
||||
if (err) {
|
||||
/* handle error */
|
||||
}
|
||||
|
||||
/* parent_task contains the value of task->parent pointer */
|
||||
|
||||
In the code snippet, we first get a pointer to the current ``task_struct`` using
|
||||
``bpf_get_current_task()``. We then use ``bpf_core_read()`` to read the parent
|
||||
field of task struct into the ``parent_task`` variable. ``bpf_core_read()`` is
|
||||
just like ``bpf_probe_read_kernel()`` BPF helper, except it records information
|
||||
about the field that should be relocated on the target kernel. i.e, if the
|
||||
``parent`` field gets shifted to a different offset within
|
||||
``struct task_struct`` due to some new field added in front of it, libbpf will
|
||||
automatically adjust the actual offset to the proper value.
|
||||
|
||||
Getting Started with libbpf
|
||||
===========================
|
||||
|
||||
Check out the `libbpf-bootstrap <https://github.com/libbpf/libbpf-bootstrap>`_
|
||||
repository with simple examples of using libbpf to build various BPF
|
||||
applications.
|
||||
|
||||
See also `libbpf API documentation
|
||||
<https://libbpf.readthedocs.io/en/latest/api.html>`_.
|
||||
|
||||
libbpf and Rust
|
||||
===============
|
||||
|
||||
If you are building BPF applications in Rust, it is recommended to use the
|
||||
`Libbpf-rs <https://github.com/libbpf/libbpf-rs>`_ library instead of bindgen
|
||||
bindings directly to libbpf. Libbpf-rs wraps libbpf functionality in
|
||||
Rust-idiomatic interfaces and provides libbpf-cargo plugin to handle BPF code
|
||||
compilation and skeleton generation. Using Libbpf-rs will make building user
|
||||
space part of the BPF application easier. Note that the BPF program themselves
|
||||
must still be written in plain C.
|
||||
|
||||
Additional Documentation
|
||||
========================
|
||||
|
||||
* `Program types and ELF Sections <https://libbpf.readthedocs.io/en/latest/program_types.html>`_
|
||||
* `API naming convention <https://libbpf.readthedocs.io/en/latest/libbpf_naming_convention.html>`_
|
||||
* `Building libbpf <https://libbpf.readthedocs.io/en/latest/libbpf_build.html>`_
|
||||
* `API documentation Convention <https://libbpf.readthedocs.io/en/latest/libbpf_naming_convention.html#api-documentation-convention>`_
|
||||
203
third_party/libbpf/docs/program_types.rst
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
|
||||
.. _program_types_and_elf:
|
||||
|
||||
Program Types and ELF Sections
|
||||
==============================
|
||||
|
||||
The table below lists the program types, their attach types where relevant and the ELF section
|
||||
names supported by libbpf for them. The ELF section names follow these rules:
|
||||
|
||||
- ``type`` is an exact match, e.g. ``SEC("socket")``
|
||||
- ``type+`` means it can be either exact ``SEC("type")`` or well-formed ``SEC("type/extras")``
|
||||
with a '``/``' separator between ``type`` and ``extras``.
|
||||
|
||||
When ``extras`` are specified, they provide details of how to auto-attach the BPF program. The
|
||||
format of ``extras`` depends on the program type, e.g. ``SEC("tracepoint/<category>/<name>")``
|
||||
for tracepoints or ``SEC("usdt/<path>:<provider>:<name>")`` for USDT probes. The extras are
|
||||
described in more detail in the footnotes.
|
||||
|
||||
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| Program Type | Attach Type | ELF Section Name | Sleepable |
|
||||
+===========================================+========================================+==================================+===========+
|
||||
| ``BPF_PROG_TYPE_CGROUP_DEVICE`` | ``BPF_CGROUP_DEVICE`` | ``cgroup/dev`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_CGROUP_SKB`` | | ``cgroup/skb`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_INET_EGRESS`` | ``cgroup_skb/egress`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_INET_INGRESS`` | ``cgroup_skb/ingress`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_CGROUP_SOCKOPT`` | ``BPF_CGROUP_GETSOCKOPT`` | ``cgroup/getsockopt`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_SETSOCKOPT`` | ``cgroup/setsockopt`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_CGROUP_SOCK_ADDR`` | ``BPF_CGROUP_INET4_BIND`` | ``cgroup/bind4`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_INET4_CONNECT`` | ``cgroup/connect4`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_INET4_GETPEERNAME`` | ``cgroup/getpeername4`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_INET4_GETSOCKNAME`` | ``cgroup/getsockname4`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_INET6_BIND`` | ``cgroup/bind6`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_INET6_CONNECT`` | ``cgroup/connect6`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_INET6_GETPEERNAME`` | ``cgroup/getpeername6`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_INET6_GETSOCKNAME`` | ``cgroup/getsockname6`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UDP4_RECVMSG`` | ``cgroup/recvmsg4`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UDP4_SENDMSG`` | ``cgroup/sendmsg4`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UDP6_RECVMSG`` | ``cgroup/recvmsg6`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UDP6_SENDMSG`` | ``cgroup/sendmsg6`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_CGROUP_SOCK`` | ``BPF_CGROUP_INET4_POST_BIND`` | ``cgroup/post_bind4`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_INET6_POST_BIND`` | ``cgroup/post_bind6`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_INET_SOCK_CREATE`` | ``cgroup/sock_create`` | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``cgroup/sock`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_INET_SOCK_RELEASE`` | ``cgroup/sock_release`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_CGROUP_SYSCTL`` | ``BPF_CGROUP_SYSCTL`` | ``cgroup/sysctl`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_EXT`` | | ``freplace+`` [#fentry]_ | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_FLOW_DISSECTOR`` | ``BPF_FLOW_DISSECTOR`` | ``flow_dissector`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_KPROBE`` | | ``kprobe+`` [#kprobe]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``kretprobe+`` [#kprobe]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``ksyscall+`` [#ksyscall]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``kretsyscall+`` [#ksyscall]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``uprobe+`` [#uprobe]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``uprobe.s+`` [#uprobe]_ | Yes |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``uretprobe+`` [#uprobe]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``uretprobe.s+`` [#uprobe]_ | Yes |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``usdt+`` [#usdt]_ | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_TRACE_KPROBE_MULTI`` | ``kprobe.multi+`` [#kpmulti]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``kretprobe.multi+`` [#kpmulti]_ | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_LIRC_MODE2`` | ``BPF_LIRC_MODE2`` | ``lirc_mode2`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_LSM`` | ``BPF_LSM_CGROUP`` | ``lsm_cgroup+`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_LSM_MAC`` | ``lsm+`` [#lsm]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``lsm.s+`` [#lsm]_ | Yes |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_LWT_IN`` | | ``lwt_in`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_LWT_OUT`` | | ``lwt_out`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_LWT_SEG6LOCAL`` | | ``lwt_seg6local`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_LWT_XMIT`` | | ``lwt_xmit`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_PERF_EVENT`` | | ``perf_event`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE`` | | ``raw_tp.w+`` [#rawtp]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``raw_tracepoint.w+`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_RAW_TRACEPOINT`` | | ``raw_tp+`` [#rawtp]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``raw_tracepoint+`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_SCHED_ACT`` | | ``action`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_SCHED_CLS`` | | ``classifier`` | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``tc`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_SK_LOOKUP`` | ``BPF_SK_LOOKUP`` | ``sk_lookup`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_SK_MSG`` | ``BPF_SK_MSG_VERDICT`` | ``sk_msg`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_SK_REUSEPORT`` | ``BPF_SK_REUSEPORT_SELECT_OR_MIGRATE`` | ``sk_reuseport/migrate`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_SK_REUSEPORT_SELECT`` | ``sk_reuseport`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_SK_SKB`` | | ``sk_skb`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_SK_SKB_STREAM_PARSER`` | ``sk_skb/stream_parser`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_SK_SKB_STREAM_VERDICT`` | ``sk_skb/stream_verdict`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_SOCKET_FILTER`` | | ``socket`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_SOCK_OPS`` | ``BPF_CGROUP_SOCK_OPS`` | ``sockops`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_STRUCT_OPS`` | | ``struct_ops+`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_SYSCALL`` | | ``syscall`` | Yes |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_TRACEPOINT`` | | ``tp+`` [#tp]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``tracepoint+`` [#tp]_ | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_TRACING`` | ``BPF_MODIFY_RETURN`` | ``fmod_ret+`` [#fentry]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``fmod_ret.s+`` [#fentry]_ | Yes |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_TRACE_FENTRY`` | ``fentry+`` [#fentry]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``fentry.s+`` [#fentry]_ | Yes |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_TRACE_FEXIT`` | ``fexit+`` [#fentry]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``fexit.s+`` [#fentry]_ | Yes |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_TRACE_ITER`` | ``iter+`` [#iter]_ | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``iter.s+`` [#iter]_ | Yes |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_TRACE_RAW_TP`` | ``tp_btf+`` [#fentry]_ | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_XDP`` | ``BPF_XDP_CPUMAP`` | ``xdp.frags/cpumap`` | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``xdp/cpumap`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_XDP_DEVMAP`` | ``xdp.frags/devmap`` | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``xdp/devmap`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_XDP`` | ``xdp.frags`` | |
|
||||
+ + +----------------------------------+-----------+
|
||||
| | | ``xdp`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
|
||||
|
||||
.. rubric:: Footnotes
|
||||
|
||||
.. [#fentry] The ``fentry`` attach format is ``fentry[.s]/<function>``.
|
||||
.. [#kprobe] The ``kprobe`` attach format is ``kprobe/<function>[+<offset>]``. Valid
|
||||
characters for ``function`` are ``a-zA-Z0-9_.`` and ``offset`` must be a valid
|
||||
non-negative integer.
|
||||
.. [#ksyscall] The ``ksyscall`` attach format is ``ksyscall/<syscall>``.
|
||||
.. [#uprobe] The ``uprobe`` attach format is ``uprobe[.s]/<path>:<function>[+<offset>]``.
|
||||
.. [#usdt] The ``usdt`` attach format is ``usdt/<path>:<provider>:<name>``.
|
||||
.. [#kpmulti] The ``kprobe.multi`` attach format is ``kprobe.multi/<pattern>`` where ``pattern``
|
||||
supports ``*`` and ``?`` wildcards. Valid characters for pattern are
|
||||
``a-zA-Z0-9_.*?``.
|
||||
.. [#lsm] The ``lsm`` attachment format is ``lsm[.s]/<hook>``.
|
||||
.. [#rawtp] The ``raw_tp`` attach format is ``raw_tracepoint[.w]/<tracepoint>``.
|
||||
.. [#tp] The ``tracepoint`` attach format is ``tracepoint/<category>/<name>``.
|
||||
.. [#iter] The ``iter`` attach format is ``iter[.s]/<struct-name>``.
|
||||
9
third_party/libbpf/docs/sphinx/Makefile
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = ../src
|
||||
BUILDDIR = build
|
||||
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)"
|
||||
|
||||
%:
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)"
|
||||
277
third_party/libbpf/docs/sphinx/doxygen/Doxyfile
vendored
Normal file
@@ -0,0 +1,277 @@
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "libbpf"
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY = ./build
|
||||
CREATE_SUBDIRS = NO
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
OUTPUT_TEXT_DIRECTION = None
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
JAVADOC_BANNER = NO
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
PYTHON_DOCSTRING = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
ALIASES =
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
OPTIMIZE_OUTPUT_SLICE = NO
|
||||
EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
TOC_INCLUDE_HEADINGS = 5
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
GROUP_NESTED_COMPOUNDS = NO
|
||||
SUBGROUPING = YES
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
NUM_PROC_THREADS = 1
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_PRIV_VIRTUAL = NO
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
RESOLVE_UNNAMED_PARAMS = YES
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
HIDE_COMPOUND_REFERENCE= NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_MEMBERS_CTORS_1ST = NO
|
||||
SORT_GROUP_NAMES = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE =
|
||||
CITE_BIB_FILES =
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_AS_ERROR = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
INPUT = ../../../src
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.c \
|
||||
*.h
|
||||
RECURSIVE = NO
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXCLUDE_SYMBOLS = ___*
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE = YES
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = NO
|
||||
REFERENCES_RELATION = NO
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
SOURCE_TOOLTIPS = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
ALPHABETICAL_INDEX = YES
|
||||
IGNORE_PREFIX =
|
||||
GENERATE_HTML = NO
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = NO
|
||||
HTML_DYNAMIC_MENUS = YES
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
CHM_INDEX_ENCODING =
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
GENERATE_QHP = NO
|
||||
QCH_FILE =
|
||||
QHP_NAMESPACE = org.doxygen.Project
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
QHP_CUST_FILTER_NAME =
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
QHG_LOCATION =
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
HTML_FORMULA_FORMAT = png
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
FORMULA_MACROFILE =
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2
|
||||
MATHJAX_EXTENSIONS =
|
||||
MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = YES
|
||||
SERVER_BASED_SEARCH = NO
|
||||
EXTERNAL_SEARCH = NO
|
||||
SEARCHENGINE_URL =
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME =
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
LATEX_MAKEINDEX_CMD = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
LATEX_FOOTER =
|
||||
LATEX_EXTRA_STYLESHEET =
|
||||
LATEX_EXTRA_FILES =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
LATEX_TIMESTAMP = NO
|
||||
LATEX_EMOJI_DIRECTORY =
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
RTF_SOURCE_CODE = NO
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_SUBDIR =
|
||||
MAN_LINKS = NO
|
||||
GENERATE_XML = YES
|
||||
XML_OUTPUT = xml
|
||||
XML_PROGRAMLISTING = YES
|
||||
XML_NS_MEMB_FILE_SCOPE = NO
|
||||
GENERATE_DOCBOOK = NO
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = NO
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
EXTERNAL_PAGES = YES
|
||||
CLASS_DIAGRAMS = YES
|
||||
DIA_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = NO
|
||||
DOT_NUM_THREADS = 0
|
||||
DOT_FONTNAME = Helvetica
|
||||
DOT_FONTSIZE = 10
|
||||
DOT_FONTPATH =
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
DOT_UML_DETAILS = NO
|
||||
DOT_WRAP_THRESHOLD = 17
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
INTERACTIVE_SVG = NO
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
DIAFILE_DIRS =
|
||||
PLANTUML_JAR_PATH =
|
||||
PLANTUML_CFG_FILE =
|
||||
PLANTUML_INCLUDE_PATH =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
1
third_party/libbpf/docs/sphinx/requirements.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
breathe
|
||||
23
third_party/libbpf/fuzz/bpf-object-fuzzer.c
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "libbpf.h"
|
||||
|
||||
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
struct bpf_object *obj = NULL;
|
||||
DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts);
|
||||
int err;
|
||||
|
||||
libbpf_set_print(libbpf_print_fn);
|
||||
|
||||
opts.object_name = "fuzz-object";
|
||||
obj = bpf_object__open_mem(data, size, &opts);
|
||||
err = libbpf_get_error(obj);
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
bpf_object__close(obj);
|
||||
return 0;
|
||||
}
|
||||
BIN
third_party/libbpf/fuzz/bpf-object-fuzzer_seed_corpus.zip
vendored
Normal file
7
third_party/libbpf/include/asm/barrier.h
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
#ifndef __ASM_BARRIER_H
|
||||
#define __ASM_BARRIER_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#endif
|
||||
70
third_party/libbpf/include/linux/compiler.h
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
|
||||
#ifndef __LINUX_COMPILER_H
|
||||
#define __LINUX_COMPILER_H
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
#define READ_ONCE(x) (*(volatile typeof(x) *)&x)
|
||||
#define WRITE_ONCE(x, v) (*(volatile typeof(x) *)&x) = (v)
|
||||
|
||||
#define barrier() asm volatile("" ::: "memory")
|
||||
|
||||
#if defined(__x86_64__)
|
||||
|
||||
# define smp_rmb() barrier()
|
||||
# define smp_wmb() barrier()
|
||||
# define smp_mb() asm volatile("lock; addl $0,-132(%%rsp)" ::: "memory", "cc")
|
||||
|
||||
# define smp_store_release(p, v) \
|
||||
do { \
|
||||
barrier(); \
|
||||
WRITE_ONCE(*p, v); \
|
||||
} while (0)
|
||||
|
||||
# define smp_load_acquire(p) \
|
||||
({ \
|
||||
typeof(*p) ___p = READ_ONCE(*p); \
|
||||
barrier(); \
|
||||
___p; \
|
||||
})
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
# define smp_rmb() asm volatile("dmb ishld" ::: "memory")
|
||||
# define smp_wmb() asm volatile("dmb ishst" ::: "memory")
|
||||
# define smp_mb() asm volatile("dmb ish" ::: "memory")
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef smp_mb
|
||||
# define smp_mb() __sync_synchronize()
|
||||
#endif
|
||||
|
||||
#ifndef smp_rmb
|
||||
# define smp_rmb() smp_mb()
|
||||
#endif
|
||||
|
||||
#ifndef smp_wmb
|
||||
# define smp_wmb() smp_mb()
|
||||
#endif
|
||||
|
||||
#ifndef smp_store_release
|
||||
# define smp_store_release(p, v) \
|
||||
do { \
|
||||
smp_mb(); \
|
||||
WRITE_ONCE(*p, v); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef smp_load_acquire
|
||||
# define smp_load_acquire(p) \
|
||||
({ \
|
||||
typeof(*p) ___p = READ_ONCE(*p); \
|
||||
smp_mb(); \
|
||||
___p; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_COMPILER_H */
|
||||
38
third_party/libbpf/include/linux/err.h
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
|
||||
#ifndef __LINUX_ERR_H
|
||||
#define __LINUX_ERR_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
#define MAX_ERRNO 4095
|
||||
|
||||
#define IS_ERR_VALUE(x) ((x) >= (unsigned long)-MAX_ERRNO)
|
||||
|
||||
static inline void * ERR_PTR(long error_)
|
||||
{
|
||||
return (void *) error_;
|
||||
}
|
||||
|
||||
static inline long PTR_ERR(const void *ptr)
|
||||
{
|
||||
return (long) ptr;
|
||||
}
|
||||
|
||||
static inline bool IS_ERR(const void *ptr)
|
||||
{
|
||||
return IS_ERR_VALUE((unsigned long)ptr);
|
||||
}
|
||||
|
||||
static inline bool IS_ERR_OR_NULL(const void *ptr)
|
||||
{
|
||||
return (!ptr) || IS_ERR_VALUE((unsigned long)ptr);
|
||||
}
|
||||
|
||||
static inline long PTR_ERR_OR_ZERO(const void *ptr)
|
||||
{
|
||||
return IS_ERR(ptr) ? PTR_ERR(ptr) : 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
134
third_party/libbpf/include/linux/filter.h
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
|
||||
#ifndef __LINUX_FILTER_H
|
||||
#define __LINUX_FILTER_H
|
||||
|
||||
#include <linux/bpf.h>
|
||||
|
||||
#define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = CODE, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = OFF, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_ALU32_IMM(OP, DST, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU | BPF_OP(OP) | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_ALU64_IMM(OP, DST, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_MOV64_IMM(DST, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU64 | BPF_MOV | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_EXIT_INSN() \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_JMP | BPF_EXIT, \
|
||||
.dst_reg = 0, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_EMIT_CALL(FUNC) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_JMP | BPF_CALL, \
|
||||
.dst_reg = 0, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = ((FUNC) - BPF_FUNC_unspec) })
|
||||
|
||||
#define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = OFF, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_STX_MEM(SIZE, DST, SRC, OFF) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = OFF, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_ST_MEM(SIZE, DST, OFF, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = OFF, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_MOV64_REG(DST, SRC) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU64 | BPF_MOV | BPF_X, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = 0, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_MOV32_IMM(DST, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU | BPF_MOV | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_LD_IMM64_RAW_FULL(DST, SRC, OFF1, OFF2, IMM1, IMM2) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_LD | BPF_DW | BPF_IMM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = OFF1, \
|
||||
.imm = IMM1 }), \
|
||||
((struct bpf_insn) { \
|
||||
.code = 0, \
|
||||
.dst_reg = 0, \
|
||||
.src_reg = 0, \
|
||||
.off = OFF2, \
|
||||
.imm = IMM2 })
|
||||
|
||||
#define BPF_LD_MAP_FD(DST, MAP_FD) \
|
||||
BPF_LD_IMM64_RAW_FULL(DST, BPF_PSEUDO_MAP_FD, 0, 0, \
|
||||
MAP_FD, 0)
|
||||
|
||||
#define BPF_LD_MAP_VALUE(DST, MAP_FD, VALUE_OFF) \
|
||||
BPF_LD_IMM64_RAW_FULL(DST, BPF_PSEUDO_MAP_VALUE, 0, 0, \
|
||||
MAP_FD, VALUE_OFF)
|
||||
|
||||
#define BPF_JMP_IMM(OP, DST, IMM, OFF) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_JMP | BPF_OP(OP) | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = OFF, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_JMP32_IMM(OP, DST, IMM, OFF) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_JMP32 | BPF_OP(OP) | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = OFF, \
|
||||
.imm = IMM })
|
||||
|
||||
#endif
|
||||
44
third_party/libbpf/include/linux/kernel.h
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
|
||||
#ifndef __LINUX_KERNEL_H
|
||||
#define __LINUX_KERNEL_H
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||
#endif
|
||||
|
||||
#ifndef container_of
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof(((type *)0)->member) * __mptr = (ptr); \
|
||||
(type *)((char *)__mptr - offsetof(type, member)); })
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(x, y) ({ \
|
||||
typeof(x) _max1 = (x); \
|
||||
typeof(y) _max2 = (y); \
|
||||
(void) (&_max1 == &_max2); \
|
||||
_max1 > _max2 ? _max1 : _max2; })
|
||||
#endif
|
||||
|
||||
#ifndef min
|
||||
#define min(x, y) ({ \
|
||||
typeof(x) _min1 = (x); \
|
||||
typeof(y) _min2 = (y); \
|
||||
(void) (&_min1 == &_min2); \
|
||||
_min1 < _min2 ? _min1 : _min2; })
|
||||
#endif
|
||||
|
||||
#ifndef roundup
|
||||
#define roundup(x, y) ( \
|
||||
{ \
|
||||
const typeof(y) __y = y; \
|
||||
(((x) + (__y - 1)) / __y) * __y; \
|
||||
} \
|
||||
)
|
||||
#endif
|
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
|
||||
|
||||
#endif
|
||||
91
third_party/libbpf/include/linux/list.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
|
||||
#ifndef __LINUX_LIST_H
|
||||
#define __LINUX_LIST_H
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
#define POISON_POINTER_DELTA 0
|
||||
#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA)
|
||||
#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA)
|
||||
|
||||
|
||||
static inline void INIT_LIST_HEAD(struct list_head *list)
|
||||
{
|
||||
list->next = list;
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
static inline void __list_add(struct list_head *new,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_del(struct list_head * prev, struct list_head * next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty() on entry does not return true after this, the entry is
|
||||
* in an undefined state.
|
||||
*/
|
||||
static inline void __list_del_entry(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
}
|
||||
|
||||
static inline void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
entry->next = LIST_POISON1;
|
||||
entry->prev = LIST_POISON2;
|
||||
}
|
||||
|
||||
static inline int list_empty(const struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
#define list_entry(ptr, type, member) \
|
||||
container_of(ptr, type, member)
|
||||
#define list_first_entry(ptr, type, member) \
|
||||
list_entry((ptr)->next, type, member)
|
||||
#define list_next_entry(pos, member) \
|
||||
list_entry((pos)->member.next, typeof(*(pos)), member)
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_first_entry(head, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_next_entry(pos, member))
|
||||
|
||||
#endif
|
||||
90
third_party/libbpf/include/linux/overflow.h
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
|
||||
#ifndef __LINUX_OVERFLOW_H
|
||||
#define __LINUX_OVERFLOW_H
|
||||
|
||||
#define is_signed_type(type) (((type)(-1)) < (type)1)
|
||||
#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
|
||||
#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
|
||||
#define type_min(T) ((T)((T)-type_max(T)-(T)1))
|
||||
|
||||
#ifndef unlikely
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define GCC_VERSION (__GNUC__ * 10000 \
|
||||
+ __GNUC_MINOR__ * 100 \
|
||||
+ __GNUC_PATCHLEVEL__)
|
||||
#if GCC_VERSION >= 50100
|
||||
#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
|
||||
|
||||
#define check_mul_overflow(a, b, d) ({ \
|
||||
typeof(a) __a = (a); \
|
||||
typeof(b) __b = (b); \
|
||||
typeof(d) __d = (d); \
|
||||
(void) (&__a == &__b); \
|
||||
(void) (&__a == __d); \
|
||||
__builtin_mul_overflow(__a, __b, __d); \
|
||||
})
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* If one of a or b is a compile-time constant, this avoids a division.
|
||||
*/
|
||||
#define __unsigned_mul_overflow(a, b, d) ({ \
|
||||
typeof(a) __a = (a); \
|
||||
typeof(b) __b = (b); \
|
||||
typeof(d) __d = (d); \
|
||||
(void) (&__a == &__b); \
|
||||
(void) (&__a == __d); \
|
||||
*__d = __a * __b; \
|
||||
__builtin_constant_p(__b) ? \
|
||||
__b > 0 && __a > type_max(typeof(__a)) / __b : \
|
||||
__a > 0 && __b > type_max(typeof(__b)) / __a; \
|
||||
})
|
||||
|
||||
/*
|
||||
* Signed multiplication is rather hard. gcc always follows C99, so
|
||||
* division is truncated towards 0. This means that we can write the
|
||||
* overflow check like this:
|
||||
*
|
||||
* (a > 0 && (b > MAX/a || b < MIN/a)) ||
|
||||
* (a < -1 && (b > MIN/a || b < MAX/a) ||
|
||||
* (a == -1 && b == MIN)
|
||||
*
|
||||
* The redundant casts of -1 are to silence an annoying -Wtype-limits
|
||||
* (included in -Wextra) warning: When the type is u8 or u16, the
|
||||
* __b_c_e in check_mul_overflow obviously selects
|
||||
* __unsigned_mul_overflow, but unfortunately gcc still parses this
|
||||
* code and warns about the limited range of __b.
|
||||
*/
|
||||
|
||||
#define __signed_mul_overflow(a, b, d) ({ \
|
||||
typeof(a) __a = (a); \
|
||||
typeof(b) __b = (b); \
|
||||
typeof(d) __d = (d); \
|
||||
typeof(a) __tmax = type_max(typeof(a)); \
|
||||
typeof(a) __tmin = type_min(typeof(a)); \
|
||||
(void) (&__a == &__b); \
|
||||
(void) (&__a == __d); \
|
||||
*__d = (__u64)__a * (__u64)__b; \
|
||||
(__b > 0 && (__a > __tmax/__b || __a < __tmin/__b)) || \
|
||||
(__b < (typeof(__b))-1 && (__a > __tmin/__b || __a < __tmax/__b)) || \
|
||||
(__b == (typeof(__b))-1 && __a == __tmin); \
|
||||
})
|
||||
|
||||
#define check_mul_overflow(a, b, d) \
|
||||
__builtin_choose_expr(is_signed_type(typeof(a)), \
|
||||
__signed_mul_overflow(a, b, d), \
|
||||
__unsigned_mul_overflow(a, b, d))
|
||||
|
||||
|
||||
#endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */
|
||||
|
||||
#endif
|
||||
18
third_party/libbpf/include/linux/ring_buffer.h
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
#ifndef _TOOLS_LINUX_RING_BUFFER_H_
|
||||
#define _TOOLS_LINUX_RING_BUFFER_H_
|
||||
|
||||
#include <linux/compiler.h>
|
||||
|
||||
static inline __u64 ring_buffer_read_head(struct perf_event_mmap_page *base)
|
||||
{
|
||||
return smp_load_acquire(&base->data_head);
|
||||
}
|
||||
|
||||
static inline void ring_buffer_write_tail(struct perf_event_mmap_page *base,
|
||||
__u64 tail)
|
||||
{
|
||||
smp_store_release(&base->data_tail, tail);
|
||||
}
|
||||
|
||||
#endif /* _TOOLS_LINUX_RING_BUFFER_H_ */
|
||||
33
third_party/libbpf/include/linux/types.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
|
||||
#ifndef __LINUX_TYPES_H
|
||||
#define __LINUX_TYPES_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <linux/stddef.h>
|
||||
|
||||
#include <asm/types.h>
|
||||
#include <asm/posix_types.h>
|
||||
|
||||
#define __bitwise__
|
||||
#define __bitwise __bitwise__
|
||||
|
||||
typedef __u16 __bitwise __le16;
|
||||
typedef __u16 __bitwise __be16;
|
||||
typedef __u32 __bitwise __le32;
|
||||
typedef __u32 __bitwise __be32;
|
||||
typedef __u64 __bitwise __le64;
|
||||
typedef __u64 __bitwise __be64;
|
||||
|
||||
#ifndef __aligned_u64
|
||||
# define __aligned_u64 __u64 __attribute__((aligned(8)))
|
||||
#endif
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#endif
|
||||
7198
third_party/libbpf/include/uapi/linux/bpf.h
vendored
Normal file
57
third_party/libbpf/include/uapi/linux/bpf_common.h
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI__LINUX_BPF_COMMON_H__
|
||||
#define _UAPI__LINUX_BPF_COMMON_H__
|
||||
|
||||
/* Instruction classes */
|
||||
#define BPF_CLASS(code) ((code) & 0x07)
|
||||
#define BPF_LD 0x00
|
||||
#define BPF_LDX 0x01
|
||||
#define BPF_ST 0x02
|
||||
#define BPF_STX 0x03
|
||||
#define BPF_ALU 0x04
|
||||
#define BPF_JMP 0x05
|
||||
#define BPF_RET 0x06
|
||||
#define BPF_MISC 0x07
|
||||
|
||||
/* ld/ldx fields */
|
||||
#define BPF_SIZE(code) ((code) & 0x18)
|
||||
#define BPF_W 0x00 /* 32-bit */
|
||||
#define BPF_H 0x08 /* 16-bit */
|
||||
#define BPF_B 0x10 /* 8-bit */
|
||||
/* eBPF BPF_DW 0x18 64-bit */
|
||||
#define BPF_MODE(code) ((code) & 0xe0)
|
||||
#define BPF_IMM 0x00
|
||||
#define BPF_ABS 0x20
|
||||
#define BPF_IND 0x40
|
||||
#define BPF_MEM 0x60
|
||||
#define BPF_LEN 0x80
|
||||
#define BPF_MSH 0xa0
|
||||
|
||||
/* alu/jmp fields */
|
||||
#define BPF_OP(code) ((code) & 0xf0)
|
||||
#define BPF_ADD 0x00
|
||||
#define BPF_SUB 0x10
|
||||
#define BPF_MUL 0x20
|
||||
#define BPF_DIV 0x30
|
||||
#define BPF_OR 0x40
|
||||
#define BPF_AND 0x50
|
||||
#define BPF_LSH 0x60
|
||||
#define BPF_RSH 0x70
|
||||
#define BPF_NEG 0x80
|
||||
#define BPF_MOD 0x90
|
||||
#define BPF_XOR 0xa0
|
||||
|
||||
#define BPF_JA 0x00
|
||||
#define BPF_JEQ 0x10
|
||||
#define BPF_JGT 0x20
|
||||
#define BPF_JGE 0x30
|
||||
#define BPF_JSET 0x40
|
||||
#define BPF_SRC(code) ((code) & 0x08)
|
||||
#define BPF_K 0x00
|
||||
#define BPF_X 0x08
|
||||
|
||||
#ifndef BPF_MAXINSNS
|
||||
#define BPF_MAXINSNS 4096
|
||||
#endif
|
||||
|
||||
#endif /* _UAPI__LINUX_BPF_COMMON_H__ */
|
||||
200
third_party/libbpf/include/uapi/linux/btf.h
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* Copyright (c) 2018 Facebook */
|
||||
#ifndef _UAPI__LINUX_BTF_H__
|
||||
#define _UAPI__LINUX_BTF_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define BTF_MAGIC 0xeB9F
|
||||
#define BTF_VERSION 1
|
||||
|
||||
struct btf_header {
|
||||
__u16 magic;
|
||||
__u8 version;
|
||||
__u8 flags;
|
||||
__u32 hdr_len;
|
||||
|
||||
/* All offsets are in bytes relative to the end of this header */
|
||||
__u32 type_off; /* offset of type section */
|
||||
__u32 type_len; /* length of type section */
|
||||
__u32 str_off; /* offset of string section */
|
||||
__u32 str_len; /* length of string section */
|
||||
};
|
||||
|
||||
/* Max # of type identifier */
|
||||
#define BTF_MAX_TYPE 0x000fffff
|
||||
/* Max offset into the string section */
|
||||
#define BTF_MAX_NAME_OFFSET 0x00ffffff
|
||||
/* Max # of struct/union/enum members or func args */
|
||||
#define BTF_MAX_VLEN 0xffff
|
||||
|
||||
struct btf_type {
|
||||
__u32 name_off;
|
||||
/* "info" bits arrangement
|
||||
* bits 0-15: vlen (e.g. # of struct's members)
|
||||
* bits 16-23: unused
|
||||
* bits 24-28: kind (e.g. int, ptr, array...etc)
|
||||
* bits 29-30: unused
|
||||
* bit 31: kind_flag, currently used by
|
||||
* struct, union, enum, fwd and enum64
|
||||
*/
|
||||
__u32 info;
|
||||
/* "size" is used by INT, ENUM, STRUCT, UNION, DATASEC and ENUM64.
|
||||
* "size" tells the size of the type it is describing.
|
||||
*
|
||||
* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
|
||||
* FUNC, FUNC_PROTO, VAR, DECL_TAG and TYPE_TAG.
|
||||
* "type" is a type_id referring to another type.
|
||||
*/
|
||||
union {
|
||||
__u32 size;
|
||||
__u32 type;
|
||||
};
|
||||
};
|
||||
|
||||
#define BTF_INFO_KIND(info) (((info) >> 24) & 0x1f)
|
||||
#define BTF_INFO_VLEN(info) ((info) & 0xffff)
|
||||
#define BTF_INFO_KFLAG(info) ((info) >> 31)
|
||||
|
||||
enum {
|
||||
BTF_KIND_UNKN = 0, /* Unknown */
|
||||
BTF_KIND_INT = 1, /* Integer */
|
||||
BTF_KIND_PTR = 2, /* Pointer */
|
||||
BTF_KIND_ARRAY = 3, /* Array */
|
||||
BTF_KIND_STRUCT = 4, /* Struct */
|
||||
BTF_KIND_UNION = 5, /* Union */
|
||||
BTF_KIND_ENUM = 6, /* Enumeration up to 32-bit values */
|
||||
BTF_KIND_FWD = 7, /* Forward */
|
||||
BTF_KIND_TYPEDEF = 8, /* Typedef */
|
||||
BTF_KIND_VOLATILE = 9, /* Volatile */
|
||||
BTF_KIND_CONST = 10, /* Const */
|
||||
BTF_KIND_RESTRICT = 11, /* Restrict */
|
||||
BTF_KIND_FUNC = 12, /* Function */
|
||||
BTF_KIND_FUNC_PROTO = 13, /* Function Proto */
|
||||
BTF_KIND_VAR = 14, /* Variable */
|
||||
BTF_KIND_DATASEC = 15, /* Section */
|
||||
BTF_KIND_FLOAT = 16, /* Floating point */
|
||||
BTF_KIND_DECL_TAG = 17, /* Decl Tag */
|
||||
BTF_KIND_TYPE_TAG = 18, /* Type Tag */
|
||||
BTF_KIND_ENUM64 = 19, /* Enumeration up to 64-bit values */
|
||||
|
||||
NR_BTF_KINDS,
|
||||
BTF_KIND_MAX = NR_BTF_KINDS - 1,
|
||||
};
|
||||
|
||||
/* For some specific BTF_KIND, "struct btf_type" is immediately
|
||||
* followed by extra data.
|
||||
*/
|
||||
|
||||
/* BTF_KIND_INT is followed by a u32 and the following
|
||||
* is the 32 bits arrangement:
|
||||
*/
|
||||
#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
|
||||
#define BTF_INT_OFFSET(VAL) (((VAL) & 0x00ff0000) >> 16)
|
||||
#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
|
||||
|
||||
/* Attributes stored in the BTF_INT_ENCODING */
|
||||
#define BTF_INT_SIGNED (1 << 0)
|
||||
#define BTF_INT_CHAR (1 << 1)
|
||||
#define BTF_INT_BOOL (1 << 2)
|
||||
|
||||
/* BTF_KIND_ENUM is followed by multiple "struct btf_enum".
|
||||
* The exact number of btf_enum is stored in the vlen (of the
|
||||
* info in "struct btf_type").
|
||||
*/
|
||||
struct btf_enum {
|
||||
__u32 name_off;
|
||||
__s32 val;
|
||||
};
|
||||
|
||||
/* BTF_KIND_ARRAY is followed by one "struct btf_array" */
|
||||
struct btf_array {
|
||||
__u32 type;
|
||||
__u32 index_type;
|
||||
__u32 nelems;
|
||||
};
|
||||
|
||||
/* BTF_KIND_STRUCT and BTF_KIND_UNION are followed
|
||||
* by multiple "struct btf_member". The exact number
|
||||
* of btf_member is stored in the vlen (of the info in
|
||||
* "struct btf_type").
|
||||
*/
|
||||
struct btf_member {
|
||||
__u32 name_off;
|
||||
__u32 type;
|
||||
/* If the type info kind_flag is set, the btf_member offset
|
||||
* contains both member bitfield size and bit offset. The
|
||||
* bitfield size is set for bitfield members. If the type
|
||||
* info kind_flag is not set, the offset contains only bit
|
||||
* offset.
|
||||
*/
|
||||
__u32 offset;
|
||||
};
|
||||
|
||||
/* If the struct/union type info kind_flag is set, the
|
||||
* following two macros are used to access bitfield_size
|
||||
* and bit_offset from btf_member.offset.
|
||||
*/
|
||||
#define BTF_MEMBER_BITFIELD_SIZE(val) ((val) >> 24)
|
||||
#define BTF_MEMBER_BIT_OFFSET(val) ((val) & 0xffffff)
|
||||
|
||||
/* BTF_KIND_FUNC_PROTO is followed by multiple "struct btf_param".
|
||||
* The exact number of btf_param is stored in the vlen (of the
|
||||
* info in "struct btf_type").
|
||||
*/
|
||||
struct btf_param {
|
||||
__u32 name_off;
|
||||
__u32 type;
|
||||
};
|
||||
|
||||
enum {
|
||||
BTF_VAR_STATIC = 0,
|
||||
BTF_VAR_GLOBAL_ALLOCATED = 1,
|
||||
BTF_VAR_GLOBAL_EXTERN = 2,
|
||||
};
|
||||
|
||||
enum btf_func_linkage {
|
||||
BTF_FUNC_STATIC = 0,
|
||||
BTF_FUNC_GLOBAL = 1,
|
||||
BTF_FUNC_EXTERN = 2,
|
||||
};
|
||||
|
||||
/* BTF_KIND_VAR is followed by a single "struct btf_var" to describe
|
||||
* additional information related to the variable such as its linkage.
|
||||
*/
|
||||
struct btf_var {
|
||||
__u32 linkage;
|
||||
};
|
||||
|
||||
/* BTF_KIND_DATASEC is followed by multiple "struct btf_var_secinfo"
|
||||
* to describe all BTF_KIND_VAR types it contains along with it's
|
||||
* in-section offset as well as size.
|
||||
*/
|
||||
struct btf_var_secinfo {
|
||||
__u32 type;
|
||||
__u32 offset;
|
||||
__u32 size;
|
||||
};
|
||||
|
||||
/* BTF_KIND_DECL_TAG is followed by a single "struct btf_decl_tag" to describe
|
||||
* additional information related to the tag applied location.
|
||||
* If component_idx == -1, the tag is applied to a struct, union,
|
||||
* variable or function. Otherwise, it is applied to a struct/union
|
||||
* member or a func argument, and component_idx indicates which member
|
||||
* or argument (0 ... vlen-1).
|
||||
*/
|
||||
struct btf_decl_tag {
|
||||
__s32 component_idx;
|
||||
};
|
||||
|
||||
/* BTF_KIND_ENUM64 is followed by multiple "struct btf_enum64".
|
||||
* The exact number of btf_enum64 is stored in the vlen (of the
|
||||
* info in "struct btf_type").
|
||||
*/
|
||||
struct btf_enum64 {
|
||||
__u32 name_off;
|
||||
__u32 val_lo32;
|
||||
__u32 val_hi32;
|
||||
};
|
||||
|
||||
#endif /* _UAPI__LINUX_BTF_H__ */
|
||||
115
third_party/libbpf/include/uapi/linux/fcntl.h
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI_LINUX_FCNTL_H
|
||||
#define _UAPI_LINUX_FCNTL_H
|
||||
|
||||
#include <asm/fcntl.h>
|
||||
#include <linux/openat2.h>
|
||||
|
||||
#define F_SETLEASE (F_LINUX_SPECIFIC_BASE + 0)
|
||||
#define F_GETLEASE (F_LINUX_SPECIFIC_BASE + 1)
|
||||
|
||||
/*
|
||||
* Cancel a blocking posix lock; internal use only until we expose an
|
||||
* asynchronous lock api to userspace:
|
||||
*/
|
||||
#define F_CANCELLK (F_LINUX_SPECIFIC_BASE + 5)
|
||||
|
||||
/* Create a file descriptor with FD_CLOEXEC set. */
|
||||
#define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
|
||||
|
||||
/*
|
||||
* Request nofications on a directory.
|
||||
* See below for events that may be notified.
|
||||
*/
|
||||
#define F_NOTIFY (F_LINUX_SPECIFIC_BASE+2)
|
||||
|
||||
/*
|
||||
* Set and get of pipe page size array
|
||||
*/
|
||||
#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
|
||||
#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
|
||||
|
||||
/*
|
||||
* Set/Get seals
|
||||
*/
|
||||
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
|
||||
#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
|
||||
|
||||
/*
|
||||
* Types of seals
|
||||
*/
|
||||
#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
|
||||
#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
|
||||
#define F_SEAL_GROW 0x0004 /* prevent file from growing */
|
||||
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
||||
#define F_SEAL_FUTURE_WRITE 0x0010 /* prevent future writes while mapped */
|
||||
#define F_SEAL_EXEC 0x0020 /* prevent chmod modifying exec bits */
|
||||
/* (1U << 31) is reserved for signed error codes */
|
||||
|
||||
/*
|
||||
* Set/Get write life time hints. {GET,SET}_RW_HINT operate on the
|
||||
* underlying inode, while {GET,SET}_FILE_RW_HINT operate only on
|
||||
* the specific file.
|
||||
*/
|
||||
#define F_GET_RW_HINT (F_LINUX_SPECIFIC_BASE + 11)
|
||||
#define F_SET_RW_HINT (F_LINUX_SPECIFIC_BASE + 12)
|
||||
#define F_GET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 13)
|
||||
#define F_SET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 14)
|
||||
|
||||
/*
|
||||
* Valid hint values for F_{GET,SET}_RW_HINT. 0 is "not set", or can be
|
||||
* used to clear any hints previously set.
|
||||
*/
|
||||
#define RWH_WRITE_LIFE_NOT_SET 0
|
||||
#define RWH_WRITE_LIFE_NONE 1
|
||||
#define RWH_WRITE_LIFE_SHORT 2
|
||||
#define RWH_WRITE_LIFE_MEDIUM 3
|
||||
#define RWH_WRITE_LIFE_LONG 4
|
||||
#define RWH_WRITE_LIFE_EXTREME 5
|
||||
|
||||
/*
|
||||
* The originally introduced spelling is remained from the first
|
||||
* versions of the patch set that introduced the feature, see commit
|
||||
* v4.13-rc1~212^2~51.
|
||||
*/
|
||||
#define RWF_WRITE_LIFE_NOT_SET RWH_WRITE_LIFE_NOT_SET
|
||||
|
||||
/*
|
||||
* Types of directory notifications that may be requested.
|
||||
*/
|
||||
#define DN_ACCESS 0x00000001 /* File accessed */
|
||||
#define DN_MODIFY 0x00000002 /* File modified */
|
||||
#define DN_CREATE 0x00000004 /* File created */
|
||||
#define DN_DELETE 0x00000008 /* File removed */
|
||||
#define DN_RENAME 0x00000010 /* File renamed */
|
||||
#define DN_ATTRIB 0x00000020 /* File changed attibutes */
|
||||
#define DN_MULTISHOT 0x80000000 /* Don't remove notifier */
|
||||
|
||||
/*
|
||||
* The constants AT_REMOVEDIR and AT_EACCESS have the same value. AT_EACCESS is
|
||||
* meaningful only to faccessat, while AT_REMOVEDIR is meaningful only to
|
||||
* unlinkat. The two functions do completely different things and therefore,
|
||||
* the flags can be allowed to overlap. For example, passing AT_REMOVEDIR to
|
||||
* faccessat would be undefined behavior and thus treating it equivalent to
|
||||
* AT_EACCESS is valid undefined behavior.
|
||||
*/
|
||||
#define AT_FDCWD -100 /* Special value used to indicate
|
||||
openat should use the current
|
||||
working directory. */
|
||||
#define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */
|
||||
#define AT_EACCESS 0x200 /* Test access permitted for
|
||||
effective IDs, not real IDs. */
|
||||
#define AT_REMOVEDIR 0x200 /* Remove directory instead of
|
||||
unlinking file. */
|
||||
#define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */
|
||||
#define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount traversal */
|
||||
#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */
|
||||
|
||||
#define AT_STATX_SYNC_TYPE 0x6000 /* Type of synchronisation required from statx() */
|
||||
#define AT_STATX_SYNC_AS_STAT 0x0000 /* - Do whatever stat() does */
|
||||
#define AT_STATX_FORCE_SYNC 0x2000 /* - Force the attributes to be sync'd with the server */
|
||||
#define AT_STATX_DONT_SYNC 0x4000 /* - Don't sync attributes with the server */
|
||||
|
||||
#define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */
|
||||
|
||||
#endif /* _UAPI_LINUX_FCNTL_H */
|
||||
1284
third_party/libbpf/include/uapi/linux/if_link.h
vendored
Normal file
111
third_party/libbpf/include/uapi/linux/if_xdp.h
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* if_xdp: XDP socket user-space interface
|
||||
* Copyright(c) 2018 Intel Corporation.
|
||||
*
|
||||
* Author(s): Björn Töpel <bjorn.topel@intel.com>
|
||||
* Magnus Karlsson <magnus.karlsson@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_IF_XDP_H
|
||||
#define _LINUX_IF_XDP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Options for the sxdp_flags field */
|
||||
#define XDP_SHARED_UMEM (1 << 0)
|
||||
#define XDP_COPY (1 << 1) /* Force copy-mode */
|
||||
#define XDP_ZEROCOPY (1 << 2) /* Force zero-copy mode */
|
||||
/* If this option is set, the driver might go sleep and in that case
|
||||
* the XDP_RING_NEED_WAKEUP flag in the fill and/or Tx rings will be
|
||||
* set. If it is set, the application need to explicitly wake up the
|
||||
* driver with a poll() (Rx and Tx) or sendto() (Tx only). If you are
|
||||
* running the driver and the application on the same core, you should
|
||||
* use this option so that the kernel will yield to the user space
|
||||
* application.
|
||||
*/
|
||||
#define XDP_USE_NEED_WAKEUP (1 << 3)
|
||||
|
||||
/* Flags for xsk_umem_config flags */
|
||||
#define XDP_UMEM_UNALIGNED_CHUNK_FLAG (1 << 0)
|
||||
|
||||
struct sockaddr_xdp {
|
||||
__u16 sxdp_family;
|
||||
__u16 sxdp_flags;
|
||||
__u32 sxdp_ifindex;
|
||||
__u32 sxdp_queue_id;
|
||||
__u32 sxdp_shared_umem_fd;
|
||||
};
|
||||
|
||||
/* XDP_RING flags */
|
||||
#define XDP_RING_NEED_WAKEUP (1 << 0)
|
||||
|
||||
struct xdp_ring_offset {
|
||||
__u64 producer;
|
||||
__u64 consumer;
|
||||
__u64 desc;
|
||||
__u64 flags;
|
||||
};
|
||||
|
||||
struct xdp_mmap_offsets {
|
||||
struct xdp_ring_offset rx;
|
||||
struct xdp_ring_offset tx;
|
||||
struct xdp_ring_offset fr; /* Fill */
|
||||
struct xdp_ring_offset cr; /* Completion */
|
||||
};
|
||||
|
||||
/* XDP socket options */
|
||||
#define XDP_MMAP_OFFSETS 1
|
||||
#define XDP_RX_RING 2
|
||||
#define XDP_TX_RING 3
|
||||
#define XDP_UMEM_REG 4
|
||||
#define XDP_UMEM_FILL_RING 5
|
||||
#define XDP_UMEM_COMPLETION_RING 6
|
||||
#define XDP_STATISTICS 7
|
||||
#define XDP_OPTIONS 8
|
||||
|
||||
struct xdp_umem_reg {
|
||||
__u64 addr; /* Start of packet data area */
|
||||
__u64 len; /* Length of packet data area */
|
||||
__u32 chunk_size;
|
||||
__u32 headroom;
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
struct xdp_statistics {
|
||||
__u64 rx_dropped; /* Dropped for other reasons */
|
||||
__u64 rx_invalid_descs; /* Dropped due to invalid descriptor */
|
||||
__u64 tx_invalid_descs; /* Dropped due to invalid descriptor */
|
||||
__u64 rx_ring_full; /* Dropped due to rx ring being full */
|
||||
__u64 rx_fill_ring_empty_descs; /* Failed to retrieve item from fill ring */
|
||||
__u64 tx_ring_empty_descs; /* Failed to retrieve item from tx ring */
|
||||
};
|
||||
|
||||
struct xdp_options {
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
/* Flags for the flags field of struct xdp_options */
|
||||
#define XDP_OPTIONS_ZEROCOPY (1 << 0)
|
||||
|
||||
/* Pgoff for mmaping the rings */
|
||||
#define XDP_PGOFF_RX_RING 0
|
||||
#define XDP_PGOFF_TX_RING 0x80000000
|
||||
#define XDP_UMEM_PGOFF_FILL_RING 0x100000000ULL
|
||||
#define XDP_UMEM_PGOFF_COMPLETION_RING 0x180000000ULL
|
||||
|
||||
/* Masks for unaligned chunks mode */
|
||||
#define XSK_UNALIGNED_BUF_OFFSET_SHIFT 48
|
||||
#define XSK_UNALIGNED_BUF_ADDR_MASK \
|
||||
((1ULL << XSK_UNALIGNED_BUF_OFFSET_SHIFT) - 1)
|
||||
|
||||
/* Rx/Tx descriptor */
|
||||
struct xdp_desc {
|
||||
__u64 addr;
|
||||
__u32 len;
|
||||
__u32 options;
|
||||
};
|
||||
|
||||
/* UMEM descriptor is __u64 */
|
||||
|
||||
#endif /* _LINUX_IF_XDP_H */
|
||||
61
third_party/libbpf/include/uapi/linux/netdev.h
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
|
||||
/* Do not edit directly, auto-generated from: */
|
||||
/* Documentation/netlink/specs/netdev.yaml */
|
||||
/* YNL-GEN uapi header */
|
||||
|
||||
#ifndef _UAPI_LINUX_NETDEV_H
|
||||
#define _UAPI_LINUX_NETDEV_H
|
||||
|
||||
#define NETDEV_FAMILY_NAME "netdev"
|
||||
#define NETDEV_FAMILY_VERSION 1
|
||||
|
||||
/**
|
||||
* enum netdev_xdp_act
|
||||
* @NETDEV_XDP_ACT_BASIC: XDP feautues set supported by all drivers
|
||||
* (XDP_ABORTED, XDP_DROP, XDP_PASS, XDP_TX)
|
||||
* @NETDEV_XDP_ACT_REDIRECT: The netdev supports XDP_REDIRECT
|
||||
* @NETDEV_XDP_ACT_NDO_XMIT: This feature informs if netdev implements
|
||||
* ndo_xdp_xmit callback.
|
||||
* @NETDEV_XDP_ACT_XSK_ZEROCOPY: This feature informs if netdev supports AF_XDP
|
||||
* in zero copy mode.
|
||||
* @NETDEV_XDP_ACT_HW_OFFLOAD: This feature informs if netdev supports XDP hw
|
||||
* offloading.
|
||||
* @NETDEV_XDP_ACT_RX_SG: This feature informs if netdev implements non-linear
|
||||
* XDP buffer support in the driver napi callback.
|
||||
* @NETDEV_XDP_ACT_NDO_XMIT_SG: This feature informs if netdev implements
|
||||
* non-linear XDP buffer support in ndo_xdp_xmit callback.
|
||||
*/
|
||||
enum netdev_xdp_act {
|
||||
NETDEV_XDP_ACT_BASIC = 1,
|
||||
NETDEV_XDP_ACT_REDIRECT = 2,
|
||||
NETDEV_XDP_ACT_NDO_XMIT = 4,
|
||||
NETDEV_XDP_ACT_XSK_ZEROCOPY = 8,
|
||||
NETDEV_XDP_ACT_HW_OFFLOAD = 16,
|
||||
NETDEV_XDP_ACT_RX_SG = 32,
|
||||
NETDEV_XDP_ACT_NDO_XMIT_SG = 64,
|
||||
|
||||
NETDEV_XDP_ACT_MASK = 127,
|
||||
};
|
||||
|
||||
enum {
|
||||
NETDEV_A_DEV_IFINDEX = 1,
|
||||
NETDEV_A_DEV_PAD,
|
||||
NETDEV_A_DEV_XDP_FEATURES,
|
||||
|
||||
__NETDEV_A_DEV_MAX,
|
||||
NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1)
|
||||
};
|
||||
|
||||
enum {
|
||||
NETDEV_CMD_DEV_GET = 1,
|
||||
NETDEV_CMD_DEV_ADD_NTF,
|
||||
NETDEV_CMD_DEV_DEL_NTF,
|
||||
NETDEV_CMD_DEV_CHANGE_NTF,
|
||||
|
||||
__NETDEV_CMD_MAX,
|
||||
NETDEV_CMD_MAX = (__NETDEV_CMD_MAX - 1)
|
||||
};
|
||||
|
||||
#define NETDEV_MCGRP_MGMT "mgmt"
|
||||
|
||||
#endif /* _UAPI_LINUX_NETDEV_H */
|
||||
252
third_party/libbpf/include/uapi/linux/netlink.h
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI__LINUX_NETLINK_H
|
||||
#define _UAPI__LINUX_NETLINK_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/socket.h> /* for __kernel_sa_family_t */
|
||||
#include <linux/types.h>
|
||||
|
||||
#define NETLINK_ROUTE 0 /* Routing/device hook */
|
||||
#define NETLINK_UNUSED 1 /* Unused number */
|
||||
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
|
||||
#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */
|
||||
#define NETLINK_SOCK_DIAG 4 /* socket monitoring */
|
||||
#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
|
||||
#define NETLINK_XFRM 6 /* ipsec */
|
||||
#define NETLINK_SELINUX 7 /* SELinux event notifications */
|
||||
#define NETLINK_ISCSI 8 /* Open-iSCSI */
|
||||
#define NETLINK_AUDIT 9 /* auditing */
|
||||
#define NETLINK_FIB_LOOKUP 10
|
||||
#define NETLINK_CONNECTOR 11
|
||||
#define NETLINK_NETFILTER 12 /* netfilter subsystem */
|
||||
#define NETLINK_IP6_FW 13
|
||||
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
|
||||
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
|
||||
#define NETLINK_GENERIC 16
|
||||
/* leave room for NETLINK_DM (DM Events) */
|
||||
#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
|
||||
#define NETLINK_ECRYPTFS 19
|
||||
#define NETLINK_RDMA 20
|
||||
#define NETLINK_CRYPTO 21 /* Crypto layer */
|
||||
#define NETLINK_SMC 22 /* SMC monitoring */
|
||||
|
||||
#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG
|
||||
|
||||
#define MAX_LINKS 32
|
||||
|
||||
struct sockaddr_nl {
|
||||
__kernel_sa_family_t nl_family; /* AF_NETLINK */
|
||||
unsigned short nl_pad; /* zero */
|
||||
__u32 nl_pid; /* port ID */
|
||||
__u32 nl_groups; /* multicast groups mask */
|
||||
};
|
||||
|
||||
struct nlmsghdr {
|
||||
__u32 nlmsg_len; /* Length of message including header */
|
||||
__u16 nlmsg_type; /* Message content */
|
||||
__u16 nlmsg_flags; /* Additional flags */
|
||||
__u32 nlmsg_seq; /* Sequence number */
|
||||
__u32 nlmsg_pid; /* Sending process port ID */
|
||||
};
|
||||
|
||||
/* Flags values */
|
||||
|
||||
#define NLM_F_REQUEST 0x01 /* It is request message. */
|
||||
#define NLM_F_MULTI 0x02 /* Multipart message, terminated by NLMSG_DONE */
|
||||
#define NLM_F_ACK 0x04 /* Reply with ack, with zero or error code */
|
||||
#define NLM_F_ECHO 0x08 /* Echo this request */
|
||||
#define NLM_F_DUMP_INTR 0x10 /* Dump was inconsistent due to sequence change */
|
||||
#define NLM_F_DUMP_FILTERED 0x20 /* Dump was filtered as requested */
|
||||
|
||||
/* Modifiers to GET request */
|
||||
#define NLM_F_ROOT 0x100 /* specify tree root */
|
||||
#define NLM_F_MATCH 0x200 /* return all matching */
|
||||
#define NLM_F_ATOMIC 0x400 /* atomic GET */
|
||||
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
|
||||
|
||||
/* Modifiers to NEW request */
|
||||
#define NLM_F_REPLACE 0x100 /* Override existing */
|
||||
#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */
|
||||
#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
|
||||
#define NLM_F_APPEND 0x800 /* Add to end of list */
|
||||
|
||||
/* Modifiers to DELETE request */
|
||||
#define NLM_F_NONREC 0x100 /* Do not delete recursively */
|
||||
|
||||
/* Flags for ACK message */
|
||||
#define NLM_F_CAPPED 0x100 /* request was capped */
|
||||
#define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */
|
||||
|
||||
/*
|
||||
4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL
|
||||
4.4BSD CHANGE NLM_F_REPLACE
|
||||
|
||||
True CHANGE NLM_F_CREATE|NLM_F_REPLACE
|
||||
Append NLM_F_CREATE
|
||||
Check NLM_F_EXCL
|
||||
*/
|
||||
|
||||
#define NLMSG_ALIGNTO 4U
|
||||
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
|
||||
#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
|
||||
#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
|
||||
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
|
||||
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
|
||||
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
|
||||
(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
|
||||
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
|
||||
(nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
|
||||
(nlh)->nlmsg_len <= (len))
|
||||
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
|
||||
|
||||
#define NLMSG_NOOP 0x1 /* Nothing. */
|
||||
#define NLMSG_ERROR 0x2 /* Error */
|
||||
#define NLMSG_DONE 0x3 /* End of a dump */
|
||||
#define NLMSG_OVERRUN 0x4 /* Data lost */
|
||||
|
||||
#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */
|
||||
|
||||
struct nlmsgerr {
|
||||
int error;
|
||||
struct nlmsghdr msg;
|
||||
/*
|
||||
* followed by the message contents unless NETLINK_CAP_ACK was set
|
||||
* or the ACK indicates success (error == 0)
|
||||
* message length is aligned with NLMSG_ALIGN()
|
||||
*/
|
||||
/*
|
||||
* followed by TLVs defined in enum nlmsgerr_attrs
|
||||
* if NETLINK_EXT_ACK was set
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nlmsgerr_attrs - nlmsgerr attributes
|
||||
* @NLMSGERR_ATTR_UNUSED: unused
|
||||
* @NLMSGERR_ATTR_MSG: error message string (string)
|
||||
* @NLMSGERR_ATTR_OFFS: offset of the invalid attribute in the original
|
||||
* message, counting from the beginning of the header (u32)
|
||||
* @NLMSGERR_ATTR_COOKIE: arbitrary subsystem specific cookie to
|
||||
* be used - in the success case - to identify a created
|
||||
* object or operation or similar (binary)
|
||||
* @__NLMSGERR_ATTR_MAX: number of attributes
|
||||
* @NLMSGERR_ATTR_MAX: highest attribute number
|
||||
*/
|
||||
enum nlmsgerr_attrs {
|
||||
NLMSGERR_ATTR_UNUSED,
|
||||
NLMSGERR_ATTR_MSG,
|
||||
NLMSGERR_ATTR_OFFS,
|
||||
NLMSGERR_ATTR_COOKIE,
|
||||
|
||||
__NLMSGERR_ATTR_MAX,
|
||||
NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1
|
||||
};
|
||||
|
||||
#define NETLINK_ADD_MEMBERSHIP 1
|
||||
#define NETLINK_DROP_MEMBERSHIP 2
|
||||
#define NETLINK_PKTINFO 3
|
||||
#define NETLINK_BROADCAST_ERROR 4
|
||||
#define NETLINK_NO_ENOBUFS 5
|
||||
#ifndef __KERNEL__
|
||||
#define NETLINK_RX_RING 6
|
||||
#define NETLINK_TX_RING 7
|
||||
#endif
|
||||
#define NETLINK_LISTEN_ALL_NSID 8
|
||||
#define NETLINK_LIST_MEMBERSHIPS 9
|
||||
#define NETLINK_CAP_ACK 10
|
||||
#define NETLINK_EXT_ACK 11
|
||||
#define NETLINK_GET_STRICT_CHK 12
|
||||
|
||||
struct nl_pktinfo {
|
||||
__u32 group;
|
||||
};
|
||||
|
||||
struct nl_mmap_req {
|
||||
unsigned int nm_block_size;
|
||||
unsigned int nm_block_nr;
|
||||
unsigned int nm_frame_size;
|
||||
unsigned int nm_frame_nr;
|
||||
};
|
||||
|
||||
struct nl_mmap_hdr {
|
||||
unsigned int nm_status;
|
||||
unsigned int nm_len;
|
||||
__u32 nm_group;
|
||||
/* credentials */
|
||||
__u32 nm_pid;
|
||||
__u32 nm_uid;
|
||||
__u32 nm_gid;
|
||||
};
|
||||
|
||||
#ifndef __KERNEL__
|
||||
enum nl_mmap_status {
|
||||
NL_MMAP_STATUS_UNUSED,
|
||||
NL_MMAP_STATUS_RESERVED,
|
||||
NL_MMAP_STATUS_VALID,
|
||||
NL_MMAP_STATUS_COPY,
|
||||
NL_MMAP_STATUS_SKIP,
|
||||
};
|
||||
|
||||
#define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO
|
||||
#define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT)
|
||||
#define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr))
|
||||
#endif
|
||||
|
||||
#define NET_MAJOR 36 /* Major 36 is reserved for networking */
|
||||
|
||||
enum {
|
||||
NETLINK_UNCONNECTED = 0,
|
||||
NETLINK_CONNECTED,
|
||||
};
|
||||
|
||||
/*
|
||||
* <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
|
||||
* +---------------------+- - -+- - - - - - - - - -+- - -+
|
||||
* | Header | Pad | Payload | Pad |
|
||||
* | (struct nlattr) | ing | | ing |
|
||||
* +---------------------+- - -+- - - - - - - - - -+- - -+
|
||||
* <-------------- nlattr->nla_len -------------->
|
||||
*/
|
||||
|
||||
struct nlattr {
|
||||
__u16 nla_len;
|
||||
__u16 nla_type;
|
||||
};
|
||||
|
||||
/*
|
||||
* nla_type (16 bits)
|
||||
* +---+---+-------------------------------+
|
||||
* | N | O | Attribute Type |
|
||||
* +---+---+-------------------------------+
|
||||
* N := Carries nested attributes
|
||||
* O := Payload stored in network byte order
|
||||
*
|
||||
* Note: The N and O flag are mutually exclusive.
|
||||
*/
|
||||
#define NLA_F_NESTED (1 << 15)
|
||||
#define NLA_F_NET_BYTEORDER (1 << 14)
|
||||
#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
|
||||
|
||||
#define NLA_ALIGNTO 4
|
||||
#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
|
||||
#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
|
||||
|
||||
/* Generic 32 bitflags attribute content sent to the kernel.
|
||||
*
|
||||
* The value is a bitmap that defines the values being set
|
||||
* The selector is a bitmask that defines which value is legit
|
||||
*
|
||||
* Examples:
|
||||
* value = 0x0, and selector = 0x1
|
||||
* implies we are selecting bit 1 and we want to set its value to 0.
|
||||
*
|
||||
* value = 0x2, and selector = 0x2
|
||||
* implies we are selecting bit 2 and we want to set its value to 1.
|
||||
*
|
||||
*/
|
||||
struct nla_bitfield32 {
|
||||
__u32 value;
|
||||
__u32 selector;
|
||||
};
|
||||
|
||||
#endif /* _UAPI__LINUX_NETLINK_H */
|
||||
43
third_party/libbpf/include/uapi/linux/openat2.h
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI_LINUX_OPENAT2_H
|
||||
#define _UAPI_LINUX_OPENAT2_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* Arguments for how openat2(2) should open the target path. If only @flags and
|
||||
* @mode are non-zero, then openat2(2) operates very similarly to openat(2).
|
||||
*
|
||||
* However, unlike openat(2), unknown or invalid bits in @flags result in
|
||||
* -EINVAL rather than being silently ignored. @mode must be zero unless one of
|
||||
* {O_CREAT, O_TMPFILE} are set.
|
||||
*
|
||||
* @flags: O_* flags.
|
||||
* @mode: O_CREAT/O_TMPFILE file mode.
|
||||
* @resolve: RESOLVE_* flags.
|
||||
*/
|
||||
struct open_how {
|
||||
__u64 flags;
|
||||
__u64 mode;
|
||||
__u64 resolve;
|
||||
};
|
||||
|
||||
/* how->resolve flags for openat2(2). */
|
||||
#define RESOLVE_NO_XDEV 0x01 /* Block mount-point crossings
|
||||
(includes bind-mounts). */
|
||||
#define RESOLVE_NO_MAGICLINKS 0x02 /* Block traversal through procfs-style
|
||||
"magic-links". */
|
||||
#define RESOLVE_NO_SYMLINKS 0x04 /* Block traversal through all symlinks
|
||||
(implies OEXT_NO_MAGICLINKS) */
|
||||
#define RESOLVE_BENEATH 0x08 /* Block "lexical" trickery like
|
||||
"..", symlinks, and absolute
|
||||
paths which escape the dirfd. */
|
||||
#define RESOLVE_IN_ROOT 0x10 /* Make all jumps to "/" and ".."
|
||||
be scoped inside the dirfd
|
||||
(similar to chroot(2)). */
|
||||
#define RESOLVE_CACHED 0x20 /* Only complete if resolution can be
|
||||
completed through cached lookup. May
|
||||
return -EAGAIN if that's not
|
||||
possible. */
|
||||
|
||||
#endif /* _UAPI_LINUX_OPENAT2_H */
|
||||
1448
third_party/libbpf/include/uapi/linux/perf_event.h
vendored
Normal file
612
third_party/libbpf/include/uapi/linux/pkt_cls.h
vendored
Normal file
@@ -0,0 +1,612 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef __LINUX_PKT_CLS_H
|
||||
#define __LINUX_PKT_CLS_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/pkt_sched.h>
|
||||
|
||||
#define TC_COOKIE_MAX_SIZE 16
|
||||
|
||||
/* Action attributes */
|
||||
enum {
|
||||
TCA_ACT_UNSPEC,
|
||||
TCA_ACT_KIND,
|
||||
TCA_ACT_OPTIONS,
|
||||
TCA_ACT_INDEX,
|
||||
TCA_ACT_STATS,
|
||||
TCA_ACT_PAD,
|
||||
TCA_ACT_COOKIE,
|
||||
__TCA_ACT_MAX
|
||||
};
|
||||
|
||||
#define TCA_ACT_MAX __TCA_ACT_MAX
|
||||
#define TCA_OLD_COMPAT (TCA_ACT_MAX+1)
|
||||
#define TCA_ACT_MAX_PRIO 32
|
||||
#define TCA_ACT_BIND 1
|
||||
#define TCA_ACT_NOBIND 0
|
||||
#define TCA_ACT_UNBIND 1
|
||||
#define TCA_ACT_NOUNBIND 0
|
||||
#define TCA_ACT_REPLACE 1
|
||||
#define TCA_ACT_NOREPLACE 0
|
||||
|
||||
#define TC_ACT_UNSPEC (-1)
|
||||
#define TC_ACT_OK 0
|
||||
#define TC_ACT_RECLASSIFY 1
|
||||
#define TC_ACT_SHOT 2
|
||||
#define TC_ACT_PIPE 3
|
||||
#define TC_ACT_STOLEN 4
|
||||
#define TC_ACT_QUEUED 5
|
||||
#define TC_ACT_REPEAT 6
|
||||
#define TC_ACT_REDIRECT 7
|
||||
#define TC_ACT_TRAP 8 /* For hw path, this means "trap to cpu"
|
||||
* and don't further process the frame
|
||||
* in hardware. For sw path, this is
|
||||
* equivalent of TC_ACT_STOLEN - drop
|
||||
* the skb and act like everything
|
||||
* is alright.
|
||||
*/
|
||||
#define TC_ACT_VALUE_MAX TC_ACT_TRAP
|
||||
|
||||
/* There is a special kind of actions called "extended actions",
|
||||
* which need a value parameter. These have a local opcode located in
|
||||
* the highest nibble, starting from 1. The rest of the bits
|
||||
* are used to carry the value. These two parts together make
|
||||
* a combined opcode.
|
||||
*/
|
||||
#define __TC_ACT_EXT_SHIFT 28
|
||||
#define __TC_ACT_EXT(local) ((local) << __TC_ACT_EXT_SHIFT)
|
||||
#define TC_ACT_EXT_VAL_MASK ((1 << __TC_ACT_EXT_SHIFT) - 1)
|
||||
#define TC_ACT_EXT_OPCODE(combined) ((combined) & (~TC_ACT_EXT_VAL_MASK))
|
||||
#define TC_ACT_EXT_CMP(combined, opcode) (TC_ACT_EXT_OPCODE(combined) == opcode)
|
||||
|
||||
#define TC_ACT_JUMP __TC_ACT_EXT(1)
|
||||
#define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)
|
||||
#define TC_ACT_EXT_OPCODE_MAX TC_ACT_GOTO_CHAIN
|
||||
|
||||
/* Action type identifiers*/
|
||||
enum {
|
||||
TCA_ID_UNSPEC=0,
|
||||
TCA_ID_POLICE=1,
|
||||
/* other actions go here */
|
||||
__TCA_ID_MAX=255
|
||||
};
|
||||
|
||||
#define TCA_ID_MAX __TCA_ID_MAX
|
||||
|
||||
struct tc_police {
|
||||
__u32 index;
|
||||
int action;
|
||||
#define TC_POLICE_UNSPEC TC_ACT_UNSPEC
|
||||
#define TC_POLICE_OK TC_ACT_OK
|
||||
#define TC_POLICE_RECLASSIFY TC_ACT_RECLASSIFY
|
||||
#define TC_POLICE_SHOT TC_ACT_SHOT
|
||||
#define TC_POLICE_PIPE TC_ACT_PIPE
|
||||
|
||||
__u32 limit;
|
||||
__u32 burst;
|
||||
__u32 mtu;
|
||||
struct tc_ratespec rate;
|
||||
struct tc_ratespec peakrate;
|
||||
int refcnt;
|
||||
int bindcnt;
|
||||
__u32 capab;
|
||||
};
|
||||
|
||||
struct tcf_t {
|
||||
__u64 install;
|
||||
__u64 lastuse;
|
||||
__u64 expires;
|
||||
__u64 firstuse;
|
||||
};
|
||||
|
||||
struct tc_cnt {
|
||||
int refcnt;
|
||||
int bindcnt;
|
||||
};
|
||||
|
||||
#define tc_gen \
|
||||
__u32 index; \
|
||||
__u32 capab; \
|
||||
int action; \
|
||||
int refcnt; \
|
||||
int bindcnt
|
||||
|
||||
enum {
|
||||
TCA_POLICE_UNSPEC,
|
||||
TCA_POLICE_TBF,
|
||||
TCA_POLICE_RATE,
|
||||
TCA_POLICE_PEAKRATE,
|
||||
TCA_POLICE_AVRATE,
|
||||
TCA_POLICE_RESULT,
|
||||
TCA_POLICE_TM,
|
||||
TCA_POLICE_PAD,
|
||||
__TCA_POLICE_MAX
|
||||
#define TCA_POLICE_RESULT TCA_POLICE_RESULT
|
||||
};
|
||||
|
||||
#define TCA_POLICE_MAX (__TCA_POLICE_MAX - 1)
|
||||
|
||||
/* tca flags definitions */
|
||||
#define TCA_CLS_FLAGS_SKIP_HW (1 << 0) /* don't offload filter to HW */
|
||||
#define TCA_CLS_FLAGS_SKIP_SW (1 << 1) /* don't use filter in SW */
|
||||
#define TCA_CLS_FLAGS_IN_HW (1 << 2) /* filter is offloaded to HW */
|
||||
#define TCA_CLS_FLAGS_NOT_IN_HW (1 << 3) /* filter isn't offloaded to HW */
|
||||
#define TCA_CLS_FLAGS_VERBOSE (1 << 4) /* verbose logging */
|
||||
|
||||
/* U32 filters */
|
||||
|
||||
#define TC_U32_HTID(h) ((h)&0xFFF00000)
|
||||
#define TC_U32_USERHTID(h) (TC_U32_HTID(h)>>20)
|
||||
#define TC_U32_HASH(h) (((h)>>12)&0xFF)
|
||||
#define TC_U32_NODE(h) ((h)&0xFFF)
|
||||
#define TC_U32_KEY(h) ((h)&0xFFFFF)
|
||||
#define TC_U32_UNSPEC 0
|
||||
#define TC_U32_ROOT (0xFFF00000)
|
||||
|
||||
enum {
|
||||
TCA_U32_UNSPEC,
|
||||
TCA_U32_CLASSID,
|
||||
TCA_U32_HASH,
|
||||
TCA_U32_LINK,
|
||||
TCA_U32_DIVISOR,
|
||||
TCA_U32_SEL,
|
||||
TCA_U32_POLICE,
|
||||
TCA_U32_ACT,
|
||||
TCA_U32_INDEV,
|
||||
TCA_U32_PCNT,
|
||||
TCA_U32_MARK,
|
||||
TCA_U32_FLAGS,
|
||||
TCA_U32_PAD,
|
||||
__TCA_U32_MAX
|
||||
};
|
||||
|
||||
#define TCA_U32_MAX (__TCA_U32_MAX - 1)
|
||||
|
||||
struct tc_u32_key {
|
||||
__be32 mask;
|
||||
__be32 val;
|
||||
int off;
|
||||
int offmask;
|
||||
};
|
||||
|
||||
struct tc_u32_sel {
|
||||
unsigned char flags;
|
||||
unsigned char offshift;
|
||||
unsigned char nkeys;
|
||||
|
||||
__be16 offmask;
|
||||
__u16 off;
|
||||
short offoff;
|
||||
|
||||
short hoff;
|
||||
__be32 hmask;
|
||||
struct tc_u32_key keys[];
|
||||
};
|
||||
|
||||
struct tc_u32_mark {
|
||||
__u32 val;
|
||||
__u32 mask;
|
||||
__u32 success;
|
||||
};
|
||||
|
||||
struct tc_u32_pcnt {
|
||||
__u64 rcnt;
|
||||
__u64 rhit;
|
||||
__u64 kcnts[];
|
||||
};
|
||||
|
||||
/* Flags */
|
||||
|
||||
#define TC_U32_TERMINAL 1
|
||||
#define TC_U32_OFFSET 2
|
||||
#define TC_U32_VAROFFSET 4
|
||||
#define TC_U32_EAT 8
|
||||
|
||||
#define TC_U32_MAXDEPTH 8
|
||||
|
||||
|
||||
/* RSVP filter */
|
||||
|
||||
enum {
|
||||
TCA_RSVP_UNSPEC,
|
||||
TCA_RSVP_CLASSID,
|
||||
TCA_RSVP_DST,
|
||||
TCA_RSVP_SRC,
|
||||
TCA_RSVP_PINFO,
|
||||
TCA_RSVP_POLICE,
|
||||
TCA_RSVP_ACT,
|
||||
__TCA_RSVP_MAX
|
||||
};
|
||||
|
||||
#define TCA_RSVP_MAX (__TCA_RSVP_MAX - 1 )
|
||||
|
||||
struct tc_rsvp_gpi {
|
||||
__u32 key;
|
||||
__u32 mask;
|
||||
int offset;
|
||||
};
|
||||
|
||||
struct tc_rsvp_pinfo {
|
||||
struct tc_rsvp_gpi dpi;
|
||||
struct tc_rsvp_gpi spi;
|
||||
__u8 protocol;
|
||||
__u8 tunnelid;
|
||||
__u8 tunnelhdr;
|
||||
__u8 pad;
|
||||
};
|
||||
|
||||
/* ROUTE filter */
|
||||
|
||||
enum {
|
||||
TCA_ROUTE4_UNSPEC,
|
||||
TCA_ROUTE4_CLASSID,
|
||||
TCA_ROUTE4_TO,
|
||||
TCA_ROUTE4_FROM,
|
||||
TCA_ROUTE4_IIF,
|
||||
TCA_ROUTE4_POLICE,
|
||||
TCA_ROUTE4_ACT,
|
||||
__TCA_ROUTE4_MAX
|
||||
};
|
||||
|
||||
#define TCA_ROUTE4_MAX (__TCA_ROUTE4_MAX - 1)
|
||||
|
||||
|
||||
/* FW filter */
|
||||
|
||||
enum {
|
||||
TCA_FW_UNSPEC,
|
||||
TCA_FW_CLASSID,
|
||||
TCA_FW_POLICE,
|
||||
TCA_FW_INDEV,
|
||||
TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */
|
||||
TCA_FW_MASK,
|
||||
__TCA_FW_MAX
|
||||
};
|
||||
|
||||
#define TCA_FW_MAX (__TCA_FW_MAX - 1)
|
||||
|
||||
/* TC index filter */
|
||||
|
||||
enum {
|
||||
TCA_TCINDEX_UNSPEC,
|
||||
TCA_TCINDEX_HASH,
|
||||
TCA_TCINDEX_MASK,
|
||||
TCA_TCINDEX_SHIFT,
|
||||
TCA_TCINDEX_FALL_THROUGH,
|
||||
TCA_TCINDEX_CLASSID,
|
||||
TCA_TCINDEX_POLICE,
|
||||
TCA_TCINDEX_ACT,
|
||||
__TCA_TCINDEX_MAX
|
||||
};
|
||||
|
||||
#define TCA_TCINDEX_MAX (__TCA_TCINDEX_MAX - 1)
|
||||
|
||||
/* Flow filter */
|
||||
|
||||
enum {
|
||||
FLOW_KEY_SRC,
|
||||
FLOW_KEY_DST,
|
||||
FLOW_KEY_PROTO,
|
||||
FLOW_KEY_PROTO_SRC,
|
||||
FLOW_KEY_PROTO_DST,
|
||||
FLOW_KEY_IIF,
|
||||
FLOW_KEY_PRIORITY,
|
||||
FLOW_KEY_MARK,
|
||||
FLOW_KEY_NFCT,
|
||||
FLOW_KEY_NFCT_SRC,
|
||||
FLOW_KEY_NFCT_DST,
|
||||
FLOW_KEY_NFCT_PROTO_SRC,
|
||||
FLOW_KEY_NFCT_PROTO_DST,
|
||||
FLOW_KEY_RTCLASSID,
|
||||
FLOW_KEY_SKUID,
|
||||
FLOW_KEY_SKGID,
|
||||
FLOW_KEY_VLAN_TAG,
|
||||
FLOW_KEY_RXHASH,
|
||||
__FLOW_KEY_MAX,
|
||||
};
|
||||
|
||||
#define FLOW_KEY_MAX (__FLOW_KEY_MAX - 1)
|
||||
|
||||
enum {
|
||||
FLOW_MODE_MAP,
|
||||
FLOW_MODE_HASH,
|
||||
};
|
||||
|
||||
enum {
|
||||
TCA_FLOW_UNSPEC,
|
||||
TCA_FLOW_KEYS,
|
||||
TCA_FLOW_MODE,
|
||||
TCA_FLOW_BASECLASS,
|
||||
TCA_FLOW_RSHIFT,
|
||||
TCA_FLOW_ADDEND,
|
||||
TCA_FLOW_MASK,
|
||||
TCA_FLOW_XOR,
|
||||
TCA_FLOW_DIVISOR,
|
||||
TCA_FLOW_ACT,
|
||||
TCA_FLOW_POLICE,
|
||||
TCA_FLOW_EMATCHES,
|
||||
TCA_FLOW_PERTURB,
|
||||
__TCA_FLOW_MAX
|
||||
};
|
||||
|
||||
#define TCA_FLOW_MAX (__TCA_FLOW_MAX - 1)
|
||||
|
||||
/* Basic filter */
|
||||
|
||||
enum {
|
||||
TCA_BASIC_UNSPEC,
|
||||
TCA_BASIC_CLASSID,
|
||||
TCA_BASIC_EMATCHES,
|
||||
TCA_BASIC_ACT,
|
||||
TCA_BASIC_POLICE,
|
||||
__TCA_BASIC_MAX
|
||||
};
|
||||
|
||||
#define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1)
|
||||
|
||||
|
||||
/* Cgroup classifier */
|
||||
|
||||
enum {
|
||||
TCA_CGROUP_UNSPEC,
|
||||
TCA_CGROUP_ACT,
|
||||
TCA_CGROUP_POLICE,
|
||||
TCA_CGROUP_EMATCHES,
|
||||
__TCA_CGROUP_MAX,
|
||||
};
|
||||
|
||||
#define TCA_CGROUP_MAX (__TCA_CGROUP_MAX - 1)
|
||||
|
||||
/* BPF classifier */
|
||||
|
||||
#define TCA_BPF_FLAG_ACT_DIRECT (1 << 0)
|
||||
|
||||
enum {
|
||||
TCA_BPF_UNSPEC,
|
||||
TCA_BPF_ACT,
|
||||
TCA_BPF_POLICE,
|
||||
TCA_BPF_CLASSID,
|
||||
TCA_BPF_OPS_LEN,
|
||||
TCA_BPF_OPS,
|
||||
TCA_BPF_FD,
|
||||
TCA_BPF_NAME,
|
||||
TCA_BPF_FLAGS,
|
||||
TCA_BPF_FLAGS_GEN,
|
||||
TCA_BPF_TAG,
|
||||
TCA_BPF_ID,
|
||||
__TCA_BPF_MAX,
|
||||
};
|
||||
|
||||
#define TCA_BPF_MAX (__TCA_BPF_MAX - 1)
|
||||
|
||||
/* Flower classifier */
|
||||
|
||||
enum {
|
||||
TCA_FLOWER_UNSPEC,
|
||||
TCA_FLOWER_CLASSID,
|
||||
TCA_FLOWER_INDEV,
|
||||
TCA_FLOWER_ACT,
|
||||
TCA_FLOWER_KEY_ETH_DST, /* ETH_ALEN */
|
||||
TCA_FLOWER_KEY_ETH_DST_MASK, /* ETH_ALEN */
|
||||
TCA_FLOWER_KEY_ETH_SRC, /* ETH_ALEN */
|
||||
TCA_FLOWER_KEY_ETH_SRC_MASK, /* ETH_ALEN */
|
||||
TCA_FLOWER_KEY_ETH_TYPE, /* be16 */
|
||||
TCA_FLOWER_KEY_IP_PROTO, /* u8 */
|
||||
TCA_FLOWER_KEY_IPV4_SRC, /* be32 */
|
||||
TCA_FLOWER_KEY_IPV4_SRC_MASK, /* be32 */
|
||||
TCA_FLOWER_KEY_IPV4_DST, /* be32 */
|
||||
TCA_FLOWER_KEY_IPV4_DST_MASK, /* be32 */
|
||||
TCA_FLOWER_KEY_IPV6_SRC, /* struct in6_addr */
|
||||
TCA_FLOWER_KEY_IPV6_SRC_MASK, /* struct in6_addr */
|
||||
TCA_FLOWER_KEY_IPV6_DST, /* struct in6_addr */
|
||||
TCA_FLOWER_KEY_IPV6_DST_MASK, /* struct in6_addr */
|
||||
TCA_FLOWER_KEY_TCP_SRC, /* be16 */
|
||||
TCA_FLOWER_KEY_TCP_DST, /* be16 */
|
||||
TCA_FLOWER_KEY_UDP_SRC, /* be16 */
|
||||
TCA_FLOWER_KEY_UDP_DST, /* be16 */
|
||||
|
||||
TCA_FLOWER_FLAGS,
|
||||
TCA_FLOWER_KEY_VLAN_ID, /* be16 */
|
||||
TCA_FLOWER_KEY_VLAN_PRIO, /* u8 */
|
||||
TCA_FLOWER_KEY_VLAN_ETH_TYPE, /* be16 */
|
||||
|
||||
TCA_FLOWER_KEY_ENC_KEY_ID, /* be32 */
|
||||
TCA_FLOWER_KEY_ENC_IPV4_SRC, /* be32 */
|
||||
TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,/* be32 */
|
||||
TCA_FLOWER_KEY_ENC_IPV4_DST, /* be32 */
|
||||
TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,/* be32 */
|
||||
TCA_FLOWER_KEY_ENC_IPV6_SRC, /* struct in6_addr */
|
||||
TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,/* struct in6_addr */
|
||||
TCA_FLOWER_KEY_ENC_IPV6_DST, /* struct in6_addr */
|
||||
TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,/* struct in6_addr */
|
||||
|
||||
TCA_FLOWER_KEY_TCP_SRC_MASK, /* be16 */
|
||||
TCA_FLOWER_KEY_TCP_DST_MASK, /* be16 */
|
||||
TCA_FLOWER_KEY_UDP_SRC_MASK, /* be16 */
|
||||
TCA_FLOWER_KEY_UDP_DST_MASK, /* be16 */
|
||||
TCA_FLOWER_KEY_SCTP_SRC_MASK, /* be16 */
|
||||
TCA_FLOWER_KEY_SCTP_DST_MASK, /* be16 */
|
||||
|
||||
TCA_FLOWER_KEY_SCTP_SRC, /* be16 */
|
||||
TCA_FLOWER_KEY_SCTP_DST, /* be16 */
|
||||
|
||||
TCA_FLOWER_KEY_ENC_UDP_SRC_PORT, /* be16 */
|
||||
TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK, /* be16 */
|
||||
TCA_FLOWER_KEY_ENC_UDP_DST_PORT, /* be16 */
|
||||
TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK, /* be16 */
|
||||
|
||||
TCA_FLOWER_KEY_FLAGS, /* be32 */
|
||||
TCA_FLOWER_KEY_FLAGS_MASK, /* be32 */
|
||||
|
||||
TCA_FLOWER_KEY_ICMPV4_CODE, /* u8 */
|
||||
TCA_FLOWER_KEY_ICMPV4_CODE_MASK,/* u8 */
|
||||
TCA_FLOWER_KEY_ICMPV4_TYPE, /* u8 */
|
||||
TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,/* u8 */
|
||||
TCA_FLOWER_KEY_ICMPV6_CODE, /* u8 */
|
||||
TCA_FLOWER_KEY_ICMPV6_CODE_MASK,/* u8 */
|
||||
TCA_FLOWER_KEY_ICMPV6_TYPE, /* u8 */
|
||||
TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,/* u8 */
|
||||
|
||||
TCA_FLOWER_KEY_ARP_SIP, /* be32 */
|
||||
TCA_FLOWER_KEY_ARP_SIP_MASK, /* be32 */
|
||||
TCA_FLOWER_KEY_ARP_TIP, /* be32 */
|
||||
TCA_FLOWER_KEY_ARP_TIP_MASK, /* be32 */
|
||||
TCA_FLOWER_KEY_ARP_OP, /* u8 */
|
||||
TCA_FLOWER_KEY_ARP_OP_MASK, /* u8 */
|
||||
TCA_FLOWER_KEY_ARP_SHA, /* ETH_ALEN */
|
||||
TCA_FLOWER_KEY_ARP_SHA_MASK, /* ETH_ALEN */
|
||||
TCA_FLOWER_KEY_ARP_THA, /* ETH_ALEN */
|
||||
TCA_FLOWER_KEY_ARP_THA_MASK, /* ETH_ALEN */
|
||||
|
||||
TCA_FLOWER_KEY_MPLS_TTL, /* u8 - 8 bits */
|
||||
TCA_FLOWER_KEY_MPLS_BOS, /* u8 - 1 bit */
|
||||
TCA_FLOWER_KEY_MPLS_TC, /* u8 - 3 bits */
|
||||
TCA_FLOWER_KEY_MPLS_LABEL, /* be32 - 20 bits */
|
||||
|
||||
TCA_FLOWER_KEY_TCP_FLAGS, /* be16 */
|
||||
TCA_FLOWER_KEY_TCP_FLAGS_MASK, /* be16 */
|
||||
|
||||
TCA_FLOWER_KEY_IP_TOS, /* u8 */
|
||||
TCA_FLOWER_KEY_IP_TOS_MASK, /* u8 */
|
||||
TCA_FLOWER_KEY_IP_TTL, /* u8 */
|
||||
TCA_FLOWER_KEY_IP_TTL_MASK, /* u8 */
|
||||
|
||||
TCA_FLOWER_KEY_CVLAN_ID, /* be16 */
|
||||
TCA_FLOWER_KEY_CVLAN_PRIO, /* u8 */
|
||||
TCA_FLOWER_KEY_CVLAN_ETH_TYPE, /* be16 */
|
||||
|
||||
TCA_FLOWER_KEY_ENC_IP_TOS, /* u8 */
|
||||
TCA_FLOWER_KEY_ENC_IP_TOS_MASK, /* u8 */
|
||||
TCA_FLOWER_KEY_ENC_IP_TTL, /* u8 */
|
||||
TCA_FLOWER_KEY_ENC_IP_TTL_MASK, /* u8 */
|
||||
|
||||
TCA_FLOWER_KEY_ENC_OPTS,
|
||||
TCA_FLOWER_KEY_ENC_OPTS_MASK,
|
||||
|
||||
TCA_FLOWER_IN_HW_COUNT,
|
||||
|
||||
__TCA_FLOWER_MAX,
|
||||
};
|
||||
|
||||
#define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
|
||||
|
||||
enum {
|
||||
TCA_FLOWER_KEY_ENC_OPTS_UNSPEC,
|
||||
TCA_FLOWER_KEY_ENC_OPTS_GENEVE, /* Nested
|
||||
* TCA_FLOWER_KEY_ENC_OPT_GENEVE_
|
||||
* attributes
|
||||
*/
|
||||
__TCA_FLOWER_KEY_ENC_OPTS_MAX,
|
||||
};
|
||||
|
||||
#define TCA_FLOWER_KEY_ENC_OPTS_MAX (__TCA_FLOWER_KEY_ENC_OPTS_MAX - 1)
|
||||
|
||||
enum {
|
||||
TCA_FLOWER_KEY_ENC_OPT_GENEVE_UNSPEC,
|
||||
TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS, /* u16 */
|
||||
TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE, /* u8 */
|
||||
TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA, /* 4 to 128 bytes */
|
||||
|
||||
__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX,
|
||||
};
|
||||
|
||||
#define TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX \
|
||||
(__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX - 1)
|
||||
|
||||
enum {
|
||||
TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
|
||||
TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
|
||||
};
|
||||
|
||||
/* Match-all classifier */
|
||||
|
||||
enum {
|
||||
TCA_MATCHALL_UNSPEC,
|
||||
TCA_MATCHALL_CLASSID,
|
||||
TCA_MATCHALL_ACT,
|
||||
TCA_MATCHALL_FLAGS,
|
||||
__TCA_MATCHALL_MAX,
|
||||
};
|
||||
|
||||
#define TCA_MATCHALL_MAX (__TCA_MATCHALL_MAX - 1)
|
||||
|
||||
/* Extended Matches */
|
||||
|
||||
struct tcf_ematch_tree_hdr {
|
||||
__u16 nmatches;
|
||||
__u16 progid;
|
||||
};
|
||||
|
||||
enum {
|
||||
TCA_EMATCH_TREE_UNSPEC,
|
||||
TCA_EMATCH_TREE_HDR,
|
||||
TCA_EMATCH_TREE_LIST,
|
||||
__TCA_EMATCH_TREE_MAX
|
||||
};
|
||||
#define TCA_EMATCH_TREE_MAX (__TCA_EMATCH_TREE_MAX - 1)
|
||||
|
||||
struct tcf_ematch_hdr {
|
||||
__u16 matchid;
|
||||
__u16 kind;
|
||||
__u16 flags;
|
||||
__u16 pad; /* currently unused */
|
||||
};
|
||||
|
||||
/* 0 1
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
* +-----------------------+-+-+---+
|
||||
* | Unused |S|I| R |
|
||||
* +-----------------------+-+-+---+
|
||||
*
|
||||
* R(2) ::= relation to next ematch
|
||||
* where: 0 0 END (last ematch)
|
||||
* 0 1 AND
|
||||
* 1 0 OR
|
||||
* 1 1 Unused (invalid)
|
||||
* I(1) ::= invert result
|
||||
* S(1) ::= simple payload
|
||||
*/
|
||||
#define TCF_EM_REL_END 0
|
||||
#define TCF_EM_REL_AND (1<<0)
|
||||
#define TCF_EM_REL_OR (1<<1)
|
||||
#define TCF_EM_INVERT (1<<2)
|
||||
#define TCF_EM_SIMPLE (1<<3)
|
||||
|
||||
#define TCF_EM_REL_MASK 3
|
||||
#define TCF_EM_REL_VALID(v) (((v) & TCF_EM_REL_MASK) != TCF_EM_REL_MASK)
|
||||
|
||||
enum {
|
||||
TCF_LAYER_LINK,
|
||||
TCF_LAYER_NETWORK,
|
||||
TCF_LAYER_TRANSPORT,
|
||||
__TCF_LAYER_MAX
|
||||
};
|
||||
#define TCF_LAYER_MAX (__TCF_LAYER_MAX - 1)
|
||||
|
||||
/* Ematch type assignments
|
||||
* 1..32767 Reserved for ematches inside kernel tree
|
||||
* 32768..65535 Free to use, not reliable
|
||||
*/
|
||||
#define TCF_EM_CONTAINER 0
|
||||
#define TCF_EM_CMP 1
|
||||
#define TCF_EM_NBYTE 2
|
||||
#define TCF_EM_U32 3
|
||||
#define TCF_EM_META 4
|
||||
#define TCF_EM_TEXT 5
|
||||
#define TCF_EM_VLAN 6
|
||||
#define TCF_EM_CANID 7
|
||||
#define TCF_EM_IPSET 8
|
||||
#define TCF_EM_IPT 9
|
||||
#define TCF_EM_MAX 9
|
||||
|
||||
enum {
|
||||
TCF_EM_PROG_TC
|
||||
};
|
||||
|
||||
enum {
|
||||
TCF_EM_OPND_EQ,
|
||||
TCF_EM_OPND_GT,
|
||||
TCF_EM_OPND_LT
|
||||
};
|
||||
|
||||
#endif
|
||||
1164
third_party/libbpf/include/uapi/linux/pkt_sched.h
vendored
Normal file
82
third_party/libbpf/scripts/build-fuzzers.sh
vendored
Executable file
@@ -0,0 +1,82 @@
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
|
||||
SANITIZER=${SANITIZER:-address}
|
||||
flags="-O1 -fno-omit-frame-pointer -g -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize=fuzzer-no-link"
|
||||
|
||||
export CC=${CC:-clang}
|
||||
export CFLAGS=${CFLAGS:-$flags}
|
||||
|
||||
export CXX=${CXX:-clang++}
|
||||
export CXXFLAGS=${CXXFLAGS:-$flags}
|
||||
|
||||
cd "$(dirname -- "$0")/.."
|
||||
|
||||
export OUT=${OUT:-"$(pwd)/out"}
|
||||
mkdir -p "$OUT"
|
||||
|
||||
export LIB_FUZZING_ENGINE=${LIB_FUZZING_ENGINE:--fsanitize=fuzzer}
|
||||
|
||||
# libelf is compiled with _FORTIFY_SOURCE by default and it
|
||||
# isn't compatible with MSan. It was borrowed
|
||||
# from https://github.com/google/oss-fuzz/pull/7422
|
||||
if [[ "$SANITIZER" == memory ]]; then
|
||||
CFLAGS+=" -U_FORTIFY_SOURCE"
|
||||
CXXFLAGS+=" -U_FORTIFY_SOURCE"
|
||||
fi
|
||||
|
||||
# The alignment check is turned off by default on OSS-Fuzz/CFLite so it should be
|
||||
# turned on explicitly there. It was borrowed from
|
||||
# https://github.com/google/oss-fuzz/pull/7092
|
||||
if [[ "$SANITIZER" == undefined ]]; then
|
||||
additional_ubsan_checks=alignment
|
||||
UBSAN_FLAGS="-fsanitize=$additional_ubsan_checks -fno-sanitize-recover=$additional_ubsan_checks"
|
||||
CFLAGS+=" $UBSAN_FLAGS"
|
||||
CXXFLAGS+=" $UBSAN_FLAGS"
|
||||
fi
|
||||
|
||||
# Ideally libbelf should be built using release tarballs available
|
||||
# at https://sourceware.org/elfutils/ftp/. Unfortunately sometimes they
|
||||
# fail to compile (for example, elfutils-0.185 fails to compile with LDFLAGS enabled
|
||||
# due to https://bugs.gentoo.org/794601) so let's just point the script to
|
||||
# commits referring to versions of libelf that actually can be built
|
||||
rm -rf elfutils
|
||||
git clone git://sourceware.org/git/elfutils.git
|
||||
(
|
||||
cd elfutils
|
||||
git checkout 67a187d4c1790058fc7fd218317851cb68bb087c
|
||||
git log --oneline -1
|
||||
|
||||
# ASan isn't compatible with -Wl,--no-undefined: https://github.com/google/sanitizers/issues/380
|
||||
sed -i 's/^\(NO_UNDEFINED=\).*/\1/' configure.ac
|
||||
|
||||
# ASan isn't compatible with -Wl,-z,defs either:
|
||||
# https://clang.llvm.org/docs/AddressSanitizer.html#usage
|
||||
sed -i 's/^\(ZDEFS_LDFLAGS=\).*/\1/' configure.ac
|
||||
|
||||
if [[ "$SANITIZER" == undefined ]]; then
|
||||
# That's basicaly what --enable-sanitize-undefined does to turn off unaligned access
|
||||
# elfutils heavily relies on on i386/x86_64 but without changing compiler flags along the way
|
||||
sed -i 's/\(check_undefined_val\)=[0-9]/\1=1/' configure.ac
|
||||
fi
|
||||
|
||||
autoreconf -i -f
|
||||
if ! ./configure --enable-maintainer-mode --disable-debuginfod --disable-libdebuginfod \
|
||||
--disable-demangler --without-bzlib --without-lzma --without-zstd \
|
||||
CC="$CC" CFLAGS="-Wno-error $CFLAGS" CXX="$CXX" CXXFLAGS="-Wno-error $CXXFLAGS" LDFLAGS="$CFLAGS"; then
|
||||
cat config.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
make -C config -j$(nproc) V=1
|
||||
make -C lib -j$(nproc) V=1
|
||||
make -C libelf -j$(nproc) V=1
|
||||
)
|
||||
|
||||
make -C src BUILD_STATIC_ONLY=y V=1 clean
|
||||
make -C src -j$(nproc) CFLAGS="-I$(pwd)/elfutils/libelf $CFLAGS" BUILD_STATIC_ONLY=y V=1
|
||||
|
||||
$CC $CFLAGS -Isrc -Iinclude -Iinclude/uapi -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c fuzz/bpf-object-fuzzer.c -o bpf-object-fuzzer.o
|
||||
$CXX $CXXFLAGS $LIB_FUZZING_ENGINE bpf-object-fuzzer.o src/libbpf.a "$(pwd)/elfutils/libelf/libelf.a" -l:libz.a -o "$OUT/bpf-object-fuzzer"
|
||||
|
||||
cp fuzz/bpf-object-fuzzer_seed_corpus.zip "$OUT"
|
||||
105
third_party/libbpf/scripts/coverity.sh
vendored
Executable file
@@ -0,0 +1,105 @@
|
||||
#!/bin/bash
|
||||
# Taken from: https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh
|
||||
# Local changes are annotated with "#[local]"
|
||||
|
||||
set -e
|
||||
|
||||
# Environment check
|
||||
echo -e "\033[33;1mNote: COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN are available on Project Settings page on scan.coverity.com\033[0m"
|
||||
[ -z "$COVERITY_SCAN_PROJECT_NAME" ] && echo "ERROR: COVERITY_SCAN_PROJECT_NAME must be set" && exit 1
|
||||
[ -z "$COVERITY_SCAN_NOTIFICATION_EMAIL" ] && echo "ERROR: COVERITY_SCAN_NOTIFICATION_EMAIL must be set" && exit 1
|
||||
[ -z "$COVERITY_SCAN_BRANCH_PATTERN" ] && echo "ERROR: COVERITY_SCAN_BRANCH_PATTERN must be set" && exit 1
|
||||
[ -z "$COVERITY_SCAN_BUILD_COMMAND" ] && echo "ERROR: COVERITY_SCAN_BUILD_COMMAND must be set" && exit 1
|
||||
[ -z "$COVERITY_SCAN_TOKEN" ] && echo "ERROR: COVERITY_SCAN_TOKEN must be set" && exit 1
|
||||
|
||||
PLATFORM=`uname`
|
||||
#[local] Use /var/tmp for TOOL_ARCHIVE and TOOL_BASE, as on certain systems
|
||||
# /tmp is tmpfs and is sometimes too small to handle all necessary tooling
|
||||
TOOL_ARCHIVE=/var//tmp/cov-analysis-${PLATFORM}.tgz
|
||||
TOOL_URL=https://scan.coverity.com/download/${PLATFORM}
|
||||
TOOL_BASE=/var/tmp/coverity-scan-analysis
|
||||
UPLOAD_URL="https://scan.coverity.com/builds"
|
||||
SCAN_URL="https://scan.coverity.com"
|
||||
|
||||
# Do not run on pull requests
|
||||
if [ "${TRAVIS_PULL_REQUEST}" = "true" ]; then
|
||||
echo -e "\033[33;1mINFO: Skipping Coverity Analysis: branch is a pull request.\033[0m"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Verify this branch should run
|
||||
IS_COVERITY_SCAN_BRANCH=`ruby -e "puts '${TRAVIS_BRANCH}' =~ /\\A$COVERITY_SCAN_BRANCH_PATTERN\\z/ ? 1 : 0"`
|
||||
if [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then
|
||||
echo -e "\033[33;1mCoverity Scan configured to run on branch ${TRAVIS_BRANCH}\033[0m"
|
||||
else
|
||||
echo -e "\033[33;1mCoverity Scan NOT configured to run on branch ${TRAVIS_BRANCH}\033[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify upload is permitted
|
||||
AUTH_RES=`curl -s --form project="$COVERITY_SCAN_PROJECT_NAME" --form token="$COVERITY_SCAN_TOKEN" $SCAN_URL/api/upload_permitted`
|
||||
if [ "$AUTH_RES" = "Access denied" ]; then
|
||||
echo -e "\033[33;1mCoverity Scan API access denied. Check COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN.\033[0m"
|
||||
exit 1
|
||||
else
|
||||
AUTH=`echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['upload_permitted']"`
|
||||
if [ "$AUTH" = "true" ]; then
|
||||
echo -e "\033[33;1mCoverity Scan analysis authorized per quota.\033[0m"
|
||||
else
|
||||
WHEN=`echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['next_upload_permitted_at']"`
|
||||
echo -e "\033[33;1mCoverity Scan analysis NOT authorized until $WHEN.\033[0m"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d $TOOL_BASE ]; then
|
||||
# Download Coverity Scan Analysis Tool
|
||||
if [ ! -e $TOOL_ARCHIVE ]; then
|
||||
echo -e "\033[33;1mDownloading Coverity Scan Analysis Tool...\033[0m"
|
||||
wget -nv -O $TOOL_ARCHIVE $TOOL_URL --post-data "project=$COVERITY_SCAN_PROJECT_NAME&token=$COVERITY_SCAN_TOKEN"
|
||||
fi
|
||||
|
||||
# Extract Coverity Scan Analysis Tool
|
||||
echo -e "\033[33;1mExtracting Coverity Scan Analysis Tool...\033[0m"
|
||||
mkdir -p $TOOL_BASE
|
||||
pushd $TOOL_BASE
|
||||
tar xzf $TOOL_ARCHIVE
|
||||
popd
|
||||
fi
|
||||
|
||||
TOOL_DIR=`find $TOOL_BASE -type d -name 'cov-analysis*'`
|
||||
export PATH=$TOOL_DIR/bin:$PATH
|
||||
|
||||
# Build
|
||||
echo -e "\033[33;1mRunning Coverity Scan Analysis Tool...\033[0m"
|
||||
COV_BUILD_OPTIONS=""
|
||||
#COV_BUILD_OPTIONS="--return-emit-failures 8 --parse-error-threshold 85"
|
||||
RESULTS_DIR="cov-int"
|
||||
eval "${COVERITY_SCAN_BUILD_COMMAND_PREPEND}"
|
||||
COVERITY_UNSUPPORTED=1 cov-build --dir $RESULTS_DIR $COV_BUILD_OPTIONS $COVERITY_SCAN_BUILD_COMMAND
|
||||
cov-import-scm --dir $RESULTS_DIR --scm git --log $RESULTS_DIR/scm_log.txt 2>&1
|
||||
|
||||
# Upload results
|
||||
echo -e "\033[33;1mTarring Coverity Scan Analysis results...\033[0m"
|
||||
RESULTS_ARCHIVE=analysis-results.tgz
|
||||
tar czf $RESULTS_ARCHIVE $RESULTS_DIR
|
||||
SHA=`git rev-parse --short HEAD`
|
||||
|
||||
echo -e "\033[33;1mUploading Coverity Scan Analysis results...\033[0m"
|
||||
response=$(curl \
|
||||
--silent --write-out "\n%{http_code}\n" \
|
||||
--form project=$COVERITY_SCAN_PROJECT_NAME \
|
||||
--form token=$COVERITY_SCAN_TOKEN \
|
||||
--form email=$COVERITY_SCAN_NOTIFICATION_EMAIL \
|
||||
--form file=@$RESULTS_ARCHIVE \
|
||||
--form version=$SHA \
|
||||
--form description="Travis CI build" \
|
||||
$UPLOAD_URL)
|
||||
status_code=$(echo "$response" | sed -n '$p')
|
||||
#[local] Coverity used to return 201 on success, but it's 200 now
|
||||
# See https://github.com/systemd/systemd/blob/master/tools/coverity.sh#L145
|
||||
if [ "$status_code" != "200" ]; then
|
||||
TEXT=$(echo "$response" | sed '$d')
|
||||
echo -e "\033[33;1mCoverity Scan upload failed: $TEXT.\033[0m"
|
||||
exit 1
|
||||
fi
|
||||
355
third_party/libbpf/scripts/sync-kernel.sh
vendored
Executable file
@@ -0,0 +1,355 @@
|
||||
#!/bin/bash
|
||||
|
||||
usage () {
|
||||
echo "USAGE: ./sync-kernel.sh <libbpf-repo> <kernel-repo> <bpf-branch>"
|
||||
echo ""
|
||||
echo "Set BPF_NEXT_BASELINE to override bpf-next tree commit, otherwise read from <libbpf-repo>/CHECKPOINT-COMMIT."
|
||||
echo "Set BPF_BASELINE to override bpf tree commit, otherwise read from <libbpf-repo>/BPF-CHECKPOINT-COMMIT."
|
||||
echo "Set MANUAL_MODE to 1 to manually control every cherry-picked commits."
|
||||
exit 1
|
||||
}
|
||||
|
||||
set -eu
|
||||
|
||||
LIBBPF_REPO=${1-""}
|
||||
LINUX_REPO=${2-""}
|
||||
BPF_BRANCH=${3-""}
|
||||
BASELINE_COMMIT=${BPF_NEXT_BASELINE:-$(cat ${LIBBPF_REPO}/CHECKPOINT-COMMIT)}
|
||||
BPF_BASELINE_COMMIT=${BPF_BASELINE:-$(cat ${LIBBPF_REPO}/BPF-CHECKPOINT-COMMIT)}
|
||||
|
||||
if [ -z "${LIBBPF_REPO}" ] || [ -z "${LINUX_REPO}" ]; then
|
||||
echo "Error: libbpf or linux repos are not specified"
|
||||
usage
|
||||
fi
|
||||
if [ -z "${BPF_BRANCH}" ]; then
|
||||
echo "Error: linux's bpf tree branch is not specified"
|
||||
usage
|
||||
fi
|
||||
if [ -z "${BASELINE_COMMIT}" ] || [ -z "${BPF_BASELINE_COMMIT}" ]; then
|
||||
echo "Error: bpf or bpf-next baseline commits are not provided"
|
||||
usage
|
||||
fi
|
||||
|
||||
SUFFIX=$(date --utc +%Y-%m-%dT%H-%M-%S.%3NZ)
|
||||
WORKDIR=$(pwd)
|
||||
TMP_DIR=$(mktemp -d)
|
||||
|
||||
trap "cd ${WORKDIR}; exit" INT TERM EXIT
|
||||
|
||||
declare -A PATH_MAP
|
||||
PATH_MAP=( \
|
||||
[tools/lib/bpf]=src \
|
||||
[tools/include/uapi/linux/bpf_common.h]=include/uapi/linux/bpf_common.h \
|
||||
[tools/include/uapi/linux/bpf.h]=include/uapi/linux/bpf.h \
|
||||
[tools/include/uapi/linux/btf.h]=include/uapi/linux/btf.h \
|
||||
[tools/include/uapi/linux/fcntl.h]=include/uapi/linux/fcntl.h \
|
||||
[tools/include/uapi/linux/openat2.h]=include/uapi/linux/openat2.h \
|
||||
[tools/include/uapi/linux/if_link.h]=include/uapi/linux/if_link.h \
|
||||
[tools/include/uapi/linux/if_xdp.h]=include/uapi/linux/if_xdp.h \
|
||||
[tools/include/uapi/linux/netdev.h]=include/uapi/linux/netdev.h \
|
||||
[tools/include/uapi/linux/netlink.h]=include/uapi/linux/netlink.h \
|
||||
[tools/include/uapi/linux/pkt_cls.h]=include/uapi/linux/pkt_cls.h \
|
||||
[tools/include/uapi/linux/pkt_sched.h]=include/uapi/linux/pkt_sched.h \
|
||||
[include/uapi/linux/perf_event.h]=include/uapi/linux/perf_event.h \
|
||||
[Documentation/bpf/libbpf]=docs \
|
||||
)
|
||||
|
||||
LIBBPF_PATHS=("${!PATH_MAP[@]}" ":^tools/lib/bpf/Makefile" ":^tools/lib/bpf/Build" ":^tools/lib/bpf/.gitignore" ":^tools/include/tools/libc_compat.h")
|
||||
LIBBPF_VIEW_PATHS=("${PATH_MAP[@]}")
|
||||
LIBBPF_VIEW_EXCLUDE_REGEX='^src/(Makefile|Build|test_libbpf\.c|bpf_helper_defs\.h|\.gitignore)$|^docs/(\.gitignore|api\.rst|conf\.py)$|^docs/sphinx/.*'
|
||||
LINUX_VIEW_EXCLUDE_REGEX='^include/tools/libc_compat.h$'
|
||||
|
||||
LIBBPF_TREE_FILTER="mkdir -p __libbpf/include/uapi/linux __libbpf/include/tools && "$'\\\n'
|
||||
for p in "${!PATH_MAP[@]}"; do
|
||||
LIBBPF_TREE_FILTER+="git mv -kf ${p} __libbpf/${PATH_MAP[${p}]} && "$'\\\n'
|
||||
done
|
||||
LIBBPF_TREE_FILTER+="git rm --ignore-unmatch -f __libbpf/src/{Makefile,Build,test_libbpf.c,.gitignore} >/dev/null"
|
||||
|
||||
cd_to()
|
||||
{
|
||||
cd ${WORKDIR} && cd "$1"
|
||||
}
|
||||
|
||||
# Output brief single-line commit description
|
||||
# $1 - commit ref
|
||||
commit_desc()
|
||||
{
|
||||
git log -n1 --pretty='%h ("%s")' $1
|
||||
}
|
||||
|
||||
# Create commit single-line signature, which consists of:
|
||||
# - full commit subject
|
||||
# - author date in ISO8601 format
|
||||
# - full commit body with newlines replaced with vertical bars (|)
|
||||
# - shortstat appended at the end
|
||||
# The idea is that this single-line signature is good enough to make final
|
||||
# decision about whether two commits are the same, across different repos.
|
||||
# $1 - commit ref
|
||||
# $2 - paths filter
|
||||
commit_signature()
|
||||
{
|
||||
local ref=$1
|
||||
shift
|
||||
git show --pretty='("%s")|%aI|%b' --shortstat $ref -- "${@-.}" | tr '\n' '|'
|
||||
}
|
||||
|
||||
# Cherry-pick commits touching libbpf-related files
|
||||
# $1 - baseline_tag
|
||||
# $2 - tip_tag
|
||||
cherry_pick_commits()
|
||||
{
|
||||
local manual_mode=${MANUAL_MODE:-0}
|
||||
local baseline_tag=$1
|
||||
local tip_tag=$2
|
||||
local new_commits
|
||||
local signature
|
||||
local should_skip
|
||||
local synced_cnt
|
||||
local manual_check
|
||||
local libbpf_conflict_cnt
|
||||
local desc
|
||||
|
||||
new_commits=$(git rev-list --no-merges --topo-order --reverse ${baseline_tag}..${tip_tag} -- "${LIBBPF_PATHS[@]}")
|
||||
for new_commit in ${new_commits}; do
|
||||
desc="$(commit_desc ${new_commit})"
|
||||
signature="$(commit_signature ${new_commit} "${LIBBPF_PATHS[@]}")"
|
||||
synced_cnt=$(grep -F "${signature}" ${TMP_DIR}/libbpf_commits.txt | wc -l)
|
||||
manual_check=0
|
||||
if ((${synced_cnt} > 0)); then
|
||||
# commit with the same subject is already in libbpf, but it's
|
||||
# not 100% the same commit, so check with user
|
||||
echo "Commit '${desc}' is synced into libbpf as:"
|
||||
grep -F "${signature}" ${TMP_DIR}/libbpf_commits.txt | \
|
||||
cut -d'|' -f1 | sed -e 's/^/- /'
|
||||
if ((${manual_mode} != 1 && ${synced_cnt} == 1)); then
|
||||
echo "Skipping '${desc}' due to unique match..."
|
||||
continue
|
||||
fi
|
||||
if ((${synced_cnt} > 1)); then
|
||||
echo "'${desc} matches multiple commits, please, double-check!"
|
||||
manual_check=1
|
||||
fi
|
||||
fi
|
||||
if ((${manual_mode} == 1 || ${manual_check} == 1)); then
|
||||
read -p "Do you want to skip '${desc}'? [y/N]: " should_skip
|
||||
case "${should_skip}" in
|
||||
"y" | "Y")
|
||||
echo "Skipping '${desc}'..."
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
# commit hasn't been synced into libbpf yet
|
||||
echo "Picking '${desc}'..."
|
||||
if ! git cherry-pick ${new_commit} &>/dev/null; then
|
||||
echo "Warning! Cherry-picking '${desc} failed, checking if it's non-libbpf files causing problems..."
|
||||
libbpf_conflict_cnt=$(git diff --name-only --diff-filter=U -- "${LIBBPF_PATHS[@]}" | wc -l)
|
||||
conflict_cnt=$(git diff --name-only | wc -l)
|
||||
prompt_resolution=1
|
||||
|
||||
if ((${libbpf_conflict_cnt} == 0)); then
|
||||
echo "Looks like only non-libbpf files have conflicts, ignoring..."
|
||||
if ((${conflict_cnt} == 0)); then
|
||||
echo "Empty cherry-pick, skipping it..."
|
||||
git cherry-pick --abort
|
||||
continue
|
||||
fi
|
||||
|
||||
git add .
|
||||
# GIT_EDITOR=true to avoid editor popping up to edit commit message
|
||||
if ! GIT_EDITOR=true git cherry-pick --continue &>/dev/null; then
|
||||
echo "Error! That still failed! Please resolve manually."
|
||||
else
|
||||
echo "Success! All cherry-pick conflicts were resolved for '${desc}'!"
|
||||
prompt_resolution=0
|
||||
fi
|
||||
fi
|
||||
|
||||
if ((${prompt_resolution} == 1)); then
|
||||
read -p "Error! Cherry-picking '${desc}' failed, please fix manually and press <return> to proceed..."
|
||||
fi
|
||||
fi
|
||||
# Append signature of just cherry-picked commit to avoid
|
||||
# potentially cherry-picking the same commit twice later when
|
||||
# processing bpf tree commits. At this point we don't know yet
|
||||
# the final commit sha in libbpf repo, so we record Linux SHA
|
||||
# instead as LINUX_<sha>.
|
||||
echo LINUX_$(git log --pretty='%h' -n1) "${signature}" >> ${TMP_DIR}/libbpf_commits.txt
|
||||
done
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
echo "Cleaning up..."
|
||||
rm -r ${TMP_DIR}
|
||||
cd_to ${LINUX_REPO}
|
||||
git checkout ${TIP_SYM_REF}
|
||||
git branch -D ${BASELINE_TAG} ${TIP_TAG} ${BPF_BASELINE_TAG} ${BPF_TIP_TAG} \
|
||||
${SQUASH_BASE_TAG} ${SQUASH_TIP_TAG} ${VIEW_TAG} || true
|
||||
|
||||
cd_to .
|
||||
echo "DONE."
|
||||
}
|
||||
|
||||
|
||||
cd_to ${LIBBPF_REPO}
|
||||
GITHUB_ABS_DIR=$(pwd)
|
||||
echo "Dumping existing libbpf commit signatures..."
|
||||
for h in $(git log --pretty='%h' -n500); do
|
||||
echo $h "$(commit_signature $h)" >> ${TMP_DIR}/libbpf_commits.txt
|
||||
done
|
||||
|
||||
# Use current kernel repo HEAD as a source of patches
|
||||
cd_to ${LINUX_REPO}
|
||||
LINUX_ABS_DIR=$(pwd)
|
||||
TIP_SYM_REF=$(git symbolic-ref -q --short HEAD || git rev-parse HEAD)
|
||||
TIP_COMMIT=$(git rev-parse HEAD)
|
||||
BPF_TIP_COMMIT=$(git rev-parse ${BPF_BRANCH})
|
||||
BASELINE_TAG=libbpf-baseline-${SUFFIX}
|
||||
TIP_TAG=libbpf-tip-${SUFFIX}
|
||||
BPF_BASELINE_TAG=libbpf-bpf-baseline-${SUFFIX}
|
||||
BPF_TIP_TAG=libbpf-bpf-tip-${SUFFIX}
|
||||
VIEW_TAG=libbpf-view-${SUFFIX}
|
||||
LIBBPF_SYNC_TAG=libbpf-sync-${SUFFIX}
|
||||
|
||||
# Squash state of kernel repo at baseline into single commit
|
||||
SQUASH_BASE_TAG=libbpf-squash-base-${SUFFIX}
|
||||
SQUASH_TIP_TAG=libbpf-squash-tip-${SUFFIX}
|
||||
SQUASH_COMMIT=$(git commit-tree ${BASELINE_COMMIT}^{tree} -m "BASELINE SQUASH ${BASELINE_COMMIT}")
|
||||
|
||||
echo "WORKDIR: ${WORKDIR}"
|
||||
echo "LINUX REPO: ${LINUX_REPO}"
|
||||
echo "LIBBPF REPO: ${LIBBPF_REPO}"
|
||||
echo "TEMP DIR: ${TMP_DIR}"
|
||||
echo "SUFFIX: ${SUFFIX}"
|
||||
echo "BASE COMMIT: '$(commit_desc ${BASELINE_COMMIT})'"
|
||||
echo "TIP COMMIT: '$(commit_desc ${TIP_COMMIT})'"
|
||||
echo "BPF BASE COMMIT: '$(commit_desc ${BPF_BASELINE_COMMIT})'"
|
||||
echo "BPF TIP COMMIT: '$(commit_desc ${BPF_TIP_COMMIT})'"
|
||||
echo "SQUASH COMMIT: ${SQUASH_COMMIT}"
|
||||
echo "BASELINE TAG: ${BASELINE_TAG}"
|
||||
echo "TIP TAG: ${TIP_TAG}"
|
||||
echo "BPF BASELINE TAG: ${BPF_BASELINE_TAG}"
|
||||
echo "BPF TIP TAG: ${BPF_TIP_TAG}"
|
||||
echo "SQUASH BASE TAG: ${SQUASH_BASE_TAG}"
|
||||
echo "SQUASH TIP TAG: ${SQUASH_TIP_TAG}"
|
||||
echo "VIEW TAG: ${VIEW_TAG}"
|
||||
echo "LIBBPF SYNC TAG: ${LIBBPF_SYNC_TAG}"
|
||||
echo "PATCHES: ${TMP_DIR}/patches"
|
||||
|
||||
git branch ${BASELINE_TAG} ${BASELINE_COMMIT}
|
||||
git branch ${TIP_TAG} ${TIP_COMMIT}
|
||||
git branch ${BPF_BASELINE_TAG} ${BPF_BASELINE_COMMIT}
|
||||
git branch ${BPF_TIP_TAG} ${BPF_TIP_COMMIT}
|
||||
git branch ${SQUASH_BASE_TAG} ${SQUASH_COMMIT}
|
||||
git checkout -b ${SQUASH_TIP_TAG} ${SQUASH_COMMIT}
|
||||
|
||||
# Cherry-pick new commits onto squashed baseline commit
|
||||
cherry_pick_commits ${BASELINE_TAG} ${TIP_TAG}
|
||||
cherry_pick_commits ${BPF_BASELINE_TAG} ${BPF_TIP_TAG}
|
||||
|
||||
# Move all libbpf files into __libbpf directory.
|
||||
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch --prune-empty -f --tree-filter "${LIBBPF_TREE_FILTER}" ${SQUASH_TIP_TAG} ${SQUASH_BASE_TAG}
|
||||
# Make __libbpf a new root directory
|
||||
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch --prune-empty -f --subdirectory-filter __libbpf ${SQUASH_TIP_TAG} ${SQUASH_BASE_TAG}
|
||||
|
||||
# If there are no new commits with libbpf-related changes, bail out
|
||||
COMMIT_CNT=$(git rev-list --count ${SQUASH_BASE_TAG}..${SQUASH_TIP_TAG})
|
||||
if ((${COMMIT_CNT} <= 0)); then
|
||||
echo "No new changes to apply, we are done!"
|
||||
cleanup
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Exclude baseline commit and generate nice cover letter with summary
|
||||
git format-patch --no-signature ${SQUASH_BASE_TAG}..${SQUASH_TIP_TAG} --cover-letter -o ${TMP_DIR}/patches
|
||||
|
||||
# Now is time to re-apply libbpf-related linux patches to libbpf repo
|
||||
cd_to ${LIBBPF_REPO}
|
||||
git checkout -b ${LIBBPF_SYNC_TAG}
|
||||
|
||||
for patch in $(ls -1 ${TMP_DIR}/patches | tail -n +2); do
|
||||
if ! git am -3 --committer-date-is-author-date "${TMP_DIR}/patches/${patch}"; then
|
||||
if ! patch -p1 --merge < "${TMP_DIR}/patches/${patch}"; then
|
||||
read -p "Applying ${TMP_DIR}/patches/${patch} failed, please resolve manually and press <return> to proceed..."
|
||||
fi
|
||||
git am --continue
|
||||
fi
|
||||
done
|
||||
|
||||
# Generate bpf_helper_defs.h and commit, if anything changed
|
||||
# restore Linux tip to use bpf_doc.py
|
||||
cd_to ${LINUX_REPO}
|
||||
git checkout ${TIP_TAG}
|
||||
# re-generate bpf_helper_defs.h
|
||||
cd_to ${LIBBPF_REPO}
|
||||
"${LINUX_ABS_DIR}/scripts/bpf_doc.py" --header \
|
||||
--file include/uapi/linux/bpf.h > src/bpf_helper_defs.h
|
||||
# if anything changed, commit it
|
||||
helpers_changes=$(git status --porcelain src/bpf_helper_defs.h | wc -l)
|
||||
if ((${helpers_changes} == 1)); then
|
||||
git add src/bpf_helper_defs.h
|
||||
git commit -s -m "sync: auto-generate latest BPF helpers
|
||||
|
||||
Latest changes to BPF helper definitions.
|
||||
" -- src/bpf_helper_defs.h
|
||||
fi
|
||||
|
||||
# Use generated cover-letter as a template for "sync commit" with
|
||||
# baseline and checkpoint commits from kernel repo (and leave summary
|
||||
# from cover letter intact, of course)
|
||||
echo ${TIP_COMMIT} > CHECKPOINT-COMMIT && \
|
||||
echo ${BPF_TIP_COMMIT} > BPF-CHECKPOINT-COMMIT && \
|
||||
git add CHECKPOINT-COMMIT && \
|
||||
git add BPF-CHECKPOINT-COMMIT && \
|
||||
awk '/\*\*\* BLURB HERE \*\*\*/ {p=1} p' ${TMP_DIR}/patches/0000-cover-letter.patch | \
|
||||
sed "s/\*\*\* BLURB HERE \*\*\*/\
|
||||
sync: latest libbpf changes from kernel\n\
|
||||
\n\
|
||||
Syncing latest libbpf commits from kernel repository.\n\
|
||||
Baseline bpf-next commit: ${BASELINE_COMMIT}\n\
|
||||
Checkpoint bpf-next commit: ${TIP_COMMIT}\n\
|
||||
Baseline bpf commit: ${BPF_BASELINE_COMMIT}\n\
|
||||
Checkpoint bpf commit: ${BPF_TIP_COMMIT}/" | \
|
||||
git commit -s --file=-
|
||||
|
||||
echo "SUCCESS! ${COMMIT_CNT} commits synced."
|
||||
|
||||
echo "Verifying Linux's and Github's libbpf state"
|
||||
|
||||
cd_to ${LINUX_REPO}
|
||||
git checkout -b ${VIEW_TAG} ${TIP_COMMIT}
|
||||
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f --tree-filter "${LIBBPF_TREE_FILTER}" ${VIEW_TAG}^..${VIEW_TAG}
|
||||
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f --subdirectory-filter __libbpf ${VIEW_TAG}^..${VIEW_TAG}
|
||||
git ls-files -- "${LIBBPF_VIEW_PATHS[@]}" | grep -v -E "${LINUX_VIEW_EXCLUDE_REGEX}" > ${TMP_DIR}/linux-view.ls
|
||||
|
||||
cd_to ${LIBBPF_REPO}
|
||||
git ls-files -- "${LIBBPF_VIEW_PATHS[@]}" | grep -v -E "${LIBBPF_VIEW_EXCLUDE_REGEX}" > ${TMP_DIR}/github-view.ls
|
||||
|
||||
echo "Comparing list of files..."
|
||||
diff -u ${TMP_DIR}/linux-view.ls ${TMP_DIR}/github-view.ls
|
||||
echo "Comparing file contents..."
|
||||
CONSISTENT=1
|
||||
for F in $(cat ${TMP_DIR}/linux-view.ls); do
|
||||
if ! diff -u "${LINUX_ABS_DIR}/${F}" "${GITHUB_ABS_DIR}/${F}"; then
|
||||
echo "${LINUX_ABS_DIR}/${F} and ${GITHUB_ABS_DIR}/${F} are different!"
|
||||
CONSISTENT=0
|
||||
fi
|
||||
done
|
||||
if ((${CONSISTENT} == 1)); then
|
||||
echo "Great! Content is identical!"
|
||||
else
|
||||
ignore_inconsistency=n
|
||||
echo "Unfortunately, there are some inconsistencies, please double check."
|
||||
read -p "Does everything look good? [y/N]: " ignore_inconsistency
|
||||
case "${ignore_inconsistency}" in
|
||||
"y" | "Y")
|
||||
echo "Ok, proceeding..."
|
||||
;;
|
||||
*)
|
||||
echo "Oops, exiting with error..."
|
||||
exit 4
|
||||
esac
|
||||
fi
|
||||
|
||||
cleanup
|
||||
6
third_party/libbpf/src/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
*.o
|
||||
*.a
|
||||
/libbpf.pc
|
||||
/libbpf.so*
|
||||
/staticobjs
|
||||
/sharedobjs
|
||||
183
third_party/libbpf/src/Makefile
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
|
||||
ifeq ($(V),1)
|
||||
Q =
|
||||
msg =
|
||||
else
|
||||
Q = @
|
||||
msg = @printf ' %-8s %s%s\n' "$(1)" "$(2)" "$(if $(3), $(3))";
|
||||
endif
|
||||
|
||||
LIBBPF_MAJOR_VERSION := 1
|
||||
LIBBPF_MINOR_VERSION := 3
|
||||
LIBBPF_PATCH_VERSION := 0
|
||||
LIBBPF_VERSION := $(LIBBPF_MAJOR_VERSION).$(LIBBPF_MINOR_VERSION).$(LIBBPF_PATCH_VERSION)
|
||||
LIBBPF_MAJMIN_VERSION := $(LIBBPF_MAJOR_VERSION).$(LIBBPF_MINOR_VERSION).0
|
||||
LIBBPF_MAP_VERSION := $(shell grep -oE '^LIBBPF_([0-9.]+)' libbpf.map | sort -rV | head -n1 | cut -d'_' -f2)
|
||||
ifneq ($(LIBBPF_MAJMIN_VERSION), $(LIBBPF_MAP_VERSION))
|
||||
$(error Libbpf release ($(LIBBPF_VERSION)) and map ($(LIBBPF_MAP_VERSION)) versions are out of sync!)
|
||||
endif
|
||||
|
||||
define allow-override
|
||||
$(if $(or $(findstring environment,$(origin $(1))),\
|
||||
$(findstring command line,$(origin $(1)))),,\
|
||||
$(eval $(1) = $(2)))
|
||||
endef
|
||||
|
||||
$(call allow-override,CC,$(CROSS_COMPILE)cc)
|
||||
$(call allow-override,LD,$(CROSS_COMPILE)ld)
|
||||
|
||||
TOPDIR = ..
|
||||
|
||||
INCLUDES := -I. -I$(TOPDIR)/include -I$(TOPDIR)/include/uapi
|
||||
ALL_CFLAGS := $(INCLUDES)
|
||||
|
||||
SHARED_CFLAGS += -fPIC -fvisibility=hidden -DSHARED
|
||||
|
||||
CFLAGS ?= -g -O2 -Werror -Wall -std=gnu89
|
||||
ALL_CFLAGS += $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 $(EXTRA_CFLAGS)
|
||||
ALL_LDFLAGS += $(LDFLAGS) $(EXTRA_LDFLAGS)
|
||||
|
||||
ifdef NO_PKG_CONFIG
|
||||
ALL_LDFLAGS += -lelf -lz
|
||||
else
|
||||
PKG_CONFIG ?= pkg-config
|
||||
ALL_CFLAGS += $(shell $(PKG_CONFIG) --cflags libelf zlib)
|
||||
ALL_LDFLAGS += $(shell $(PKG_CONFIG) --libs libelf zlib)
|
||||
endif
|
||||
|
||||
OBJDIR ?= .
|
||||
SHARED_OBJDIR := $(OBJDIR)/sharedobjs
|
||||
STATIC_OBJDIR := $(OBJDIR)/staticobjs
|
||||
OBJS := bpf.o btf.o libbpf.o libbpf_errno.o netlink.o \
|
||||
nlattr.o str_error.o libbpf_probes.o bpf_prog_linfo.o \
|
||||
btf_dump.o hashmap.o ringbuf.o strset.o linker.o gen_loader.o \
|
||||
relo_core.o usdt.o zip.o
|
||||
SHARED_OBJS := $(addprefix $(SHARED_OBJDIR)/,$(OBJS))
|
||||
STATIC_OBJS := $(addprefix $(STATIC_OBJDIR)/,$(OBJS))
|
||||
|
||||
STATIC_LIBS := $(OBJDIR)/libbpf.a
|
||||
ifndef BUILD_STATIC_ONLY
|
||||
SHARED_LIBS := $(OBJDIR)/libbpf.so \
|
||||
$(OBJDIR)/libbpf.so.$(LIBBPF_MAJOR_VERSION) \
|
||||
$(OBJDIR)/libbpf.so.$(LIBBPF_VERSION)
|
||||
VERSION_SCRIPT := libbpf.map
|
||||
endif
|
||||
|
||||
HEADERS := bpf.h libbpf.h btf.h libbpf_common.h libbpf_legacy.h \
|
||||
bpf_helpers.h bpf_helper_defs.h bpf_tracing.h \
|
||||
bpf_endian.h bpf_core_read.h skel_internal.h libbpf_version.h \
|
||||
usdt.bpf.h
|
||||
UAPI_HEADERS := $(addprefix $(TOPDIR)/include/uapi/linux/,\
|
||||
bpf.h bpf_common.h btf.h)
|
||||
|
||||
PC_FILE := $(OBJDIR)/libbpf.pc
|
||||
|
||||
INSTALL = install
|
||||
|
||||
DESTDIR ?=
|
||||
|
||||
HOSTARCH = $(firstword $(subst -, ,$(shell $(CC) -dumpmachine)))
|
||||
ifeq ($(filter-out %64 %64be %64eb %64le %64el s390x, $(HOSTARCH)),)
|
||||
LIBSUBDIR := lib64
|
||||
else
|
||||
LIBSUBDIR := lib
|
||||
endif
|
||||
|
||||
# By default let the pc file itself use ${prefix} in includedir/libdir so that
|
||||
# the prefix can be overridden at runtime (eg: --define-prefix)
|
||||
ifndef LIBDIR
|
||||
LIBDIR_PC := $$\{prefix\}/$(LIBSUBDIR)
|
||||
else
|
||||
LIBDIR_PC := $(LIBDIR)
|
||||
endif
|
||||
PREFIX ?= /usr
|
||||
LIBDIR ?= $(PREFIX)/$(LIBSUBDIR)
|
||||
INCLUDEDIR ?= $(PREFIX)/include
|
||||
UAPIDIR ?= $(PREFIX)/include
|
||||
|
||||
TAGS_PROG := $(if $(shell which etags 2>/dev/null),etags,ctags)
|
||||
|
||||
all: $(STATIC_LIBS) $(SHARED_LIBS) $(PC_FILE)
|
||||
|
||||
$(OBJDIR)/libbpf.a: $(STATIC_OBJS)
|
||||
$(call msg,AR,$@)
|
||||
$(Q)$(AR) rcs $@ $^
|
||||
|
||||
$(OBJDIR)/libbpf.so: $(OBJDIR)/libbpf.so.$(LIBBPF_MAJOR_VERSION)
|
||||
$(Q)ln -sf $(^F) $@
|
||||
|
||||
$(OBJDIR)/libbpf.so.$(LIBBPF_MAJOR_VERSION): $(OBJDIR)/libbpf.so.$(LIBBPF_VERSION)
|
||||
$(Q)ln -sf $(^F) $@
|
||||
|
||||
$(OBJDIR)/libbpf.so.$(LIBBPF_VERSION): $(SHARED_OBJS)
|
||||
$(call msg,CC,$@)
|
||||
$(Q)$(CC) -shared -Wl,--version-script=$(VERSION_SCRIPT) \
|
||||
-Wl,-soname,libbpf.so.$(LIBBPF_MAJOR_VERSION) \
|
||||
$^ $(ALL_LDFLAGS) -o $@
|
||||
|
||||
$(OBJDIR)/libbpf.pc: force
|
||||
$(Q)sed -e "s|@PREFIX@|$(PREFIX)|" \
|
||||
-e "s|@LIBDIR@|$(LIBDIR_PC)|" \
|
||||
-e "s|@VERSION@|$(LIBBPF_VERSION)|" \
|
||||
< libbpf.pc.template > $@
|
||||
|
||||
$(STATIC_OBJDIR) $(SHARED_OBJDIR):
|
||||
$(call msg,MKDIR,$@)
|
||||
$(Q)mkdir -p $@
|
||||
|
||||
$(STATIC_OBJDIR)/%.o: %.c | $(STATIC_OBJDIR)
|
||||
$(call msg,CC,$@)
|
||||
$(Q)$(CC) $(ALL_CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||
|
||||
$(SHARED_OBJDIR)/%.o: %.c | $(SHARED_OBJDIR)
|
||||
$(call msg,CC,$@)
|
||||
$(Q)$(CC) $(ALL_CFLAGS) $(SHARED_CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||
|
||||
define do_install
|
||||
$(call msg,INSTALL,$1)
|
||||
$(Q)if [ ! -d '$(DESTDIR)$2' ]; then \
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR)$2'; \
|
||||
fi;
|
||||
$(Q)$(INSTALL) $(if $3,-m $3,) $1 '$(DESTDIR)$2'
|
||||
endef
|
||||
|
||||
# Preserve symlinks at installation.
|
||||
define do_s_install
|
||||
$(call msg,INSTALL,$1)
|
||||
$(Q)if [ ! -d '$(DESTDIR)$2' ]; then \
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR)$2'; \
|
||||
fi;
|
||||
$(Q)cp -fR $1 '$(DESTDIR)$2'
|
||||
endef
|
||||
|
||||
install: all install_headers install_pkgconfig
|
||||
$(call do_s_install,$(STATIC_LIBS) $(SHARED_LIBS),$(LIBDIR))
|
||||
|
||||
install_headers:
|
||||
$(call do_install,$(HEADERS),$(INCLUDEDIR)/bpf,644)
|
||||
|
||||
# UAPI headers can be installed by a different package so they're not installed
|
||||
# in by install rule.
|
||||
install_uapi_headers:
|
||||
$(call do_install,$(UAPI_HEADERS),$(UAPIDIR)/linux,644)
|
||||
|
||||
install_pkgconfig: $(PC_FILE)
|
||||
$(call do_install,$(PC_FILE),$(LIBDIR)/pkgconfig,644)
|
||||
|
||||
clean:
|
||||
$(call msg,CLEAN)
|
||||
$(Q)rm -rf *.o *.a *.so *.so.* *.pc $(SHARED_OBJDIR) $(STATIC_OBJDIR)
|
||||
|
||||
.PHONY: cscope tags force
|
||||
cscope:
|
||||
$(call msg,CSCOPE)
|
||||
$(Q)ls *.c *.h > cscope.files
|
||||
$(Q)cscope -b -q -f cscope.out
|
||||
|
||||
tags:
|
||||
$(call msg,CTAGS)
|
||||
$(Q)rm -f TAGS tags
|
||||
$(Q)ls *.c *.h | xargs $(TAGS_PROG) -a
|
||||
|
||||
force:
|
||||
1211
third_party/libbpf/src/bpf.c
vendored
Normal file
564
third_party/libbpf/src/bpf.h
vendored
Normal file
@@ -0,0 +1,564 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
|
||||
/*
|
||||
* Common BPF ELF operations.
|
||||
*
|
||||
* Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
|
||||
* Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
|
||||
* Copyright (C) 2015 Huawei Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License (not later!)
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, see <http://www.gnu.org/licenses>
|
||||
*/
|
||||
#ifndef __LIBBPF_BPF_H
|
||||
#define __LIBBPF_BPF_H
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libbpf_common.h"
|
||||
#include "libbpf_legacy.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int libbpf_set_memlock_rlim(size_t memlock_bytes);
|
||||
|
||||
struct bpf_map_create_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
|
||||
__u32 btf_fd;
|
||||
__u32 btf_key_type_id;
|
||||
__u32 btf_value_type_id;
|
||||
__u32 btf_vmlinux_value_type_id;
|
||||
|
||||
__u32 inner_map_fd;
|
||||
__u32 map_flags;
|
||||
__u64 map_extra;
|
||||
|
||||
__u32 numa_node;
|
||||
__u32 map_ifindex;
|
||||
};
|
||||
#define bpf_map_create_opts__last_field map_ifindex
|
||||
|
||||
LIBBPF_API int bpf_map_create(enum bpf_map_type map_type,
|
||||
const char *map_name,
|
||||
__u32 key_size,
|
||||
__u32 value_size,
|
||||
__u32 max_entries,
|
||||
const struct bpf_map_create_opts *opts);
|
||||
|
||||
struct bpf_prog_load_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
|
||||
/* libbpf can retry BPF_PROG_LOAD command if bpf() syscall returns
|
||||
* -EAGAIN. This field determines how many attempts libbpf has to
|
||||
* make. If not specified, libbpf will use default value of 5.
|
||||
*/
|
||||
int attempts;
|
||||
|
||||
enum bpf_attach_type expected_attach_type;
|
||||
__u32 prog_btf_fd;
|
||||
__u32 prog_flags;
|
||||
__u32 prog_ifindex;
|
||||
__u32 kern_version;
|
||||
|
||||
__u32 attach_btf_id;
|
||||
__u32 attach_prog_fd;
|
||||
__u32 attach_btf_obj_fd;
|
||||
|
||||
const int *fd_array;
|
||||
|
||||
/* .BTF.ext func info data */
|
||||
const void *func_info;
|
||||
__u32 func_info_cnt;
|
||||
__u32 func_info_rec_size;
|
||||
|
||||
/* .BTF.ext line info data */
|
||||
const void *line_info;
|
||||
__u32 line_info_cnt;
|
||||
__u32 line_info_rec_size;
|
||||
|
||||
/* verifier log options */
|
||||
__u32 log_level;
|
||||
__u32 log_size;
|
||||
char *log_buf;
|
||||
/* output: actual total log contents size (including termintaing zero).
|
||||
* It could be both larger than original log_size (if log was
|
||||
* truncated), or smaller (if log buffer wasn't filled completely).
|
||||
* If kernel doesn't support this feature, log_size is left unchanged.
|
||||
*/
|
||||
__u32 log_true_size;
|
||||
size_t :0;
|
||||
};
|
||||
#define bpf_prog_load_opts__last_field log_true_size
|
||||
|
||||
LIBBPF_API int bpf_prog_load(enum bpf_prog_type prog_type,
|
||||
const char *prog_name, const char *license,
|
||||
const struct bpf_insn *insns, size_t insn_cnt,
|
||||
struct bpf_prog_load_opts *opts);
|
||||
|
||||
/* Flags to direct loading requirements */
|
||||
#define MAPS_RELAX_COMPAT 0x01
|
||||
|
||||
/* Recommended log buffer size */
|
||||
#define BPF_LOG_BUF_SIZE (UINT32_MAX >> 8) /* verifier maximum in kernels <= 5.1 */
|
||||
|
||||
struct bpf_btf_load_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
|
||||
/* kernel log options */
|
||||
char *log_buf;
|
||||
__u32 log_level;
|
||||
__u32 log_size;
|
||||
/* output: actual total log contents size (including termintaing zero).
|
||||
* It could be both larger than original log_size (if log was
|
||||
* truncated), or smaller (if log buffer wasn't filled completely).
|
||||
* If kernel doesn't support this feature, log_size is left unchanged.
|
||||
*/
|
||||
__u32 log_true_size;
|
||||
size_t :0;
|
||||
};
|
||||
#define bpf_btf_load_opts__last_field log_true_size
|
||||
|
||||
LIBBPF_API int bpf_btf_load(const void *btf_data, size_t btf_size,
|
||||
struct bpf_btf_load_opts *opts);
|
||||
|
||||
LIBBPF_API int bpf_map_update_elem(int fd, const void *key, const void *value,
|
||||
__u64 flags);
|
||||
|
||||
LIBBPF_API int bpf_map_lookup_elem(int fd, const void *key, void *value);
|
||||
LIBBPF_API int bpf_map_lookup_elem_flags(int fd, const void *key, void *value,
|
||||
__u64 flags);
|
||||
LIBBPF_API int bpf_map_lookup_and_delete_elem(int fd, const void *key,
|
||||
void *value);
|
||||
LIBBPF_API int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key,
|
||||
void *value, __u64 flags);
|
||||
LIBBPF_API int bpf_map_delete_elem(int fd, const void *key);
|
||||
LIBBPF_API int bpf_map_delete_elem_flags(int fd, const void *key, __u64 flags);
|
||||
LIBBPF_API int bpf_map_get_next_key(int fd, const void *key, void *next_key);
|
||||
LIBBPF_API int bpf_map_freeze(int fd);
|
||||
|
||||
struct bpf_map_batch_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
__u64 elem_flags;
|
||||
__u64 flags;
|
||||
};
|
||||
#define bpf_map_batch_opts__last_field flags
|
||||
|
||||
|
||||
/**
|
||||
* @brief **bpf_map_delete_batch()** allows for batch deletion of multiple
|
||||
* elements in a BPF map.
|
||||
*
|
||||
* @param fd BPF map file descriptor
|
||||
* @param keys pointer to an array of *count* keys
|
||||
* @param count input and output parameter; on input **count** represents the
|
||||
* number of elements in the map to delete in batch;
|
||||
* on output if a non-EFAULT error is returned, **count** represents the number of deleted
|
||||
* elements if the output **count** value is not equal to the input **count** value
|
||||
* If EFAULT is returned, **count** should not be trusted to be correct.
|
||||
* @param opts options for configuring the way the batch deletion works
|
||||
* @return 0, on success; negative error code, otherwise (errno is also set to
|
||||
* the error code)
|
||||
*/
|
||||
LIBBPF_API int bpf_map_delete_batch(int fd, const void *keys,
|
||||
__u32 *count,
|
||||
const struct bpf_map_batch_opts *opts);
|
||||
|
||||
/**
|
||||
* @brief **bpf_map_lookup_batch()** allows for batch lookup of BPF map elements.
|
||||
*
|
||||
* The parameter *in_batch* is the address of the first element in the batch to read.
|
||||
* *out_batch* is an output parameter that should be passed as *in_batch* to subsequent
|
||||
* calls to **bpf_map_lookup_batch()**. NULL can be passed for *in_batch* to indicate
|
||||
* that the batched lookup starts from the beginning of the map.
|
||||
*
|
||||
* The *keys* and *values* are output parameters which must point to memory large enough to
|
||||
* hold *count* items based on the key and value size of the map *map_fd*. The *keys*
|
||||
* buffer must be of *key_size* * *count*. The *values* buffer must be of
|
||||
* *value_size* * *count*.
|
||||
*
|
||||
* @param fd BPF map file descriptor
|
||||
* @param in_batch address of the first element in batch to read, can pass NULL to
|
||||
* indicate that the batched lookup starts from the beginning of the map.
|
||||
* @param out_batch output parameter that should be passed to next call as *in_batch*
|
||||
* @param keys pointer to an array large enough for *count* keys
|
||||
* @param values pointer to an array large enough for *count* values
|
||||
* @param count input and output parameter; on input it's the number of elements
|
||||
* in the map to read in batch; on output it's the number of elements that were
|
||||
* successfully read.
|
||||
* If a non-EFAULT error is returned, count will be set as the number of elements
|
||||
* that were read before the error occurred.
|
||||
* If EFAULT is returned, **count** should not be trusted to be correct.
|
||||
* @param opts options for configuring the way the batch lookup works
|
||||
* @return 0, on success; negative error code, otherwise (errno is also set to
|
||||
* the error code)
|
||||
*/
|
||||
LIBBPF_API int bpf_map_lookup_batch(int fd, void *in_batch, void *out_batch,
|
||||
void *keys, void *values, __u32 *count,
|
||||
const struct bpf_map_batch_opts *opts);
|
||||
|
||||
/**
|
||||
* @brief **bpf_map_lookup_and_delete_batch()** allows for batch lookup and deletion
|
||||
* of BPF map elements where each element is deleted after being retrieved.
|
||||
*
|
||||
* @param fd BPF map file descriptor
|
||||
* @param in_batch address of the first element in batch to read, can pass NULL to
|
||||
* get address of the first element in *out_batch*
|
||||
* @param out_batch output parameter that should be passed to next call as *in_batch*
|
||||
* @param keys pointer to an array of *count* keys
|
||||
* @param values pointer to an array large enough for *count* values
|
||||
* @param count input and output parameter; on input it's the number of elements
|
||||
* in the map to read and delete in batch; on output it represents the number of
|
||||
* elements that were successfully read and deleted
|
||||
* If a non-**EFAULT** error code is returned and if the output **count** value
|
||||
* is not equal to the input **count** value, up to **count** elements may
|
||||
* have been deleted.
|
||||
* if **EFAULT** is returned up to *count* elements may have been deleted without
|
||||
* being returned via the *keys* and *values* output parameters.
|
||||
* @param opts options for configuring the way the batch lookup and delete works
|
||||
* @return 0, on success; negative error code, otherwise (errno is also set to
|
||||
* the error code)
|
||||
*/
|
||||
LIBBPF_API int bpf_map_lookup_and_delete_batch(int fd, void *in_batch,
|
||||
void *out_batch, void *keys,
|
||||
void *values, __u32 *count,
|
||||
const struct bpf_map_batch_opts *opts);
|
||||
|
||||
/**
|
||||
* @brief **bpf_map_update_batch()** updates multiple elements in a map
|
||||
* by specifying keys and their corresponding values.
|
||||
*
|
||||
* The *keys* and *values* parameters must point to memory large enough
|
||||
* to hold *count* items based on the key and value size of the map.
|
||||
*
|
||||
* The *opts* parameter can be used to control how *bpf_map_update_batch()*
|
||||
* should handle keys that either do or do not already exist in the map.
|
||||
* In particular the *flags* parameter of *bpf_map_batch_opts* can be
|
||||
* one of the following:
|
||||
*
|
||||
* Note that *count* is an input and output parameter, where on output it
|
||||
* represents how many elements were successfully updated. Also note that if
|
||||
* **EFAULT** then *count* should not be trusted to be correct.
|
||||
*
|
||||
* **BPF_ANY**
|
||||
* Create new elements or update existing.
|
||||
*
|
||||
* **BPF_NOEXIST**
|
||||
* Create new elements only if they do not exist.
|
||||
*
|
||||
* **BPF_EXIST**
|
||||
* Update existing elements.
|
||||
*
|
||||
* **BPF_F_LOCK**
|
||||
* Update spin_lock-ed map elements. This must be
|
||||
* specified if the map value contains a spinlock.
|
||||
*
|
||||
* @param fd BPF map file descriptor
|
||||
* @param keys pointer to an array of *count* keys
|
||||
* @param values pointer to an array of *count* values
|
||||
* @param count input and output parameter; on input it's the number of elements
|
||||
* in the map to update in batch; on output if a non-EFAULT error is returned,
|
||||
* **count** represents the number of updated elements if the output **count**
|
||||
* value is not equal to the input **count** value.
|
||||
* If EFAULT is returned, **count** should not be trusted to be correct.
|
||||
* @param opts options for configuring the way the batch update works
|
||||
* @return 0, on success; negative error code, otherwise (errno is also set to
|
||||
* the error code)
|
||||
*/
|
||||
LIBBPF_API int bpf_map_update_batch(int fd, const void *keys, const void *values,
|
||||
__u32 *count,
|
||||
const struct bpf_map_batch_opts *opts);
|
||||
|
||||
struct bpf_obj_pin_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
|
||||
__u32 file_flags;
|
||||
int path_fd;
|
||||
|
||||
size_t :0;
|
||||
};
|
||||
#define bpf_obj_pin_opts__last_field path_fd
|
||||
|
||||
LIBBPF_API int bpf_obj_pin(int fd, const char *pathname);
|
||||
LIBBPF_API int bpf_obj_pin_opts(int fd, const char *pathname,
|
||||
const struct bpf_obj_pin_opts *opts);
|
||||
|
||||
struct bpf_obj_get_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
|
||||
__u32 file_flags;
|
||||
int path_fd;
|
||||
|
||||
size_t :0;
|
||||
};
|
||||
#define bpf_obj_get_opts__last_field path_fd
|
||||
|
||||
LIBBPF_API int bpf_obj_get(const char *pathname);
|
||||
LIBBPF_API int bpf_obj_get_opts(const char *pathname,
|
||||
const struct bpf_obj_get_opts *opts);
|
||||
|
||||
struct bpf_prog_attach_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
unsigned int flags;
|
||||
int replace_prog_fd;
|
||||
};
|
||||
#define bpf_prog_attach_opts__last_field replace_prog_fd
|
||||
|
||||
LIBBPF_API int bpf_prog_attach(int prog_fd, int attachable_fd,
|
||||
enum bpf_attach_type type, unsigned int flags);
|
||||
LIBBPF_API int bpf_prog_attach_opts(int prog_fd, int attachable_fd,
|
||||
enum bpf_attach_type type,
|
||||
const struct bpf_prog_attach_opts *opts);
|
||||
LIBBPF_API int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
|
||||
LIBBPF_API int bpf_prog_detach2(int prog_fd, int attachable_fd,
|
||||
enum bpf_attach_type type);
|
||||
|
||||
union bpf_iter_link_info; /* defined in up-to-date linux/bpf.h */
|
||||
struct bpf_link_create_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
__u32 flags;
|
||||
union bpf_iter_link_info *iter_info;
|
||||
__u32 iter_info_len;
|
||||
__u32 target_btf_id;
|
||||
union {
|
||||
struct {
|
||||
__u64 bpf_cookie;
|
||||
} perf_event;
|
||||
struct {
|
||||
__u32 flags;
|
||||
__u32 cnt;
|
||||
const char **syms;
|
||||
const unsigned long *addrs;
|
||||
const __u64 *cookies;
|
||||
} kprobe_multi;
|
||||
struct {
|
||||
__u64 cookie;
|
||||
} tracing;
|
||||
struct {
|
||||
__u32 pf;
|
||||
__u32 hooknum;
|
||||
__s32 priority;
|
||||
__u32 flags;
|
||||
} netfilter;
|
||||
};
|
||||
size_t :0;
|
||||
};
|
||||
#define bpf_link_create_opts__last_field kprobe_multi.cookies
|
||||
|
||||
LIBBPF_API int bpf_link_create(int prog_fd, int target_fd,
|
||||
enum bpf_attach_type attach_type,
|
||||
const struct bpf_link_create_opts *opts);
|
||||
|
||||
LIBBPF_API int bpf_link_detach(int link_fd);
|
||||
|
||||
struct bpf_link_update_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
__u32 flags; /* extra flags */
|
||||
__u32 old_prog_fd; /* expected old program FD */
|
||||
__u32 old_map_fd; /* expected old map FD */
|
||||
};
|
||||
#define bpf_link_update_opts__last_field old_map_fd
|
||||
|
||||
LIBBPF_API int bpf_link_update(int link_fd, int new_prog_fd,
|
||||
const struct bpf_link_update_opts *opts);
|
||||
|
||||
LIBBPF_API int bpf_iter_create(int link_fd);
|
||||
|
||||
struct bpf_prog_test_run_attr {
|
||||
int prog_fd;
|
||||
int repeat;
|
||||
const void *data_in;
|
||||
__u32 data_size_in;
|
||||
void *data_out; /* optional */
|
||||
__u32 data_size_out; /* in: max length of data_out
|
||||
* out: length of data_out */
|
||||
__u32 retval; /* out: return code of the BPF program */
|
||||
__u32 duration; /* out: average per repetition in ns */
|
||||
const void *ctx_in; /* optional */
|
||||
__u32 ctx_size_in;
|
||||
void *ctx_out; /* optional */
|
||||
__u32 ctx_size_out; /* in: max length of ctx_out
|
||||
* out: length of cxt_out */
|
||||
};
|
||||
|
||||
LIBBPF_API int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id);
|
||||
LIBBPF_API int bpf_map_get_next_id(__u32 start_id, __u32 *next_id);
|
||||
LIBBPF_API int bpf_btf_get_next_id(__u32 start_id, __u32 *next_id);
|
||||
LIBBPF_API int bpf_link_get_next_id(__u32 start_id, __u32 *next_id);
|
||||
|
||||
struct bpf_get_fd_by_id_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
__u32 open_flags; /* permissions requested for the operation on fd */
|
||||
size_t :0;
|
||||
};
|
||||
#define bpf_get_fd_by_id_opts__last_field open_flags
|
||||
|
||||
LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id);
|
||||
LIBBPF_API int bpf_prog_get_fd_by_id_opts(__u32 id,
|
||||
const struct bpf_get_fd_by_id_opts *opts);
|
||||
LIBBPF_API int bpf_map_get_fd_by_id(__u32 id);
|
||||
LIBBPF_API int bpf_map_get_fd_by_id_opts(__u32 id,
|
||||
const struct bpf_get_fd_by_id_opts *opts);
|
||||
LIBBPF_API int bpf_btf_get_fd_by_id(__u32 id);
|
||||
LIBBPF_API int bpf_btf_get_fd_by_id_opts(__u32 id,
|
||||
const struct bpf_get_fd_by_id_opts *opts);
|
||||
LIBBPF_API int bpf_link_get_fd_by_id(__u32 id);
|
||||
LIBBPF_API int bpf_link_get_fd_by_id_opts(__u32 id,
|
||||
const struct bpf_get_fd_by_id_opts *opts);
|
||||
LIBBPF_API int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len);
|
||||
|
||||
/**
|
||||
* @brief **bpf_prog_get_info_by_fd()** obtains information about the BPF
|
||||
* program corresponding to *prog_fd*.
|
||||
*
|
||||
* Populates up to *info_len* bytes of *info* and updates *info_len* with the
|
||||
* actual number of bytes written to *info*.
|
||||
*
|
||||
* @param prog_fd BPF program file descriptor
|
||||
* @param info pointer to **struct bpf_prog_info** that will be populated with
|
||||
* BPF program information
|
||||
* @param info_len pointer to the size of *info*; on success updated with the
|
||||
* number of bytes written to *info*
|
||||
* @return 0, on success; negative error code, otherwise (errno is also set to
|
||||
* the error code)
|
||||
*/
|
||||
LIBBPF_API int bpf_prog_get_info_by_fd(int prog_fd, struct bpf_prog_info *info, __u32 *info_len);
|
||||
|
||||
/**
|
||||
* @brief **bpf_map_get_info_by_fd()** obtains information about the BPF
|
||||
* map corresponding to *map_fd*.
|
||||
*
|
||||
* Populates up to *info_len* bytes of *info* and updates *info_len* with the
|
||||
* actual number of bytes written to *info*.
|
||||
*
|
||||
* @param map_fd BPF map file descriptor
|
||||
* @param info pointer to **struct bpf_map_info** that will be populated with
|
||||
* BPF map information
|
||||
* @param info_len pointer to the size of *info*; on success updated with the
|
||||
* number of bytes written to *info*
|
||||
* @return 0, on success; negative error code, otherwise (errno is also set to
|
||||
* the error code)
|
||||
*/
|
||||
LIBBPF_API int bpf_map_get_info_by_fd(int map_fd, struct bpf_map_info *info, __u32 *info_len);
|
||||
|
||||
/**
|
||||
* @brief **bpf_btf_get_info_by_fd()** obtains information about the
|
||||
* BTF object corresponding to *btf_fd*.
|
||||
*
|
||||
* Populates up to *info_len* bytes of *info* and updates *info_len* with the
|
||||
* actual number of bytes written to *info*.
|
||||
*
|
||||
* @param btf_fd BTF object file descriptor
|
||||
* @param info pointer to **struct bpf_btf_info** that will be populated with
|
||||
* BTF object information
|
||||
* @param info_len pointer to the size of *info*; on success updated with the
|
||||
* number of bytes written to *info*
|
||||
* @return 0, on success; negative error code, otherwise (errno is also set to
|
||||
* the error code)
|
||||
*/
|
||||
LIBBPF_API int bpf_btf_get_info_by_fd(int btf_fd, struct bpf_btf_info *info, __u32 *info_len);
|
||||
|
||||
/**
|
||||
* @brief **bpf_btf_get_info_by_fd()** obtains information about the BPF
|
||||
* link corresponding to *link_fd*.
|
||||
*
|
||||
* Populates up to *info_len* bytes of *info* and updates *info_len* with the
|
||||
* actual number of bytes written to *info*.
|
||||
*
|
||||
* @param link_fd BPF link file descriptor
|
||||
* @param info pointer to **struct bpf_link_info** that will be populated with
|
||||
* BPF link information
|
||||
* @param info_len pointer to the size of *info*; on success updated with the
|
||||
* number of bytes written to *info*
|
||||
* @return 0, on success; negative error code, otherwise (errno is also set to
|
||||
* the error code)
|
||||
*/
|
||||
LIBBPF_API int bpf_link_get_info_by_fd(int link_fd, struct bpf_link_info *info, __u32 *info_len);
|
||||
|
||||
struct bpf_prog_query_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
__u32 query_flags;
|
||||
__u32 attach_flags; /* output argument */
|
||||
__u32 *prog_ids;
|
||||
__u32 prog_cnt; /* input+output argument */
|
||||
__u32 *prog_attach_flags;
|
||||
};
|
||||
#define bpf_prog_query_opts__last_field prog_attach_flags
|
||||
|
||||
LIBBPF_API int bpf_prog_query_opts(int target_fd,
|
||||
enum bpf_attach_type type,
|
||||
struct bpf_prog_query_opts *opts);
|
||||
LIBBPF_API int bpf_prog_query(int target_fd, enum bpf_attach_type type,
|
||||
__u32 query_flags, __u32 *attach_flags,
|
||||
__u32 *prog_ids, __u32 *prog_cnt);
|
||||
|
||||
LIBBPF_API int bpf_raw_tracepoint_open(const char *name, int prog_fd);
|
||||
LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
|
||||
__u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
|
||||
__u64 *probe_offset, __u64 *probe_addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* forward-declaring enums in C++ isn't compatible with pure C enums, so
|
||||
* instead define bpf_enable_stats() as accepting int as an input
|
||||
*/
|
||||
LIBBPF_API int bpf_enable_stats(int type);
|
||||
#else
|
||||
enum bpf_stats_type; /* defined in up-to-date linux/bpf.h */
|
||||
LIBBPF_API int bpf_enable_stats(enum bpf_stats_type type);
|
||||
#endif
|
||||
|
||||
struct bpf_prog_bind_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
__u32 flags;
|
||||
};
|
||||
#define bpf_prog_bind_opts__last_field flags
|
||||
|
||||
LIBBPF_API int bpf_prog_bind_map(int prog_fd, int map_fd,
|
||||
const struct bpf_prog_bind_opts *opts);
|
||||
|
||||
struct bpf_test_run_opts {
|
||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||
const void *data_in; /* optional */
|
||||
void *data_out; /* optional */
|
||||
__u32 data_size_in;
|
||||
__u32 data_size_out; /* in: max length of data_out
|
||||
* out: length of data_out
|
||||
*/
|
||||
const void *ctx_in; /* optional */
|
||||
void *ctx_out; /* optional */
|
||||
__u32 ctx_size_in;
|
||||
__u32 ctx_size_out; /* in: max length of ctx_out
|
||||
* out: length of cxt_out
|
||||
*/
|
||||
__u32 retval; /* out: return code of the BPF program */
|
||||
int repeat;
|
||||
__u32 duration; /* out: average per repetition in ns */
|
||||
__u32 flags;
|
||||
__u32 cpu;
|
||||
__u32 batch_size;
|
||||
};
|
||||
#define bpf_test_run_opts__last_field batch_size
|
||||
|
||||
LIBBPF_API int bpf_prog_test_run_opts(int prog_fd,
|
||||
struct bpf_test_run_opts *opts);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __LIBBPF_BPF_H */
|
||||
484
third_party/libbpf/src/bpf_core_read.h
vendored
Normal file
@@ -0,0 +1,484 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
#ifndef __BPF_CORE_READ_H__
|
||||
#define __BPF_CORE_READ_H__
|
||||
|
||||
/*
|
||||
* enum bpf_field_info_kind is passed as a second argument into
|
||||
* __builtin_preserve_field_info() built-in to get a specific aspect of
|
||||
* a field, captured as a first argument. __builtin_preserve_field_info(field,
|
||||
* info_kind) returns __u32 integer and produces BTF field relocation, which
|
||||
* is understood and processed by libbpf during BPF object loading. See
|
||||
* selftests/bpf for examples.
|
||||
*/
|
||||
enum bpf_field_info_kind {
|
||||
BPF_FIELD_BYTE_OFFSET = 0, /* field byte offset */
|
||||
BPF_FIELD_BYTE_SIZE = 1,
|
||||
BPF_FIELD_EXISTS = 2, /* field existence in target kernel */
|
||||
BPF_FIELD_SIGNED = 3,
|
||||
BPF_FIELD_LSHIFT_U64 = 4,
|
||||
BPF_FIELD_RSHIFT_U64 = 5,
|
||||
};
|
||||
|
||||
/* second argument to __builtin_btf_type_id() built-in */
|
||||
enum bpf_type_id_kind {
|
||||
BPF_TYPE_ID_LOCAL = 0, /* BTF type ID in local program */
|
||||
BPF_TYPE_ID_TARGET = 1, /* BTF type ID in target kernel */
|
||||
};
|
||||
|
||||
/* second argument to __builtin_preserve_type_info() built-in */
|
||||
enum bpf_type_info_kind {
|
||||
BPF_TYPE_EXISTS = 0, /* type existence in target kernel */
|
||||
BPF_TYPE_SIZE = 1, /* type size in target kernel */
|
||||
BPF_TYPE_MATCHES = 2, /* type match in target kernel */
|
||||
};
|
||||
|
||||
/* second argument to __builtin_preserve_enum_value() built-in */
|
||||
enum bpf_enum_value_kind {
|
||||
BPF_ENUMVAL_EXISTS = 0, /* enum value existence in kernel */
|
||||
BPF_ENUMVAL_VALUE = 1, /* enum value value relocation */
|
||||
};
|
||||
|
||||
#define __CORE_RELO(src, field, info) \
|
||||
__builtin_preserve_field_info((src)->field, BPF_FIELD_##info)
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define __CORE_BITFIELD_PROBE_READ(dst, src, fld) \
|
||||
bpf_probe_read_kernel( \
|
||||
(void *)dst, \
|
||||
__CORE_RELO(src, fld, BYTE_SIZE), \
|
||||
(const void *)src + __CORE_RELO(src, fld, BYTE_OFFSET))
|
||||
#else
|
||||
/* semantics of LSHIFT_64 assumes loading values into low-ordered bytes, so
|
||||
* for big-endian we need to adjust destination pointer accordingly, based on
|
||||
* field byte size
|
||||
*/
|
||||
#define __CORE_BITFIELD_PROBE_READ(dst, src, fld) \
|
||||
bpf_probe_read_kernel( \
|
||||
(void *)dst + (8 - __CORE_RELO(src, fld, BYTE_SIZE)), \
|
||||
__CORE_RELO(src, fld, BYTE_SIZE), \
|
||||
(const void *)src + __CORE_RELO(src, fld, BYTE_OFFSET))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Extract bitfield, identified by s->field, and return its value as u64.
|
||||
* All this is done in relocatable manner, so bitfield changes such as
|
||||
* signedness, bit size, offset changes, this will be handled automatically.
|
||||
* This version of macro is using bpf_probe_read_kernel() to read underlying
|
||||
* integer storage. Macro functions as an expression and its return type is
|
||||
* bpf_probe_read_kernel()'s return value: 0, on success, <0 on error.
|
||||
*/
|
||||
#define BPF_CORE_READ_BITFIELD_PROBED(s, field) ({ \
|
||||
unsigned long long val = 0; \
|
||||
\
|
||||
__CORE_BITFIELD_PROBE_READ(&val, s, field); \
|
||||
val <<= __CORE_RELO(s, field, LSHIFT_U64); \
|
||||
if (__CORE_RELO(s, field, SIGNED)) \
|
||||
val = ((long long)val) >> __CORE_RELO(s, field, RSHIFT_U64); \
|
||||
else \
|
||||
val = val >> __CORE_RELO(s, field, RSHIFT_U64); \
|
||||
val; \
|
||||
})
|
||||
|
||||
/*
|
||||
* Extract bitfield, identified by s->field, and return its value as u64.
|
||||
* This version of macro is using direct memory reads and should be used from
|
||||
* BPF program types that support such functionality (e.g., typed raw
|
||||
* tracepoints).
|
||||
*/
|
||||
#define BPF_CORE_READ_BITFIELD(s, field) ({ \
|
||||
const void *p = (const void *)s + __CORE_RELO(s, field, BYTE_OFFSET); \
|
||||
unsigned long long val; \
|
||||
\
|
||||
/* This is a so-called barrier_var() operation that makes specified \
|
||||
* variable "a black box" for optimizing compiler. \
|
||||
* It forces compiler to perform BYTE_OFFSET relocation on p and use \
|
||||
* its calculated value in the switch below, instead of applying \
|
||||
* the same relocation 4 times for each individual memory load. \
|
||||
*/ \
|
||||
asm volatile("" : "=r"(p) : "0"(p)); \
|
||||
\
|
||||
switch (__CORE_RELO(s, field, BYTE_SIZE)) { \
|
||||
case 1: val = *(const unsigned char *)p; break; \
|
||||
case 2: val = *(const unsigned short *)p; break; \
|
||||
case 4: val = *(const unsigned int *)p; break; \
|
||||
case 8: val = *(const unsigned long long *)p; break; \
|
||||
} \
|
||||
val <<= __CORE_RELO(s, field, LSHIFT_U64); \
|
||||
if (__CORE_RELO(s, field, SIGNED)) \
|
||||
val = ((long long)val) >> __CORE_RELO(s, field, RSHIFT_U64); \
|
||||
else \
|
||||
val = val >> __CORE_RELO(s, field, RSHIFT_U64); \
|
||||
val; \
|
||||
})
|
||||
|
||||
#define ___bpf_field_ref1(field) (field)
|
||||
#define ___bpf_field_ref2(type, field) (((typeof(type) *)0)->field)
|
||||
#define ___bpf_field_ref(args...) \
|
||||
___bpf_apply(___bpf_field_ref, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
* Convenience macro to check that field actually exists in target kernel's.
|
||||
* Returns:
|
||||
* 1, if matching field is present in target kernel;
|
||||
* 0, if no matching field found.
|
||||
*
|
||||
* Supports two forms:
|
||||
* - field reference through variable access:
|
||||
* bpf_core_field_exists(p->my_field);
|
||||
* - field reference through type and field names:
|
||||
* bpf_core_field_exists(struct my_type, my_field).
|
||||
*/
|
||||
#define bpf_core_field_exists(field...) \
|
||||
__builtin_preserve_field_info(___bpf_field_ref(field), BPF_FIELD_EXISTS)
|
||||
|
||||
/*
|
||||
* Convenience macro to get the byte size of a field. Works for integers,
|
||||
* struct/unions, pointers, arrays, and enums.
|
||||
*
|
||||
* Supports two forms:
|
||||
* - field reference through variable access:
|
||||
* bpf_core_field_size(p->my_field);
|
||||
* - field reference through type and field names:
|
||||
* bpf_core_field_size(struct my_type, my_field).
|
||||
*/
|
||||
#define bpf_core_field_size(field...) \
|
||||
__builtin_preserve_field_info(___bpf_field_ref(field), BPF_FIELD_BYTE_SIZE)
|
||||
|
||||
/*
|
||||
* Convenience macro to get field's byte offset.
|
||||
*
|
||||
* Supports two forms:
|
||||
* - field reference through variable access:
|
||||
* bpf_core_field_offset(p->my_field);
|
||||
* - field reference through type and field names:
|
||||
* bpf_core_field_offset(struct my_type, my_field).
|
||||
*/
|
||||
#define bpf_core_field_offset(field...) \
|
||||
__builtin_preserve_field_info(___bpf_field_ref(field), BPF_FIELD_BYTE_OFFSET)
|
||||
|
||||
/*
|
||||
* Convenience macro to get BTF type ID of a specified type, using a local BTF
|
||||
* information. Return 32-bit unsigned integer with type ID from program's own
|
||||
* BTF. Always succeeds.
|
||||
*/
|
||||
#define bpf_core_type_id_local(type) \
|
||||
__builtin_btf_type_id(*(typeof(type) *)0, BPF_TYPE_ID_LOCAL)
|
||||
|
||||
/*
|
||||
* Convenience macro to get BTF type ID of a target kernel's type that matches
|
||||
* specified local type.
|
||||
* Returns:
|
||||
* - valid 32-bit unsigned type ID in kernel BTF;
|
||||
* - 0, if no matching type was found in a target kernel BTF.
|
||||
*/
|
||||
#define bpf_core_type_id_kernel(type) \
|
||||
__builtin_btf_type_id(*(typeof(type) *)0, BPF_TYPE_ID_TARGET)
|
||||
|
||||
/*
|
||||
* Convenience macro to check that provided named type
|
||||
* (struct/union/enum/typedef) exists in a target kernel.
|
||||
* Returns:
|
||||
* 1, if such type is present in target kernel's BTF;
|
||||
* 0, if no matching type is found.
|
||||
*/
|
||||
#define bpf_core_type_exists(type) \
|
||||
__builtin_preserve_type_info(*(typeof(type) *)0, BPF_TYPE_EXISTS)
|
||||
|
||||
/*
|
||||
* Convenience macro to check that provided named type
|
||||
* (struct/union/enum/typedef) "matches" that in a target kernel.
|
||||
* Returns:
|
||||
* 1, if the type matches in the target kernel's BTF;
|
||||
* 0, if the type does not match any in the target kernel
|
||||
*/
|
||||
#define bpf_core_type_matches(type) \
|
||||
__builtin_preserve_type_info(*(typeof(type) *)0, BPF_TYPE_MATCHES)
|
||||
|
||||
/*
|
||||
* Convenience macro to get the byte size of a provided named type
|
||||
* (struct/union/enum/typedef) in a target kernel.
|
||||
* Returns:
|
||||
* >= 0 size (in bytes), if type is present in target kernel's BTF;
|
||||
* 0, if no matching type is found.
|
||||
*/
|
||||
#define bpf_core_type_size(type) \
|
||||
__builtin_preserve_type_info(*(typeof(type) *)0, BPF_TYPE_SIZE)
|
||||
|
||||
/*
|
||||
* Convenience macro to check that provided enumerator value is defined in
|
||||
* a target kernel.
|
||||
* Returns:
|
||||
* 1, if specified enum type and its enumerator value are present in target
|
||||
* kernel's BTF;
|
||||
* 0, if no matching enum and/or enum value within that enum is found.
|
||||
*/
|
||||
#define bpf_core_enum_value_exists(enum_type, enum_value) \
|
||||
__builtin_preserve_enum_value(*(typeof(enum_type) *)enum_value, BPF_ENUMVAL_EXISTS)
|
||||
|
||||
/*
|
||||
* Convenience macro to get the integer value of an enumerator value in
|
||||
* a target kernel.
|
||||
* Returns:
|
||||
* 64-bit value, if specified enum type and its enumerator value are
|
||||
* present in target kernel's BTF;
|
||||
* 0, if no matching enum and/or enum value within that enum is found.
|
||||
*/
|
||||
#define bpf_core_enum_value(enum_type, enum_value) \
|
||||
__builtin_preserve_enum_value(*(typeof(enum_type) *)enum_value, BPF_ENUMVAL_VALUE)
|
||||
|
||||
/*
|
||||
* bpf_core_read() abstracts away bpf_probe_read_kernel() call and captures
|
||||
* offset relocation for source address using __builtin_preserve_access_index()
|
||||
* built-in, provided by Clang.
|
||||
*
|
||||
* __builtin_preserve_access_index() takes as an argument an expression of
|
||||
* taking an address of a field within struct/union. It makes compiler emit
|
||||
* a relocation, which records BTF type ID describing root struct/union and an
|
||||
* accessor string which describes exact embedded field that was used to take
|
||||
* an address. See detailed description of this relocation format and
|
||||
* semantics in comments to struct bpf_field_reloc in libbpf_internal.h.
|
||||
*
|
||||
* This relocation allows libbpf to adjust BPF instruction to use correct
|
||||
* actual field offset, based on target kernel BTF type that matches original
|
||||
* (local) BTF, used to record relocation.
|
||||
*/
|
||||
#define bpf_core_read(dst, sz, src) \
|
||||
bpf_probe_read_kernel(dst, sz, (const void *)__builtin_preserve_access_index(src))
|
||||
|
||||
/* NOTE: see comments for BPF_CORE_READ_USER() about the proper types use. */
|
||||
#define bpf_core_read_user(dst, sz, src) \
|
||||
bpf_probe_read_user(dst, sz, (const void *)__builtin_preserve_access_index(src))
|
||||
/*
|
||||
* bpf_core_read_str() is a thin wrapper around bpf_probe_read_str()
|
||||
* additionally emitting BPF CO-RE field relocation for specified source
|
||||
* argument.
|
||||
*/
|
||||
#define bpf_core_read_str(dst, sz, src) \
|
||||
bpf_probe_read_kernel_str(dst, sz, (const void *)__builtin_preserve_access_index(src))
|
||||
|
||||
/* NOTE: see comments for BPF_CORE_READ_USER() about the proper types use. */
|
||||
#define bpf_core_read_user_str(dst, sz, src) \
|
||||
bpf_probe_read_user_str(dst, sz, (const void *)__builtin_preserve_access_index(src))
|
||||
|
||||
#define ___concat(a, b) a ## b
|
||||
#define ___apply(fn, n) ___concat(fn, n)
|
||||
#define ___nth(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, __11, N, ...) N
|
||||
|
||||
/*
|
||||
* return number of provided arguments; used for switch-based variadic macro
|
||||
* definitions (see ___last, ___arrow, etc below)
|
||||
*/
|
||||
#define ___narg(...) ___nth(_, ##__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
/*
|
||||
* return 0 if no arguments are passed, N - otherwise; used for
|
||||
* recursively-defined macros to specify termination (0) case, and generic
|
||||
* (N) case (e.g., ___read_ptrs, ___core_read)
|
||||
*/
|
||||
#define ___empty(...) ___nth(_, ##__VA_ARGS__, N, N, N, N, N, N, N, N, N, N, 0)
|
||||
|
||||
#define ___last1(x) x
|
||||
#define ___last2(a, x) x
|
||||
#define ___last3(a, b, x) x
|
||||
#define ___last4(a, b, c, x) x
|
||||
#define ___last5(a, b, c, d, x) x
|
||||
#define ___last6(a, b, c, d, e, x) x
|
||||
#define ___last7(a, b, c, d, e, f, x) x
|
||||
#define ___last8(a, b, c, d, e, f, g, x) x
|
||||
#define ___last9(a, b, c, d, e, f, g, h, x) x
|
||||
#define ___last10(a, b, c, d, e, f, g, h, i, x) x
|
||||
#define ___last(...) ___apply(___last, ___narg(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#define ___nolast2(a, _) a
|
||||
#define ___nolast3(a, b, _) a, b
|
||||
#define ___nolast4(a, b, c, _) a, b, c
|
||||
#define ___nolast5(a, b, c, d, _) a, b, c, d
|
||||
#define ___nolast6(a, b, c, d, e, _) a, b, c, d, e
|
||||
#define ___nolast7(a, b, c, d, e, f, _) a, b, c, d, e, f
|
||||
#define ___nolast8(a, b, c, d, e, f, g, _) a, b, c, d, e, f, g
|
||||
#define ___nolast9(a, b, c, d, e, f, g, h, _) a, b, c, d, e, f, g, h
|
||||
#define ___nolast10(a, b, c, d, e, f, g, h, i, _) a, b, c, d, e, f, g, h, i
|
||||
#define ___nolast(...) ___apply(___nolast, ___narg(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#define ___arrow1(a) a
|
||||
#define ___arrow2(a, b) a->b
|
||||
#define ___arrow3(a, b, c) a->b->c
|
||||
#define ___arrow4(a, b, c, d) a->b->c->d
|
||||
#define ___arrow5(a, b, c, d, e) a->b->c->d->e
|
||||
#define ___arrow6(a, b, c, d, e, f) a->b->c->d->e->f
|
||||
#define ___arrow7(a, b, c, d, e, f, g) a->b->c->d->e->f->g
|
||||
#define ___arrow8(a, b, c, d, e, f, g, h) a->b->c->d->e->f->g->h
|
||||
#define ___arrow9(a, b, c, d, e, f, g, h, i) a->b->c->d->e->f->g->h->i
|
||||
#define ___arrow10(a, b, c, d, e, f, g, h, i, j) a->b->c->d->e->f->g->h->i->j
|
||||
#define ___arrow(...) ___apply(___arrow, ___narg(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#define ___type(...) typeof(___arrow(__VA_ARGS__))
|
||||
|
||||
#define ___read(read_fn, dst, src_type, src, accessor) \
|
||||
read_fn((void *)(dst), sizeof(*(dst)), &((src_type)(src))->accessor)
|
||||
|
||||
/* "recursively" read a sequence of inner pointers using local __t var */
|
||||
#define ___rd_first(fn, src, a) ___read(fn, &__t, ___type(src), src, a);
|
||||
#define ___rd_last(fn, ...) \
|
||||
___read(fn, &__t, ___type(___nolast(__VA_ARGS__)), __t, ___last(__VA_ARGS__));
|
||||
#define ___rd_p1(fn, ...) const void *__t; ___rd_first(fn, __VA_ARGS__)
|
||||
#define ___rd_p2(fn, ...) ___rd_p1(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
|
||||
#define ___rd_p3(fn, ...) ___rd_p2(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
|
||||
#define ___rd_p4(fn, ...) ___rd_p3(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
|
||||
#define ___rd_p5(fn, ...) ___rd_p4(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
|
||||
#define ___rd_p6(fn, ...) ___rd_p5(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
|
||||
#define ___rd_p7(fn, ...) ___rd_p6(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
|
||||
#define ___rd_p8(fn, ...) ___rd_p7(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
|
||||
#define ___rd_p9(fn, ...) ___rd_p8(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
|
||||
#define ___read_ptrs(fn, src, ...) \
|
||||
___apply(___rd_p, ___narg(__VA_ARGS__))(fn, src, __VA_ARGS__)
|
||||
|
||||
#define ___core_read0(fn, fn_ptr, dst, src, a) \
|
||||
___read(fn, dst, ___type(src), src, a);
|
||||
#define ___core_readN(fn, fn_ptr, dst, src, ...) \
|
||||
___read_ptrs(fn_ptr, src, ___nolast(__VA_ARGS__)) \
|
||||
___read(fn, dst, ___type(src, ___nolast(__VA_ARGS__)), __t, \
|
||||
___last(__VA_ARGS__));
|
||||
#define ___core_read(fn, fn_ptr, dst, src, a, ...) \
|
||||
___apply(___core_read, ___empty(__VA_ARGS__))(fn, fn_ptr, dst, \
|
||||
src, a, ##__VA_ARGS__)
|
||||
|
||||
/*
|
||||
* BPF_CORE_READ_INTO() is a more performance-conscious variant of
|
||||
* BPF_CORE_READ(), in which final field is read into user-provided storage.
|
||||
* See BPF_CORE_READ() below for more details on general usage.
|
||||
*/
|
||||
#define BPF_CORE_READ_INTO(dst, src, a, ...) ({ \
|
||||
___core_read(bpf_core_read, bpf_core_read, \
|
||||
dst, (src), a, ##__VA_ARGS__) \
|
||||
})
|
||||
|
||||
/*
|
||||
* Variant of BPF_CORE_READ_INTO() for reading from user-space memory.
|
||||
*
|
||||
* NOTE: see comments for BPF_CORE_READ_USER() about the proper types use.
|
||||
*/
|
||||
#define BPF_CORE_READ_USER_INTO(dst, src, a, ...) ({ \
|
||||
___core_read(bpf_core_read_user, bpf_core_read_user, \
|
||||
dst, (src), a, ##__VA_ARGS__) \
|
||||
})
|
||||
|
||||
/* Non-CO-RE variant of BPF_CORE_READ_INTO() */
|
||||
#define BPF_PROBE_READ_INTO(dst, src, a, ...) ({ \
|
||||
___core_read(bpf_probe_read_kernel, bpf_probe_read_kernel, \
|
||||
dst, (src), a, ##__VA_ARGS__) \
|
||||
})
|
||||
|
||||
/* Non-CO-RE variant of BPF_CORE_READ_USER_INTO().
|
||||
*
|
||||
* As no CO-RE relocations are emitted, source types can be arbitrary and are
|
||||
* not restricted to kernel types only.
|
||||
*/
|
||||
#define BPF_PROBE_READ_USER_INTO(dst, src, a, ...) ({ \
|
||||
___core_read(bpf_probe_read_user, bpf_probe_read_user, \
|
||||
dst, (src), a, ##__VA_ARGS__) \
|
||||
})
|
||||
|
||||
/*
|
||||
* BPF_CORE_READ_STR_INTO() does same "pointer chasing" as
|
||||
* BPF_CORE_READ() for intermediate pointers, but then executes (and returns
|
||||
* corresponding error code) bpf_core_read_str() for final string read.
|
||||
*/
|
||||
#define BPF_CORE_READ_STR_INTO(dst, src, a, ...) ({ \
|
||||
___core_read(bpf_core_read_str, bpf_core_read, \
|
||||
dst, (src), a, ##__VA_ARGS__) \
|
||||
})
|
||||
|
||||
/*
|
||||
* Variant of BPF_CORE_READ_STR_INTO() for reading from user-space memory.
|
||||
*
|
||||
* NOTE: see comments for BPF_CORE_READ_USER() about the proper types use.
|
||||
*/
|
||||
#define BPF_CORE_READ_USER_STR_INTO(dst, src, a, ...) ({ \
|
||||
___core_read(bpf_core_read_user_str, bpf_core_read_user, \
|
||||
dst, (src), a, ##__VA_ARGS__) \
|
||||
})
|
||||
|
||||
/* Non-CO-RE variant of BPF_CORE_READ_STR_INTO() */
|
||||
#define BPF_PROBE_READ_STR_INTO(dst, src, a, ...) ({ \
|
||||
___core_read(bpf_probe_read_kernel_str, bpf_probe_read_kernel, \
|
||||
dst, (src), a, ##__VA_ARGS__) \
|
||||
})
|
||||
|
||||
/*
|
||||
* Non-CO-RE variant of BPF_CORE_READ_USER_STR_INTO().
|
||||
*
|
||||
* As no CO-RE relocations are emitted, source types can be arbitrary and are
|
||||
* not restricted to kernel types only.
|
||||
*/
|
||||
#define BPF_PROBE_READ_USER_STR_INTO(dst, src, a, ...) ({ \
|
||||
___core_read(bpf_probe_read_user_str, bpf_probe_read_user, \
|
||||
dst, (src), a, ##__VA_ARGS__) \
|
||||
})
|
||||
|
||||
/*
|
||||
* BPF_CORE_READ() is used to simplify BPF CO-RE relocatable read, especially
|
||||
* when there are few pointer chasing steps.
|
||||
* E.g., what in non-BPF world (or in BPF w/ BCC) would be something like:
|
||||
* int x = s->a.b.c->d.e->f->g;
|
||||
* can be succinctly achieved using BPF_CORE_READ as:
|
||||
* int x = BPF_CORE_READ(s, a.b.c, d.e, f, g);
|
||||
*
|
||||
* BPF_CORE_READ will decompose above statement into 4 bpf_core_read (BPF
|
||||
* CO-RE relocatable bpf_probe_read_kernel() wrapper) calls, logically
|
||||
* equivalent to:
|
||||
* 1. const void *__t = s->a.b.c;
|
||||
* 2. __t = __t->d.e;
|
||||
* 3. __t = __t->f;
|
||||
* 4. return __t->g;
|
||||
*
|
||||
* Equivalence is logical, because there is a heavy type casting/preservation
|
||||
* involved, as well as all the reads are happening through
|
||||
* bpf_probe_read_kernel() calls using __builtin_preserve_access_index() to
|
||||
* emit CO-RE relocations.
|
||||
*
|
||||
* N.B. Only up to 9 "field accessors" are supported, which should be more
|
||||
* than enough for any practical purpose.
|
||||
*/
|
||||
#define BPF_CORE_READ(src, a, ...) ({ \
|
||||
___type((src), a, ##__VA_ARGS__) __r; \
|
||||
BPF_CORE_READ_INTO(&__r, (src), a, ##__VA_ARGS__); \
|
||||
__r; \
|
||||
})
|
||||
|
||||
/*
|
||||
* Variant of BPF_CORE_READ() for reading from user-space memory.
|
||||
*
|
||||
* NOTE: all the source types involved are still *kernel types* and need to
|
||||
* exist in kernel (or kernel module) BTF, otherwise CO-RE relocation will
|
||||
* fail. Custom user types are not relocatable with CO-RE.
|
||||
* The typical situation in which BPF_CORE_READ_USER() might be used is to
|
||||
* read kernel UAPI types from the user-space memory passed in as a syscall
|
||||
* input argument.
|
||||
*/
|
||||
#define BPF_CORE_READ_USER(src, a, ...) ({ \
|
||||
___type((src), a, ##__VA_ARGS__) __r; \
|
||||
BPF_CORE_READ_USER_INTO(&__r, (src), a, ##__VA_ARGS__); \
|
||||
__r; \
|
||||
})
|
||||
|
||||
/* Non-CO-RE variant of BPF_CORE_READ() */
|
||||
#define BPF_PROBE_READ(src, a, ...) ({ \
|
||||
___type((src), a, ##__VA_ARGS__) __r; \
|
||||
BPF_PROBE_READ_INTO(&__r, (src), a, ##__VA_ARGS__); \
|
||||
__r; \
|
||||
})
|
||||
|
||||
/*
|
||||
* Non-CO-RE variant of BPF_CORE_READ_USER().
|
||||
*
|
||||
* As no CO-RE relocations are emitted, source types can be arbitrary and are
|
||||
* not restricted to kernel types only.
|
||||
*/
|
||||
#define BPF_PROBE_READ_USER(src, a, ...) ({ \
|
||||
___type((src), a, ##__VA_ARGS__) __r; \
|
||||
BPF_PROBE_READ_USER_INTO(&__r, (src), a, ##__VA_ARGS__); \
|
||||
__r; \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
||||
99
third_party/libbpf/src/bpf_endian.h
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
#ifndef __BPF_ENDIAN__
|
||||
#define __BPF_ENDIAN__
|
||||
|
||||
/*
|
||||
* Isolate byte #n and put it into byte #m, for __u##b type.
|
||||
* E.g., moving byte #6 (nnnnnnnn) into byte #1 (mmmmmmmm) for __u64:
|
||||
* 1) xxxxxxxx nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx
|
||||
* 2) nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx 00000000
|
||||
* 3) 00000000 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn
|
||||
* 4) 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn 00000000
|
||||
*/
|
||||
#define ___bpf_mvb(x, b, n, m) ((__u##b)(x) << (b-(n+1)*8) >> (b-8) << (m*8))
|
||||
|
||||
#define ___bpf_swab16(x) ((__u16)( \
|
||||
___bpf_mvb(x, 16, 0, 1) | \
|
||||
___bpf_mvb(x, 16, 1, 0)))
|
||||
|
||||
#define ___bpf_swab32(x) ((__u32)( \
|
||||
___bpf_mvb(x, 32, 0, 3) | \
|
||||
___bpf_mvb(x, 32, 1, 2) | \
|
||||
___bpf_mvb(x, 32, 2, 1) | \
|
||||
___bpf_mvb(x, 32, 3, 0)))
|
||||
|
||||
#define ___bpf_swab64(x) ((__u64)( \
|
||||
___bpf_mvb(x, 64, 0, 7) | \
|
||||
___bpf_mvb(x, 64, 1, 6) | \
|
||||
___bpf_mvb(x, 64, 2, 5) | \
|
||||
___bpf_mvb(x, 64, 3, 4) | \
|
||||
___bpf_mvb(x, 64, 4, 3) | \
|
||||
___bpf_mvb(x, 64, 5, 2) | \
|
||||
___bpf_mvb(x, 64, 6, 1) | \
|
||||
___bpf_mvb(x, 64, 7, 0)))
|
||||
|
||||
/* LLVM's BPF target selects the endianness of the CPU
|
||||
* it compiles on, or the user specifies (bpfel/bpfeb),
|
||||
* respectively. The used __BYTE_ORDER__ is defined by
|
||||
* the compiler, we cannot rely on __BYTE_ORDER from
|
||||
* libc headers, since it doesn't reflect the actual
|
||||
* requested byte order.
|
||||
*
|
||||
* Note, LLVM's BPF target has different __builtin_bswapX()
|
||||
* semantics. It does map to BPF_ALU | BPF_END | BPF_TO_BE
|
||||
* in bpfel and bpfeb case, which means below, that we map
|
||||
* to cpu_to_be16(). We could use it unconditionally in BPF
|
||||
* case, but better not rely on it, so that this header here
|
||||
* can be used from application and BPF program side, which
|
||||
* use different targets.
|
||||
*/
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
# define __bpf_ntohs(x) __builtin_bswap16(x)
|
||||
# define __bpf_htons(x) __builtin_bswap16(x)
|
||||
# define __bpf_constant_ntohs(x) ___bpf_swab16(x)
|
||||
# define __bpf_constant_htons(x) ___bpf_swab16(x)
|
||||
# define __bpf_ntohl(x) __builtin_bswap32(x)
|
||||
# define __bpf_htonl(x) __builtin_bswap32(x)
|
||||
# define __bpf_constant_ntohl(x) ___bpf_swab32(x)
|
||||
# define __bpf_constant_htonl(x) ___bpf_swab32(x)
|
||||
# define __bpf_be64_to_cpu(x) __builtin_bswap64(x)
|
||||
# define __bpf_cpu_to_be64(x) __builtin_bswap64(x)
|
||||
# define __bpf_constant_be64_to_cpu(x) ___bpf_swab64(x)
|
||||
# define __bpf_constant_cpu_to_be64(x) ___bpf_swab64(x)
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
# define __bpf_ntohs(x) (x)
|
||||
# define __bpf_htons(x) (x)
|
||||
# define __bpf_constant_ntohs(x) (x)
|
||||
# define __bpf_constant_htons(x) (x)
|
||||
# define __bpf_ntohl(x) (x)
|
||||
# define __bpf_htonl(x) (x)
|
||||
# define __bpf_constant_ntohl(x) (x)
|
||||
# define __bpf_constant_htonl(x) (x)
|
||||
# define __bpf_be64_to_cpu(x) (x)
|
||||
# define __bpf_cpu_to_be64(x) (x)
|
||||
# define __bpf_constant_be64_to_cpu(x) (x)
|
||||
# define __bpf_constant_cpu_to_be64(x) (x)
|
||||
#else
|
||||
# error "Fix your compiler's __BYTE_ORDER__?!"
|
||||
#endif
|
||||
|
||||
#define bpf_htons(x) \
|
||||
(__builtin_constant_p(x) ? \
|
||||
__bpf_constant_htons(x) : __bpf_htons(x))
|
||||
#define bpf_ntohs(x) \
|
||||
(__builtin_constant_p(x) ? \
|
||||
__bpf_constant_ntohs(x) : __bpf_ntohs(x))
|
||||
#define bpf_htonl(x) \
|
||||
(__builtin_constant_p(x) ? \
|
||||
__bpf_constant_htonl(x) : __bpf_htonl(x))
|
||||
#define bpf_ntohl(x) \
|
||||
(__builtin_constant_p(x) ? \
|
||||
__bpf_constant_ntohl(x) : __bpf_ntohl(x))
|
||||
#define bpf_cpu_to_be64(x) \
|
||||
(__builtin_constant_p(x) ? \
|
||||
__bpf_constant_cpu_to_be64(x) : __bpf_cpu_to_be64(x))
|
||||
#define bpf_be64_to_cpu(x) \
|
||||
(__builtin_constant_p(x) ? \
|
||||
__bpf_constant_be64_to_cpu(x) : __bpf_be64_to_cpu(x))
|
||||
|
||||
#endif /* __BPF_ENDIAN__ */
|
||||
74
third_party/libbpf/src/bpf_gen_internal.h
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
/* Copyright (c) 2021 Facebook */
|
||||
#ifndef __BPF_GEN_INTERNAL_H
|
||||
#define __BPF_GEN_INTERNAL_H
|
||||
|
||||
#include "bpf.h"
|
||||
|
||||
struct ksym_relo_desc {
|
||||
const char *name;
|
||||
int kind;
|
||||
int insn_idx;
|
||||
bool is_weak;
|
||||
bool is_typeless;
|
||||
bool is_ld64;
|
||||
};
|
||||
|
||||
struct ksym_desc {
|
||||
const char *name;
|
||||
int ref;
|
||||
int kind;
|
||||
union {
|
||||
/* used for kfunc */
|
||||
int off;
|
||||
/* used for typeless ksym */
|
||||
bool typeless;
|
||||
};
|
||||
int insn;
|
||||
bool is_ld64;
|
||||
};
|
||||
|
||||
struct bpf_gen {
|
||||
struct gen_loader_opts *opts;
|
||||
void *data_start;
|
||||
void *data_cur;
|
||||
void *insn_start;
|
||||
void *insn_cur;
|
||||
ssize_t cleanup_label;
|
||||
__u32 nr_progs;
|
||||
__u32 nr_maps;
|
||||
int log_level;
|
||||
int error;
|
||||
struct ksym_relo_desc *relos;
|
||||
int relo_cnt;
|
||||
struct bpf_core_relo *core_relos;
|
||||
int core_relo_cnt;
|
||||
char attach_target[128];
|
||||
int attach_kind;
|
||||
struct ksym_desc *ksyms;
|
||||
__u32 nr_ksyms;
|
||||
int fd_array;
|
||||
int nr_fd_array;
|
||||
};
|
||||
|
||||
void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps);
|
||||
int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps);
|
||||
void bpf_gen__free(struct bpf_gen *gen);
|
||||
void bpf_gen__load_btf(struct bpf_gen *gen, const void *raw_data, __u32 raw_size);
|
||||
void bpf_gen__map_create(struct bpf_gen *gen,
|
||||
enum bpf_map_type map_type, const char *map_name,
|
||||
__u32 key_size, __u32 value_size, __u32 max_entries,
|
||||
struct bpf_map_create_opts *map_attr, int map_idx);
|
||||
void bpf_gen__prog_load(struct bpf_gen *gen,
|
||||
enum bpf_prog_type prog_type, const char *prog_name,
|
||||
const char *license, struct bpf_insn *insns, size_t insn_cnt,
|
||||
struct bpf_prog_load_opts *load_attr, int prog_idx);
|
||||
void bpf_gen__map_update_elem(struct bpf_gen *gen, int map_idx, void *value, __u32 value_size);
|
||||
void bpf_gen__map_freeze(struct bpf_gen *gen, int map_idx);
|
||||
void bpf_gen__record_attach_target(struct bpf_gen *gen, const char *name, enum bpf_attach_type type);
|
||||
void bpf_gen__record_extern(struct bpf_gen *gen, const char *name, bool is_weak,
|
||||
bool is_typeless, bool is_ld64, int kind, int insn_idx);
|
||||
void bpf_gen__record_relo_core(struct bpf_gen *gen, const struct bpf_core_relo *core_relo);
|
||||
void bpf_gen__populate_outer_map(struct bpf_gen *gen, int outer_map_idx, int key, int inner_map_idx);
|
||||
|
||||
#endif
|
||||
4752
third_party/libbpf/src/bpf_helper_defs.h
vendored
Normal file
402
third_party/libbpf/src/bpf_helpers.h
vendored
Normal file
@@ -0,0 +1,402 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
#ifndef __BPF_HELPERS__
|
||||
#define __BPF_HELPERS__
|
||||
|
||||
/*
|
||||
* Note that bpf programs need to include either
|
||||
* vmlinux.h (auto-generated from BTF) or linux/types.h
|
||||
* in advance since bpf_helper_defs.h uses such types
|
||||
* as __u64.
|
||||
*/
|
||||
#include "bpf_helper_defs.h"
|
||||
|
||||
#define __uint(name, val) int (*name)[val]
|
||||
#define __type(name, val) typeof(val) *name
|
||||
#define __array(name, val) typeof(val) *name[]
|
||||
|
||||
/*
|
||||
* Helper macro to place programs, maps, license in
|
||||
* different sections in elf_bpf file. Section names
|
||||
* are interpreted by libbpf depending on the context (BPF programs, BPF maps,
|
||||
* extern variables, etc).
|
||||
* To allow use of SEC() with externs (e.g., for extern .maps declarations),
|
||||
* make sure __attribute__((unused)) doesn't trigger compilation warning.
|
||||
*/
|
||||
#if __GNUC__ && !__clang__
|
||||
|
||||
/*
|
||||
* Pragma macros are broken on GCC
|
||||
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55578
|
||||
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90400
|
||||
*/
|
||||
#define SEC(name) __attribute__((section(name), used))
|
||||
|
||||
#else
|
||||
|
||||
#define SEC(name) \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wignored-attributes\"") \
|
||||
__attribute__((section(name), used)) \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
|
||||
#endif
|
||||
|
||||
/* Avoid 'linux/stddef.h' definition of '__always_inline'. */
|
||||
#undef __always_inline
|
||||
#define __always_inline inline __attribute__((always_inline))
|
||||
|
||||
#ifndef __noinline
|
||||
#define __noinline __attribute__((noinline))
|
||||
#endif
|
||||
#ifndef __weak
|
||||
#define __weak __attribute__((weak))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use __hidden attribute to mark a non-static BPF subprogram effectively
|
||||
* static for BPF verifier's verification algorithm purposes, allowing more
|
||||
* extensive and permissive BPF verification process, taking into account
|
||||
* subprogram's caller context.
|
||||
*/
|
||||
#define __hidden __attribute__((visibility("hidden")))
|
||||
|
||||
/* When utilizing vmlinux.h with BPF CO-RE, user BPF programs can't include
|
||||
* any system-level headers (such as stddef.h, linux/version.h, etc), and
|
||||
* commonly-used macros like NULL and KERNEL_VERSION aren't available through
|
||||
* vmlinux.h. This just adds unnecessary hurdles and forces users to re-define
|
||||
* them on their own. So as a convenience, provide such definitions here.
|
||||
*/
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#ifndef KERNEL_VERSION
|
||||
#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper macros to manipulate data structures
|
||||
*/
|
||||
|
||||
/* offsetof() definition that uses __builtin_offset() might not preserve field
|
||||
* offset CO-RE relocation properly, so force-redefine offsetof() using
|
||||
* old-school approach which works with CO-RE correctly
|
||||
*/
|
||||
#undef offsetof
|
||||
#define offsetof(type, member) ((unsigned long)&((type *)0)->member)
|
||||
|
||||
/* redefined container_of() to ensure we use the above offsetof() macro */
|
||||
#undef container_of
|
||||
#define container_of(ptr, type, member) \
|
||||
({ \
|
||||
void *__mptr = (void *)(ptr); \
|
||||
((type *)(__mptr - offsetof(type, member))); \
|
||||
})
|
||||
|
||||
/*
|
||||
* Compiler (optimization) barrier.
|
||||
*/
|
||||
#ifndef barrier
|
||||
#define barrier() asm volatile("" ::: "memory")
|
||||
#endif
|
||||
|
||||
/* Variable-specific compiler (optimization) barrier. It's a no-op which makes
|
||||
* compiler believe that there is some black box modification of a given
|
||||
* variable and thus prevents compiler from making extra assumption about its
|
||||
* value and potential simplifications and optimizations on this variable.
|
||||
*
|
||||
* E.g., compiler might often delay or even omit 32-bit to 64-bit casting of
|
||||
* a variable, making some code patterns unverifiable. Putting barrier_var()
|
||||
* in place will ensure that cast is performed before the barrier_var()
|
||||
* invocation, because compiler has to pessimistically assume that embedded
|
||||
* asm section might perform some extra operations on that variable.
|
||||
*
|
||||
* This is a variable-specific variant of more global barrier().
|
||||
*/
|
||||
#ifndef barrier_var
|
||||
#define barrier_var(var) asm volatile("" : "+r"(var))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper macro to throw a compilation error if __bpf_unreachable() gets
|
||||
* built into the resulting code. This works given BPF back end does not
|
||||
* implement __builtin_trap(). This is useful to assert that certain paths
|
||||
* of the program code are never used and hence eliminated by the compiler.
|
||||
*
|
||||
* For example, consider a switch statement that covers known cases used by
|
||||
* the program. __bpf_unreachable() can then reside in the default case. If
|
||||
* the program gets extended such that a case is not covered in the switch
|
||||
* statement, then it will throw a build error due to the default case not
|
||||
* being compiled out.
|
||||
*/
|
||||
#ifndef __bpf_unreachable
|
||||
# define __bpf_unreachable() __builtin_trap()
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper function to perform a tail call with a constant/immediate map slot.
|
||||
*/
|
||||
#if __clang_major__ >= 8 && defined(__bpf__)
|
||||
static __always_inline void
|
||||
bpf_tail_call_static(void *ctx, const void *map, const __u32 slot)
|
||||
{
|
||||
if (!__builtin_constant_p(slot))
|
||||
__bpf_unreachable();
|
||||
|
||||
/*
|
||||
* Provide a hard guarantee that LLVM won't optimize setting r2 (map
|
||||
* pointer) and r3 (constant map index) from _different paths_ ending
|
||||
* up at the _same_ call insn as otherwise we won't be able to use the
|
||||
* jmpq/nopl retpoline-free patching by the x86-64 JIT in the kernel
|
||||
* given they mismatch. See also d2e4c1e6c294 ("bpf: Constant map key
|
||||
* tracking for prog array pokes") for details on verifier tracking.
|
||||
*
|
||||
* Note on clobber list: we need to stay in-line with BPF calling
|
||||
* convention, so even if we don't end up using r0, r4, r5, we need
|
||||
* to mark them as clobber so that LLVM doesn't end up using them
|
||||
* before / after the call.
|
||||
*/
|
||||
asm volatile("r1 = %[ctx]\n\t"
|
||||
"r2 = %[map]\n\t"
|
||||
"r3 = %[slot]\n\t"
|
||||
"call 12"
|
||||
:: [ctx]"r"(ctx), [map]"r"(map), [slot]"i"(slot)
|
||||
: "r0", "r1", "r2", "r3", "r4", "r5");
|
||||
}
|
||||
#endif
|
||||
|
||||
enum libbpf_pin_type {
|
||||
LIBBPF_PIN_NONE,
|
||||
/* PIN_BY_NAME: pin maps by name (in /sys/fs/bpf by default) */
|
||||
LIBBPF_PIN_BY_NAME,
|
||||
};
|
||||
|
||||
enum libbpf_tristate {
|
||||
TRI_NO = 0,
|
||||
TRI_YES = 1,
|
||||
TRI_MODULE = 2,
|
||||
};
|
||||
|
||||
#define __kconfig __attribute__((section(".kconfig")))
|
||||
#define __ksym __attribute__((section(".ksyms")))
|
||||
#define __kptr_untrusted __attribute__((btf_type_tag("kptr_untrusted")))
|
||||
#define __kptr __attribute__((btf_type_tag("kptr")))
|
||||
|
||||
#define bpf_ksym_exists(sym) ({ \
|
||||
_Static_assert(!__builtin_constant_p(!!sym), #sym " should be marked as __weak"); \
|
||||
!!sym; \
|
||||
})
|
||||
|
||||
#ifndef ___bpf_concat
|
||||
#define ___bpf_concat(a, b) a ## b
|
||||
#endif
|
||||
#ifndef ___bpf_apply
|
||||
#define ___bpf_apply(fn, n) ___bpf_concat(fn, n)
|
||||
#endif
|
||||
#ifndef ___bpf_nth
|
||||
#define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N
|
||||
#endif
|
||||
#ifndef ___bpf_narg
|
||||
#define ___bpf_narg(...) \
|
||||
___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
#endif
|
||||
|
||||
#define ___bpf_fill0(arr, p, x) do {} while (0)
|
||||
#define ___bpf_fill1(arr, p, x) arr[p] = x
|
||||
#define ___bpf_fill2(arr, p, x, args...) arr[p] = x; ___bpf_fill1(arr, p + 1, args)
|
||||
#define ___bpf_fill3(arr, p, x, args...) arr[p] = x; ___bpf_fill2(arr, p + 1, args)
|
||||
#define ___bpf_fill4(arr, p, x, args...) arr[p] = x; ___bpf_fill3(arr, p + 1, args)
|
||||
#define ___bpf_fill5(arr, p, x, args...) arr[p] = x; ___bpf_fill4(arr, p + 1, args)
|
||||
#define ___bpf_fill6(arr, p, x, args...) arr[p] = x; ___bpf_fill5(arr, p + 1, args)
|
||||
#define ___bpf_fill7(arr, p, x, args...) arr[p] = x; ___bpf_fill6(arr, p + 1, args)
|
||||
#define ___bpf_fill8(arr, p, x, args...) arr[p] = x; ___bpf_fill7(arr, p + 1, args)
|
||||
#define ___bpf_fill9(arr, p, x, args...) arr[p] = x; ___bpf_fill8(arr, p + 1, args)
|
||||
#define ___bpf_fill10(arr, p, x, args...) arr[p] = x; ___bpf_fill9(arr, p + 1, args)
|
||||
#define ___bpf_fill11(arr, p, x, args...) arr[p] = x; ___bpf_fill10(arr, p + 1, args)
|
||||
#define ___bpf_fill12(arr, p, x, args...) arr[p] = x; ___bpf_fill11(arr, p + 1, args)
|
||||
#define ___bpf_fill(arr, args...) \
|
||||
___bpf_apply(___bpf_fill, ___bpf_narg(args))(arr, 0, args)
|
||||
|
||||
/*
|
||||
* BPF_SEQ_PRINTF to wrap bpf_seq_printf to-be-printed values
|
||||
* in a structure.
|
||||
*/
|
||||
#define BPF_SEQ_PRINTF(seq, fmt, args...) \
|
||||
({ \
|
||||
static const char ___fmt[] = fmt; \
|
||||
unsigned long long ___param[___bpf_narg(args)]; \
|
||||
\
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||
___bpf_fill(___param, args); \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
\
|
||||
bpf_seq_printf(seq, ___fmt, sizeof(___fmt), \
|
||||
___param, sizeof(___param)); \
|
||||
})
|
||||
|
||||
/*
|
||||
* BPF_SNPRINTF wraps the bpf_snprintf helper with variadic arguments instead of
|
||||
* an array of u64.
|
||||
*/
|
||||
#define BPF_SNPRINTF(out, out_size, fmt, args...) \
|
||||
({ \
|
||||
static const char ___fmt[] = fmt; \
|
||||
unsigned long long ___param[___bpf_narg(args)]; \
|
||||
\
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||
___bpf_fill(___param, args); \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
\
|
||||
bpf_snprintf(out, out_size, ___fmt, \
|
||||
___param, sizeof(___param)); \
|
||||
})
|
||||
|
||||
#ifdef BPF_NO_GLOBAL_DATA
|
||||
#define BPF_PRINTK_FMT_MOD
|
||||
#else
|
||||
#define BPF_PRINTK_FMT_MOD static const
|
||||
#endif
|
||||
|
||||
#define __bpf_printk(fmt, ...) \
|
||||
({ \
|
||||
BPF_PRINTK_FMT_MOD char ____fmt[] = fmt; \
|
||||
bpf_trace_printk(____fmt, sizeof(____fmt), \
|
||||
##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
/*
|
||||
* __bpf_vprintk wraps the bpf_trace_vprintk helper with variadic arguments
|
||||
* instead of an array of u64.
|
||||
*/
|
||||
#define __bpf_vprintk(fmt, args...) \
|
||||
({ \
|
||||
static const char ___fmt[] = fmt; \
|
||||
unsigned long long ___param[___bpf_narg(args)]; \
|
||||
\
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||
___bpf_fill(___param, args); \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
\
|
||||
bpf_trace_vprintk(___fmt, sizeof(___fmt), \
|
||||
___param, sizeof(___param)); \
|
||||
})
|
||||
|
||||
/* Use __bpf_printk when bpf_printk call has 3 or fewer fmt args
|
||||
* Otherwise use __bpf_vprintk
|
||||
*/
|
||||
#define ___bpf_pick_printk(...) \
|
||||
___bpf_nth(_, ##__VA_ARGS__, __bpf_vprintk, __bpf_vprintk, __bpf_vprintk, \
|
||||
__bpf_vprintk, __bpf_vprintk, __bpf_vprintk, __bpf_vprintk, \
|
||||
__bpf_vprintk, __bpf_vprintk, __bpf_printk /*3*/, __bpf_printk /*2*/,\
|
||||
__bpf_printk /*1*/, __bpf_printk /*0*/)
|
||||
|
||||
/* Helper macro to print out debug messages */
|
||||
#define bpf_printk(fmt, args...) ___bpf_pick_printk(args)(fmt, ##args)
|
||||
|
||||
struct bpf_iter_num;
|
||||
|
||||
extern int bpf_iter_num_new(struct bpf_iter_num *it, int start, int end) __weak __ksym;
|
||||
extern int *bpf_iter_num_next(struct bpf_iter_num *it) __weak __ksym;
|
||||
extern void bpf_iter_num_destroy(struct bpf_iter_num *it) __weak __ksym;
|
||||
|
||||
#ifndef bpf_for_each
|
||||
/* bpf_for_each(iter_type, cur_elem, args...) provides generic construct for
|
||||
* using BPF open-coded iterators without having to write mundane explicit
|
||||
* low-level loop logic. Instead, it provides for()-like generic construct
|
||||
* that can be used pretty naturally. E.g., for some hypothetical cgroup
|
||||
* iterator, you'd write:
|
||||
*
|
||||
* struct cgroup *cg, *parent_cg = <...>;
|
||||
*
|
||||
* bpf_for_each(cgroup, cg, parent_cg, CG_ITER_CHILDREN) {
|
||||
* bpf_printk("Child cgroup id = %d", cg->cgroup_id);
|
||||
* if (cg->cgroup_id == 123)
|
||||
* break;
|
||||
* }
|
||||
*
|
||||
* I.e., it looks almost like high-level for each loop in other languages,
|
||||
* supports continue/break, and is verifiable by BPF verifier.
|
||||
*
|
||||
* For iterating integers, the difference betwen bpf_for_each(num, i, N, M)
|
||||
* and bpf_for(i, N, M) is in that bpf_for() provides additional proof to
|
||||
* verifier that i is in [N, M) range, and in bpf_for_each() case i is `int
|
||||
* *`, not just `int`. So for integers bpf_for() is more convenient.
|
||||
*
|
||||
* Note: this macro relies on C99 feature of allowing to declare variables
|
||||
* inside for() loop, bound to for() loop lifetime. It also utilizes GCC
|
||||
* extension: __attribute__((cleanup(<func>))), supported by both GCC and
|
||||
* Clang.
|
||||
*/
|
||||
#define bpf_for_each(type, cur, args...) for ( \
|
||||
/* initialize and define destructor */ \
|
||||
struct bpf_iter_##type ___it __attribute__((aligned(8), /* enforce, just in case */, \
|
||||
cleanup(bpf_iter_##type##_destroy))), \
|
||||
/* ___p pointer is just to call bpf_iter_##type##_new() *once* to init ___it */ \
|
||||
*___p __attribute__((unused)) = ( \
|
||||
bpf_iter_##type##_new(&___it, ##args), \
|
||||
/* this is a workaround for Clang bug: it currently doesn't emit BTF */ \
|
||||
/* for bpf_iter_##type##_destroy() when used from cleanup() attribute */ \
|
||||
(void)bpf_iter_##type##_destroy, (void *)0); \
|
||||
/* iteration and termination check */ \
|
||||
(((cur) = bpf_iter_##type##_next(&___it))); \
|
||||
)
|
||||
#endif /* bpf_for_each */
|
||||
|
||||
#ifndef bpf_for
|
||||
/* bpf_for(i, start, end) implements a for()-like looping construct that sets
|
||||
* provided integer variable *i* to values starting from *start* through,
|
||||
* but not including, *end*. It also proves to BPF verifier that *i* belongs
|
||||
* to range [start, end), so this can be used for accessing arrays without
|
||||
* extra checks.
|
||||
*
|
||||
* Note: *start* and *end* are assumed to be expressions with no side effects
|
||||
* and whose values do not change throughout bpf_for() loop execution. They do
|
||||
* not have to be statically known or constant, though.
|
||||
*
|
||||
* Note: similarly to bpf_for_each(), it relies on C99 feature of declaring for()
|
||||
* loop bound variables and cleanup attribute, supported by GCC and Clang.
|
||||
*/
|
||||
#define bpf_for(i, start, end) for ( \
|
||||
/* initialize and define destructor */ \
|
||||
struct bpf_iter_num ___it __attribute__((aligned(8), /* enforce, just in case */ \
|
||||
cleanup(bpf_iter_num_destroy))), \
|
||||
/* ___p pointer is necessary to call bpf_iter_num_new() *once* to init ___it */ \
|
||||
*___p __attribute__((unused)) = ( \
|
||||
bpf_iter_num_new(&___it, (start), (end)), \
|
||||
/* this is a workaround for Clang bug: it currently doesn't emit BTF */ \
|
||||
/* for bpf_iter_num_destroy() when used from cleanup() attribute */ \
|
||||
(void)bpf_iter_num_destroy, (void *)0); \
|
||||
({ \
|
||||
/* iteration step */ \
|
||||
int *___t = bpf_iter_num_next(&___it); \
|
||||
/* termination and bounds check */ \
|
||||
(___t && ((i) = *___t, (i) >= (start) && (i) < (end))); \
|
||||
}); \
|
||||
)
|
||||
#endif /* bpf_for */
|
||||
|
||||
#ifndef bpf_repeat
|
||||
/* bpf_repeat(N) performs N iterations without exposing iteration number
|
||||
*
|
||||
* Note: similarly to bpf_for_each(), it relies on C99 feature of declaring for()
|
||||
* loop bound variables and cleanup attribute, supported by GCC and Clang.
|
||||
*/
|
||||
#define bpf_repeat(N) for ( \
|
||||
/* initialize and define destructor */ \
|
||||
struct bpf_iter_num ___it __attribute__((aligned(8), /* enforce, just in case */ \
|
||||
cleanup(bpf_iter_num_destroy))), \
|
||||
/* ___p pointer is necessary to call bpf_iter_num_new() *once* to init ___it */ \
|
||||
*___p __attribute__((unused)) = ( \
|
||||
bpf_iter_num_new(&___it, 0, (N)), \
|
||||
/* this is a workaround for Clang bug: it currently doesn't emit BTF */ \
|
||||
/* for bpf_iter_num_destroy() when used from cleanup() attribute */ \
|
||||
(void)bpf_iter_num_destroy, (void *)0); \
|
||||
bpf_iter_num_next(&___it); \
|
||||
/* nothing here */ \
|
||||
)
|
||||
#endif /* bpf_repeat */
|
||||
|
||||
#endif
|
||||
246
third_party/libbpf/src/bpf_prog_linfo.c
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
/* Copyright (c) 2018 Facebook */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/bpf.h>
|
||||
#include "libbpf.h"
|
||||
#include "libbpf_internal.h"
|
||||
|
||||
struct bpf_prog_linfo {
|
||||
void *raw_linfo;
|
||||
void *raw_jited_linfo;
|
||||
__u32 *nr_jited_linfo_per_func;
|
||||
__u32 *jited_linfo_func_idx;
|
||||
__u32 nr_linfo;
|
||||
__u32 nr_jited_func;
|
||||
__u32 rec_size;
|
||||
__u32 jited_rec_size;
|
||||
};
|
||||
|
||||
static int dissect_jited_func(struct bpf_prog_linfo *prog_linfo,
|
||||
const __u64 *ksym_func, const __u32 *ksym_len)
|
||||
{
|
||||
__u32 nr_jited_func, nr_linfo;
|
||||
const void *raw_jited_linfo;
|
||||
const __u64 *jited_linfo;
|
||||
__u64 last_jited_linfo;
|
||||
/*
|
||||
* Index to raw_jited_linfo:
|
||||
* i: Index for searching the next ksym_func
|
||||
* prev_i: Index to the last found ksym_func
|
||||
*/
|
||||
__u32 i, prev_i;
|
||||
__u32 f; /* Index to ksym_func */
|
||||
|
||||
raw_jited_linfo = prog_linfo->raw_jited_linfo;
|
||||
jited_linfo = raw_jited_linfo;
|
||||
if (ksym_func[0] != *jited_linfo)
|
||||
goto errout;
|
||||
|
||||
prog_linfo->jited_linfo_func_idx[0] = 0;
|
||||
nr_jited_func = prog_linfo->nr_jited_func;
|
||||
nr_linfo = prog_linfo->nr_linfo;
|
||||
|
||||
for (prev_i = 0, i = 1, f = 1;
|
||||
i < nr_linfo && f < nr_jited_func;
|
||||
i++) {
|
||||
raw_jited_linfo += prog_linfo->jited_rec_size;
|
||||
last_jited_linfo = *jited_linfo;
|
||||
jited_linfo = raw_jited_linfo;
|
||||
|
||||
if (ksym_func[f] == *jited_linfo) {
|
||||
prog_linfo->jited_linfo_func_idx[f] = i;
|
||||
|
||||
/* Sanity check */
|
||||
if (last_jited_linfo - ksym_func[f - 1] + 1 >
|
||||
ksym_len[f - 1])
|
||||
goto errout;
|
||||
|
||||
prog_linfo->nr_jited_linfo_per_func[f - 1] =
|
||||
i - prev_i;
|
||||
prev_i = i;
|
||||
|
||||
/*
|
||||
* The ksym_func[f] is found in jited_linfo.
|
||||
* Look for the next one.
|
||||
*/
|
||||
f++;
|
||||
} else if (*jited_linfo <= last_jited_linfo) {
|
||||
/* Ensure the addr is increasing _within_ a func */
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
if (f != nr_jited_func)
|
||||
goto errout;
|
||||
|
||||
prog_linfo->nr_jited_linfo_per_func[nr_jited_func - 1] =
|
||||
nr_linfo - prev_i;
|
||||
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void bpf_prog_linfo__free(struct bpf_prog_linfo *prog_linfo)
|
||||
{
|
||||
if (!prog_linfo)
|
||||
return;
|
||||
|
||||
free(prog_linfo->raw_linfo);
|
||||
free(prog_linfo->raw_jited_linfo);
|
||||
free(prog_linfo->nr_jited_linfo_per_func);
|
||||
free(prog_linfo->jited_linfo_func_idx);
|
||||
free(prog_linfo);
|
||||
}
|
||||
|
||||
struct bpf_prog_linfo *bpf_prog_linfo__new(const struct bpf_prog_info *info)
|
||||
{
|
||||
struct bpf_prog_linfo *prog_linfo;
|
||||
__u32 nr_linfo, nr_jited_func;
|
||||
__u64 data_sz;
|
||||
|
||||
nr_linfo = info->nr_line_info;
|
||||
|
||||
if (!nr_linfo)
|
||||
return errno = EINVAL, NULL;
|
||||
|
||||
/*
|
||||
* The min size that bpf_prog_linfo has to access for
|
||||
* searching purpose.
|
||||
*/
|
||||
if (info->line_info_rec_size <
|
||||
offsetof(struct bpf_line_info, file_name_off))
|
||||
return errno = EINVAL, NULL;
|
||||
|
||||
prog_linfo = calloc(1, sizeof(*prog_linfo));
|
||||
if (!prog_linfo)
|
||||
return errno = ENOMEM, NULL;
|
||||
|
||||
/* Copy xlated line_info */
|
||||
prog_linfo->nr_linfo = nr_linfo;
|
||||
prog_linfo->rec_size = info->line_info_rec_size;
|
||||
data_sz = (__u64)nr_linfo * prog_linfo->rec_size;
|
||||
prog_linfo->raw_linfo = malloc(data_sz);
|
||||
if (!prog_linfo->raw_linfo)
|
||||
goto err_free;
|
||||
memcpy(prog_linfo->raw_linfo, (void *)(long)info->line_info, data_sz);
|
||||
|
||||
nr_jited_func = info->nr_jited_ksyms;
|
||||
if (!nr_jited_func ||
|
||||
!info->jited_line_info ||
|
||||
info->nr_jited_line_info != nr_linfo ||
|
||||
info->jited_line_info_rec_size < sizeof(__u64) ||
|
||||
info->nr_jited_func_lens != nr_jited_func ||
|
||||
!info->jited_ksyms ||
|
||||
!info->jited_func_lens)
|
||||
/* Not enough info to provide jited_line_info */
|
||||
return prog_linfo;
|
||||
|
||||
/* Copy jited_line_info */
|
||||
prog_linfo->nr_jited_func = nr_jited_func;
|
||||
prog_linfo->jited_rec_size = info->jited_line_info_rec_size;
|
||||
data_sz = (__u64)nr_linfo * prog_linfo->jited_rec_size;
|
||||
prog_linfo->raw_jited_linfo = malloc(data_sz);
|
||||
if (!prog_linfo->raw_jited_linfo)
|
||||
goto err_free;
|
||||
memcpy(prog_linfo->raw_jited_linfo,
|
||||
(void *)(long)info->jited_line_info, data_sz);
|
||||
|
||||
/* Number of jited_line_info per jited func */
|
||||
prog_linfo->nr_jited_linfo_per_func = malloc(nr_jited_func *
|
||||
sizeof(__u32));
|
||||
if (!prog_linfo->nr_jited_linfo_per_func)
|
||||
goto err_free;
|
||||
|
||||
/*
|
||||
* For each jited func,
|
||||
* the start idx to the "linfo" and "jited_linfo" array,
|
||||
*/
|
||||
prog_linfo->jited_linfo_func_idx = malloc(nr_jited_func *
|
||||
sizeof(__u32));
|
||||
if (!prog_linfo->jited_linfo_func_idx)
|
||||
goto err_free;
|
||||
|
||||
if (dissect_jited_func(prog_linfo,
|
||||
(__u64 *)(long)info->jited_ksyms,
|
||||
(__u32 *)(long)info->jited_func_lens))
|
||||
goto err_free;
|
||||
|
||||
return prog_linfo;
|
||||
|
||||
err_free:
|
||||
bpf_prog_linfo__free(prog_linfo);
|
||||
return errno = EINVAL, NULL;
|
||||
}
|
||||
|
||||
const struct bpf_line_info *
|
||||
bpf_prog_linfo__lfind_addr_func(const struct bpf_prog_linfo *prog_linfo,
|
||||
__u64 addr, __u32 func_idx, __u32 nr_skip)
|
||||
{
|
||||
__u32 jited_rec_size, rec_size, nr_linfo, start, i;
|
||||
const void *raw_jited_linfo, *raw_linfo;
|
||||
const __u64 *jited_linfo;
|
||||
|
||||
if (func_idx >= prog_linfo->nr_jited_func)
|
||||
return errno = ENOENT, NULL;
|
||||
|
||||
nr_linfo = prog_linfo->nr_jited_linfo_per_func[func_idx];
|
||||
if (nr_skip >= nr_linfo)
|
||||
return errno = ENOENT, NULL;
|
||||
|
||||
start = prog_linfo->jited_linfo_func_idx[func_idx] + nr_skip;
|
||||
jited_rec_size = prog_linfo->jited_rec_size;
|
||||
raw_jited_linfo = prog_linfo->raw_jited_linfo +
|
||||
(start * jited_rec_size);
|
||||
jited_linfo = raw_jited_linfo;
|
||||
if (addr < *jited_linfo)
|
||||
return errno = ENOENT, NULL;
|
||||
|
||||
nr_linfo -= nr_skip;
|
||||
rec_size = prog_linfo->rec_size;
|
||||
raw_linfo = prog_linfo->raw_linfo + (start * rec_size);
|
||||
for (i = 0; i < nr_linfo; i++) {
|
||||
if (addr < *jited_linfo)
|
||||
break;
|
||||
|
||||
raw_linfo += rec_size;
|
||||
raw_jited_linfo += jited_rec_size;
|
||||
jited_linfo = raw_jited_linfo;
|
||||
}
|
||||
|
||||
return raw_linfo - rec_size;
|
||||
}
|
||||
|
||||
const struct bpf_line_info *
|
||||
bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo,
|
||||
__u32 insn_off, __u32 nr_skip)
|
||||
{
|
||||
const struct bpf_line_info *linfo;
|
||||
__u32 rec_size, nr_linfo, i;
|
||||
const void *raw_linfo;
|
||||
|
||||
nr_linfo = prog_linfo->nr_linfo;
|
||||
if (nr_skip >= nr_linfo)
|
||||
return errno = ENOENT, NULL;
|
||||
|
||||
rec_size = prog_linfo->rec_size;
|
||||
raw_linfo = prog_linfo->raw_linfo + (nr_skip * rec_size);
|
||||
linfo = raw_linfo;
|
||||
if (insn_off < linfo->insn_off)
|
||||
return errno = ENOENT, NULL;
|
||||
|
||||
nr_linfo -= nr_skip;
|
||||
for (i = 0; i < nr_linfo; i++) {
|
||||
if (insn_off < linfo->insn_off)
|
||||
break;
|
||||
|
||||
raw_linfo += rec_size;
|
||||
linfo = raw_linfo;
|
||||
}
|
||||
|
||||
return raw_linfo - rec_size;
|
||||
}
|
||||
924
third_party/libbpf/src/bpf_tracing.h
vendored
Normal file
@@ -0,0 +1,924 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
#ifndef __BPF_TRACING_H__
|
||||
#define __BPF_TRACING_H__
|
||||
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
/* Scan the ARCH passed in from ARCH env variable (see Makefile) */
|
||||
#if defined(__TARGET_ARCH_x86)
|
||||
#define bpf_target_x86
|
||||
#define bpf_target_defined
|
||||
#elif defined(__TARGET_ARCH_s390)
|
||||
#define bpf_target_s390
|
||||
#define bpf_target_defined
|
||||
#elif defined(__TARGET_ARCH_arm)
|
||||
#define bpf_target_arm
|
||||
#define bpf_target_defined
|
||||
#elif defined(__TARGET_ARCH_arm64)
|
||||
#define bpf_target_arm64
|
||||
#define bpf_target_defined
|
||||
#elif defined(__TARGET_ARCH_mips)
|
||||
#define bpf_target_mips
|
||||
#define bpf_target_defined
|
||||
#elif defined(__TARGET_ARCH_powerpc)
|
||||
#define bpf_target_powerpc
|
||||
#define bpf_target_defined
|
||||
#elif defined(__TARGET_ARCH_sparc)
|
||||
#define bpf_target_sparc
|
||||
#define bpf_target_defined
|
||||
#elif defined(__TARGET_ARCH_riscv)
|
||||
#define bpf_target_riscv
|
||||
#define bpf_target_defined
|
||||
#elif defined(__TARGET_ARCH_arc)
|
||||
#define bpf_target_arc
|
||||
#define bpf_target_defined
|
||||
#elif defined(__TARGET_ARCH_loongarch)
|
||||
#define bpf_target_loongarch
|
||||
#define bpf_target_defined
|
||||
#else
|
||||
|
||||
/* Fall back to what the compiler says */
|
||||
#if defined(__x86_64__)
|
||||
#define bpf_target_x86
|
||||
#define bpf_target_defined
|
||||
#elif defined(__s390__)
|
||||
#define bpf_target_s390
|
||||
#define bpf_target_defined
|
||||
#elif defined(__arm__)
|
||||
#define bpf_target_arm
|
||||
#define bpf_target_defined
|
||||
#elif defined(__aarch64__)
|
||||
#define bpf_target_arm64
|
||||
#define bpf_target_defined
|
||||
#elif defined(__mips__)
|
||||
#define bpf_target_mips
|
||||
#define bpf_target_defined
|
||||
#elif defined(__powerpc__)
|
||||
#define bpf_target_powerpc
|
||||
#define bpf_target_defined
|
||||
#elif defined(__sparc__)
|
||||
#define bpf_target_sparc
|
||||
#define bpf_target_defined
|
||||
#elif defined(__riscv) && __riscv_xlen == 64
|
||||
#define bpf_target_riscv
|
||||
#define bpf_target_defined
|
||||
#elif defined(__arc__)
|
||||
#define bpf_target_arc
|
||||
#define bpf_target_defined
|
||||
#elif defined(__loongarch__)
|
||||
#define bpf_target_loongarch
|
||||
#define bpf_target_defined
|
||||
#endif /* no compiler target */
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __BPF_TARGET_MISSING
|
||||
#define __BPF_TARGET_MISSING "GCC error \"Must specify a BPF target arch via __TARGET_ARCH_xxx\""
|
||||
#endif
|
||||
|
||||
#if defined(bpf_target_x86)
|
||||
|
||||
/*
|
||||
* https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI
|
||||
*/
|
||||
|
||||
#if defined(__KERNEL__) || defined(__VMLINUX_H__)
|
||||
|
||||
#define __PT_PARM1_REG di
|
||||
#define __PT_PARM2_REG si
|
||||
#define __PT_PARM3_REG dx
|
||||
#define __PT_PARM4_REG cx
|
||||
#define __PT_PARM5_REG r8
|
||||
#define __PT_PARM6_REG r9
|
||||
/*
|
||||
* Syscall uses r10 for PARM4. See arch/x86/entry/entry_64.S:entry_SYSCALL_64
|
||||
* comments in Linux sources. And refer to syscall(2) manpage.
|
||||
*/
|
||||
#define __PT_PARM1_SYSCALL_REG __PT_PARM1_REG
|
||||
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
|
||||
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
|
||||
#define __PT_PARM4_SYSCALL_REG r10
|
||||
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
||||
#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG
|
||||
|
||||
#define __PT_RET_REG sp
|
||||
#define __PT_FP_REG bp
|
||||
#define __PT_RC_REG ax
|
||||
#define __PT_SP_REG sp
|
||||
#define __PT_IP_REG ip
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
/* i386 kernel is built with -mregparm=3 */
|
||||
#define __PT_PARM1_REG eax
|
||||
#define __PT_PARM2_REG edx
|
||||
#define __PT_PARM3_REG ecx
|
||||
/* i386 syscall ABI is very different, refer to syscall(2) manpage */
|
||||
#define __PT_PARM1_SYSCALL_REG ebx
|
||||
#define __PT_PARM2_SYSCALL_REG ecx
|
||||
#define __PT_PARM3_SYSCALL_REG edx
|
||||
#define __PT_PARM4_SYSCALL_REG esi
|
||||
#define __PT_PARM5_SYSCALL_REG edi
|
||||
#define __PT_PARM6_SYSCALL_REG ebp
|
||||
|
||||
#define __PT_RET_REG esp
|
||||
#define __PT_FP_REG ebp
|
||||
#define __PT_RC_REG eax
|
||||
#define __PT_SP_REG esp
|
||||
#define __PT_IP_REG eip
|
||||
|
||||
#else /* __i386__ */
|
||||
|
||||
#define __PT_PARM1_REG rdi
|
||||
#define __PT_PARM2_REG rsi
|
||||
#define __PT_PARM3_REG rdx
|
||||
#define __PT_PARM4_REG rcx
|
||||
#define __PT_PARM5_REG r8
|
||||
#define __PT_PARM6_REG r9
|
||||
|
||||
#define __PT_PARM1_SYSCALL_REG __PT_PARM1_REG
|
||||
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
|
||||
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
|
||||
#define __PT_PARM4_SYSCALL_REG r10
|
||||
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
||||
#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG
|
||||
|
||||
#define __PT_RET_REG rsp
|
||||
#define __PT_FP_REG rbp
|
||||
#define __PT_RC_REG rax
|
||||
#define __PT_SP_REG rsp
|
||||
#define __PT_IP_REG rip
|
||||
|
||||
#endif /* __i386__ */
|
||||
|
||||
#endif /* __KERNEL__ || __VMLINUX_H__ */
|
||||
|
||||
#elif defined(bpf_target_s390)
|
||||
|
||||
/*
|
||||
* https://github.com/IBM/s390x-abi/releases/download/v1.6/lzsabi_s390x.pdf
|
||||
*/
|
||||
|
||||
struct pt_regs___s390 {
|
||||
unsigned long orig_gpr2;
|
||||
};
|
||||
|
||||
/* s390 provides user_pt_regs instead of struct pt_regs to userspace */
|
||||
#define __PT_REGS_CAST(x) ((const user_pt_regs *)(x))
|
||||
#define __PT_PARM1_REG gprs[2]
|
||||
#define __PT_PARM2_REG gprs[3]
|
||||
#define __PT_PARM3_REG gprs[4]
|
||||
#define __PT_PARM4_REG gprs[5]
|
||||
#define __PT_PARM5_REG gprs[6]
|
||||
|
||||
#define __PT_PARM1_SYSCALL_REG orig_gpr2
|
||||
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
|
||||
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
|
||||
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
||||
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
||||
#define __PT_PARM6_SYSCALL_REG gprs[7]
|
||||
#define PT_REGS_PARM1_SYSCALL(x) PT_REGS_PARM1_CORE_SYSCALL(x)
|
||||
#define PT_REGS_PARM1_CORE_SYSCALL(x) \
|
||||
BPF_CORE_READ((const struct pt_regs___s390 *)(x), __PT_PARM1_SYSCALL_REG)
|
||||
|
||||
#define __PT_RET_REG gprs[14]
|
||||
#define __PT_FP_REG gprs[11] /* Works only with CONFIG_FRAME_POINTER */
|
||||
#define __PT_RC_REG gprs[2]
|
||||
#define __PT_SP_REG gprs[15]
|
||||
#define __PT_IP_REG psw.addr
|
||||
|
||||
#elif defined(bpf_target_arm)
|
||||
|
||||
/*
|
||||
* https://github.com/ARM-software/abi-aa/blob/main/aapcs32/aapcs32.rst#machine-registers
|
||||
*/
|
||||
|
||||
#define __PT_PARM1_REG uregs[0]
|
||||
#define __PT_PARM2_REG uregs[1]
|
||||
#define __PT_PARM3_REG uregs[2]
|
||||
#define __PT_PARM4_REG uregs[3]
|
||||
|
||||
#define __PT_PARM1_SYSCALL_REG __PT_PARM1_REG
|
||||
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
|
||||
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
|
||||
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
||||
#define __PT_PARM5_SYSCALL_REG uregs[4]
|
||||
#define __PT_PARM6_SYSCALL_REG uregs[5]
|
||||
#define __PT_PARM7_SYSCALL_REG uregs[6]
|
||||
|
||||
#define __PT_RET_REG uregs[14]
|
||||
#define __PT_FP_REG uregs[11] /* Works only with CONFIG_FRAME_POINTER */
|
||||
#define __PT_RC_REG uregs[0]
|
||||
#define __PT_SP_REG uregs[13]
|
||||
#define __PT_IP_REG uregs[12]
|
||||
|
||||
#elif defined(bpf_target_arm64)
|
||||
|
||||
/*
|
||||
* https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#machine-registers
|
||||
*/
|
||||
|
||||
struct pt_regs___arm64 {
|
||||
unsigned long orig_x0;
|
||||
};
|
||||
|
||||
/* arm64 provides struct user_pt_regs instead of struct pt_regs to userspace */
|
||||
#define __PT_REGS_CAST(x) ((const struct user_pt_regs *)(x))
|
||||
#define __PT_PARM1_REG regs[0]
|
||||
#define __PT_PARM2_REG regs[1]
|
||||
#define __PT_PARM3_REG regs[2]
|
||||
#define __PT_PARM4_REG regs[3]
|
||||
#define __PT_PARM5_REG regs[4]
|
||||
#define __PT_PARM6_REG regs[5]
|
||||
#define __PT_PARM7_REG regs[6]
|
||||
#define __PT_PARM8_REG regs[7]
|
||||
|
||||
#define __PT_PARM1_SYSCALL_REG orig_x0
|
||||
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
|
||||
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
|
||||
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
||||
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
||||
#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG
|
||||
#define PT_REGS_PARM1_SYSCALL(x) PT_REGS_PARM1_CORE_SYSCALL(x)
|
||||
#define PT_REGS_PARM1_CORE_SYSCALL(x) \
|
||||
BPF_CORE_READ((const struct pt_regs___arm64 *)(x), __PT_PARM1_SYSCALL_REG)
|
||||
|
||||
#define __PT_RET_REG regs[30]
|
||||
#define __PT_FP_REG regs[29] /* Works only with CONFIG_FRAME_POINTER */
|
||||
#define __PT_RC_REG regs[0]
|
||||
#define __PT_SP_REG sp
|
||||
#define __PT_IP_REG pc
|
||||
|
||||
#elif defined(bpf_target_mips)
|
||||
|
||||
/*
|
||||
* N64 ABI is assumed right now.
|
||||
* https://en.wikipedia.org/wiki/MIPS_architecture#Calling_conventions
|
||||
*/
|
||||
|
||||
#define __PT_PARM1_REG regs[4]
|
||||
#define __PT_PARM2_REG regs[5]
|
||||
#define __PT_PARM3_REG regs[6]
|
||||
#define __PT_PARM4_REG regs[7]
|
||||
#define __PT_PARM5_REG regs[8]
|
||||
#define __PT_PARM6_REG regs[9]
|
||||
#define __PT_PARM7_REG regs[10]
|
||||
#define __PT_PARM8_REG regs[11]
|
||||
|
||||
#define __PT_PARM1_SYSCALL_REG __PT_PARM1_REG
|
||||
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
|
||||
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
|
||||
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
||||
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG /* only N32/N64 */
|
||||
#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG /* only N32/N64 */
|
||||
|
||||
#define __PT_RET_REG regs[31]
|
||||
#define __PT_FP_REG regs[30] /* Works only with CONFIG_FRAME_POINTER */
|
||||
#define __PT_RC_REG regs[2]
|
||||
#define __PT_SP_REG regs[29]
|
||||
#define __PT_IP_REG cp0_epc
|
||||
|
||||
#elif defined(bpf_target_powerpc)
|
||||
|
||||
/*
|
||||
* http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf (page 3-14,
|
||||
* section "Function Calling Sequence")
|
||||
*/
|
||||
|
||||
#define __PT_PARM1_REG gpr[3]
|
||||
#define __PT_PARM2_REG gpr[4]
|
||||
#define __PT_PARM3_REG gpr[5]
|
||||
#define __PT_PARM4_REG gpr[6]
|
||||
#define __PT_PARM5_REG gpr[7]
|
||||
#define __PT_PARM6_REG gpr[8]
|
||||
#define __PT_PARM7_REG gpr[9]
|
||||
#define __PT_PARM8_REG gpr[10]
|
||||
|
||||
/* powerpc does not select ARCH_HAS_SYSCALL_WRAPPER. */
|
||||
#define PT_REGS_SYSCALL_REGS(ctx) ctx
|
||||
#define __PT_PARM1_SYSCALL_REG orig_gpr3
|
||||
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
|
||||
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
|
||||
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
||||
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
||||
#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG
|
||||
#if !defined(__arch64__)
|
||||
#define __PT_PARM7_SYSCALL_REG __PT_PARM7_REG /* only powerpc (not powerpc64) */
|
||||
#endif
|
||||
|
||||
#define __PT_RET_REG regs[31]
|
||||
#define __PT_FP_REG __unsupported__
|
||||
#define __PT_RC_REG gpr[3]
|
||||
#define __PT_SP_REG sp
|
||||
#define __PT_IP_REG nip
|
||||
|
||||
#elif defined(bpf_target_sparc)
|
||||
|
||||
/*
|
||||
* https://en.wikipedia.org/wiki/Calling_convention#SPARC
|
||||
*/
|
||||
|
||||
#define __PT_PARM1_REG u_regs[UREG_I0]
|
||||
#define __PT_PARM2_REG u_regs[UREG_I1]
|
||||
#define __PT_PARM3_REG u_regs[UREG_I2]
|
||||
#define __PT_PARM4_REG u_regs[UREG_I3]
|
||||
#define __PT_PARM5_REG u_regs[UREG_I4]
|
||||
#define __PT_PARM6_REG u_regs[UREG_I5]
|
||||
|
||||
#define __PT_PARM1_SYSCALL_REG __PT_PARM1_REG
|
||||
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
|
||||
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
|
||||
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
||||
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
||||
#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG
|
||||
|
||||
#define __PT_RET_REG u_regs[UREG_I7]
|
||||
#define __PT_FP_REG __unsupported__
|
||||
#define __PT_RC_REG u_regs[UREG_I0]
|
||||
#define __PT_SP_REG u_regs[UREG_FP]
|
||||
/* Should this also be a bpf_target check for the sparc case? */
|
||||
#if defined(__arch64__)
|
||||
#define __PT_IP_REG tpc
|
||||
#else
|
||||
#define __PT_IP_REG pc
|
||||
#endif
|
||||
|
||||
#elif defined(bpf_target_riscv)
|
||||
|
||||
/*
|
||||
* https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#risc-v-calling-conventions
|
||||
*/
|
||||
|
||||
/* riscv provides struct user_regs_struct instead of struct pt_regs to userspace */
|
||||
#define __PT_REGS_CAST(x) ((const struct user_regs_struct *)(x))
|
||||
#define __PT_PARM1_REG a0
|
||||
#define __PT_PARM2_REG a1
|
||||
#define __PT_PARM3_REG a2
|
||||
#define __PT_PARM4_REG a3
|
||||
#define __PT_PARM5_REG a4
|
||||
#define __PT_PARM6_REG a5
|
||||
#define __PT_PARM7_REG a6
|
||||
#define __PT_PARM8_REG a7
|
||||
|
||||
/* riscv does not select ARCH_HAS_SYSCALL_WRAPPER. */
|
||||
#define PT_REGS_SYSCALL_REGS(ctx) ctx
|
||||
#define __PT_PARM1_SYSCALL_REG __PT_PARM1_REG
|
||||
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
|
||||
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
|
||||
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
||||
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
||||
#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG
|
||||
|
||||
#define __PT_RET_REG ra
|
||||
#define __PT_FP_REG s0
|
||||
#define __PT_RC_REG a0
|
||||
#define __PT_SP_REG sp
|
||||
#define __PT_IP_REG pc
|
||||
|
||||
#elif defined(bpf_target_arc)
|
||||
|
||||
/*
|
||||
* Section "Function Calling Sequence" (page 24):
|
||||
* https://raw.githubusercontent.com/wiki/foss-for-synopsys-dwc-arc-processors/toolchain/files/ARCv2_ABI.pdf
|
||||
*/
|
||||
|
||||
/* arc provides struct user_regs_struct instead of struct pt_regs to userspace */
|
||||
#define __PT_REGS_CAST(x) ((const struct user_regs_struct *)(x))
|
||||
#define __PT_PARM1_REG scratch.r0
|
||||
#define __PT_PARM2_REG scratch.r1
|
||||
#define __PT_PARM3_REG scratch.r2
|
||||
#define __PT_PARM4_REG scratch.r3
|
||||
#define __PT_PARM5_REG scratch.r4
|
||||
#define __PT_PARM6_REG scratch.r5
|
||||
#define __PT_PARM7_REG scratch.r6
|
||||
#define __PT_PARM8_REG scratch.r7
|
||||
|
||||
/* arc does not select ARCH_HAS_SYSCALL_WRAPPER. */
|
||||
#define PT_REGS_SYSCALL_REGS(ctx) ctx
|
||||
#define __PT_PARM1_SYSCALL_REG __PT_PARM1_REG
|
||||
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
|
||||
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
|
||||
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
||||
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
||||
#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG
|
||||
|
||||
#define __PT_RET_REG scratch.blink
|
||||
#define __PT_FP_REG scratch.fp
|
||||
#define __PT_RC_REG scratch.r0
|
||||
#define __PT_SP_REG scratch.sp
|
||||
#define __PT_IP_REG scratch.ret
|
||||
|
||||
#elif defined(bpf_target_loongarch)
|
||||
|
||||
/*
|
||||
* https://docs.kernel.org/loongarch/introduction.html
|
||||
* https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html
|
||||
*/
|
||||
|
||||
/* loongarch provides struct user_pt_regs instead of struct pt_regs to userspace */
|
||||
#define __PT_REGS_CAST(x) ((const struct user_pt_regs *)(x))
|
||||
#define __PT_PARM1_REG regs[4]
|
||||
#define __PT_PARM2_REG regs[5]
|
||||
#define __PT_PARM3_REG regs[6]
|
||||
#define __PT_PARM4_REG regs[7]
|
||||
#define __PT_PARM5_REG regs[8]
|
||||
#define __PT_PARM6_REG regs[9]
|
||||
#define __PT_PARM7_REG regs[10]
|
||||
#define __PT_PARM8_REG regs[11]
|
||||
|
||||
/* loongarch does not select ARCH_HAS_SYSCALL_WRAPPER. */
|
||||
#define PT_REGS_SYSCALL_REGS(ctx) ctx
|
||||
#define __PT_PARM1_SYSCALL_REG __PT_PARM1_REG
|
||||
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
|
||||
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
|
||||
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
||||
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
||||
#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG
|
||||
|
||||
#define __PT_RET_REG regs[1]
|
||||
#define __PT_FP_REG regs[22]
|
||||
#define __PT_RC_REG regs[4]
|
||||
#define __PT_SP_REG regs[3]
|
||||
#define __PT_IP_REG csr_era
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(bpf_target_defined)
|
||||
|
||||
struct pt_regs;
|
||||
|
||||
/* allow some architectures to override `struct pt_regs` */
|
||||
#ifndef __PT_REGS_CAST
|
||||
#define __PT_REGS_CAST(x) (x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Different architectures support different number of arguments passed
|
||||
* through registers. i386 supports just 3, some arches support up to 8.
|
||||
*/
|
||||
#ifndef __PT_PARM4_REG
|
||||
#define __PT_PARM4_REG __unsupported__
|
||||
#endif
|
||||
#ifndef __PT_PARM5_REG
|
||||
#define __PT_PARM5_REG __unsupported__
|
||||
#endif
|
||||
#ifndef __PT_PARM6_REG
|
||||
#define __PT_PARM6_REG __unsupported__
|
||||
#endif
|
||||
#ifndef __PT_PARM7_REG
|
||||
#define __PT_PARM7_REG __unsupported__
|
||||
#endif
|
||||
#ifndef __PT_PARM8_REG
|
||||
#define __PT_PARM8_REG __unsupported__
|
||||
#endif
|
||||
/*
|
||||
* Similarly, syscall-specific conventions might differ between function call
|
||||
* conventions within each architecutre. All supported architectures pass
|
||||
* either 6 or 7 syscall arguments in registers.
|
||||
*
|
||||
* See syscall(2) manpage for succinct table with information on each arch.
|
||||
*/
|
||||
#ifndef __PT_PARM7_SYSCALL_REG
|
||||
#define __PT_PARM7_SYSCALL_REG __unsupported__
|
||||
#endif
|
||||
|
||||
#define PT_REGS_PARM1(x) (__PT_REGS_CAST(x)->__PT_PARM1_REG)
|
||||
#define PT_REGS_PARM2(x) (__PT_REGS_CAST(x)->__PT_PARM2_REG)
|
||||
#define PT_REGS_PARM3(x) (__PT_REGS_CAST(x)->__PT_PARM3_REG)
|
||||
#define PT_REGS_PARM4(x) (__PT_REGS_CAST(x)->__PT_PARM4_REG)
|
||||
#define PT_REGS_PARM5(x) (__PT_REGS_CAST(x)->__PT_PARM5_REG)
|
||||
#define PT_REGS_PARM6(x) (__PT_REGS_CAST(x)->__PT_PARM6_REG)
|
||||
#define PT_REGS_PARM7(x) (__PT_REGS_CAST(x)->__PT_PARM7_REG)
|
||||
#define PT_REGS_PARM8(x) (__PT_REGS_CAST(x)->__PT_PARM8_REG)
|
||||
#define PT_REGS_RET(x) (__PT_REGS_CAST(x)->__PT_RET_REG)
|
||||
#define PT_REGS_FP(x) (__PT_REGS_CAST(x)->__PT_FP_REG)
|
||||
#define PT_REGS_RC(x) (__PT_REGS_CAST(x)->__PT_RC_REG)
|
||||
#define PT_REGS_SP(x) (__PT_REGS_CAST(x)->__PT_SP_REG)
|
||||
#define PT_REGS_IP(x) (__PT_REGS_CAST(x)->__PT_IP_REG)
|
||||
|
||||
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM1_REG)
|
||||
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM2_REG)
|
||||
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM3_REG)
|
||||
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM4_REG)
|
||||
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM5_REG)
|
||||
#define PT_REGS_PARM6_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM6_REG)
|
||||
#define PT_REGS_PARM7_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM7_REG)
|
||||
#define PT_REGS_PARM8_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM8_REG)
|
||||
#define PT_REGS_RET_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_RET_REG)
|
||||
#define PT_REGS_FP_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_FP_REG)
|
||||
#define PT_REGS_RC_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_RC_REG)
|
||||
#define PT_REGS_SP_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_SP_REG)
|
||||
#define PT_REGS_IP_CORE(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_IP_REG)
|
||||
|
||||
#if defined(bpf_target_powerpc)
|
||||
|
||||
#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; })
|
||||
#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
|
||||
|
||||
#elif defined(bpf_target_sparc)
|
||||
|
||||
#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); })
|
||||
#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
|
||||
|
||||
#else
|
||||
|
||||
#define BPF_KPROBE_READ_RET_IP(ip, ctx) \
|
||||
({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); })
|
||||
#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) \
|
||||
({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef PT_REGS_PARM1_SYSCALL
|
||||
#define PT_REGS_PARM1_SYSCALL(x) (__PT_REGS_CAST(x)->__PT_PARM1_SYSCALL_REG)
|
||||
#define PT_REGS_PARM1_CORE_SYSCALL(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM1_SYSCALL_REG)
|
||||
#endif
|
||||
#ifndef PT_REGS_PARM2_SYSCALL
|
||||
#define PT_REGS_PARM2_SYSCALL(x) (__PT_REGS_CAST(x)->__PT_PARM2_SYSCALL_REG)
|
||||
#define PT_REGS_PARM2_CORE_SYSCALL(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM2_SYSCALL_REG)
|
||||
#endif
|
||||
#ifndef PT_REGS_PARM3_SYSCALL
|
||||
#define PT_REGS_PARM3_SYSCALL(x) (__PT_REGS_CAST(x)->__PT_PARM3_SYSCALL_REG)
|
||||
#define PT_REGS_PARM3_CORE_SYSCALL(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM3_SYSCALL_REG)
|
||||
#endif
|
||||
#ifndef PT_REGS_PARM4_SYSCALL
|
||||
#define PT_REGS_PARM4_SYSCALL(x) (__PT_REGS_CAST(x)->__PT_PARM4_SYSCALL_REG)
|
||||
#define PT_REGS_PARM4_CORE_SYSCALL(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM4_SYSCALL_REG)
|
||||
#endif
|
||||
#ifndef PT_REGS_PARM5_SYSCALL
|
||||
#define PT_REGS_PARM5_SYSCALL(x) (__PT_REGS_CAST(x)->__PT_PARM5_SYSCALL_REG)
|
||||
#define PT_REGS_PARM5_CORE_SYSCALL(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM5_SYSCALL_REG)
|
||||
#endif
|
||||
#ifndef PT_REGS_PARM6_SYSCALL
|
||||
#define PT_REGS_PARM6_SYSCALL(x) (__PT_REGS_CAST(x)->__PT_PARM6_SYSCALL_REG)
|
||||
#define PT_REGS_PARM6_CORE_SYSCALL(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM6_SYSCALL_REG)
|
||||
#endif
|
||||
#ifndef PT_REGS_PARM7_SYSCALL
|
||||
#define PT_REGS_PARM7_SYSCALL(x) (__PT_REGS_CAST(x)->__PT_PARM7_SYSCALL_REG)
|
||||
#define PT_REGS_PARM7_CORE_SYSCALL(x) BPF_CORE_READ(__PT_REGS_CAST(x), __PT_PARM7_SYSCALL_REG)
|
||||
#endif
|
||||
|
||||
#else /* defined(bpf_target_defined) */
|
||||
|
||||
#define PT_REGS_PARM1(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM2(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM3(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM4(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM5(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM6(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM7(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM8(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_RET(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_FP(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_RC(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_SP(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_IP(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
|
||||
#define PT_REGS_PARM1_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM2_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM3_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM4_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM5_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM6_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM7_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM8_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_RET_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_FP_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_RC_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_SP_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_IP_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
|
||||
#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
|
||||
#define PT_REGS_PARM1_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM2_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM3_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM4_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM5_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM6_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM7_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
|
||||
#define PT_REGS_PARM1_CORE_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM2_CORE_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM3_CORE_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM4_CORE_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM5_CORE_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM6_CORE_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
#define PT_REGS_PARM7_CORE_SYSCALL(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
|
||||
|
||||
#endif /* defined(bpf_target_defined) */
|
||||
|
||||
/*
|
||||
* When invoked from a syscall handler kprobe, returns a pointer to a
|
||||
* struct pt_regs containing syscall arguments and suitable for passing to
|
||||
* PT_REGS_PARMn_SYSCALL() and PT_REGS_PARMn_CORE_SYSCALL().
|
||||
*/
|
||||
#ifndef PT_REGS_SYSCALL_REGS
|
||||
/* By default, assume that the arch selects ARCH_HAS_SYSCALL_WRAPPER. */
|
||||
#define PT_REGS_SYSCALL_REGS(ctx) ((struct pt_regs *)PT_REGS_PARM1(ctx))
|
||||
#endif
|
||||
|
||||
#ifndef ___bpf_concat
|
||||
#define ___bpf_concat(a, b) a ## b
|
||||
#endif
|
||||
#ifndef ___bpf_apply
|
||||
#define ___bpf_apply(fn, n) ___bpf_concat(fn, n)
|
||||
#endif
|
||||
#ifndef ___bpf_nth
|
||||
#define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N
|
||||
#endif
|
||||
#ifndef ___bpf_narg
|
||||
#define ___bpf_narg(...) ___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
#endif
|
||||
|
||||
#define ___bpf_ctx_cast0() ctx
|
||||
#define ___bpf_ctx_cast1(x) ___bpf_ctx_cast0(), (void *)ctx[0]
|
||||
#define ___bpf_ctx_cast2(x, args...) ___bpf_ctx_cast1(args), (void *)ctx[1]
|
||||
#define ___bpf_ctx_cast3(x, args...) ___bpf_ctx_cast2(args), (void *)ctx[2]
|
||||
#define ___bpf_ctx_cast4(x, args...) ___bpf_ctx_cast3(args), (void *)ctx[3]
|
||||
#define ___bpf_ctx_cast5(x, args...) ___bpf_ctx_cast4(args), (void *)ctx[4]
|
||||
#define ___bpf_ctx_cast6(x, args...) ___bpf_ctx_cast5(args), (void *)ctx[5]
|
||||
#define ___bpf_ctx_cast7(x, args...) ___bpf_ctx_cast6(args), (void *)ctx[6]
|
||||
#define ___bpf_ctx_cast8(x, args...) ___bpf_ctx_cast7(args), (void *)ctx[7]
|
||||
#define ___bpf_ctx_cast9(x, args...) ___bpf_ctx_cast8(args), (void *)ctx[8]
|
||||
#define ___bpf_ctx_cast10(x, args...) ___bpf_ctx_cast9(args), (void *)ctx[9]
|
||||
#define ___bpf_ctx_cast11(x, args...) ___bpf_ctx_cast10(args), (void *)ctx[10]
|
||||
#define ___bpf_ctx_cast12(x, args...) ___bpf_ctx_cast11(args), (void *)ctx[11]
|
||||
#define ___bpf_ctx_cast(args...) ___bpf_apply(___bpf_ctx_cast, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
* BPF_PROG is a convenience wrapper for generic tp_btf/fentry/fexit and
|
||||
* similar kinds of BPF programs, that accept input arguments as a single
|
||||
* pointer to untyped u64 array, where each u64 can actually be a typed
|
||||
* pointer or integer of different size. Instead of requring user to write
|
||||
* manual casts and work with array elements by index, BPF_PROG macro
|
||||
* allows user to declare a list of named and typed input arguments in the
|
||||
* same syntax as for normal C function. All the casting is hidden and
|
||||
* performed transparently, while user code can just assume working with
|
||||
* function arguments of specified type and name.
|
||||
*
|
||||
* Original raw context argument is preserved as well as 'ctx' argument.
|
||||
* This is useful when using BPF helpers that expect original context
|
||||
* as one of the parameters (e.g., for bpf_perf_event_output()).
|
||||
*/
|
||||
#define BPF_PROG(name, args...) \
|
||||
name(unsigned long long *ctx); \
|
||||
static __always_inline typeof(name(0)) \
|
||||
____##name(unsigned long long *ctx, ##args); \
|
||||
typeof(name(0)) name(unsigned long long *ctx) \
|
||||
{ \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||
return ____##name(___bpf_ctx_cast(args)); \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
} \
|
||||
static __always_inline typeof(name(0)) \
|
||||
____##name(unsigned long long *ctx, ##args)
|
||||
|
||||
#ifndef ___bpf_nth2
|
||||
#define ___bpf_nth2(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, \
|
||||
_14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, N, ...) N
|
||||
#endif
|
||||
#ifndef ___bpf_narg2
|
||||
#define ___bpf_narg2(...) \
|
||||
___bpf_nth2(_, ##__VA_ARGS__, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, \
|
||||
6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0)
|
||||
#endif
|
||||
|
||||
#define ___bpf_treg_cnt(t) \
|
||||
__builtin_choose_expr(sizeof(t) == 1, 1, \
|
||||
__builtin_choose_expr(sizeof(t) == 2, 1, \
|
||||
__builtin_choose_expr(sizeof(t) == 4, 1, \
|
||||
__builtin_choose_expr(sizeof(t) == 8, 1, \
|
||||
__builtin_choose_expr(sizeof(t) == 16, 2, \
|
||||
(void)0)))))
|
||||
|
||||
#define ___bpf_reg_cnt0() (0)
|
||||
#define ___bpf_reg_cnt1(t, x) (___bpf_reg_cnt0() + ___bpf_treg_cnt(t))
|
||||
#define ___bpf_reg_cnt2(t, x, args...) (___bpf_reg_cnt1(args) + ___bpf_treg_cnt(t))
|
||||
#define ___bpf_reg_cnt3(t, x, args...) (___bpf_reg_cnt2(args) + ___bpf_treg_cnt(t))
|
||||
#define ___bpf_reg_cnt4(t, x, args...) (___bpf_reg_cnt3(args) + ___bpf_treg_cnt(t))
|
||||
#define ___bpf_reg_cnt5(t, x, args...) (___bpf_reg_cnt4(args) + ___bpf_treg_cnt(t))
|
||||
#define ___bpf_reg_cnt6(t, x, args...) (___bpf_reg_cnt5(args) + ___bpf_treg_cnt(t))
|
||||
#define ___bpf_reg_cnt7(t, x, args...) (___bpf_reg_cnt6(args) + ___bpf_treg_cnt(t))
|
||||
#define ___bpf_reg_cnt8(t, x, args...) (___bpf_reg_cnt7(args) + ___bpf_treg_cnt(t))
|
||||
#define ___bpf_reg_cnt9(t, x, args...) (___bpf_reg_cnt8(args) + ___bpf_treg_cnt(t))
|
||||
#define ___bpf_reg_cnt10(t, x, args...) (___bpf_reg_cnt9(args) + ___bpf_treg_cnt(t))
|
||||
#define ___bpf_reg_cnt11(t, x, args...) (___bpf_reg_cnt10(args) + ___bpf_treg_cnt(t))
|
||||
#define ___bpf_reg_cnt12(t, x, args...) (___bpf_reg_cnt11(args) + ___bpf_treg_cnt(t))
|
||||
#define ___bpf_reg_cnt(args...) ___bpf_apply(___bpf_reg_cnt, ___bpf_narg2(args))(args)
|
||||
|
||||
#define ___bpf_union_arg(t, x, n) \
|
||||
__builtin_choose_expr(sizeof(t) == 1, ({ union { __u8 z[1]; t x; } ___t = { .z = {ctx[n]}}; ___t.x; }), \
|
||||
__builtin_choose_expr(sizeof(t) == 2, ({ union { __u16 z[1]; t x; } ___t = { .z = {ctx[n]} }; ___t.x; }), \
|
||||
__builtin_choose_expr(sizeof(t) == 4, ({ union { __u32 z[1]; t x; } ___t = { .z = {ctx[n]} }; ___t.x; }), \
|
||||
__builtin_choose_expr(sizeof(t) == 8, ({ union { __u64 z[1]; t x; } ___t = {.z = {ctx[n]} }; ___t.x; }), \
|
||||
__builtin_choose_expr(sizeof(t) == 16, ({ union { __u64 z[2]; t x; } ___t = {.z = {ctx[n], ctx[n + 1]} }; ___t.x; }), \
|
||||
(void)0)))))
|
||||
|
||||
#define ___bpf_ctx_arg0(n, args...)
|
||||
#define ___bpf_ctx_arg1(n, t, x) , ___bpf_union_arg(t, x, n - ___bpf_reg_cnt1(t, x))
|
||||
#define ___bpf_ctx_arg2(n, t, x, args...) , ___bpf_union_arg(t, x, n - ___bpf_reg_cnt2(t, x, args)) ___bpf_ctx_arg1(n, args)
|
||||
#define ___bpf_ctx_arg3(n, t, x, args...) , ___bpf_union_arg(t, x, n - ___bpf_reg_cnt3(t, x, args)) ___bpf_ctx_arg2(n, args)
|
||||
#define ___bpf_ctx_arg4(n, t, x, args...) , ___bpf_union_arg(t, x, n - ___bpf_reg_cnt4(t, x, args)) ___bpf_ctx_arg3(n, args)
|
||||
#define ___bpf_ctx_arg5(n, t, x, args...) , ___bpf_union_arg(t, x, n - ___bpf_reg_cnt5(t, x, args)) ___bpf_ctx_arg4(n, args)
|
||||
#define ___bpf_ctx_arg6(n, t, x, args...) , ___bpf_union_arg(t, x, n - ___bpf_reg_cnt6(t, x, args)) ___bpf_ctx_arg5(n, args)
|
||||
#define ___bpf_ctx_arg7(n, t, x, args...) , ___bpf_union_arg(t, x, n - ___bpf_reg_cnt7(t, x, args)) ___bpf_ctx_arg6(n, args)
|
||||
#define ___bpf_ctx_arg8(n, t, x, args...) , ___bpf_union_arg(t, x, n - ___bpf_reg_cnt8(t, x, args)) ___bpf_ctx_arg7(n, args)
|
||||
#define ___bpf_ctx_arg9(n, t, x, args...) , ___bpf_union_arg(t, x, n - ___bpf_reg_cnt9(t, x, args)) ___bpf_ctx_arg8(n, args)
|
||||
#define ___bpf_ctx_arg10(n, t, x, args...) , ___bpf_union_arg(t, x, n - ___bpf_reg_cnt10(t, x, args)) ___bpf_ctx_arg9(n, args)
|
||||
#define ___bpf_ctx_arg11(n, t, x, args...) , ___bpf_union_arg(t, x, n - ___bpf_reg_cnt11(t, x, args)) ___bpf_ctx_arg10(n, args)
|
||||
#define ___bpf_ctx_arg12(n, t, x, args...) , ___bpf_union_arg(t, x, n - ___bpf_reg_cnt12(t, x, args)) ___bpf_ctx_arg11(n, args)
|
||||
#define ___bpf_ctx_arg(args...) ___bpf_apply(___bpf_ctx_arg, ___bpf_narg2(args))(___bpf_reg_cnt(args), args)
|
||||
|
||||
#define ___bpf_ctx_decl0()
|
||||
#define ___bpf_ctx_decl1(t, x) , t x
|
||||
#define ___bpf_ctx_decl2(t, x, args...) , t x ___bpf_ctx_decl1(args)
|
||||
#define ___bpf_ctx_decl3(t, x, args...) , t x ___bpf_ctx_decl2(args)
|
||||
#define ___bpf_ctx_decl4(t, x, args...) , t x ___bpf_ctx_decl3(args)
|
||||
#define ___bpf_ctx_decl5(t, x, args...) , t x ___bpf_ctx_decl4(args)
|
||||
#define ___bpf_ctx_decl6(t, x, args...) , t x ___bpf_ctx_decl5(args)
|
||||
#define ___bpf_ctx_decl7(t, x, args...) , t x ___bpf_ctx_decl6(args)
|
||||
#define ___bpf_ctx_decl8(t, x, args...) , t x ___bpf_ctx_decl7(args)
|
||||
#define ___bpf_ctx_decl9(t, x, args...) , t x ___bpf_ctx_decl8(args)
|
||||
#define ___bpf_ctx_decl10(t, x, args...) , t x ___bpf_ctx_decl9(args)
|
||||
#define ___bpf_ctx_decl11(t, x, args...) , t x ___bpf_ctx_decl10(args)
|
||||
#define ___bpf_ctx_decl12(t, x, args...) , t x ___bpf_ctx_decl11(args)
|
||||
#define ___bpf_ctx_decl(args...) ___bpf_apply(___bpf_ctx_decl, ___bpf_narg2(args))(args)
|
||||
|
||||
/*
|
||||
* BPF_PROG2 is an enhanced version of BPF_PROG in order to handle struct
|
||||
* arguments. Since each struct argument might take one or two u64 values
|
||||
* in the trampoline stack, argument type size is needed to place proper number
|
||||
* of u64 values for each argument. Therefore, BPF_PROG2 has different
|
||||
* syntax from BPF_PROG. For example, for the following BPF_PROG syntax:
|
||||
*
|
||||
* int BPF_PROG(test2, int a, int b) { ... }
|
||||
*
|
||||
* the corresponding BPF_PROG2 syntax is:
|
||||
*
|
||||
* int BPF_PROG2(test2, int, a, int, b) { ... }
|
||||
*
|
||||
* where type and the corresponding argument name are separated by comma.
|
||||
*
|
||||
* Use BPF_PROG2 macro if one of the arguments might be a struct/union larger
|
||||
* than 8 bytes:
|
||||
*
|
||||
* int BPF_PROG2(test_struct_arg, struct bpf_testmod_struct_arg_1, a, int, b,
|
||||
* int, c, int, d, struct bpf_testmod_struct_arg_2, e, int, ret)
|
||||
* {
|
||||
* // access a, b, c, d, e, and ret directly
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
#define BPF_PROG2(name, args...) \
|
||||
name(unsigned long long *ctx); \
|
||||
static __always_inline typeof(name(0)) \
|
||||
____##name(unsigned long long *ctx ___bpf_ctx_decl(args)); \
|
||||
typeof(name(0)) name(unsigned long long *ctx) \
|
||||
{ \
|
||||
return ____##name(ctx ___bpf_ctx_arg(args)); \
|
||||
} \
|
||||
static __always_inline typeof(name(0)) \
|
||||
____##name(unsigned long long *ctx ___bpf_ctx_decl(args))
|
||||
|
||||
struct pt_regs;
|
||||
|
||||
#define ___bpf_kprobe_args0() ctx
|
||||
#define ___bpf_kprobe_args1(x) ___bpf_kprobe_args0(), (void *)PT_REGS_PARM1(ctx)
|
||||
#define ___bpf_kprobe_args2(x, args...) ___bpf_kprobe_args1(args), (void *)PT_REGS_PARM2(ctx)
|
||||
#define ___bpf_kprobe_args3(x, args...) ___bpf_kprobe_args2(args), (void *)PT_REGS_PARM3(ctx)
|
||||
#define ___bpf_kprobe_args4(x, args...) ___bpf_kprobe_args3(args), (void *)PT_REGS_PARM4(ctx)
|
||||
#define ___bpf_kprobe_args5(x, args...) ___bpf_kprobe_args4(args), (void *)PT_REGS_PARM5(ctx)
|
||||
#define ___bpf_kprobe_args6(x, args...) ___bpf_kprobe_args5(args), (void *)PT_REGS_PARM6(ctx)
|
||||
#define ___bpf_kprobe_args7(x, args...) ___bpf_kprobe_args6(args), (void *)PT_REGS_PARM7(ctx)
|
||||
#define ___bpf_kprobe_args8(x, args...) ___bpf_kprobe_args7(args), (void *)PT_REGS_PARM8(ctx)
|
||||
#define ___bpf_kprobe_args(args...) ___bpf_apply(___bpf_kprobe_args, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
* BPF_KPROBE serves the same purpose for kprobes as BPF_PROG for
|
||||
* tp_btf/fentry/fexit BPF programs. It hides the underlying platform-specific
|
||||
* low-level way of getting kprobe input arguments from struct pt_regs, and
|
||||
* provides a familiar typed and named function arguments syntax and
|
||||
* semantics of accessing kprobe input paremeters.
|
||||
*
|
||||
* Original struct pt_regs* context is preserved as 'ctx' argument. This might
|
||||
* be necessary when using BPF helpers like bpf_perf_event_output().
|
||||
*/
|
||||
#define BPF_KPROBE(name, args...) \
|
||||
name(struct pt_regs *ctx); \
|
||||
static __always_inline typeof(name(0)) \
|
||||
____##name(struct pt_regs *ctx, ##args); \
|
||||
typeof(name(0)) name(struct pt_regs *ctx) \
|
||||
{ \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||
return ____##name(___bpf_kprobe_args(args)); \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
} \
|
||||
static __always_inline typeof(name(0)) \
|
||||
____##name(struct pt_regs *ctx, ##args)
|
||||
|
||||
#define ___bpf_kretprobe_args0() ctx
|
||||
#define ___bpf_kretprobe_args1(x) ___bpf_kretprobe_args0(), (void *)PT_REGS_RC(ctx)
|
||||
#define ___bpf_kretprobe_args(args...) ___bpf_apply(___bpf_kretprobe_args, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
* BPF_KRETPROBE is similar to BPF_KPROBE, except, it only provides optional
|
||||
* return value (in addition to `struct pt_regs *ctx`), but no input
|
||||
* arguments, because they will be clobbered by the time probed function
|
||||
* returns.
|
||||
*/
|
||||
#define BPF_KRETPROBE(name, args...) \
|
||||
name(struct pt_regs *ctx); \
|
||||
static __always_inline typeof(name(0)) \
|
||||
____##name(struct pt_regs *ctx, ##args); \
|
||||
typeof(name(0)) name(struct pt_regs *ctx) \
|
||||
{ \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||
return ____##name(___bpf_kretprobe_args(args)); \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
} \
|
||||
static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)
|
||||
|
||||
/* If kernel has CONFIG_ARCH_HAS_SYSCALL_WRAPPER, read pt_regs directly */
|
||||
#define ___bpf_syscall_args0() ctx
|
||||
#define ___bpf_syscall_args1(x) ___bpf_syscall_args0(), (void *)PT_REGS_PARM1_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args2(x, args...) ___bpf_syscall_args1(args), (void *)PT_REGS_PARM2_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args3(x, args...) ___bpf_syscall_args2(args), (void *)PT_REGS_PARM3_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args4(x, args...) ___bpf_syscall_args3(args), (void *)PT_REGS_PARM4_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args5(x, args...) ___bpf_syscall_args4(args), (void *)PT_REGS_PARM5_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args6(x, args...) ___bpf_syscall_args5(args), (void *)PT_REGS_PARM6_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args7(x, args...) ___bpf_syscall_args6(args), (void *)PT_REGS_PARM7_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args(args...) ___bpf_apply(___bpf_syscall_args, ___bpf_narg(args))(args)
|
||||
|
||||
/* If kernel doesn't have CONFIG_ARCH_HAS_SYSCALL_WRAPPER, we have to BPF_CORE_READ from pt_regs */
|
||||
#define ___bpf_syswrap_args0() ctx
|
||||
#define ___bpf_syswrap_args1(x) ___bpf_syswrap_args0(), (void *)PT_REGS_PARM1_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args2(x, args...) ___bpf_syswrap_args1(args), (void *)PT_REGS_PARM2_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args3(x, args...) ___bpf_syswrap_args2(args), (void *)PT_REGS_PARM3_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args4(x, args...) ___bpf_syswrap_args3(args), (void *)PT_REGS_PARM4_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args5(x, args...) ___bpf_syswrap_args4(args), (void *)PT_REGS_PARM5_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args6(x, args...) ___bpf_syswrap_args5(args), (void *)PT_REGS_PARM6_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args7(x, args...) ___bpf_syswrap_args6(args), (void *)PT_REGS_PARM7_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args(args...) ___bpf_apply(___bpf_syswrap_args, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
* BPF_KSYSCALL is a variant of BPF_KPROBE, which is intended for
|
||||
* tracing syscall functions, like __x64_sys_close. It hides the underlying
|
||||
* platform-specific low-level way of getting syscall input arguments from
|
||||
* struct pt_regs, and provides a familiar typed and named function arguments
|
||||
* syntax and semantics of accessing syscall input parameters.
|
||||
*
|
||||
* Original struct pt_regs * context is preserved as 'ctx' argument. This might
|
||||
* be necessary when using BPF helpers like bpf_perf_event_output().
|
||||
*
|
||||
* At the moment BPF_KSYSCALL does not transparently handle all the calling
|
||||
* convention quirks for the following syscalls:
|
||||
*
|
||||
* - mmap(): __ARCH_WANT_SYS_OLD_MMAP.
|
||||
* - clone(): CONFIG_CLONE_BACKWARDS, CONFIG_CLONE_BACKWARDS2 and
|
||||
* CONFIG_CLONE_BACKWARDS3.
|
||||
* - socket-related syscalls: __ARCH_WANT_SYS_SOCKETCALL.
|
||||
* - compat syscalls.
|
||||
*
|
||||
* This may or may not change in the future. User needs to take extra measures
|
||||
* to handle such quirks explicitly, if necessary.
|
||||
*
|
||||
* This macro relies on BPF CO-RE support and virtual __kconfig externs.
|
||||
*/
|
||||
#define BPF_KSYSCALL(name, args...) \
|
||||
name(struct pt_regs *ctx); \
|
||||
extern _Bool LINUX_HAS_SYSCALL_WRAPPER __kconfig; \
|
||||
static __always_inline typeof(name(0)) \
|
||||
____##name(struct pt_regs *ctx, ##args); \
|
||||
typeof(name(0)) name(struct pt_regs *ctx) \
|
||||
{ \
|
||||
struct pt_regs *regs = LINUX_HAS_SYSCALL_WRAPPER \
|
||||
? (struct pt_regs *)PT_REGS_PARM1(ctx) \
|
||||
: ctx; \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||
if (LINUX_HAS_SYSCALL_WRAPPER) \
|
||||
return ____##name(___bpf_syswrap_args(args)); \
|
||||
else \
|
||||
return ____##name(___bpf_syscall_args(args)); \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
} \
|
||||
static __always_inline typeof(name(0)) \
|
||||
____##name(struct pt_regs *ctx, ##args)
|
||||
|
||||
#define BPF_KPROBE_SYSCALL BPF_KSYSCALL
|
||||
|
||||
/* BPF_UPROBE and BPF_URETPROBE are identical to BPF_KPROBE and BPF_KRETPROBE,
|
||||
* but are named way less confusingly for SEC("uprobe") and SEC("uretprobe")
|
||||
* use cases.
|
||||
*/
|
||||
#define BPF_UPROBE(name, args...) BPF_KPROBE(name, ##args)
|
||||
#define BPF_URETPROBE(name, args...) BPF_KRETPROBE(name, ##args)
|
||||
|
||||
#endif
|
||||
5025
third_party/libbpf/src/btf.c
vendored
Normal file
575
third_party/libbpf/src/btf.h
vendored
Normal file
@@ -0,0 +1,575 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
/* Copyright (c) 2018 Facebook */
|
||||
/*! \file */
|
||||
|
||||
#ifndef __LIBBPF_BTF_H
|
||||
#define __LIBBPF_BTF_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <linux/btf.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "libbpf_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BTF_ELF_SEC ".BTF"
|
||||
#define BTF_EXT_ELF_SEC ".BTF.ext"
|
||||
#define MAPS_ELF_SEC ".maps"
|
||||
|
||||
struct btf;
|
||||
struct btf_ext;
|
||||
struct btf_type;
|
||||
|
||||
struct bpf_object;
|
||||
|
||||
enum btf_endianness {
|
||||
BTF_LITTLE_ENDIAN = 0,
|
||||
BTF_BIG_ENDIAN = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief **btf__free()** frees all data of a BTF object
|
||||
* @param btf BTF object to free
|
||||
*/
|
||||
LIBBPF_API void btf__free(struct btf *btf);
|
||||
|
||||
/**
|
||||
* @brief **btf__new()** creates a new instance of a BTF object from the raw
|
||||
* bytes of an ELF's BTF section
|
||||
* @param data raw bytes
|
||||
* @param size number of bytes passed in `data`
|
||||
* @return new BTF object instance which has to be eventually freed with
|
||||
* **btf__free()**
|
||||
*
|
||||
* On error, error-code-encoded-as-pointer is returned, not a NULL. To extract
|
||||
* error code from such a pointer `libbpf_get_error()` should be used. If
|
||||
* `libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS)` is enabled, NULL is
|
||||
* returned on error instead. In both cases thread-local `errno` variable is
|
||||
* always set to error code as well.
|
||||
*/
|
||||
LIBBPF_API struct btf *btf__new(const void *data, __u32 size);
|
||||
|
||||
/**
|
||||
* @brief **btf__new_split()** create a new instance of a BTF object from the
|
||||
* provided raw data bytes. It takes another BTF instance, **base_btf**, which
|
||||
* serves as a base BTF, which is extended by types in a newly created BTF
|
||||
* instance
|
||||
* @param data raw bytes
|
||||
* @param size length of raw bytes
|
||||
* @param base_btf the base BTF object
|
||||
* @return new BTF object instance which has to be eventually freed with
|
||||
* **btf__free()**
|
||||
*
|
||||
* If *base_btf* is NULL, `btf__new_split()` is equivalent to `btf__new()` and
|
||||
* creates non-split BTF.
|
||||
*
|
||||
* On error, error-code-encoded-as-pointer is returned, not a NULL. To extract
|
||||
* error code from such a pointer `libbpf_get_error()` should be used. If
|
||||
* `libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS)` is enabled, NULL is
|
||||
* returned on error instead. In both cases thread-local `errno` variable is
|
||||
* always set to error code as well.
|
||||
*/
|
||||
LIBBPF_API struct btf *btf__new_split(const void *data, __u32 size, struct btf *base_btf);
|
||||
|
||||
/**
|
||||
* @brief **btf__new_empty()** creates an empty BTF object. Use
|
||||
* `btf__add_*()` to populate such BTF object.
|
||||
* @return new BTF object instance which has to be eventually freed with
|
||||
* **btf__free()**
|
||||
*
|
||||
* On error, error-code-encoded-as-pointer is returned, not a NULL. To extract
|
||||
* error code from such a pointer `libbpf_get_error()` should be used. If
|
||||
* `libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS)` is enabled, NULL is
|
||||
* returned on error instead. In both cases thread-local `errno` variable is
|
||||
* always set to error code as well.
|
||||
*/
|
||||
LIBBPF_API struct btf *btf__new_empty(void);
|
||||
|
||||
/**
|
||||
* @brief **btf__new_empty_split()** creates an unpopulated BTF object from an
|
||||
* ELF BTF section except with a base BTF on top of which split BTF should be
|
||||
* based
|
||||
* @return new BTF object instance which has to be eventually freed with
|
||||
* **btf__free()**
|
||||
*
|
||||
* If *base_btf* is NULL, `btf__new_empty_split()` is equivalent to
|
||||
* `btf__new_empty()` and creates non-split BTF.
|
||||
*
|
||||
* On error, error-code-encoded-as-pointer is returned, not a NULL. To extract
|
||||
* error code from such a pointer `libbpf_get_error()` should be used. If
|
||||
* `libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS)` is enabled, NULL is
|
||||
* returned on error instead. In both cases thread-local `errno` variable is
|
||||
* always set to error code as well.
|
||||
*/
|
||||
LIBBPF_API struct btf *btf__new_empty_split(struct btf *base_btf);
|
||||
|
||||
LIBBPF_API struct btf *btf__parse(const char *path, struct btf_ext **btf_ext);
|
||||
LIBBPF_API struct btf *btf__parse_split(const char *path, struct btf *base_btf);
|
||||
LIBBPF_API struct btf *btf__parse_elf(const char *path, struct btf_ext **btf_ext);
|
||||
LIBBPF_API struct btf *btf__parse_elf_split(const char *path, struct btf *base_btf);
|
||||
LIBBPF_API struct btf *btf__parse_raw(const char *path);
|
||||
LIBBPF_API struct btf *btf__parse_raw_split(const char *path, struct btf *base_btf);
|
||||
|
||||
LIBBPF_API struct btf *btf__load_vmlinux_btf(void);
|
||||
LIBBPF_API struct btf *btf__load_module_btf(const char *module_name, struct btf *vmlinux_btf);
|
||||
|
||||
LIBBPF_API struct btf *btf__load_from_kernel_by_id(__u32 id);
|
||||
LIBBPF_API struct btf *btf__load_from_kernel_by_id_split(__u32 id, struct btf *base_btf);
|
||||
|
||||
LIBBPF_API int btf__load_into_kernel(struct btf *btf);
|
||||
LIBBPF_API __s32 btf__find_by_name(const struct btf *btf,
|
||||
const char *type_name);
|
||||
LIBBPF_API __s32 btf__find_by_name_kind(const struct btf *btf,
|
||||
const char *type_name, __u32 kind);
|
||||
LIBBPF_API __u32 btf__type_cnt(const struct btf *btf);
|
||||
LIBBPF_API const struct btf *btf__base_btf(const struct btf *btf);
|
||||
LIBBPF_API const struct btf_type *btf__type_by_id(const struct btf *btf,
|
||||
__u32 id);
|
||||
LIBBPF_API size_t btf__pointer_size(const struct btf *btf);
|
||||
LIBBPF_API int btf__set_pointer_size(struct btf *btf, size_t ptr_sz);
|
||||
LIBBPF_API enum btf_endianness btf__endianness(const struct btf *btf);
|
||||
LIBBPF_API int btf__set_endianness(struct btf *btf, enum btf_endianness endian);
|
||||
LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
|
||||
LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);
|
||||
LIBBPF_API int btf__align_of(const struct btf *btf, __u32 id);
|
||||
LIBBPF_API int btf__fd(const struct btf *btf);
|
||||
LIBBPF_API void btf__set_fd(struct btf *btf, int fd);
|
||||
LIBBPF_API const void *btf__raw_data(const struct btf *btf, __u32 *size);
|
||||
LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
|
||||
LIBBPF_API const char *btf__str_by_offset(const struct btf *btf, __u32 offset);
|
||||
|
||||
LIBBPF_API struct btf_ext *btf_ext__new(const __u8 *data, __u32 size);
|
||||
LIBBPF_API void btf_ext__free(struct btf_ext *btf_ext);
|
||||
LIBBPF_API const void *btf_ext__raw_data(const struct btf_ext *btf_ext, __u32 *size);
|
||||
|
||||
LIBBPF_API int btf__find_str(struct btf *btf, const char *s);
|
||||
LIBBPF_API int btf__add_str(struct btf *btf, const char *s);
|
||||
LIBBPF_API int btf__add_type(struct btf *btf, const struct btf *src_btf,
|
||||
const struct btf_type *src_type);
|
||||
/**
|
||||
* @brief **btf__add_btf()** appends all the BTF types from *src_btf* into *btf*
|
||||
* @param btf BTF object which all the BTF types and strings are added to
|
||||
* @param src_btf BTF object which all BTF types and referenced strings are copied from
|
||||
* @return BTF type ID of the first appended BTF type, or negative error code
|
||||
*
|
||||
* **btf__add_btf()** can be used to simply and efficiently append the entire
|
||||
* contents of one BTF object to another one. All the BTF type data is copied
|
||||
* over, all referenced type IDs are adjusted by adding a necessary ID offset.
|
||||
* Only strings referenced from BTF types are copied over and deduplicated, so
|
||||
* if there were some unused strings in *src_btf*, those won't be copied over,
|
||||
* which is consistent with the general string deduplication semantics of BTF
|
||||
* writing APIs.
|
||||
*
|
||||
* If any error is encountered during this process, the contents of *btf* is
|
||||
* left intact, which means that **btf__add_btf()** follows the transactional
|
||||
* semantics and the operation as a whole is all-or-nothing.
|
||||
*
|
||||
* *src_btf* has to be non-split BTF, as of now copying types from split BTF
|
||||
* is not supported and will result in -ENOTSUP error code returned.
|
||||
*/
|
||||
LIBBPF_API int btf__add_btf(struct btf *btf, const struct btf *src_btf);
|
||||
|
||||
LIBBPF_API int btf__add_int(struct btf *btf, const char *name, size_t byte_sz, int encoding);
|
||||
LIBBPF_API int btf__add_float(struct btf *btf, const char *name, size_t byte_sz);
|
||||
LIBBPF_API int btf__add_ptr(struct btf *btf, int ref_type_id);
|
||||
LIBBPF_API int btf__add_array(struct btf *btf,
|
||||
int index_type_id, int elem_type_id, __u32 nr_elems);
|
||||
/* struct/union construction APIs */
|
||||
LIBBPF_API int btf__add_struct(struct btf *btf, const char *name, __u32 sz);
|
||||
LIBBPF_API int btf__add_union(struct btf *btf, const char *name, __u32 sz);
|
||||
LIBBPF_API int btf__add_field(struct btf *btf, const char *name, int field_type_id,
|
||||
__u32 bit_offset, __u32 bit_size);
|
||||
|
||||
/* enum construction APIs */
|
||||
LIBBPF_API int btf__add_enum(struct btf *btf, const char *name, __u32 bytes_sz);
|
||||
LIBBPF_API int btf__add_enum_value(struct btf *btf, const char *name, __s64 value);
|
||||
LIBBPF_API int btf__add_enum64(struct btf *btf, const char *name, __u32 bytes_sz, bool is_signed);
|
||||
LIBBPF_API int btf__add_enum64_value(struct btf *btf, const char *name, __u64 value);
|
||||
|
||||
enum btf_fwd_kind {
|
||||
BTF_FWD_STRUCT = 0,
|
||||
BTF_FWD_UNION = 1,
|
||||
BTF_FWD_ENUM = 2,
|
||||
};
|
||||
|
||||
LIBBPF_API int btf__add_fwd(struct btf *btf, const char *name, enum btf_fwd_kind fwd_kind);
|
||||
LIBBPF_API int btf__add_typedef(struct btf *btf, const char *name, int ref_type_id);
|
||||
LIBBPF_API int btf__add_volatile(struct btf *btf, int ref_type_id);
|
||||
LIBBPF_API int btf__add_const(struct btf *btf, int ref_type_id);
|
||||
LIBBPF_API int btf__add_restrict(struct btf *btf, int ref_type_id);
|
||||
LIBBPF_API int btf__add_type_tag(struct btf *btf, const char *value, int ref_type_id);
|
||||
|
||||
/* func and func_proto construction APIs */
|
||||
LIBBPF_API int btf__add_func(struct btf *btf, const char *name,
|
||||
enum btf_func_linkage linkage, int proto_type_id);
|
||||
LIBBPF_API int btf__add_func_proto(struct btf *btf, int ret_type_id);
|
||||
LIBBPF_API int btf__add_func_param(struct btf *btf, const char *name, int type_id);
|
||||
|
||||
/* var & datasec construction APIs */
|
||||
LIBBPF_API int btf__add_var(struct btf *btf, const char *name, int linkage, int type_id);
|
||||
LIBBPF_API int btf__add_datasec(struct btf *btf, const char *name, __u32 byte_sz);
|
||||
LIBBPF_API int btf__add_datasec_var_info(struct btf *btf, int var_type_id,
|
||||
__u32 offset, __u32 byte_sz);
|
||||
|
||||
/* tag construction API */
|
||||
LIBBPF_API int btf__add_decl_tag(struct btf *btf, const char *value, int ref_type_id,
|
||||
int component_idx);
|
||||
|
||||
struct btf_dedup_opts {
|
||||
size_t sz;
|
||||
/* optional .BTF.ext info to dedup along the main BTF info */
|
||||
struct btf_ext *btf_ext;
|
||||
/* force hash collisions (used for testing) */
|
||||
bool force_collisions;
|
||||
size_t :0;
|
||||
};
|
||||
#define btf_dedup_opts__last_field force_collisions
|
||||
|
||||
LIBBPF_API int btf__dedup(struct btf *btf, const struct btf_dedup_opts *opts);
|
||||
|
||||
struct btf_dump;
|
||||
|
||||
struct btf_dump_opts {
|
||||
size_t sz;
|
||||
};
|
||||
#define btf_dump_opts__last_field sz
|
||||
|
||||
typedef void (*btf_dump_printf_fn_t)(void *ctx, const char *fmt, va_list args);
|
||||
|
||||
LIBBPF_API struct btf_dump *btf_dump__new(const struct btf *btf,
|
||||
btf_dump_printf_fn_t printf_fn,
|
||||
void *ctx,
|
||||
const struct btf_dump_opts *opts);
|
||||
|
||||
LIBBPF_API void btf_dump__free(struct btf_dump *d);
|
||||
|
||||
LIBBPF_API int btf_dump__dump_type(struct btf_dump *d, __u32 id);
|
||||
|
||||
struct btf_dump_emit_type_decl_opts {
|
||||
/* size of this struct, for forward/backward compatiblity */
|
||||
size_t sz;
|
||||
/* optional field name for type declaration, e.g.:
|
||||
* - struct my_struct <FNAME>
|
||||
* - void (*<FNAME>)(int)
|
||||
* - char (*<FNAME>)[123]
|
||||
*/
|
||||
const char *field_name;
|
||||
/* extra indentation level (in number of tabs) to emit for multi-line
|
||||
* type declarations (e.g., anonymous struct); applies for lines
|
||||
* starting from the second one (first line is assumed to have
|
||||
* necessary indentation already
|
||||
*/
|
||||
int indent_level;
|
||||
/* strip all the const/volatile/restrict mods */
|
||||
bool strip_mods;
|
||||
size_t :0;
|
||||
};
|
||||
#define btf_dump_emit_type_decl_opts__last_field strip_mods
|
||||
|
||||
LIBBPF_API int
|
||||
btf_dump__emit_type_decl(struct btf_dump *d, __u32 id,
|
||||
const struct btf_dump_emit_type_decl_opts *opts);
|
||||
|
||||
|
||||
struct btf_dump_type_data_opts {
|
||||
/* size of this struct, for forward/backward compatibility */
|
||||
size_t sz;
|
||||
const char *indent_str;
|
||||
int indent_level;
|
||||
/* below match "show" flags for bpf_show_snprintf() */
|
||||
bool compact; /* no newlines/indentation */
|
||||
bool skip_names; /* skip member/type names */
|
||||
bool emit_zeroes; /* show 0-valued fields */
|
||||
size_t :0;
|
||||
};
|
||||
#define btf_dump_type_data_opts__last_field emit_zeroes
|
||||
|
||||
LIBBPF_API int
|
||||
btf_dump__dump_type_data(struct btf_dump *d, __u32 id,
|
||||
const void *data, size_t data_sz,
|
||||
const struct btf_dump_type_data_opts *opts);
|
||||
|
||||
/*
|
||||
* A set of helpers for easier BTF types handling.
|
||||
*
|
||||
* The inline functions below rely on constants from the kernel headers which
|
||||
* may not be available for applications including this header file. To avoid
|
||||
* compilation errors, we define all the constants here that were added after
|
||||
* the initial introduction of the BTF_KIND* constants.
|
||||
*/
|
||||
#ifndef BTF_KIND_FUNC
|
||||
#define BTF_KIND_FUNC 12 /* Function */
|
||||
#define BTF_KIND_FUNC_PROTO 13 /* Function Proto */
|
||||
#endif
|
||||
#ifndef BTF_KIND_VAR
|
||||
#define BTF_KIND_VAR 14 /* Variable */
|
||||
#define BTF_KIND_DATASEC 15 /* Section */
|
||||
#endif
|
||||
#ifndef BTF_KIND_FLOAT
|
||||
#define BTF_KIND_FLOAT 16 /* Floating point */
|
||||
#endif
|
||||
/* The kernel header switched to enums, so the following were never #defined */
|
||||
#define BTF_KIND_DECL_TAG 17 /* Decl Tag */
|
||||
#define BTF_KIND_TYPE_TAG 18 /* Type Tag */
|
||||
#define BTF_KIND_ENUM64 19 /* Enum for up-to 64bit values */
|
||||
|
||||
static inline __u16 btf_kind(const struct btf_type *t)
|
||||
{
|
||||
return BTF_INFO_KIND(t->info);
|
||||
}
|
||||
|
||||
static inline __u16 btf_vlen(const struct btf_type *t)
|
||||
{
|
||||
return BTF_INFO_VLEN(t->info);
|
||||
}
|
||||
|
||||
static inline bool btf_kflag(const struct btf_type *t)
|
||||
{
|
||||
return BTF_INFO_KFLAG(t->info);
|
||||
}
|
||||
|
||||
static inline bool btf_is_void(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_UNKN;
|
||||
}
|
||||
|
||||
static inline bool btf_is_int(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_INT;
|
||||
}
|
||||
|
||||
static inline bool btf_is_ptr(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_PTR;
|
||||
}
|
||||
|
||||
static inline bool btf_is_array(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_ARRAY;
|
||||
}
|
||||
|
||||
static inline bool btf_is_struct(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_STRUCT;
|
||||
}
|
||||
|
||||
static inline bool btf_is_union(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_UNION;
|
||||
}
|
||||
|
||||
static inline bool btf_is_composite(const struct btf_type *t)
|
||||
{
|
||||
__u16 kind = btf_kind(t);
|
||||
|
||||
return kind == BTF_KIND_STRUCT || kind == BTF_KIND_UNION;
|
||||
}
|
||||
|
||||
static inline bool btf_is_enum(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_ENUM;
|
||||
}
|
||||
|
||||
static inline bool btf_is_enum64(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_ENUM64;
|
||||
}
|
||||
|
||||
static inline bool btf_is_fwd(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_FWD;
|
||||
}
|
||||
|
||||
static inline bool btf_is_typedef(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_TYPEDEF;
|
||||
}
|
||||
|
||||
static inline bool btf_is_volatile(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_VOLATILE;
|
||||
}
|
||||
|
||||
static inline bool btf_is_const(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_CONST;
|
||||
}
|
||||
|
||||
static inline bool btf_is_restrict(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_RESTRICT;
|
||||
}
|
||||
|
||||
static inline bool btf_is_mod(const struct btf_type *t)
|
||||
{
|
||||
__u16 kind = btf_kind(t);
|
||||
|
||||
return kind == BTF_KIND_VOLATILE ||
|
||||
kind == BTF_KIND_CONST ||
|
||||
kind == BTF_KIND_RESTRICT ||
|
||||
kind == BTF_KIND_TYPE_TAG;
|
||||
}
|
||||
|
||||
static inline bool btf_is_func(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_FUNC;
|
||||
}
|
||||
|
||||
static inline bool btf_is_func_proto(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_FUNC_PROTO;
|
||||
}
|
||||
|
||||
static inline bool btf_is_var(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_VAR;
|
||||
}
|
||||
|
||||
static inline bool btf_is_datasec(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_DATASEC;
|
||||
}
|
||||
|
||||
static inline bool btf_is_float(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_FLOAT;
|
||||
}
|
||||
|
||||
static inline bool btf_is_decl_tag(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_DECL_TAG;
|
||||
}
|
||||
|
||||
static inline bool btf_is_type_tag(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_TYPE_TAG;
|
||||
}
|
||||
|
||||
static inline bool btf_is_any_enum(const struct btf_type *t)
|
||||
{
|
||||
return btf_is_enum(t) || btf_is_enum64(t);
|
||||
}
|
||||
|
||||
static inline bool btf_kind_core_compat(const struct btf_type *t1,
|
||||
const struct btf_type *t2)
|
||||
{
|
||||
return btf_kind(t1) == btf_kind(t2) ||
|
||||
(btf_is_any_enum(t1) && btf_is_any_enum(t2));
|
||||
}
|
||||
|
||||
static inline __u8 btf_int_encoding(const struct btf_type *t)
|
||||
{
|
||||
return BTF_INT_ENCODING(*(__u32 *)(t + 1));
|
||||
}
|
||||
|
||||
static inline __u8 btf_int_offset(const struct btf_type *t)
|
||||
{
|
||||
return BTF_INT_OFFSET(*(__u32 *)(t + 1));
|
||||
}
|
||||
|
||||
static inline __u8 btf_int_bits(const struct btf_type *t)
|
||||
{
|
||||
return BTF_INT_BITS(*(__u32 *)(t + 1));
|
||||
}
|
||||
|
||||
static inline struct btf_array *btf_array(const struct btf_type *t)
|
||||
{
|
||||
return (struct btf_array *)(t + 1);
|
||||
}
|
||||
|
||||
static inline struct btf_enum *btf_enum(const struct btf_type *t)
|
||||
{
|
||||
return (struct btf_enum *)(t + 1);
|
||||
}
|
||||
|
||||
struct btf_enum64;
|
||||
|
||||
static inline struct btf_enum64 *btf_enum64(const struct btf_type *t)
|
||||
{
|
||||
return (struct btf_enum64 *)(t + 1);
|
||||
}
|
||||
|
||||
static inline __u64 btf_enum64_value(const struct btf_enum64 *e)
|
||||
{
|
||||
/* struct btf_enum64 is introduced in Linux 6.0, which is very
|
||||
* bleeding-edge. Here we are avoiding relying on struct btf_enum64
|
||||
* definition coming from kernel UAPI headers to support wider range
|
||||
* of system-wide kernel headers.
|
||||
*
|
||||
* Given this header can be also included from C++ applications, that
|
||||
* further restricts C tricks we can use (like using compatible
|
||||
* anonymous struct). So just treat struct btf_enum64 as
|
||||
* a three-element array of u32 and access second (lo32) and third
|
||||
* (hi32) elements directly.
|
||||
*
|
||||
* For reference, here is a struct btf_enum64 definition:
|
||||
*
|
||||
* const struct btf_enum64 {
|
||||
* __u32 name_off;
|
||||
* __u32 val_lo32;
|
||||
* __u32 val_hi32;
|
||||
* };
|
||||
*/
|
||||
const __u32 *e64 = (const __u32 *)e;
|
||||
|
||||
return ((__u64)e64[2] << 32) | e64[1];
|
||||
}
|
||||
|
||||
static inline struct btf_member *btf_members(const struct btf_type *t)
|
||||
{
|
||||
return (struct btf_member *)(t + 1);
|
||||
}
|
||||
|
||||
/* Get bit offset of a member with specified index. */
|
||||
static inline __u32 btf_member_bit_offset(const struct btf_type *t,
|
||||
__u32 member_idx)
|
||||
{
|
||||
const struct btf_member *m = btf_members(t) + member_idx;
|
||||
bool kflag = btf_kflag(t);
|
||||
|
||||
return kflag ? BTF_MEMBER_BIT_OFFSET(m->offset) : m->offset;
|
||||
}
|
||||
/*
|
||||
* Get bitfield size of a member, assuming t is BTF_KIND_STRUCT or
|
||||
* BTF_KIND_UNION. If member is not a bitfield, zero is returned.
|
||||
*/
|
||||
static inline __u32 btf_member_bitfield_size(const struct btf_type *t,
|
||||
__u32 member_idx)
|
||||
{
|
||||
const struct btf_member *m = btf_members(t) + member_idx;
|
||||
bool kflag = btf_kflag(t);
|
||||
|
||||
return kflag ? BTF_MEMBER_BITFIELD_SIZE(m->offset) : 0;
|
||||
}
|
||||
|
||||
static inline struct btf_param *btf_params(const struct btf_type *t)
|
||||
{
|
||||
return (struct btf_param *)(t + 1);
|
||||
}
|
||||
|
||||
static inline struct btf_var *btf_var(const struct btf_type *t)
|
||||
{
|
||||
return (struct btf_var *)(t + 1);
|
||||
}
|
||||
|
||||
static inline struct btf_var_secinfo *
|
||||
btf_var_secinfos(const struct btf_type *t)
|
||||
{
|
||||
return (struct btf_var_secinfo *)(t + 1);
|
||||
}
|
||||
|
||||
struct btf_decl_tag;
|
||||
static inline struct btf_decl_tag *btf_decl_tag(const struct btf_type *t)
|
||||
{
|
||||
return (struct btf_decl_tag *)(t + 1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __LIBBPF_BTF_H */
|
||||
2542
third_party/libbpf/src/btf_dump.c
vendored
Normal file
1123
third_party/libbpf/src/gen_loader.c
vendored
Normal file
240
third_party/libbpf/src/hashmap.c
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
|
||||
/*
|
||||
* Generic non-thread safe hash map implementation.
|
||||
*
|
||||
* Copyright (c) 2019 Facebook
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <linux/err.h>
|
||||
#include "hashmap.h"
|
||||
|
||||
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||
|
||||
/* prevent accidental re-addition of reallocarray() */
|
||||
#pragma GCC poison reallocarray
|
||||
|
||||
/* start with 4 buckets */
|
||||
#define HASHMAP_MIN_CAP_BITS 2
|
||||
|
||||
static void hashmap_add_entry(struct hashmap_entry **pprev,
|
||||
struct hashmap_entry *entry)
|
||||
{
|
||||
entry->next = *pprev;
|
||||
*pprev = entry;
|
||||
}
|
||||
|
||||
static void hashmap_del_entry(struct hashmap_entry **pprev,
|
||||
struct hashmap_entry *entry)
|
||||
{
|
||||
*pprev = entry->next;
|
||||
entry->next = NULL;
|
||||
}
|
||||
|
||||
void hashmap__init(struct hashmap *map, hashmap_hash_fn hash_fn,
|
||||
hashmap_equal_fn equal_fn, void *ctx)
|
||||
{
|
||||
map->hash_fn = hash_fn;
|
||||
map->equal_fn = equal_fn;
|
||||
map->ctx = ctx;
|
||||
|
||||
map->buckets = NULL;
|
||||
map->cap = 0;
|
||||
map->cap_bits = 0;
|
||||
map->sz = 0;
|
||||
}
|
||||
|
||||
struct hashmap *hashmap__new(hashmap_hash_fn hash_fn,
|
||||
hashmap_equal_fn equal_fn,
|
||||
void *ctx)
|
||||
{
|
||||
struct hashmap *map = malloc(sizeof(struct hashmap));
|
||||
|
||||
if (!map)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
hashmap__init(map, hash_fn, equal_fn, ctx);
|
||||
return map;
|
||||
}
|
||||
|
||||
void hashmap__clear(struct hashmap *map)
|
||||
{
|
||||
struct hashmap_entry *cur, *tmp;
|
||||
size_t bkt;
|
||||
|
||||
hashmap__for_each_entry_safe(map, cur, tmp, bkt) {
|
||||
free(cur);
|
||||
}
|
||||
free(map->buckets);
|
||||
map->buckets = NULL;
|
||||
map->cap = map->cap_bits = map->sz = 0;
|
||||
}
|
||||
|
||||
void hashmap__free(struct hashmap *map)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(map))
|
||||
return;
|
||||
|
||||
hashmap__clear(map);
|
||||
free(map);
|
||||
}
|
||||
|
||||
size_t hashmap__size(const struct hashmap *map)
|
||||
{
|
||||
return map->sz;
|
||||
}
|
||||
|
||||
size_t hashmap__capacity(const struct hashmap *map)
|
||||
{
|
||||
return map->cap;
|
||||
}
|
||||
|
||||
static bool hashmap_needs_to_grow(struct hashmap *map)
|
||||
{
|
||||
/* grow if empty or more than 75% filled */
|
||||
return (map->cap == 0) || ((map->sz + 1) * 4 / 3 > map->cap);
|
||||
}
|
||||
|
||||
static int hashmap_grow(struct hashmap *map)
|
||||
{
|
||||
struct hashmap_entry **new_buckets;
|
||||
struct hashmap_entry *cur, *tmp;
|
||||
size_t new_cap_bits, new_cap;
|
||||
size_t h, bkt;
|
||||
|
||||
new_cap_bits = map->cap_bits + 1;
|
||||
if (new_cap_bits < HASHMAP_MIN_CAP_BITS)
|
||||
new_cap_bits = HASHMAP_MIN_CAP_BITS;
|
||||
|
||||
new_cap = 1UL << new_cap_bits;
|
||||
new_buckets = calloc(new_cap, sizeof(new_buckets[0]));
|
||||
if (!new_buckets)
|
||||
return -ENOMEM;
|
||||
|
||||
hashmap__for_each_entry_safe(map, cur, tmp, bkt) {
|
||||
h = hash_bits(map->hash_fn(cur->key, map->ctx), new_cap_bits);
|
||||
hashmap_add_entry(&new_buckets[h], cur);
|
||||
}
|
||||
|
||||
map->cap = new_cap;
|
||||
map->cap_bits = new_cap_bits;
|
||||
free(map->buckets);
|
||||
map->buckets = new_buckets;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool hashmap_find_entry(const struct hashmap *map,
|
||||
const long key, size_t hash,
|
||||
struct hashmap_entry ***pprev,
|
||||
struct hashmap_entry **entry)
|
||||
{
|
||||
struct hashmap_entry *cur, **prev_ptr;
|
||||
|
||||
if (!map->buckets)
|
||||
return false;
|
||||
|
||||
for (prev_ptr = &map->buckets[hash], cur = *prev_ptr;
|
||||
cur;
|
||||
prev_ptr = &cur->next, cur = cur->next) {
|
||||
if (map->equal_fn(cur->key, key, map->ctx)) {
|
||||
if (pprev)
|
||||
*pprev = prev_ptr;
|
||||
*entry = cur;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int hashmap_insert(struct hashmap *map, long key, long value,
|
||||
enum hashmap_insert_strategy strategy,
|
||||
long *old_key, long *old_value)
|
||||
{
|
||||
struct hashmap_entry *entry;
|
||||
size_t h;
|
||||
int err;
|
||||
|
||||
if (old_key)
|
||||
*old_key = 0;
|
||||
if (old_value)
|
||||
*old_value = 0;
|
||||
|
||||
h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits);
|
||||
if (strategy != HASHMAP_APPEND &&
|
||||
hashmap_find_entry(map, key, h, NULL, &entry)) {
|
||||
if (old_key)
|
||||
*old_key = entry->key;
|
||||
if (old_value)
|
||||
*old_value = entry->value;
|
||||
|
||||
if (strategy == HASHMAP_SET || strategy == HASHMAP_UPDATE) {
|
||||
entry->key = key;
|
||||
entry->value = value;
|
||||
return 0;
|
||||
} else if (strategy == HASHMAP_ADD) {
|
||||
return -EEXIST;
|
||||
}
|
||||
}
|
||||
|
||||
if (strategy == HASHMAP_UPDATE)
|
||||
return -ENOENT;
|
||||
|
||||
if (hashmap_needs_to_grow(map)) {
|
||||
err = hashmap_grow(map);
|
||||
if (err)
|
||||
return err;
|
||||
h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits);
|
||||
}
|
||||
|
||||
entry = malloc(sizeof(struct hashmap_entry));
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
entry->key = key;
|
||||
entry->value = value;
|
||||
hashmap_add_entry(&map->buckets[h], entry);
|
||||
map->sz++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool hashmap_find(const struct hashmap *map, long key, long *value)
|
||||
{
|
||||
struct hashmap_entry *entry;
|
||||
size_t h;
|
||||
|
||||
h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits);
|
||||
if (!hashmap_find_entry(map, key, h, NULL, &entry))
|
||||
return false;
|
||||
|
||||
if (value)
|
||||
*value = entry->value;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hashmap_delete(struct hashmap *map, long key,
|
||||
long *old_key, long *old_value)
|
||||
{
|
||||
struct hashmap_entry **pprev, *entry;
|
||||
size_t h;
|
||||
|
||||
h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits);
|
||||
if (!hashmap_find_entry(map, key, h, &pprev, &entry))
|
||||
return false;
|
||||
|
||||
if (old_key)
|
||||
*old_key = entry->key;
|
||||
if (old_value)
|
||||
*old_value = entry->value;
|
||||
|
||||
hashmap_del_entry(pprev, entry);
|
||||
free(entry);
|
||||
map->sz--;
|
||||
|
||||
return true;
|
||||
}
|
||||
208
third_party/libbpf/src/hashmap.h
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
|
||||
/*
|
||||
* Generic non-thread safe hash map implementation.
|
||||
*
|
||||
* Copyright (c) 2019 Facebook
|
||||
*/
|
||||
#ifndef __LIBBPF_HASHMAP_H
|
||||
#define __LIBBPF_HASHMAP_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
static inline size_t hash_bits(size_t h, int bits)
|
||||
{
|
||||
/* shuffle bits and return requested number of upper bits */
|
||||
if (bits == 0)
|
||||
return 0;
|
||||
|
||||
#if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__)
|
||||
/* LP64 case */
|
||||
return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits);
|
||||
#elif (__SIZEOF_SIZE_T__ <= __SIZEOF_LONG__)
|
||||
return (h * 2654435769lu) >> (__SIZEOF_LONG__ * 8 - bits);
|
||||
#else
|
||||
# error "Unsupported size_t size"
|
||||
#endif
|
||||
}
|
||||
|
||||
/* generic C-string hashing function */
|
||||
static inline size_t str_hash(const char *s)
|
||||
{
|
||||
size_t h = 0;
|
||||
|
||||
while (*s) {
|
||||
h = h * 31 + *s;
|
||||
s++;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
typedef size_t (*hashmap_hash_fn)(long key, void *ctx);
|
||||
typedef bool (*hashmap_equal_fn)(long key1, long key2, void *ctx);
|
||||
|
||||
/*
|
||||
* Hashmap interface is polymorphic, keys and values could be either
|
||||
* long-sized integers or pointers, this is achieved as follows:
|
||||
* - interface functions that operate on keys and values are hidden
|
||||
* behind auxiliary macros, e.g. hashmap_insert <-> hashmap__insert;
|
||||
* - these auxiliary macros cast the key and value parameters as
|
||||
* long or long *, so the user does not have to specify the casts explicitly;
|
||||
* - for pointer parameters (e.g. old_key) the size of the pointed
|
||||
* type is verified by hashmap_cast_ptr using _Static_assert;
|
||||
* - when iterating using hashmap__for_each_* forms
|
||||
* hasmap_entry->key should be used for integer keys and
|
||||
* hasmap_entry->pkey should be used for pointer keys,
|
||||
* same goes for values.
|
||||
*/
|
||||
struct hashmap_entry {
|
||||
union {
|
||||
long key;
|
||||
const void *pkey;
|
||||
};
|
||||
union {
|
||||
long value;
|
||||
void *pvalue;
|
||||
};
|
||||
struct hashmap_entry *next;
|
||||
};
|
||||
|
||||
struct hashmap {
|
||||
hashmap_hash_fn hash_fn;
|
||||
hashmap_equal_fn equal_fn;
|
||||
void *ctx;
|
||||
|
||||
struct hashmap_entry **buckets;
|
||||
size_t cap;
|
||||
size_t cap_bits;
|
||||
size_t sz;
|
||||
};
|
||||
|
||||
void hashmap__init(struct hashmap *map, hashmap_hash_fn hash_fn,
|
||||
hashmap_equal_fn equal_fn, void *ctx);
|
||||
struct hashmap *hashmap__new(hashmap_hash_fn hash_fn,
|
||||
hashmap_equal_fn equal_fn,
|
||||
void *ctx);
|
||||
void hashmap__clear(struct hashmap *map);
|
||||
void hashmap__free(struct hashmap *map);
|
||||
|
||||
size_t hashmap__size(const struct hashmap *map);
|
||||
size_t hashmap__capacity(const struct hashmap *map);
|
||||
|
||||
/*
|
||||
* Hashmap insertion strategy:
|
||||
* - HASHMAP_ADD - only add key/value if key doesn't exist yet;
|
||||
* - HASHMAP_SET - add key/value pair if key doesn't exist yet; otherwise,
|
||||
* update value;
|
||||
* - HASHMAP_UPDATE - update value, if key already exists; otherwise, do
|
||||
* nothing and return -ENOENT;
|
||||
* - HASHMAP_APPEND - always add key/value pair, even if key already exists.
|
||||
* This turns hashmap into a multimap by allowing multiple values to be
|
||||
* associated with the same key. Most useful read API for such hashmap is
|
||||
* hashmap__for_each_key_entry() iteration. If hashmap__find() is still
|
||||
* used, it will return last inserted key/value entry (first in a bucket
|
||||
* chain).
|
||||
*/
|
||||
enum hashmap_insert_strategy {
|
||||
HASHMAP_ADD,
|
||||
HASHMAP_SET,
|
||||
HASHMAP_UPDATE,
|
||||
HASHMAP_APPEND,
|
||||
};
|
||||
|
||||
#define hashmap_cast_ptr(p) ({ \
|
||||
_Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) || \
|
||||
sizeof(*(p)) == sizeof(long), \
|
||||
#p " pointee should be a long-sized integer or a pointer"); \
|
||||
(long *)(p); \
|
||||
})
|
||||
|
||||
/*
|
||||
* hashmap__insert() adds key/value entry w/ various semantics, depending on
|
||||
* provided strategy value. If a given key/value pair replaced already
|
||||
* existing key/value pair, both old key and old value will be returned
|
||||
* through old_key and old_value to allow calling code do proper memory
|
||||
* management.
|
||||
*/
|
||||
int hashmap_insert(struct hashmap *map, long key, long value,
|
||||
enum hashmap_insert_strategy strategy,
|
||||
long *old_key, long *old_value);
|
||||
|
||||
#define hashmap__insert(map, key, value, strategy, old_key, old_value) \
|
||||
hashmap_insert((map), (long)(key), (long)(value), (strategy), \
|
||||
hashmap_cast_ptr(old_key), \
|
||||
hashmap_cast_ptr(old_value))
|
||||
|
||||
#define hashmap__add(map, key, value) \
|
||||
hashmap__insert((map), (key), (value), HASHMAP_ADD, NULL, NULL)
|
||||
|
||||
#define hashmap__set(map, key, value, old_key, old_value) \
|
||||
hashmap__insert((map), (key), (value), HASHMAP_SET, (old_key), (old_value))
|
||||
|
||||
#define hashmap__update(map, key, value, old_key, old_value) \
|
||||
hashmap__insert((map), (key), (value), HASHMAP_UPDATE, (old_key), (old_value))
|
||||
|
||||
#define hashmap__append(map, key, value) \
|
||||
hashmap__insert((map), (key), (value), HASHMAP_APPEND, NULL, NULL)
|
||||
|
||||
bool hashmap_delete(struct hashmap *map, long key, long *old_key, long *old_value);
|
||||
|
||||
#define hashmap__delete(map, key, old_key, old_value) \
|
||||
hashmap_delete((map), (long)(key), \
|
||||
hashmap_cast_ptr(old_key), \
|
||||
hashmap_cast_ptr(old_value))
|
||||
|
||||
bool hashmap_find(const struct hashmap *map, long key, long *value);
|
||||
|
||||
#define hashmap__find(map, key, value) \
|
||||
hashmap_find((map), (long)(key), hashmap_cast_ptr(value))
|
||||
|
||||
/*
|
||||
* hashmap__for_each_entry - iterate over all entries in hashmap
|
||||
* @map: hashmap to iterate
|
||||
* @cur: struct hashmap_entry * used as a loop cursor
|
||||
* @bkt: integer used as a bucket loop cursor
|
||||
*/
|
||||
#define hashmap__for_each_entry(map, cur, bkt) \
|
||||
for (bkt = 0; bkt < map->cap; bkt++) \
|
||||
for (cur = map->buckets[bkt]; cur; cur = cur->next)
|
||||
|
||||
/*
|
||||
* hashmap__for_each_entry_safe - iterate over all entries in hashmap, safe
|
||||
* against removals
|
||||
* @map: hashmap to iterate
|
||||
* @cur: struct hashmap_entry * used as a loop cursor
|
||||
* @tmp: struct hashmap_entry * used as a temporary next cursor storage
|
||||
* @bkt: integer used as a bucket loop cursor
|
||||
*/
|
||||
#define hashmap__for_each_entry_safe(map, cur, tmp, bkt) \
|
||||
for (bkt = 0; bkt < map->cap; bkt++) \
|
||||
for (cur = map->buckets[bkt]; \
|
||||
cur && ({tmp = cur->next; true; }); \
|
||||
cur = tmp)
|
||||
|
||||
/*
|
||||
* hashmap__for_each_key_entry - iterate over entries associated with given key
|
||||
* @map: hashmap to iterate
|
||||
* @cur: struct hashmap_entry * used as a loop cursor
|
||||
* @key: key to iterate entries for
|
||||
*/
|
||||
#define hashmap__for_each_key_entry(map, cur, _key) \
|
||||
for (cur = map->buckets \
|
||||
? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \
|
||||
: NULL; \
|
||||
cur; \
|
||||
cur = cur->next) \
|
||||
if (map->equal_fn(cur->key, (_key), map->ctx))
|
||||
|
||||
#define hashmap__for_each_key_entry_safe(map, cur, tmp, _key) \
|
||||
for (cur = map->buckets \
|
||||
? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \
|
||||
: NULL; \
|
||||
cur && ({ tmp = cur->next; true; }); \
|
||||
cur = tmp) \
|
||||
if (map->equal_fn(cur->key, (_key), map->ctx))
|
||||
|
||||
#endif /* __LIBBPF_HASHMAP_H */
|
||||
13129
third_party/libbpf/src/libbpf.c
vendored
Normal file
1685
third_party/libbpf/src/libbpf.h
vendored
Normal file
399
third_party/libbpf/src/libbpf.map
vendored
Normal file
@@ -0,0 +1,399 @@
|
||||
LIBBPF_0.0.1 {
|
||||
global:
|
||||
bpf_btf_get_fd_by_id;
|
||||
bpf_map__btf_key_type_id;
|
||||
bpf_map__btf_value_type_id;
|
||||
bpf_map__fd;
|
||||
bpf_map__name;
|
||||
bpf_map__pin;
|
||||
bpf_map__reuse_fd;
|
||||
bpf_map__set_ifindex;
|
||||
bpf_map__set_inner_map_fd;
|
||||
bpf_map__unpin;
|
||||
bpf_map_delete_elem;
|
||||
bpf_map_get_fd_by_id;
|
||||
bpf_map_get_next_id;
|
||||
bpf_map_get_next_key;
|
||||
bpf_map_lookup_and_delete_elem;
|
||||
bpf_map_lookup_elem;
|
||||
bpf_map_update_elem;
|
||||
bpf_obj_get;
|
||||
bpf_obj_get_info_by_fd;
|
||||
bpf_obj_pin;
|
||||
bpf_object__btf_fd;
|
||||
bpf_object__close;
|
||||
bpf_object__find_map_by_name;
|
||||
bpf_object__kversion;
|
||||
bpf_object__load;
|
||||
bpf_object__name;
|
||||
bpf_object__open;
|
||||
bpf_object__pin;
|
||||
bpf_object__pin_maps;
|
||||
bpf_object__pin_programs;
|
||||
bpf_object__unpin_maps;
|
||||
bpf_object__unpin_programs;
|
||||
bpf_prog_attach;
|
||||
bpf_prog_detach;
|
||||
bpf_prog_detach2;
|
||||
bpf_prog_get_fd_by_id;
|
||||
bpf_prog_get_next_id;
|
||||
bpf_prog_query;
|
||||
bpf_program__fd;
|
||||
bpf_program__pin;
|
||||
bpf_program__set_expected_attach_type;
|
||||
bpf_program__set_ifindex;
|
||||
bpf_program__set_type;
|
||||
bpf_program__unload;
|
||||
bpf_program__unpin;
|
||||
bpf_prog_linfo__free;
|
||||
bpf_prog_linfo__new;
|
||||
bpf_prog_linfo__lfind_addr_func;
|
||||
bpf_prog_linfo__lfind;
|
||||
bpf_raw_tracepoint_open;
|
||||
bpf_task_fd_query;
|
||||
btf__fd;
|
||||
btf__find_by_name;
|
||||
btf__free;
|
||||
btf__name_by_offset;
|
||||
btf__new;
|
||||
btf__resolve_size;
|
||||
btf__resolve_type;
|
||||
btf__type_by_id;
|
||||
libbpf_attach_type_by_name;
|
||||
libbpf_get_error;
|
||||
libbpf_prog_type_by_name;
|
||||
libbpf_set_print;
|
||||
libbpf_strerror;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
LIBBPF_0.0.2 {
|
||||
global:
|
||||
bpf_map_lookup_elem_flags;
|
||||
bpf_object__btf;
|
||||
bpf_object__find_map_fd_by_name;
|
||||
btf__get_raw_data;
|
||||
btf_ext__free;
|
||||
btf_ext__get_raw_data;
|
||||
btf_ext__new;
|
||||
} LIBBPF_0.0.1;
|
||||
|
||||
LIBBPF_0.0.3 {
|
||||
global:
|
||||
bpf_map__is_internal;
|
||||
bpf_map_freeze;
|
||||
} LIBBPF_0.0.2;
|
||||
|
||||
LIBBPF_0.0.4 {
|
||||
global:
|
||||
bpf_link__destroy;
|
||||
bpf_program__attach_kprobe;
|
||||
bpf_program__attach_perf_event;
|
||||
bpf_program__attach_raw_tracepoint;
|
||||
bpf_program__attach_tracepoint;
|
||||
bpf_program__attach_uprobe;
|
||||
btf_dump__dump_type;
|
||||
btf_dump__free;
|
||||
btf__parse_elf;
|
||||
libbpf_num_possible_cpus;
|
||||
perf_buffer__free;
|
||||
perf_buffer__poll;
|
||||
} LIBBPF_0.0.3;
|
||||
|
||||
LIBBPF_0.0.5 {
|
||||
global:
|
||||
bpf_btf_get_next_id;
|
||||
} LIBBPF_0.0.4;
|
||||
|
||||
LIBBPF_0.0.6 {
|
||||
global:
|
||||
bpf_map__get_pin_path;
|
||||
bpf_map__is_pinned;
|
||||
bpf_map__set_pin_path;
|
||||
bpf_object__open_file;
|
||||
bpf_object__open_mem;
|
||||
bpf_program__attach_trace;
|
||||
bpf_program__get_expected_attach_type;
|
||||
bpf_program__get_type;
|
||||
btf__find_by_name_kind;
|
||||
libbpf_find_vmlinux_btf_id;
|
||||
} LIBBPF_0.0.5;
|
||||
|
||||
LIBBPF_0.0.7 {
|
||||
global:
|
||||
btf_dump__emit_type_decl;
|
||||
bpf_link__disconnect;
|
||||
bpf_map__attach_struct_ops;
|
||||
bpf_map_delete_batch;
|
||||
bpf_map_lookup_and_delete_batch;
|
||||
bpf_map_lookup_batch;
|
||||
bpf_map_update_batch;
|
||||
bpf_object__find_program_by_name;
|
||||
bpf_object__attach_skeleton;
|
||||
bpf_object__destroy_skeleton;
|
||||
bpf_object__detach_skeleton;
|
||||
bpf_object__load_skeleton;
|
||||
bpf_object__open_skeleton;
|
||||
bpf_program__attach;
|
||||
bpf_program__name;
|
||||
btf__align_of;
|
||||
libbpf_find_kernel_btf;
|
||||
} LIBBPF_0.0.6;
|
||||
|
||||
LIBBPF_0.0.8 {
|
||||
global:
|
||||
bpf_link__fd;
|
||||
bpf_link__open;
|
||||
bpf_link__pin;
|
||||
bpf_link__pin_path;
|
||||
bpf_link__unpin;
|
||||
bpf_link__update_program;
|
||||
bpf_link_create;
|
||||
bpf_link_update;
|
||||
bpf_map__set_initial_value;
|
||||
bpf_prog_attach_opts;
|
||||
bpf_program__attach_cgroup;
|
||||
bpf_program__attach_lsm;
|
||||
bpf_program__set_attach_target;
|
||||
} LIBBPF_0.0.7;
|
||||
|
||||
LIBBPF_0.0.9 {
|
||||
global:
|
||||
bpf_enable_stats;
|
||||
bpf_iter_create;
|
||||
bpf_link_get_fd_by_id;
|
||||
bpf_link_get_next_id;
|
||||
bpf_program__attach_iter;
|
||||
bpf_program__attach_netns;
|
||||
perf_buffer__consume;
|
||||
ring_buffer__add;
|
||||
ring_buffer__consume;
|
||||
ring_buffer__free;
|
||||
ring_buffer__new;
|
||||
ring_buffer__poll;
|
||||
} LIBBPF_0.0.8;
|
||||
|
||||
LIBBPF_0.1.0 {
|
||||
global:
|
||||
bpf_link__detach;
|
||||
bpf_link_detach;
|
||||
bpf_map__ifindex;
|
||||
bpf_map__key_size;
|
||||
bpf_map__map_flags;
|
||||
bpf_map__max_entries;
|
||||
bpf_map__numa_node;
|
||||
bpf_map__set_key_size;
|
||||
bpf_map__set_map_flags;
|
||||
bpf_map__set_max_entries;
|
||||
bpf_map__set_numa_node;
|
||||
bpf_map__set_type;
|
||||
bpf_map__set_value_size;
|
||||
bpf_map__type;
|
||||
bpf_map__value_size;
|
||||
bpf_program__attach_xdp;
|
||||
bpf_program__autoload;
|
||||
bpf_program__set_autoload;
|
||||
btf__parse;
|
||||
btf__parse_raw;
|
||||
btf__pointer_size;
|
||||
btf__set_fd;
|
||||
btf__set_pointer_size;
|
||||
} LIBBPF_0.0.9;
|
||||
|
||||
LIBBPF_0.2.0 {
|
||||
global:
|
||||
bpf_prog_bind_map;
|
||||
bpf_prog_test_run_opts;
|
||||
bpf_program__attach_freplace;
|
||||
bpf_program__section_name;
|
||||
btf__add_array;
|
||||
btf__add_const;
|
||||
btf__add_enum;
|
||||
btf__add_enum_value;
|
||||
btf__add_datasec;
|
||||
btf__add_datasec_var_info;
|
||||
btf__add_field;
|
||||
btf__add_func;
|
||||
btf__add_func_param;
|
||||
btf__add_func_proto;
|
||||
btf__add_fwd;
|
||||
btf__add_int;
|
||||
btf__add_ptr;
|
||||
btf__add_restrict;
|
||||
btf__add_str;
|
||||
btf__add_struct;
|
||||
btf__add_typedef;
|
||||
btf__add_union;
|
||||
btf__add_var;
|
||||
btf__add_volatile;
|
||||
btf__endianness;
|
||||
btf__find_str;
|
||||
btf__new_empty;
|
||||
btf__set_endianness;
|
||||
btf__str_by_offset;
|
||||
perf_buffer__buffer_cnt;
|
||||
perf_buffer__buffer_fd;
|
||||
perf_buffer__epoll_fd;
|
||||
perf_buffer__consume_buffer;
|
||||
} LIBBPF_0.1.0;
|
||||
|
||||
LIBBPF_0.3.0 {
|
||||
global:
|
||||
btf__base_btf;
|
||||
btf__parse_elf_split;
|
||||
btf__parse_raw_split;
|
||||
btf__parse_split;
|
||||
btf__new_empty_split;
|
||||
btf__new_split;
|
||||
ring_buffer__epoll_fd;
|
||||
} LIBBPF_0.2.0;
|
||||
|
||||
LIBBPF_0.4.0 {
|
||||
global:
|
||||
btf__add_float;
|
||||
btf__add_type;
|
||||
bpf_linker__add_file;
|
||||
bpf_linker__finalize;
|
||||
bpf_linker__free;
|
||||
bpf_linker__new;
|
||||
bpf_map__inner_map;
|
||||
bpf_object__set_kversion;
|
||||
bpf_tc_attach;
|
||||
bpf_tc_detach;
|
||||
bpf_tc_hook_create;
|
||||
bpf_tc_hook_destroy;
|
||||
bpf_tc_query;
|
||||
} LIBBPF_0.3.0;
|
||||
|
||||
LIBBPF_0.5.0 {
|
||||
global:
|
||||
bpf_map__initial_value;
|
||||
bpf_map__pin_path;
|
||||
bpf_map_lookup_and_delete_elem_flags;
|
||||
bpf_program__attach_kprobe_opts;
|
||||
bpf_program__attach_perf_event_opts;
|
||||
bpf_program__attach_tracepoint_opts;
|
||||
bpf_program__attach_uprobe_opts;
|
||||
bpf_object__gen_loader;
|
||||
btf__load_from_kernel_by_id;
|
||||
btf__load_from_kernel_by_id_split;
|
||||
btf__load_into_kernel;
|
||||
btf__load_module_btf;
|
||||
btf__load_vmlinux_btf;
|
||||
btf_dump__dump_type_data;
|
||||
libbpf_set_strict_mode;
|
||||
} LIBBPF_0.4.0;
|
||||
|
||||
LIBBPF_0.6.0 {
|
||||
global:
|
||||
bpf_map__map_extra;
|
||||
bpf_map__set_map_extra;
|
||||
bpf_map_create;
|
||||
bpf_object__next_map;
|
||||
bpf_object__next_program;
|
||||
bpf_object__prev_map;
|
||||
bpf_object__prev_program;
|
||||
bpf_prog_load;
|
||||
bpf_program__flags;
|
||||
bpf_program__insn_cnt;
|
||||
bpf_program__insns;
|
||||
bpf_program__set_flags;
|
||||
btf__add_btf;
|
||||
btf__add_decl_tag;
|
||||
btf__add_type_tag;
|
||||
btf__dedup;
|
||||
btf__raw_data;
|
||||
btf__type_cnt;
|
||||
btf_dump__new;
|
||||
libbpf_major_version;
|
||||
libbpf_minor_version;
|
||||
libbpf_version_string;
|
||||
perf_buffer__new;
|
||||
perf_buffer__new_raw;
|
||||
} LIBBPF_0.5.0;
|
||||
|
||||
LIBBPF_0.7.0 {
|
||||
global:
|
||||
bpf_btf_load;
|
||||
bpf_program__expected_attach_type;
|
||||
bpf_program__log_buf;
|
||||
bpf_program__log_level;
|
||||
bpf_program__set_log_buf;
|
||||
bpf_program__set_log_level;
|
||||
bpf_program__type;
|
||||
bpf_xdp_attach;
|
||||
bpf_xdp_detach;
|
||||
bpf_xdp_query;
|
||||
bpf_xdp_query_id;
|
||||
btf_ext__raw_data;
|
||||
libbpf_probe_bpf_helper;
|
||||
libbpf_probe_bpf_map_type;
|
||||
libbpf_probe_bpf_prog_type;
|
||||
libbpf_set_memlock_rlim;
|
||||
} LIBBPF_0.6.0;
|
||||
|
||||
LIBBPF_0.8.0 {
|
||||
global:
|
||||
bpf_map__autocreate;
|
||||
bpf_map__get_next_key;
|
||||
bpf_map__delete_elem;
|
||||
bpf_map__lookup_and_delete_elem;
|
||||
bpf_map__lookup_elem;
|
||||
bpf_map__set_autocreate;
|
||||
bpf_map__update_elem;
|
||||
bpf_map_delete_elem_flags;
|
||||
bpf_object__destroy_subskeleton;
|
||||
bpf_object__open_subskeleton;
|
||||
bpf_program__attach_kprobe_multi_opts;
|
||||
bpf_program__attach_trace_opts;
|
||||
bpf_program__attach_usdt;
|
||||
bpf_program__set_insns;
|
||||
libbpf_register_prog_handler;
|
||||
libbpf_unregister_prog_handler;
|
||||
} LIBBPF_0.7.0;
|
||||
|
||||
LIBBPF_1.0.0 {
|
||||
global:
|
||||
bpf_obj_get_opts;
|
||||
bpf_prog_query_opts;
|
||||
bpf_program__attach_ksyscall;
|
||||
bpf_program__autoattach;
|
||||
bpf_program__set_autoattach;
|
||||
btf__add_enum64;
|
||||
btf__add_enum64_value;
|
||||
libbpf_bpf_attach_type_str;
|
||||
libbpf_bpf_link_type_str;
|
||||
libbpf_bpf_map_type_str;
|
||||
libbpf_bpf_prog_type_str;
|
||||
perf_buffer__buffer;
|
||||
} LIBBPF_0.8.0;
|
||||
|
||||
LIBBPF_1.1.0 {
|
||||
global:
|
||||
bpf_btf_get_fd_by_id_opts;
|
||||
bpf_link_get_fd_by_id_opts;
|
||||
bpf_map_get_fd_by_id_opts;
|
||||
bpf_prog_get_fd_by_id_opts;
|
||||
user_ring_buffer__discard;
|
||||
user_ring_buffer__free;
|
||||
user_ring_buffer__new;
|
||||
user_ring_buffer__reserve;
|
||||
user_ring_buffer__reserve_blocking;
|
||||
user_ring_buffer__submit;
|
||||
} LIBBPF_1.0.0;
|
||||
|
||||
LIBBPF_1.2.0 {
|
||||
global:
|
||||
bpf_btf_get_info_by_fd;
|
||||
bpf_link__update_map;
|
||||
bpf_link_get_info_by_fd;
|
||||
bpf_map_get_info_by_fd;
|
||||
bpf_prog_get_info_by_fd;
|
||||
} LIBBPF_1.1.0;
|
||||
|
||||
LIBBPF_1.3.0 {
|
||||
global:
|
||||
bpf_obj_pin_opts;
|
||||
bpf_program__attach_netfilter;
|
||||
} LIBBPF_1.2.0;
|
||||
12
third_party/libbpf/src/libbpf.pc.template
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
|
||||
prefix=@PREFIX@
|
||||
libdir=@LIBDIR@
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: libbpf
|
||||
Description: BPF library
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lbpf
|
||||
Requires.private: libelf zlib
|
||||
Cflags: -I${includedir}
|
||||
73
third_party/libbpf/src/libbpf_common.h
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
|
||||
/*
|
||||
* Common user-facing libbpf helpers.
|
||||
*
|
||||
* Copyright (c) 2019 Facebook
|
||||
*/
|
||||
|
||||
#ifndef __LIBBPF_LIBBPF_COMMON_H
|
||||
#define __LIBBPF_LIBBPF_COMMON_H
|
||||
|
||||
#include <string.h>
|
||||
#include "libbpf_version.h"
|
||||
|
||||
#ifndef LIBBPF_API
|
||||
#define LIBBPF_API __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#define LIBBPF_DEPRECATED(msg) __attribute__((deprecated(msg)))
|
||||
|
||||
/* Mark a symbol as deprecated when libbpf version is >= {major}.{minor} */
|
||||
#define LIBBPF_DEPRECATED_SINCE(major, minor, msg) \
|
||||
__LIBBPF_MARK_DEPRECATED_ ## major ## _ ## minor \
|
||||
(LIBBPF_DEPRECATED("libbpf v" # major "." # minor "+: " msg))
|
||||
|
||||
#define __LIBBPF_CURRENT_VERSION_GEQ(major, minor) \
|
||||
(LIBBPF_MAJOR_VERSION > (major) || \
|
||||
(LIBBPF_MAJOR_VERSION == (major) && LIBBPF_MINOR_VERSION >= (minor)))
|
||||
|
||||
/* Add checks for other versions below when planning deprecation of API symbols
|
||||
* with the LIBBPF_DEPRECATED_SINCE macro.
|
||||
*/
|
||||
#if __LIBBPF_CURRENT_VERSION_GEQ(1, 0)
|
||||
#define __LIBBPF_MARK_DEPRECATED_1_0(X) X
|
||||
#else
|
||||
#define __LIBBPF_MARK_DEPRECATED_1_0(X)
|
||||
#endif
|
||||
|
||||
/* This set of internal macros allows to do "function overloading" based on
|
||||
* number of arguments provided by used in backwards-compatible way during the
|
||||
* transition to libbpf 1.0
|
||||
* It's ugly but necessary evil that will be cleaned up when we get to 1.0.
|
||||
* See bpf_prog_load() overload for example.
|
||||
*/
|
||||
#define ___libbpf_cat(A, B) A ## B
|
||||
#define ___libbpf_select(NAME, NUM) ___libbpf_cat(NAME, NUM)
|
||||
#define ___libbpf_nth(_1, _2, _3, _4, _5, _6, N, ...) N
|
||||
#define ___libbpf_cnt(...) ___libbpf_nth(__VA_ARGS__, 6, 5, 4, 3, 2, 1)
|
||||
#define ___libbpf_overload(NAME, ...) ___libbpf_select(NAME, ___libbpf_cnt(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
/* Helper macro to declare and initialize libbpf options struct
|
||||
*
|
||||
* This dance with uninitialized declaration, followed by memset to zero,
|
||||
* followed by assignment using compound literal syntax is done to preserve
|
||||
* ability to use a nice struct field initialization syntax and **hopefully**
|
||||
* have all the padding bytes initialized to zero. It's not guaranteed though,
|
||||
* when copying literal, that compiler won't copy garbage in literal's padding
|
||||
* bytes, but that's the best way I've found and it seems to work in practice.
|
||||
*
|
||||
* Macro declares opts struct of given type and name, zero-initializes,
|
||||
* including any extra padding, it with memset() and then assigns initial
|
||||
* values provided by users in struct initializer-syntax as varargs.
|
||||
*/
|
||||
#define LIBBPF_OPTS(TYPE, NAME, ...) \
|
||||
struct TYPE NAME = ({ \
|
||||
memset(&NAME, 0, sizeof(struct TYPE)); \
|
||||
(struct TYPE) { \
|
||||
.sz = sizeof(struct TYPE), \
|
||||
__VA_ARGS__ \
|
||||
}; \
|
||||
})
|
||||
|
||||
#endif /* __LIBBPF_LIBBPF_COMMON_H */
|
||||
75
third_party/libbpf/src/libbpf_errno.c
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
|
||||
* Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
|
||||
* Copyright (C) 2015 Huawei Inc.
|
||||
* Copyright (C) 2017 Nicira, Inc.
|
||||
*/
|
||||
|
||||
#undef _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libbpf.h"
|
||||
#include "libbpf_internal.h"
|
||||
|
||||
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||
|
||||
#define ERRNO_OFFSET(e) ((e) - __LIBBPF_ERRNO__START)
|
||||
#define ERRCODE_OFFSET(c) ERRNO_OFFSET(LIBBPF_ERRNO__##c)
|
||||
#define NR_ERRNO (__LIBBPF_ERRNO__END - __LIBBPF_ERRNO__START)
|
||||
|
||||
static const char *libbpf_strerror_table[NR_ERRNO] = {
|
||||
[ERRCODE_OFFSET(LIBELF)] = "Something wrong in libelf",
|
||||
[ERRCODE_OFFSET(FORMAT)] = "BPF object format invalid",
|
||||
[ERRCODE_OFFSET(KVERSION)] = "'version' section incorrect or lost",
|
||||
[ERRCODE_OFFSET(ENDIAN)] = "Endian mismatch",
|
||||
[ERRCODE_OFFSET(INTERNAL)] = "Internal error in libbpf",
|
||||
[ERRCODE_OFFSET(RELOC)] = "Relocation failed",
|
||||
[ERRCODE_OFFSET(VERIFY)] = "Kernel verifier blocks program loading",
|
||||
[ERRCODE_OFFSET(PROG2BIG)] = "Program too big",
|
||||
[ERRCODE_OFFSET(KVER)] = "Incorrect kernel version",
|
||||
[ERRCODE_OFFSET(PROGTYPE)] = "Kernel doesn't support this program type",
|
||||
[ERRCODE_OFFSET(WRNGPID)] = "Wrong pid in netlink message",
|
||||
[ERRCODE_OFFSET(INVSEQ)] = "Invalid netlink sequence",
|
||||
[ERRCODE_OFFSET(NLPARSE)] = "Incorrect netlink message parsing",
|
||||
};
|
||||
|
||||
int libbpf_strerror(int err, char *buf, size_t size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!buf || !size)
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
err = err > 0 ? err : -err;
|
||||
|
||||
if (err < __LIBBPF_ERRNO__START) {
|
||||
ret = strerror_r(err, buf, size);
|
||||
buf[size - 1] = '\0';
|
||||
return libbpf_err_errno(ret);
|
||||
}
|
||||
|
||||
if (err < __LIBBPF_ERRNO__END) {
|
||||
const char *msg;
|
||||
|
||||
msg = libbpf_strerror_table[ERRNO_OFFSET(err)];
|
||||
ret = snprintf(buf, size, "%s", msg);
|
||||
buf[size - 1] = '\0';
|
||||
/* The length of the buf and msg is positive.
|
||||
* A negative number may be returned only when the
|
||||
* size exceeds INT_MAX. Not likely to appear.
|
||||
*/
|
||||
if (ret >= size)
|
||||
return libbpf_err(-ERANGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = snprintf(buf, size, "Unknown libbpf error %d", err);
|
||||
buf[size - 1] = '\0';
|
||||
if (ret >= size)
|
||||
return libbpf_err(-ERANGE);
|
||||
return libbpf_err(-ENOENT);
|
||||
}
|
||||
580
third_party/libbpf/src/libbpf_internal.h
vendored
Normal file
@@ -0,0 +1,580 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
|
||||
/*
|
||||
* Internal libbpf helpers.
|
||||
*
|
||||
* Copyright (c) 2019 Facebook
|
||||
*/
|
||||
|
||||
#ifndef __LIBBPF_LIBBPF_INTERNAL_H
|
||||
#define __LIBBPF_LIBBPF_INTERNAL_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "relo_core.h"
|
||||
|
||||
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||
|
||||
/* prevent accidental re-addition of reallocarray() */
|
||||
#pragma GCC poison reallocarray
|
||||
|
||||
#include "libbpf.h"
|
||||
#include "btf.h"
|
||||
|
||||
#ifndef EM_BPF
|
||||
#define EM_BPF 247
|
||||
#endif
|
||||
|
||||
#ifndef R_BPF_64_64
|
||||
#define R_BPF_64_64 1
|
||||
#endif
|
||||
#ifndef R_BPF_64_ABS64
|
||||
#define R_BPF_64_ABS64 2
|
||||
#endif
|
||||
#ifndef R_BPF_64_ABS32
|
||||
#define R_BPF_64_ABS32 3
|
||||
#endif
|
||||
#ifndef R_BPF_64_32
|
||||
#define R_BPF_64_32 10
|
||||
#endif
|
||||
|
||||
#ifndef SHT_LLVM_ADDRSIG
|
||||
#define SHT_LLVM_ADDRSIG 0x6FFF4C03
|
||||
#endif
|
||||
|
||||
/* if libelf is old and doesn't support mmap(), fall back to read() */
|
||||
#ifndef ELF_C_READ_MMAP
|
||||
#define ELF_C_READ_MMAP ELF_C_READ
|
||||
#endif
|
||||
|
||||
/* Older libelf all end up in this expression, for both 32 and 64 bit */
|
||||
#ifndef ELF64_ST_VISIBILITY
|
||||
#define ELF64_ST_VISIBILITY(o) ((o) & 0x03)
|
||||
#endif
|
||||
|
||||
#define BTF_INFO_ENC(kind, kind_flag, vlen) \
|
||||
((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
|
||||
#define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type)
|
||||
#define BTF_INT_ENC(encoding, bits_offset, nr_bits) \
|
||||
((encoding) << 24 | (bits_offset) << 16 | (nr_bits))
|
||||
#define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \
|
||||
BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \
|
||||
BTF_INT_ENC(encoding, bits_offset, bits)
|
||||
#define BTF_MEMBER_ENC(name, type, bits_offset) (name), (type), (bits_offset)
|
||||
#define BTF_PARAM_ENC(name, type) (name), (type)
|
||||
#define BTF_VAR_SECINFO_ENC(type, offset, size) (type), (offset), (size)
|
||||
#define BTF_TYPE_FLOAT_ENC(name, sz) \
|
||||
BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_FLOAT, 0, 0), sz)
|
||||
#define BTF_TYPE_DECL_TAG_ENC(value, type, component_idx) \
|
||||
BTF_TYPE_ENC(value, BTF_INFO_ENC(BTF_KIND_DECL_TAG, 0, 0), type), (component_idx)
|
||||
#define BTF_TYPE_TYPE_TAG_ENC(value, type) \
|
||||
BTF_TYPE_ENC(value, BTF_INFO_ENC(BTF_KIND_TYPE_TAG, 0, 0), type)
|
||||
|
||||
#ifndef likely
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
#ifndef min
|
||||
# define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
#endif
|
||||
#ifndef max
|
||||
# define max(x, y) ((x) < (y) ? (y) : (x))
|
||||
#endif
|
||||
#ifndef offsetofend
|
||||
# define offsetofend(TYPE, FIELD) \
|
||||
(offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD))
|
||||
#endif
|
||||
#ifndef __alias
|
||||
#define __alias(symbol) __attribute__((alias(#symbol)))
|
||||
#endif
|
||||
|
||||
/* Check whether a string `str` has prefix `pfx`, regardless if `pfx` is
|
||||
* a string literal known at compilation time or char * pointer known only at
|
||||
* runtime.
|
||||
*/
|
||||
#define str_has_pfx(str, pfx) \
|
||||
(strncmp(str, pfx, __builtin_constant_p(pfx) ? sizeof(pfx) - 1 : strlen(pfx)) == 0)
|
||||
|
||||
/* suffix check */
|
||||
static inline bool str_has_sfx(const char *str, const char *sfx)
|
||||
{
|
||||
size_t str_len = strlen(str);
|
||||
size_t sfx_len = strlen(sfx);
|
||||
|
||||
if (sfx_len > str_len)
|
||||
return false;
|
||||
return strcmp(str + str_len - sfx_len, sfx) == 0;
|
||||
}
|
||||
|
||||
/* Symbol versioning is different between static and shared library.
|
||||
* Properly versioned symbols are needed for shared library, but
|
||||
* only the symbol of the new version is needed for static library.
|
||||
* Starting with GNU C 10, use symver attribute instead of .symver assembler
|
||||
* directive, which works better with GCC LTO builds.
|
||||
*/
|
||||
#if defined(SHARED) && defined(__GNUC__) && __GNUC__ >= 10
|
||||
|
||||
#define DEFAULT_VERSION(internal_name, api_name, version) \
|
||||
__attribute__((symver(#api_name "@@" #version)))
|
||||
#define COMPAT_VERSION(internal_name, api_name, version) \
|
||||
__attribute__((symver(#api_name "@" #version)))
|
||||
|
||||
#elif defined(SHARED)
|
||||
|
||||
#define COMPAT_VERSION(internal_name, api_name, version) \
|
||||
asm(".symver " #internal_name "," #api_name "@" #version);
|
||||
#define DEFAULT_VERSION(internal_name, api_name, version) \
|
||||
asm(".symver " #internal_name "," #api_name "@@" #version);
|
||||
|
||||
#else /* !SHARED */
|
||||
|
||||
#define COMPAT_VERSION(internal_name, api_name, version)
|
||||
#define DEFAULT_VERSION(internal_name, api_name, version) \
|
||||
extern typeof(internal_name) api_name \
|
||||
__attribute__((alias(#internal_name)));
|
||||
|
||||
#endif
|
||||
|
||||
extern void libbpf_print(enum libbpf_print_level level,
|
||||
const char *format, ...)
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
|
||||
#define __pr(level, fmt, ...) \
|
||||
do { \
|
||||
libbpf_print(level, "libbpf: " fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define pr_warn(fmt, ...) __pr(LIBBPF_WARN, fmt, ##__VA_ARGS__)
|
||||
#define pr_info(fmt, ...) __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__)
|
||||
#define pr_debug(fmt, ...) __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__)
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
struct bpf_link {
|
||||
int (*detach)(struct bpf_link *link);
|
||||
void (*dealloc)(struct bpf_link *link);
|
||||
char *pin_path; /* NULL, if not pinned */
|
||||
int fd; /* hook FD, -1 if not applicable */
|
||||
bool disconnected;
|
||||
};
|
||||
|
||||
/*
|
||||
* Re-implement glibc's reallocarray() for libbpf internal-only use.
|
||||
* reallocarray(), unfortunately, is not available in all versions of glibc,
|
||||
* so requires extra feature detection and using reallocarray() stub from
|
||||
* <tools/libc_compat.h> and COMPAT_NEED_REALLOCARRAY. All this complicates
|
||||
* build of libbpf unnecessarily and is just a maintenance burden. Instead,
|
||||
* it's trivial to implement libbpf-specific internal version and use it
|
||||
* throughout libbpf.
|
||||
*/
|
||||
static inline void *libbpf_reallocarray(void *ptr, size_t nmemb, size_t size)
|
||||
{
|
||||
size_t total;
|
||||
|
||||
#if __has_builtin(__builtin_mul_overflow)
|
||||
if (unlikely(__builtin_mul_overflow(nmemb, size, &total)))
|
||||
return NULL;
|
||||
#else
|
||||
if (size == 0 || nmemb > ULONG_MAX / size)
|
||||
return NULL;
|
||||
total = nmemb * size;
|
||||
#endif
|
||||
return realloc(ptr, total);
|
||||
}
|
||||
|
||||
/* Copy up to sz - 1 bytes from zero-terminated src string and ensure that dst
|
||||
* is zero-terminated string no matter what (unless sz == 0, in which case
|
||||
* it's a no-op). It's conceptually close to FreeBSD's strlcpy(), but differs
|
||||
* in what is returned. Given this is internal helper, it's trivial to extend
|
||||
* this, when necessary. Use this instead of strncpy inside libbpf source code.
|
||||
*/
|
||||
static inline void libbpf_strlcpy(char *dst, const char *src, size_t sz)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (sz == 0)
|
||||
return;
|
||||
|
||||
sz--;
|
||||
for (i = 0; i < sz && src[i]; i++)
|
||||
dst[i] = src[i];
|
||||
dst[i] = '\0';
|
||||
}
|
||||
|
||||
__u32 get_kernel_version(void);
|
||||
|
||||
struct btf;
|
||||
struct btf_type;
|
||||
|
||||
struct btf_type *btf_type_by_id(const struct btf *btf, __u32 type_id);
|
||||
const char *btf_kind_str(const struct btf_type *t);
|
||||
const struct btf_type *skip_mods_and_typedefs(const struct btf *btf, __u32 id, __u32 *res_id);
|
||||
|
||||
static inline enum btf_func_linkage btf_func_linkage(const struct btf_type *t)
|
||||
{
|
||||
return (enum btf_func_linkage)(int)btf_vlen(t);
|
||||
}
|
||||
|
||||
static inline __u32 btf_type_info(int kind, int vlen, int kflag)
|
||||
{
|
||||
return (kflag << 31) | (kind << 24) | vlen;
|
||||
}
|
||||
|
||||
enum map_def_parts {
|
||||
MAP_DEF_MAP_TYPE = 0x001,
|
||||
MAP_DEF_KEY_TYPE = 0x002,
|
||||
MAP_DEF_KEY_SIZE = 0x004,
|
||||
MAP_DEF_VALUE_TYPE = 0x008,
|
||||
MAP_DEF_VALUE_SIZE = 0x010,
|
||||
MAP_DEF_MAX_ENTRIES = 0x020,
|
||||
MAP_DEF_MAP_FLAGS = 0x040,
|
||||
MAP_DEF_NUMA_NODE = 0x080,
|
||||
MAP_DEF_PINNING = 0x100,
|
||||
MAP_DEF_INNER_MAP = 0x200,
|
||||
MAP_DEF_MAP_EXTRA = 0x400,
|
||||
|
||||
MAP_DEF_ALL = 0x7ff, /* combination of all above */
|
||||
};
|
||||
|
||||
struct btf_map_def {
|
||||
enum map_def_parts parts;
|
||||
__u32 map_type;
|
||||
__u32 key_type_id;
|
||||
__u32 key_size;
|
||||
__u32 value_type_id;
|
||||
__u32 value_size;
|
||||
__u32 max_entries;
|
||||
__u32 map_flags;
|
||||
__u32 numa_node;
|
||||
__u32 pinning;
|
||||
__u64 map_extra;
|
||||
};
|
||||
|
||||
int parse_btf_map_def(const char *map_name, struct btf *btf,
|
||||
const struct btf_type *def_t, bool strict,
|
||||
struct btf_map_def *map_def, struct btf_map_def *inner_def);
|
||||
|
||||
void *libbpf_add_mem(void **data, size_t *cap_cnt, size_t elem_sz,
|
||||
size_t cur_cnt, size_t max_cnt, size_t add_cnt);
|
||||
int libbpf_ensure_mem(void **data, size_t *cap_cnt, size_t elem_sz, size_t need_cnt);
|
||||
|
||||
static inline bool libbpf_is_mem_zeroed(const char *p, ssize_t len)
|
||||
{
|
||||
while (len > 0) {
|
||||
if (*p)
|
||||
return false;
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool libbpf_validate_opts(const char *opts,
|
||||
size_t opts_sz, size_t user_sz,
|
||||
const char *type_name)
|
||||
{
|
||||
if (user_sz < sizeof(size_t)) {
|
||||
pr_warn("%s size (%zu) is too small\n", type_name, user_sz);
|
||||
return false;
|
||||
}
|
||||
if (!libbpf_is_mem_zeroed(opts + opts_sz, (ssize_t)user_sz - opts_sz)) {
|
||||
pr_warn("%s has non-zero extra bytes\n", type_name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define OPTS_VALID(opts, type) \
|
||||
(!(opts) || libbpf_validate_opts((const char *)opts, \
|
||||
offsetofend(struct type, \
|
||||
type##__last_field), \
|
||||
(opts)->sz, #type))
|
||||
#define OPTS_HAS(opts, field) \
|
||||
((opts) && opts->sz >= offsetofend(typeof(*(opts)), field))
|
||||
#define OPTS_GET(opts, field, fallback_value) \
|
||||
(OPTS_HAS(opts, field) ? (opts)->field : fallback_value)
|
||||
#define OPTS_SET(opts, field, value) \
|
||||
do { \
|
||||
if (OPTS_HAS(opts, field)) \
|
||||
(opts)->field = value; \
|
||||
} while (0)
|
||||
|
||||
#define OPTS_ZEROED(opts, last_nonzero_field) \
|
||||
({ \
|
||||
ssize_t __off = offsetofend(typeof(*(opts)), last_nonzero_field); \
|
||||
!(opts) || libbpf_is_mem_zeroed((const void *)opts + __off, \
|
||||
(opts)->sz - __off); \
|
||||
})
|
||||
|
||||
enum kern_feature_id {
|
||||
/* v4.14: kernel support for program & map names. */
|
||||
FEAT_PROG_NAME,
|
||||
/* v5.2: kernel support for global data sections. */
|
||||
FEAT_GLOBAL_DATA,
|
||||
/* BTF support */
|
||||
FEAT_BTF,
|
||||
/* BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO support */
|
||||
FEAT_BTF_FUNC,
|
||||
/* BTF_KIND_VAR and BTF_KIND_DATASEC support */
|
||||
FEAT_BTF_DATASEC,
|
||||
/* BTF_FUNC_GLOBAL is supported */
|
||||
FEAT_BTF_GLOBAL_FUNC,
|
||||
/* BPF_F_MMAPABLE is supported for arrays */
|
||||
FEAT_ARRAY_MMAP,
|
||||
/* kernel support for expected_attach_type in BPF_PROG_LOAD */
|
||||
FEAT_EXP_ATTACH_TYPE,
|
||||
/* bpf_probe_read_{kernel,user}[_str] helpers */
|
||||
FEAT_PROBE_READ_KERN,
|
||||
/* BPF_PROG_BIND_MAP is supported */
|
||||
FEAT_PROG_BIND_MAP,
|
||||
/* Kernel support for module BTFs */
|
||||
FEAT_MODULE_BTF,
|
||||
/* BTF_KIND_FLOAT support */
|
||||
FEAT_BTF_FLOAT,
|
||||
/* BPF perf link support */
|
||||
FEAT_PERF_LINK,
|
||||
/* BTF_KIND_DECL_TAG support */
|
||||
FEAT_BTF_DECL_TAG,
|
||||
/* BTF_KIND_TYPE_TAG support */
|
||||
FEAT_BTF_TYPE_TAG,
|
||||
/* memcg-based accounting for BPF maps and progs */
|
||||
FEAT_MEMCG_ACCOUNT,
|
||||
/* BPF cookie (bpf_get_attach_cookie() BPF helper) support */
|
||||
FEAT_BPF_COOKIE,
|
||||
/* BTF_KIND_ENUM64 support and BTF_KIND_ENUM kflag support */
|
||||
FEAT_BTF_ENUM64,
|
||||
/* Kernel uses syscall wrapper (CONFIG_ARCH_HAS_SYSCALL_WRAPPER) */
|
||||
FEAT_SYSCALL_WRAPPER,
|
||||
__FEAT_CNT,
|
||||
};
|
||||
|
||||
int probe_memcg_account(void);
|
||||
bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id);
|
||||
int bump_rlimit_memlock(void);
|
||||
|
||||
int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz);
|
||||
int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz);
|
||||
int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
|
||||
const char *str_sec, size_t str_len);
|
||||
int btf_load_into_kernel(struct btf *btf, char *log_buf, size_t log_sz, __u32 log_level);
|
||||
|
||||
struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf);
|
||||
void btf_get_kernel_prefix_kind(enum bpf_attach_type attach_type,
|
||||
const char **prefix, int *kind);
|
||||
|
||||
struct btf_ext_info {
|
||||
/*
|
||||
* info points to the individual info section (e.g. func_info and
|
||||
* line_info) from the .BTF.ext. It does not include the __u32 rec_size.
|
||||
*/
|
||||
void *info;
|
||||
__u32 rec_size;
|
||||
__u32 len;
|
||||
/* optional (maintained internally by libbpf) mapping between .BTF.ext
|
||||
* section and corresponding ELF section. This is used to join
|
||||
* information like CO-RE relocation records with corresponding BPF
|
||||
* programs defined in ELF sections
|
||||
*/
|
||||
__u32 *sec_idxs;
|
||||
int sec_cnt;
|
||||
};
|
||||
|
||||
#define for_each_btf_ext_sec(seg, sec) \
|
||||
for (sec = (seg)->info; \
|
||||
(void *)sec < (seg)->info + (seg)->len; \
|
||||
sec = (void *)sec + sizeof(struct btf_ext_info_sec) + \
|
||||
(seg)->rec_size * sec->num_info)
|
||||
|
||||
#define for_each_btf_ext_rec(seg, sec, i, rec) \
|
||||
for (i = 0, rec = (void *)&(sec)->data; \
|
||||
i < (sec)->num_info; \
|
||||
i++, rec = (void *)rec + (seg)->rec_size)
|
||||
|
||||
/*
|
||||
* The .BTF.ext ELF section layout defined as
|
||||
* struct btf_ext_header
|
||||
* func_info subsection
|
||||
*
|
||||
* The func_info subsection layout:
|
||||
* record size for struct bpf_func_info in the func_info subsection
|
||||
* struct btf_sec_func_info for section #1
|
||||
* a list of bpf_func_info records for section #1
|
||||
* where struct bpf_func_info mimics one in include/uapi/linux/bpf.h
|
||||
* but may not be identical
|
||||
* struct btf_sec_func_info for section #2
|
||||
* a list of bpf_func_info records for section #2
|
||||
* ......
|
||||
*
|
||||
* Note that the bpf_func_info record size in .BTF.ext may not
|
||||
* be the same as the one defined in include/uapi/linux/bpf.h.
|
||||
* The loader should ensure that record_size meets minimum
|
||||
* requirement and pass the record as is to the kernel. The
|
||||
* kernel will handle the func_info properly based on its contents.
|
||||
*/
|
||||
struct btf_ext_header {
|
||||
__u16 magic;
|
||||
__u8 version;
|
||||
__u8 flags;
|
||||
__u32 hdr_len;
|
||||
|
||||
/* All offsets are in bytes relative to the end of this header */
|
||||
__u32 func_info_off;
|
||||
__u32 func_info_len;
|
||||
__u32 line_info_off;
|
||||
__u32 line_info_len;
|
||||
|
||||
/* optional part of .BTF.ext header */
|
||||
__u32 core_relo_off;
|
||||
__u32 core_relo_len;
|
||||
};
|
||||
|
||||
struct btf_ext {
|
||||
union {
|
||||
struct btf_ext_header *hdr;
|
||||
void *data;
|
||||
};
|
||||
struct btf_ext_info func_info;
|
||||
struct btf_ext_info line_info;
|
||||
struct btf_ext_info core_relo_info;
|
||||
__u32 data_size;
|
||||
};
|
||||
|
||||
struct btf_ext_info_sec {
|
||||
__u32 sec_name_off;
|
||||
__u32 num_info;
|
||||
/* Followed by num_info * record_size number of bytes */
|
||||
__u8 data[];
|
||||
};
|
||||
|
||||
/* The minimum bpf_func_info checked by the loader */
|
||||
struct bpf_func_info_min {
|
||||
__u32 insn_off;
|
||||
__u32 type_id;
|
||||
};
|
||||
|
||||
/* The minimum bpf_line_info checked by the loader */
|
||||
struct bpf_line_info_min {
|
||||
__u32 insn_off;
|
||||
__u32 file_name_off;
|
||||
__u32 line_off;
|
||||
__u32 line_col;
|
||||
};
|
||||
|
||||
|
||||
typedef int (*type_id_visit_fn)(__u32 *type_id, void *ctx);
|
||||
typedef int (*str_off_visit_fn)(__u32 *str_off, void *ctx);
|
||||
int btf_type_visit_type_ids(struct btf_type *t, type_id_visit_fn visit, void *ctx);
|
||||
int btf_type_visit_str_offs(struct btf_type *t, str_off_visit_fn visit, void *ctx);
|
||||
int btf_ext_visit_type_ids(struct btf_ext *btf_ext, type_id_visit_fn visit, void *ctx);
|
||||
int btf_ext_visit_str_offs(struct btf_ext *btf_ext, str_off_visit_fn visit, void *ctx);
|
||||
__s32 btf__find_by_name_kind_own(const struct btf *btf, const char *type_name,
|
||||
__u32 kind);
|
||||
|
||||
typedef int (*kallsyms_cb_t)(unsigned long long sym_addr, char sym_type,
|
||||
const char *sym_name, void *ctx);
|
||||
|
||||
int libbpf_kallsyms_parse(kallsyms_cb_t cb, void *arg);
|
||||
|
||||
/* handle direct returned errors */
|
||||
static inline int libbpf_err(int ret)
|
||||
{
|
||||
if (ret < 0)
|
||||
errno = -ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* handle errno-based (e.g., syscall or libc) errors according to libbpf's
|
||||
* strict mode settings
|
||||
*/
|
||||
static inline int libbpf_err_errno(int ret)
|
||||
{
|
||||
/* errno is already assumed to be set on error */
|
||||
return ret < 0 ? -errno : ret;
|
||||
}
|
||||
|
||||
/* handle error for pointer-returning APIs, err is assumed to be < 0 always */
|
||||
static inline void *libbpf_err_ptr(int err)
|
||||
{
|
||||
/* set errno on error, this doesn't break anything */
|
||||
errno = -err;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* handle pointer-returning APIs' error handling */
|
||||
static inline void *libbpf_ptr(void *ret)
|
||||
{
|
||||
/* set errno on error, this doesn't break anything */
|
||||
if (IS_ERR(ret))
|
||||
errno = -PTR_ERR(ret);
|
||||
|
||||
return IS_ERR(ret) ? NULL : ret;
|
||||
}
|
||||
|
||||
static inline bool str_is_empty(const char *s)
|
||||
{
|
||||
return !s || !s[0];
|
||||
}
|
||||
|
||||
static inline bool is_ldimm64_insn(struct bpf_insn *insn)
|
||||
{
|
||||
return insn->code == (BPF_LD | BPF_IMM | BPF_DW);
|
||||
}
|
||||
|
||||
/* if fd is stdin, stdout, or stderr, dup to a fd greater than 2
|
||||
* Takes ownership of the fd passed in, and closes it if calling
|
||||
* fcntl(fd, F_DUPFD_CLOEXEC, 3).
|
||||
*/
|
||||
static inline int ensure_good_fd(int fd)
|
||||
{
|
||||
int old_fd = fd, saved_errno;
|
||||
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
if (fd < 3) {
|
||||
fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
|
||||
saved_errno = errno;
|
||||
close(old_fd);
|
||||
errno = saved_errno;
|
||||
if (fd < 0) {
|
||||
pr_warn("failed to dup FD %d to FD > 2: %d\n", old_fd, -saved_errno);
|
||||
errno = saved_errno;
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* The following two functions are exposed to bpftool */
|
||||
int bpf_core_add_cands(struct bpf_core_cand *local_cand,
|
||||
size_t local_essent_len,
|
||||
const struct btf *targ_btf,
|
||||
const char *targ_btf_name,
|
||||
int targ_start_id,
|
||||
struct bpf_core_cand_list *cands);
|
||||
void bpf_core_free_cands(struct bpf_core_cand_list *cands);
|
||||
|
||||
struct usdt_manager *usdt_manager_new(struct bpf_object *obj);
|
||||
void usdt_manager_free(struct usdt_manager *man);
|
||||
struct bpf_link * usdt_manager_attach_usdt(struct usdt_manager *man,
|
||||
const struct bpf_program *prog,
|
||||
pid_t pid, const char *path,
|
||||
const char *usdt_provider, const char *usdt_name,
|
||||
__u64 usdt_cookie);
|
||||
|
||||
static inline bool is_pow_of_2(size_t x)
|
||||
{
|
||||
return x && (x & (x - 1)) == 0;
|
||||
}
|
||||
|
||||
#define PROG_LOAD_ATTEMPTS 5
|
||||
int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts);
|
||||
|
||||
#endif /* __LIBBPF_LIBBPF_INTERNAL_H */
|
||||
140
third_party/libbpf/src/libbpf_legacy.h
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
|
||||
/*
|
||||
* Libbpf legacy APIs (either discouraged or deprecated, as mentioned in [0])
|
||||
*
|
||||
* [0] https://docs.google.com/document/d/1UyjTZuPFWiPFyKk1tV5an11_iaRuec6U-ZESZ54nNTY
|
||||
*
|
||||
* Copyright (C) 2021 Facebook
|
||||
*/
|
||||
#ifndef __LIBBPF_LEGACY_BPF_H
|
||||
#define __LIBBPF_LEGACY_BPF_H
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "libbpf_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* As of libbpf 1.0 libbpf_set_strict_mode() and enum libbpf_struct_mode have
|
||||
* no effect. But they are left in libbpf_legacy.h so that applications that
|
||||
* prepared for libbpf 1.0 before final release by using
|
||||
* libbpf_set_strict_mode() still work with libbpf 1.0+ without any changes.
|
||||
*/
|
||||
enum libbpf_strict_mode {
|
||||
/* Turn on all supported strict features of libbpf to simulate libbpf
|
||||
* v1.0 behavior.
|
||||
* This will be the default behavior in libbpf v1.0.
|
||||
*/
|
||||
LIBBPF_STRICT_ALL = 0xffffffff,
|
||||
|
||||
/*
|
||||
* Disable any libbpf 1.0 behaviors. This is the default before libbpf
|
||||
* v1.0. It won't be supported anymore in v1.0, please update your
|
||||
* code so that it handles LIBBPF_STRICT_ALL mode before libbpf v1.0.
|
||||
*/
|
||||
LIBBPF_STRICT_NONE = 0x00,
|
||||
/*
|
||||
* Return NULL pointers on error, not ERR_PTR(err).
|
||||
* Additionally, libbpf also always sets errno to corresponding Exx
|
||||
* (positive) error code.
|
||||
*/
|
||||
LIBBPF_STRICT_CLEAN_PTRS = 0x01,
|
||||
/*
|
||||
* Return actual error codes from low-level APIs directly, not just -1.
|
||||
* Additionally, libbpf also always sets errno to corresponding Exx
|
||||
* (positive) error code.
|
||||
*/
|
||||
LIBBPF_STRICT_DIRECT_ERRS = 0x02,
|
||||
/*
|
||||
* Enforce strict BPF program section (SEC()) names.
|
||||
* E.g., while prefiously SEC("xdp_whatever") or SEC("perf_event_blah") were
|
||||
* allowed, with LIBBPF_STRICT_SEC_PREFIX this will become
|
||||
* unrecognized by libbpf and would have to be just SEC("xdp") and
|
||||
* SEC("xdp") and SEC("perf_event").
|
||||
*
|
||||
* Note, in this mode the program pin path will be based on the
|
||||
* function name instead of section name.
|
||||
*
|
||||
* Additionally, routines in the .text section are always considered
|
||||
* sub-programs. Legacy behavior allows for a single routine in .text
|
||||
* to be a program.
|
||||
*/
|
||||
LIBBPF_STRICT_SEC_NAME = 0x04,
|
||||
/*
|
||||
* Disable the global 'bpf_objects_list'. Maintaining this list adds
|
||||
* a race condition to bpf_object__open() and bpf_object__close().
|
||||
* Clients can maintain it on their own if it is valuable for them.
|
||||
*/
|
||||
LIBBPF_STRICT_NO_OBJECT_LIST = 0x08,
|
||||
/*
|
||||
* Automatically bump RLIMIT_MEMLOCK using setrlimit() before the
|
||||
* first BPF program or map creation operation. This is done only if
|
||||
* kernel is too old to support memcg-based memory accounting for BPF
|
||||
* subsystem. By default, RLIMIT_MEMLOCK limit is set to RLIM_INFINITY,
|
||||
* but it can be overriden with libbpf_set_memlock_rlim() API.
|
||||
* Note that libbpf_set_memlock_rlim() needs to be called before
|
||||
* the very first bpf_prog_load(), bpf_map_create() or bpf_object__load()
|
||||
* operation.
|
||||
*/
|
||||
LIBBPF_STRICT_AUTO_RLIMIT_MEMLOCK = 0x10,
|
||||
/*
|
||||
* Error out on any SEC("maps") map definition, which are deprecated
|
||||
* in favor of BTF-defined map definitions in SEC(".maps").
|
||||
*/
|
||||
LIBBPF_STRICT_MAP_DEFINITIONS = 0x20,
|
||||
|
||||
__LIBBPF_STRICT_LAST,
|
||||
};
|
||||
|
||||
LIBBPF_API int libbpf_set_strict_mode(enum libbpf_strict_mode mode);
|
||||
|
||||
/**
|
||||
* @brief **libbpf_get_error()** extracts the error code from the passed
|
||||
* pointer
|
||||
* @param ptr pointer returned from libbpf API function
|
||||
* @return error code; or 0 if no error occured
|
||||
*
|
||||
* Note, as of libbpf 1.0 this function is not necessary and not recommended
|
||||
* to be used. Libbpf doesn't return error code embedded into the pointer
|
||||
* itself. Instead, NULL is returned on error and error code is passed through
|
||||
* thread-local errno variable. **libbpf_get_error()** is just returning -errno
|
||||
* value if it receives NULL, which is correct only if errno hasn't been
|
||||
* modified between libbpf API call and corresponding **libbpf_get_error()**
|
||||
* call. Prefer to check return for NULL and use errno directly.
|
||||
*
|
||||
* This API is left in libbpf 1.0 to allow applications that were 1.0-ready
|
||||
* before final libbpf 1.0 without needing to change them.
|
||||
*/
|
||||
LIBBPF_API long libbpf_get_error(const void *ptr);
|
||||
|
||||
#define DECLARE_LIBBPF_OPTS LIBBPF_OPTS
|
||||
|
||||
/* "Discouraged" APIs which don't follow consistent libbpf naming patterns.
|
||||
* They are normally a trivial aliases or wrappers for proper APIs and are
|
||||
* left to minimize unnecessary disruption for users of libbpf. But they
|
||||
* shouldn't be used going forward.
|
||||
*/
|
||||
|
||||
struct bpf_program;
|
||||
struct bpf_map;
|
||||
struct btf;
|
||||
struct btf_ext;
|
||||
|
||||
LIBBPF_API struct btf *libbpf_find_kernel_btf(void);
|
||||
|
||||
LIBBPF_API enum bpf_prog_type bpf_program__get_type(const struct bpf_program *prog);
|
||||
LIBBPF_API enum bpf_attach_type bpf_program__get_expected_attach_type(const struct bpf_program *prog);
|
||||
LIBBPF_API const char *bpf_map__get_pin_path(const struct bpf_map *map);
|
||||
LIBBPF_API const void *btf__get_raw_data(const struct btf *btf, __u32 *size);
|
||||
LIBBPF_API const void *btf_ext__get_raw_data(const struct btf_ext *btf_ext, __u32 *size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __LIBBPF_LEGACY_BPF_H */
|
||||
450
third_party/libbpf/src/libbpf_probes.c
vendored
Normal file
@@ -0,0 +1,450 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
/* Copyright (c) 2019 Netronome Systems, Inc. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <linux/btf.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "bpf.h"
|
||||
#include "libbpf.h"
|
||||
#include "libbpf_internal.h"
|
||||
|
||||
/* On Ubuntu LINUX_VERSION_CODE doesn't correspond to info.release,
|
||||
* but Ubuntu provides /proc/version_signature file, as described at
|
||||
* https://ubuntu.com/kernel, with an example contents below, which we
|
||||
* can use to get a proper LINUX_VERSION_CODE.
|
||||
*
|
||||
* Ubuntu 5.4.0-12.15-generic 5.4.8
|
||||
*
|
||||
* In the above, 5.4.8 is what kernel is actually expecting, while
|
||||
* uname() call will return 5.4.0 in info.release.
|
||||
*/
|
||||
static __u32 get_ubuntu_kernel_version(void)
|
||||
{
|
||||
const char *ubuntu_kver_file = "/proc/version_signature";
|
||||
__u32 major, minor, patch;
|
||||
int ret;
|
||||
FILE *f;
|
||||
|
||||
if (faccessat(AT_FDCWD, ubuntu_kver_file, R_OK, AT_EACCESS) != 0)
|
||||
return 0;
|
||||
|
||||
f = fopen(ubuntu_kver_file, "re");
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
ret = fscanf(f, "%*s %*s %u.%u.%u\n", &major, &minor, &patch);
|
||||
fclose(f);
|
||||
if (ret != 3)
|
||||
return 0;
|
||||
|
||||
return KERNEL_VERSION(major, minor, patch);
|
||||
}
|
||||
|
||||
/* On Debian LINUX_VERSION_CODE doesn't correspond to info.release.
|
||||
* Instead, it is provided in info.version. An example content of
|
||||
* Debian 10 looks like the below.
|
||||
*
|
||||
* utsname::release 4.19.0-22-amd64
|
||||
* utsname::version #1 SMP Debian 4.19.260-1 (2022-09-29)
|
||||
*
|
||||
* In the above, 4.19.260 is what kernel is actually expecting, while
|
||||
* uname() call will return 4.19.0 in info.release.
|
||||
*/
|
||||
static __u32 get_debian_kernel_version(struct utsname *info)
|
||||
{
|
||||
__u32 major, minor, patch;
|
||||
char *p;
|
||||
|
||||
p = strstr(info->version, "Debian ");
|
||||
if (!p) {
|
||||
/* This is not a Debian kernel. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sscanf(p, "Debian %u.%u.%u", &major, &minor, &patch) != 3)
|
||||
return 0;
|
||||
|
||||
return KERNEL_VERSION(major, minor, patch);
|
||||
}
|
||||
|
||||
__u32 get_kernel_version(void)
|
||||
{
|
||||
__u32 major, minor, patch, version;
|
||||
struct utsname info;
|
||||
|
||||
/* Check if this is an Ubuntu kernel. */
|
||||
version = get_ubuntu_kernel_version();
|
||||
if (version != 0)
|
||||
return version;
|
||||
|
||||
uname(&info);
|
||||
|
||||
/* Check if this is a Debian kernel. */
|
||||
version = get_debian_kernel_version(&info);
|
||||
if (version != 0)
|
||||
return version;
|
||||
|
||||
if (sscanf(info.release, "%u.%u.%u", &major, &minor, &patch) != 3)
|
||||
return 0;
|
||||
|
||||
return KERNEL_VERSION(major, minor, patch);
|
||||
}
|
||||
|
||||
static int probe_prog_load(enum bpf_prog_type prog_type,
|
||||
const struct bpf_insn *insns, size_t insns_cnt,
|
||||
char *log_buf, size_t log_buf_sz)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_prog_load_opts, opts,
|
||||
.log_buf = log_buf,
|
||||
.log_size = log_buf_sz,
|
||||
.log_level = log_buf ? 1 : 0,
|
||||
);
|
||||
int fd, err, exp_err = 0;
|
||||
const char *exp_msg = NULL;
|
||||
char buf[4096];
|
||||
|
||||
switch (prog_type) {
|
||||
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
|
||||
opts.expected_attach_type = BPF_CGROUP_INET4_CONNECT;
|
||||
break;
|
||||
case BPF_PROG_TYPE_CGROUP_SOCKOPT:
|
||||
opts.expected_attach_type = BPF_CGROUP_GETSOCKOPT;
|
||||
break;
|
||||
case BPF_PROG_TYPE_SK_LOOKUP:
|
||||
opts.expected_attach_type = BPF_SK_LOOKUP;
|
||||
break;
|
||||
case BPF_PROG_TYPE_KPROBE:
|
||||
opts.kern_version = get_kernel_version();
|
||||
break;
|
||||
case BPF_PROG_TYPE_LIRC_MODE2:
|
||||
opts.expected_attach_type = BPF_LIRC_MODE2;
|
||||
break;
|
||||
case BPF_PROG_TYPE_TRACING:
|
||||
case BPF_PROG_TYPE_LSM:
|
||||
opts.log_buf = buf;
|
||||
opts.log_size = sizeof(buf);
|
||||
opts.log_level = 1;
|
||||
if (prog_type == BPF_PROG_TYPE_TRACING)
|
||||
opts.expected_attach_type = BPF_TRACE_FENTRY;
|
||||
else
|
||||
opts.expected_attach_type = BPF_MODIFY_RETURN;
|
||||
opts.attach_btf_id = 1;
|
||||
|
||||
exp_err = -EINVAL;
|
||||
exp_msg = "attach_btf_id 1 is not a function";
|
||||
break;
|
||||
case BPF_PROG_TYPE_EXT:
|
||||
opts.log_buf = buf;
|
||||
opts.log_size = sizeof(buf);
|
||||
opts.log_level = 1;
|
||||
opts.attach_btf_id = 1;
|
||||
|
||||
exp_err = -EINVAL;
|
||||
exp_msg = "Cannot replace kernel functions";
|
||||
break;
|
||||
case BPF_PROG_TYPE_SYSCALL:
|
||||
opts.prog_flags = BPF_F_SLEEPABLE;
|
||||
break;
|
||||
case BPF_PROG_TYPE_STRUCT_OPS:
|
||||
exp_err = -524; /* -ENOTSUPP */
|
||||
break;
|
||||
case BPF_PROG_TYPE_UNSPEC:
|
||||
case BPF_PROG_TYPE_SOCKET_FILTER:
|
||||
case BPF_PROG_TYPE_SCHED_CLS:
|
||||
case BPF_PROG_TYPE_SCHED_ACT:
|
||||
case BPF_PROG_TYPE_TRACEPOINT:
|
||||
case BPF_PROG_TYPE_XDP:
|
||||
case BPF_PROG_TYPE_PERF_EVENT:
|
||||
case BPF_PROG_TYPE_CGROUP_SKB:
|
||||
case BPF_PROG_TYPE_CGROUP_SOCK:
|
||||
case BPF_PROG_TYPE_LWT_IN:
|
||||
case BPF_PROG_TYPE_LWT_OUT:
|
||||
case BPF_PROG_TYPE_LWT_XMIT:
|
||||
case BPF_PROG_TYPE_SOCK_OPS:
|
||||
case BPF_PROG_TYPE_SK_SKB:
|
||||
case BPF_PROG_TYPE_CGROUP_DEVICE:
|
||||
case BPF_PROG_TYPE_SK_MSG:
|
||||
case BPF_PROG_TYPE_RAW_TRACEPOINT:
|
||||
case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
|
||||
case BPF_PROG_TYPE_LWT_SEG6LOCAL:
|
||||
case BPF_PROG_TYPE_SK_REUSEPORT:
|
||||
case BPF_PROG_TYPE_FLOW_DISSECTOR:
|
||||
case BPF_PROG_TYPE_CGROUP_SYSCTL:
|
||||
break;
|
||||
case BPF_PROG_TYPE_NETFILTER:
|
||||
opts.expected_attach_type = BPF_NETFILTER;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
fd = bpf_prog_load(prog_type, NULL, "GPL", insns, insns_cnt, &opts);
|
||||
err = -errno;
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
if (exp_err) {
|
||||
if (fd >= 0 || err != exp_err)
|
||||
return 0;
|
||||
if (exp_msg && !strstr(buf, exp_msg))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
return fd >= 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
int libbpf_probe_bpf_prog_type(enum bpf_prog_type prog_type, const void *opts)
|
||||
{
|
||||
struct bpf_insn insns[] = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_EXIT_INSN()
|
||||
};
|
||||
const size_t insn_cnt = ARRAY_SIZE(insns);
|
||||
int ret;
|
||||
|
||||
if (opts)
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
ret = probe_prog_load(prog_type, insns, insn_cnt, NULL, 0);
|
||||
return libbpf_err(ret);
|
||||
}
|
||||
|
||||
int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
|
||||
const char *str_sec, size_t str_len)
|
||||
{
|
||||
struct btf_header hdr = {
|
||||
.magic = BTF_MAGIC,
|
||||
.version = BTF_VERSION,
|
||||
.hdr_len = sizeof(struct btf_header),
|
||||
.type_len = types_len,
|
||||
.str_off = types_len,
|
||||
.str_len = str_len,
|
||||
};
|
||||
int btf_fd, btf_len;
|
||||
__u8 *raw_btf;
|
||||
|
||||
btf_len = hdr.hdr_len + hdr.type_len + hdr.str_len;
|
||||
raw_btf = malloc(btf_len);
|
||||
if (!raw_btf)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(raw_btf, &hdr, sizeof(hdr));
|
||||
memcpy(raw_btf + hdr.hdr_len, raw_types, hdr.type_len);
|
||||
memcpy(raw_btf + hdr.hdr_len + hdr.type_len, str_sec, hdr.str_len);
|
||||
|
||||
btf_fd = bpf_btf_load(raw_btf, btf_len, NULL);
|
||||
|
||||
free(raw_btf);
|
||||
return btf_fd;
|
||||
}
|
||||
|
||||
static int load_local_storage_btf(void)
|
||||
{
|
||||
const char strs[] = "\0bpf_spin_lock\0val\0cnt\0l";
|
||||
/* struct bpf_spin_lock {
|
||||
* int val;
|
||||
* };
|
||||
* struct val {
|
||||
* int cnt;
|
||||
* struct bpf_spin_lock l;
|
||||
* };
|
||||
*/
|
||||
__u32 types[] = {
|
||||
/* int */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
|
||||
/* struct bpf_spin_lock */ /* [2] */
|
||||
BTF_TYPE_ENC(1, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 4),
|
||||
BTF_MEMBER_ENC(15, 1, 0), /* int val; */
|
||||
/* struct val */ /* [3] */
|
||||
BTF_TYPE_ENC(15, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
|
||||
BTF_MEMBER_ENC(19, 1, 0), /* int cnt; */
|
||||
BTF_MEMBER_ENC(23, 2, 32),/* struct bpf_spin_lock l; */
|
||||
};
|
||||
|
||||
return libbpf__load_raw_btf((char *)types, sizeof(types),
|
||||
strs, sizeof(strs));
|
||||
}
|
||||
|
||||
static int probe_map_create(enum bpf_map_type map_type)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_map_create_opts, opts);
|
||||
int key_size, value_size, max_entries;
|
||||
__u32 btf_key_type_id = 0, btf_value_type_id = 0;
|
||||
int fd = -1, btf_fd = -1, fd_inner = -1, exp_err = 0, err = 0;
|
||||
|
||||
key_size = sizeof(__u32);
|
||||
value_size = sizeof(__u32);
|
||||
max_entries = 1;
|
||||
|
||||
switch (map_type) {
|
||||
case BPF_MAP_TYPE_STACK_TRACE:
|
||||
value_size = sizeof(__u64);
|
||||
break;
|
||||
case BPF_MAP_TYPE_LPM_TRIE:
|
||||
key_size = sizeof(__u64);
|
||||
value_size = sizeof(__u64);
|
||||
opts.map_flags = BPF_F_NO_PREALLOC;
|
||||
break;
|
||||
case BPF_MAP_TYPE_CGROUP_STORAGE:
|
||||
case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE:
|
||||
key_size = sizeof(struct bpf_cgroup_storage_key);
|
||||
value_size = sizeof(__u64);
|
||||
max_entries = 0;
|
||||
break;
|
||||
case BPF_MAP_TYPE_QUEUE:
|
||||
case BPF_MAP_TYPE_STACK:
|
||||
key_size = 0;
|
||||
break;
|
||||
case BPF_MAP_TYPE_SK_STORAGE:
|
||||
case BPF_MAP_TYPE_INODE_STORAGE:
|
||||
case BPF_MAP_TYPE_TASK_STORAGE:
|
||||
case BPF_MAP_TYPE_CGRP_STORAGE:
|
||||
btf_key_type_id = 1;
|
||||
btf_value_type_id = 3;
|
||||
value_size = 8;
|
||||
max_entries = 0;
|
||||
opts.map_flags = BPF_F_NO_PREALLOC;
|
||||
btf_fd = load_local_storage_btf();
|
||||
if (btf_fd < 0)
|
||||
return btf_fd;
|
||||
break;
|
||||
case BPF_MAP_TYPE_RINGBUF:
|
||||
case BPF_MAP_TYPE_USER_RINGBUF:
|
||||
key_size = 0;
|
||||
value_size = 0;
|
||||
max_entries = sysconf(_SC_PAGE_SIZE);
|
||||
break;
|
||||
case BPF_MAP_TYPE_STRUCT_OPS:
|
||||
/* we'll get -ENOTSUPP for invalid BTF type ID for struct_ops */
|
||||
opts.btf_vmlinux_value_type_id = 1;
|
||||
exp_err = -524; /* -ENOTSUPP */
|
||||
break;
|
||||
case BPF_MAP_TYPE_BLOOM_FILTER:
|
||||
key_size = 0;
|
||||
max_entries = 1;
|
||||
break;
|
||||
case BPF_MAP_TYPE_HASH:
|
||||
case BPF_MAP_TYPE_ARRAY:
|
||||
case BPF_MAP_TYPE_PROG_ARRAY:
|
||||
case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
|
||||
case BPF_MAP_TYPE_PERCPU_HASH:
|
||||
case BPF_MAP_TYPE_PERCPU_ARRAY:
|
||||
case BPF_MAP_TYPE_CGROUP_ARRAY:
|
||||
case BPF_MAP_TYPE_LRU_HASH:
|
||||
case BPF_MAP_TYPE_LRU_PERCPU_HASH:
|
||||
case BPF_MAP_TYPE_ARRAY_OF_MAPS:
|
||||
case BPF_MAP_TYPE_HASH_OF_MAPS:
|
||||
case BPF_MAP_TYPE_DEVMAP:
|
||||
case BPF_MAP_TYPE_DEVMAP_HASH:
|
||||
case BPF_MAP_TYPE_SOCKMAP:
|
||||
case BPF_MAP_TYPE_CPUMAP:
|
||||
case BPF_MAP_TYPE_XSKMAP:
|
||||
case BPF_MAP_TYPE_SOCKHASH:
|
||||
case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
|
||||
break;
|
||||
case BPF_MAP_TYPE_UNSPEC:
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
|
||||
map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
|
||||
fd_inner = bpf_map_create(BPF_MAP_TYPE_HASH, NULL,
|
||||
sizeof(__u32), sizeof(__u32), 1, NULL);
|
||||
if (fd_inner < 0)
|
||||
goto cleanup;
|
||||
|
||||
opts.inner_map_fd = fd_inner;
|
||||
}
|
||||
|
||||
if (btf_fd >= 0) {
|
||||
opts.btf_fd = btf_fd;
|
||||
opts.btf_key_type_id = btf_key_type_id;
|
||||
opts.btf_value_type_id = btf_value_type_id;
|
||||
}
|
||||
|
||||
fd = bpf_map_create(map_type, NULL, key_size, value_size, max_entries, &opts);
|
||||
err = -errno;
|
||||
|
||||
cleanup:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
if (fd_inner >= 0)
|
||||
close(fd_inner);
|
||||
if (btf_fd >= 0)
|
||||
close(btf_fd);
|
||||
|
||||
if (exp_err)
|
||||
return fd < 0 && err == exp_err ? 1 : 0;
|
||||
else
|
||||
return fd >= 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
int libbpf_probe_bpf_map_type(enum bpf_map_type map_type, const void *opts)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (opts)
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
ret = probe_map_create(map_type);
|
||||
return libbpf_err(ret);
|
||||
}
|
||||
|
||||
int libbpf_probe_bpf_helper(enum bpf_prog_type prog_type, enum bpf_func_id helper_id,
|
||||
const void *opts)
|
||||
{
|
||||
struct bpf_insn insns[] = {
|
||||
BPF_EMIT_CALL((__u32)helper_id),
|
||||
BPF_EXIT_INSN(),
|
||||
};
|
||||
const size_t insn_cnt = ARRAY_SIZE(insns);
|
||||
char buf[4096];
|
||||
int ret;
|
||||
|
||||
if (opts)
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
/* we can't successfully load all prog types to check for BPF helper
|
||||
* support, so bail out with -EOPNOTSUPP error
|
||||
*/
|
||||
switch (prog_type) {
|
||||
case BPF_PROG_TYPE_TRACING:
|
||||
case BPF_PROG_TYPE_EXT:
|
||||
case BPF_PROG_TYPE_LSM:
|
||||
case BPF_PROG_TYPE_STRUCT_OPS:
|
||||
return -EOPNOTSUPP;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
buf[0] = '\0';
|
||||
ret = probe_prog_load(prog_type, insns, insn_cnt, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
return libbpf_err(ret);
|
||||
|
||||
/* If BPF verifier doesn't recognize BPF helper ID (enum bpf_func_id)
|
||||
* at all, it will emit something like "invalid func unknown#181".
|
||||
* If BPF verifier recognizes BPF helper but it's not supported for
|
||||
* given BPF program type, it will emit "unknown func bpf_sys_bpf#166".
|
||||
* In both cases, provided combination of BPF program type and BPF
|
||||
* helper is not supported by the kernel.
|
||||
* In all other cases, probe_prog_load() above will either succeed (e.g.,
|
||||
* because BPF helper happens to accept no input arguments or it
|
||||
* accepts one input argument and initial PTR_TO_CTX is fine for
|
||||
* that), or we'll get some more specific BPF verifier error about
|
||||
* some unsatisfied conditions.
|
||||
*/
|
||||
if (ret == 0 && (strstr(buf, "invalid func ") || strstr(buf, "unknown func ")))
|
||||
return 0;
|
||||
return 1; /* assume supported */
|
||||
}
|
||||
9
third_party/libbpf/src/libbpf_version.h
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
/* Copyright (C) 2021 Facebook */
|
||||
#ifndef __LIBBPF_VERSION_H
|
||||
#define __LIBBPF_VERSION_H
|
||||
|
||||
#define LIBBPF_MAJOR_VERSION 1
|
||||
#define LIBBPF_MINOR_VERSION 3
|
||||
|
||||
#endif /* __LIBBPF_VERSION_H */
|
||||
2905
third_party/libbpf/src/linker.c
vendored
Normal file
917
third_party/libbpf/src/netlink.c
vendored
Normal file
@@ -0,0 +1,917 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
/* Copyright (c) 2018 Facebook */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/pkt_cls.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/netdev.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "bpf.h"
|
||||
#include "libbpf.h"
|
||||
#include "libbpf_internal.h"
|
||||
#include "nlattr.h"
|
||||
|
||||
#ifndef SOL_NETLINK
|
||||
#define SOL_NETLINK 270
|
||||
#endif
|
||||
|
||||
typedef int (*libbpf_dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb);
|
||||
|
||||
typedef int (*__dump_nlmsg_t)(struct nlmsghdr *nlmsg, libbpf_dump_nlmsg_t,
|
||||
void *cookie);
|
||||
|
||||
struct xdp_link_info {
|
||||
__u32 prog_id;
|
||||
__u32 drv_prog_id;
|
||||
__u32 hw_prog_id;
|
||||
__u32 skb_prog_id;
|
||||
__u8 attach_mode;
|
||||
};
|
||||
|
||||
struct xdp_id_md {
|
||||
int ifindex;
|
||||
__u32 flags;
|
||||
struct xdp_link_info info;
|
||||
__u64 feature_flags;
|
||||
};
|
||||
|
||||
struct xdp_features_md {
|
||||
int ifindex;
|
||||
__u64 flags;
|
||||
};
|
||||
|
||||
static int libbpf_netlink_open(__u32 *nl_pid, int proto)
|
||||
{
|
||||
struct sockaddr_nl sa;
|
||||
socklen_t addrlen;
|
||||
int one = 1, ret;
|
||||
int sock;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.nl_family = AF_NETLINK;
|
||||
|
||||
sock = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, proto);
|
||||
if (sock < 0)
|
||||
return -errno;
|
||||
|
||||
if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK,
|
||||
&one, sizeof(one)) < 0) {
|
||||
pr_warn("Netlink error reporting not supported\n");
|
||||
}
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
|
||||
ret = -errno;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
addrlen = sizeof(sa);
|
||||
if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) {
|
||||
ret = -errno;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (addrlen != sizeof(sa)) {
|
||||
ret = -LIBBPF_ERRNO__INTERNAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*nl_pid = sa.nl_pid;
|
||||
return sock;
|
||||
|
||||
cleanup:
|
||||
close(sock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void libbpf_netlink_close(int sock)
|
||||
{
|
||||
close(sock);
|
||||
}
|
||||
|
||||
enum {
|
||||
NL_CONT,
|
||||
NL_NEXT,
|
||||
NL_DONE,
|
||||
};
|
||||
|
||||
static int netlink_recvmsg(int sock, struct msghdr *mhdr, int flags)
|
||||
{
|
||||
int len;
|
||||
|
||||
do {
|
||||
len = recvmsg(sock, mhdr, flags);
|
||||
} while (len < 0 && (errno == EINTR || errno == EAGAIN));
|
||||
|
||||
if (len < 0)
|
||||
return -errno;
|
||||
return len;
|
||||
}
|
||||
|
||||
static int alloc_iov(struct iovec *iov, int len)
|
||||
{
|
||||
void *nbuf;
|
||||
|
||||
nbuf = realloc(iov->iov_base, len);
|
||||
if (!nbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
iov->iov_base = nbuf;
|
||||
iov->iov_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libbpf_netlink_recv(int sock, __u32 nl_pid, int seq,
|
||||
__dump_nlmsg_t _fn, libbpf_dump_nlmsg_t fn,
|
||||
void *cookie)
|
||||
{
|
||||
struct iovec iov = {};
|
||||
struct msghdr mhdr = {
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
};
|
||||
bool multipart = true;
|
||||
struct nlmsgerr *err;
|
||||
struct nlmsghdr *nh;
|
||||
int len, ret;
|
||||
|
||||
ret = alloc_iov(&iov, 4096);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
while (multipart) {
|
||||
start:
|
||||
multipart = false;
|
||||
len = netlink_recvmsg(sock, &mhdr, MSG_PEEK | MSG_TRUNC);
|
||||
if (len < 0) {
|
||||
ret = len;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (len > iov.iov_len) {
|
||||
ret = alloc_iov(&iov, len);
|
||||
if (ret)
|
||||
goto done;
|
||||
}
|
||||
|
||||
len = netlink_recvmsg(sock, &mhdr, 0);
|
||||
if (len < 0) {
|
||||
ret = len;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (len == 0)
|
||||
break;
|
||||
|
||||
for (nh = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(nh, len);
|
||||
nh = NLMSG_NEXT(nh, len)) {
|
||||
if (nh->nlmsg_pid != nl_pid) {
|
||||
ret = -LIBBPF_ERRNO__WRNGPID;
|
||||
goto done;
|
||||
}
|
||||
if (nh->nlmsg_seq != seq) {
|
||||
ret = -LIBBPF_ERRNO__INVSEQ;
|
||||
goto done;
|
||||
}
|
||||
if (nh->nlmsg_flags & NLM_F_MULTI)
|
||||
multipart = true;
|
||||
switch (nh->nlmsg_type) {
|
||||
case NLMSG_ERROR:
|
||||
err = (struct nlmsgerr *)NLMSG_DATA(nh);
|
||||
if (!err->error)
|
||||
continue;
|
||||
ret = err->error;
|
||||
libbpf_nla_dump_errormsg(nh);
|
||||
goto done;
|
||||
case NLMSG_DONE:
|
||||
ret = 0;
|
||||
goto done;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (_fn) {
|
||||
ret = _fn(nh, fn, cookie);
|
||||
switch (ret) {
|
||||
case NL_CONT:
|
||||
break;
|
||||
case NL_NEXT:
|
||||
goto start;
|
||||
case NL_DONE:
|
||||
ret = 0;
|
||||
goto done;
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
done:
|
||||
free(iov.iov_base);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int libbpf_netlink_send_recv(struct libbpf_nla_req *req,
|
||||
int proto, __dump_nlmsg_t parse_msg,
|
||||
libbpf_dump_nlmsg_t parse_attr,
|
||||
void *cookie)
|
||||
{
|
||||
__u32 nl_pid = 0;
|
||||
int sock, ret;
|
||||
|
||||
sock = libbpf_netlink_open(&nl_pid, proto);
|
||||
if (sock < 0)
|
||||
return sock;
|
||||
|
||||
req->nh.nlmsg_pid = 0;
|
||||
req->nh.nlmsg_seq = time(NULL);
|
||||
|
||||
if (send(sock, req, req->nh.nlmsg_len, 0) < 0) {
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = libbpf_netlink_recv(sock, nl_pid, req->nh.nlmsg_seq,
|
||||
parse_msg, parse_attr, cookie);
|
||||
out:
|
||||
libbpf_netlink_close(sock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int parse_genl_family_id(struct nlmsghdr *nh, libbpf_dump_nlmsg_t fn,
|
||||
void *cookie)
|
||||
{
|
||||
struct genlmsghdr *gnl = NLMSG_DATA(nh);
|
||||
struct nlattr *na = (struct nlattr *)((void *)gnl + GENL_HDRLEN);
|
||||
struct nlattr *tb[CTRL_ATTR_FAMILY_ID + 1];
|
||||
__u16 *id = cookie;
|
||||
|
||||
libbpf_nla_parse(tb, CTRL_ATTR_FAMILY_ID, na,
|
||||
NLMSG_PAYLOAD(nh, sizeof(*gnl)), NULL);
|
||||
if (!tb[CTRL_ATTR_FAMILY_ID])
|
||||
return NL_CONT;
|
||||
|
||||
*id = libbpf_nla_getattr_u16(tb[CTRL_ATTR_FAMILY_ID]);
|
||||
return NL_DONE;
|
||||
}
|
||||
|
||||
static int libbpf_netlink_resolve_genl_family_id(const char *name,
|
||||
__u16 len, __u16 *id)
|
||||
{
|
||||
struct libbpf_nla_req req = {
|
||||
.nh.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN),
|
||||
.nh.nlmsg_type = GENL_ID_CTRL,
|
||||
.nh.nlmsg_flags = NLM_F_REQUEST,
|
||||
.gnl.cmd = CTRL_CMD_GETFAMILY,
|
||||
.gnl.version = 2,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = nlattr_add(&req, CTRL_ATTR_FAMILY_NAME, name, len);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return libbpf_netlink_send_recv(&req, NETLINK_GENERIC,
|
||||
parse_genl_family_id, NULL, id);
|
||||
}
|
||||
|
||||
static int __bpf_set_link_xdp_fd_replace(int ifindex, int fd, int old_fd,
|
||||
__u32 flags)
|
||||
{
|
||||
struct nlattr *nla;
|
||||
int ret;
|
||||
struct libbpf_nla_req req;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
req.nh.nlmsg_type = RTM_SETLINK;
|
||||
req.ifinfo.ifi_family = AF_UNSPEC;
|
||||
req.ifinfo.ifi_index = ifindex;
|
||||
|
||||
nla = nlattr_begin_nested(&req, IFLA_XDP);
|
||||
if (!nla)
|
||||
return -EMSGSIZE;
|
||||
ret = nlattr_add(&req, IFLA_XDP_FD, &fd, sizeof(fd));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (flags) {
|
||||
ret = nlattr_add(&req, IFLA_XDP_FLAGS, &flags, sizeof(flags));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
if (flags & XDP_FLAGS_REPLACE) {
|
||||
ret = nlattr_add(&req, IFLA_XDP_EXPECTED_FD, &old_fd,
|
||||
sizeof(old_fd));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
nlattr_end_nested(&req, nla);
|
||||
|
||||
return libbpf_netlink_send_recv(&req, NETLINK_ROUTE, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
int bpf_xdp_attach(int ifindex, int prog_fd, __u32 flags, const struct bpf_xdp_attach_opts *opts)
|
||||
{
|
||||
int old_prog_fd, err;
|
||||
|
||||
if (!OPTS_VALID(opts, bpf_xdp_attach_opts))
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);
|
||||
if (old_prog_fd)
|
||||
flags |= XDP_FLAGS_REPLACE;
|
||||
else
|
||||
old_prog_fd = -1;
|
||||
|
||||
err = __bpf_set_link_xdp_fd_replace(ifindex, prog_fd, old_prog_fd, flags);
|
||||
return libbpf_err(err);
|
||||
}
|
||||
|
||||
int bpf_xdp_detach(int ifindex, __u32 flags, const struct bpf_xdp_attach_opts *opts)
|
||||
{
|
||||
return bpf_xdp_attach(ifindex, -1, flags, opts);
|
||||
}
|
||||
|
||||
static int __dump_link_nlmsg(struct nlmsghdr *nlh,
|
||||
libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie)
|
||||
{
|
||||
struct nlattr *tb[IFLA_MAX + 1], *attr;
|
||||
struct ifinfomsg *ifi = NLMSG_DATA(nlh);
|
||||
int len;
|
||||
|
||||
len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
|
||||
attr = (struct nlattr *) ((void *) ifi + NLMSG_ALIGN(sizeof(*ifi)));
|
||||
|
||||
if (libbpf_nla_parse(tb, IFLA_MAX, attr, len, NULL) != 0)
|
||||
return -LIBBPF_ERRNO__NLPARSE;
|
||||
|
||||
return dump_link_nlmsg(cookie, ifi, tb);
|
||||
}
|
||||
|
||||
static int get_xdp_info(void *cookie, void *msg, struct nlattr **tb)
|
||||
{
|
||||
struct nlattr *xdp_tb[IFLA_XDP_MAX + 1];
|
||||
struct xdp_id_md *xdp_id = cookie;
|
||||
struct ifinfomsg *ifinfo = msg;
|
||||
int ret;
|
||||
|
||||
if (xdp_id->ifindex && xdp_id->ifindex != ifinfo->ifi_index)
|
||||
return 0;
|
||||
|
||||
if (!tb[IFLA_XDP])
|
||||
return 0;
|
||||
|
||||
ret = libbpf_nla_parse_nested(xdp_tb, IFLA_XDP_MAX, tb[IFLA_XDP], NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!xdp_tb[IFLA_XDP_ATTACHED])
|
||||
return 0;
|
||||
|
||||
xdp_id->info.attach_mode = libbpf_nla_getattr_u8(
|
||||
xdp_tb[IFLA_XDP_ATTACHED]);
|
||||
|
||||
if (xdp_id->info.attach_mode == XDP_ATTACHED_NONE)
|
||||
return 0;
|
||||
|
||||
if (xdp_tb[IFLA_XDP_PROG_ID])
|
||||
xdp_id->info.prog_id = libbpf_nla_getattr_u32(
|
||||
xdp_tb[IFLA_XDP_PROG_ID]);
|
||||
|
||||
if (xdp_tb[IFLA_XDP_SKB_PROG_ID])
|
||||
xdp_id->info.skb_prog_id = libbpf_nla_getattr_u32(
|
||||
xdp_tb[IFLA_XDP_SKB_PROG_ID]);
|
||||
|
||||
if (xdp_tb[IFLA_XDP_DRV_PROG_ID])
|
||||
xdp_id->info.drv_prog_id = libbpf_nla_getattr_u32(
|
||||
xdp_tb[IFLA_XDP_DRV_PROG_ID]);
|
||||
|
||||
if (xdp_tb[IFLA_XDP_HW_PROG_ID])
|
||||
xdp_id->info.hw_prog_id = libbpf_nla_getattr_u32(
|
||||
xdp_tb[IFLA_XDP_HW_PROG_ID]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_xdp_features(struct nlmsghdr *nh, libbpf_dump_nlmsg_t fn,
|
||||
void *cookie)
|
||||
{
|
||||
struct genlmsghdr *gnl = NLMSG_DATA(nh);
|
||||
struct nlattr *na = (struct nlattr *)((void *)gnl + GENL_HDRLEN);
|
||||
struct nlattr *tb[NETDEV_CMD_MAX + 1];
|
||||
struct xdp_features_md *md = cookie;
|
||||
__u32 ifindex;
|
||||
|
||||
libbpf_nla_parse(tb, NETDEV_CMD_MAX, na,
|
||||
NLMSG_PAYLOAD(nh, sizeof(*gnl)), NULL);
|
||||
|
||||
if (!tb[NETDEV_A_DEV_IFINDEX] || !tb[NETDEV_A_DEV_XDP_FEATURES])
|
||||
return NL_CONT;
|
||||
|
||||
ifindex = libbpf_nla_getattr_u32(tb[NETDEV_A_DEV_IFINDEX]);
|
||||
if (ifindex != md->ifindex)
|
||||
return NL_CONT;
|
||||
|
||||
md->flags = libbpf_nla_getattr_u64(tb[NETDEV_A_DEV_XDP_FEATURES]);
|
||||
return NL_DONE;
|
||||
}
|
||||
|
||||
int bpf_xdp_query(int ifindex, int xdp_flags, struct bpf_xdp_query_opts *opts)
|
||||
{
|
||||
struct libbpf_nla_req req = {
|
||||
.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
|
||||
.nh.nlmsg_type = RTM_GETLINK,
|
||||
.nh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
|
||||
.ifinfo.ifi_family = AF_PACKET,
|
||||
};
|
||||
struct xdp_id_md xdp_id = {};
|
||||
struct xdp_features_md md = {
|
||||
.ifindex = ifindex,
|
||||
};
|
||||
__u16 id;
|
||||
int err;
|
||||
|
||||
if (!OPTS_VALID(opts, bpf_xdp_query_opts))
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
if (xdp_flags & ~XDP_FLAGS_MASK)
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
/* Check whether the single {HW,DRV,SKB} mode is set */
|
||||
xdp_flags &= XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE;
|
||||
if (xdp_flags & (xdp_flags - 1))
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
xdp_id.ifindex = ifindex;
|
||||
xdp_id.flags = xdp_flags;
|
||||
|
||||
err = libbpf_netlink_send_recv(&req, NETLINK_ROUTE, __dump_link_nlmsg,
|
||||
get_xdp_info, &xdp_id);
|
||||
if (err)
|
||||
return libbpf_err(err);
|
||||
|
||||
OPTS_SET(opts, prog_id, xdp_id.info.prog_id);
|
||||
OPTS_SET(opts, drv_prog_id, xdp_id.info.drv_prog_id);
|
||||
OPTS_SET(opts, hw_prog_id, xdp_id.info.hw_prog_id);
|
||||
OPTS_SET(opts, skb_prog_id, xdp_id.info.skb_prog_id);
|
||||
OPTS_SET(opts, attach_mode, xdp_id.info.attach_mode);
|
||||
|
||||
if (!OPTS_HAS(opts, feature_flags))
|
||||
return 0;
|
||||
|
||||
err = libbpf_netlink_resolve_genl_family_id("netdev", sizeof("netdev"), &id);
|
||||
if (err < 0) {
|
||||
if (err == -ENOENT) {
|
||||
opts->feature_flags = 0;
|
||||
goto skip_feature_flags;
|
||||
}
|
||||
return libbpf_err(err);
|
||||
}
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.nh.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
|
||||
req.nh.nlmsg_flags = NLM_F_REQUEST;
|
||||
req.nh.nlmsg_type = id;
|
||||
req.gnl.cmd = NETDEV_CMD_DEV_GET;
|
||||
req.gnl.version = 2;
|
||||
|
||||
err = nlattr_add(&req, NETDEV_A_DEV_IFINDEX, &ifindex, sizeof(ifindex));
|
||||
if (err < 0)
|
||||
return libbpf_err(err);
|
||||
|
||||
err = libbpf_netlink_send_recv(&req, NETLINK_GENERIC,
|
||||
parse_xdp_features, NULL, &md);
|
||||
if (err)
|
||||
return libbpf_err(err);
|
||||
|
||||
opts->feature_flags = md.flags;
|
||||
|
||||
skip_feature_flags:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bpf_xdp_query_id(int ifindex, int flags, __u32 *prog_id)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_xdp_query_opts, opts);
|
||||
int ret;
|
||||
|
||||
ret = bpf_xdp_query(ifindex, flags, &opts);
|
||||
if (ret)
|
||||
return libbpf_err(ret);
|
||||
|
||||
flags &= XDP_FLAGS_MODES;
|
||||
|
||||
if (opts.attach_mode != XDP_ATTACHED_MULTI && !flags)
|
||||
*prog_id = opts.prog_id;
|
||||
else if (flags & XDP_FLAGS_DRV_MODE)
|
||||
*prog_id = opts.drv_prog_id;
|
||||
else if (flags & XDP_FLAGS_HW_MODE)
|
||||
*prog_id = opts.hw_prog_id;
|
||||
else if (flags & XDP_FLAGS_SKB_MODE)
|
||||
*prog_id = opts.skb_prog_id;
|
||||
else
|
||||
*prog_id = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
typedef int (*qdisc_config_t)(struct libbpf_nla_req *req);
|
||||
|
||||
static int clsact_config(struct libbpf_nla_req *req)
|
||||
{
|
||||
req->tc.tcm_parent = TC_H_CLSACT;
|
||||
req->tc.tcm_handle = TC_H_MAKE(TC_H_CLSACT, 0);
|
||||
|
||||
return nlattr_add(req, TCA_KIND, "clsact", sizeof("clsact"));
|
||||
}
|
||||
|
||||
static int attach_point_to_config(struct bpf_tc_hook *hook,
|
||||
qdisc_config_t *config)
|
||||
{
|
||||
switch (OPTS_GET(hook, attach_point, 0)) {
|
||||
case BPF_TC_INGRESS:
|
||||
case BPF_TC_EGRESS:
|
||||
case BPF_TC_INGRESS | BPF_TC_EGRESS:
|
||||
if (OPTS_GET(hook, parent, 0))
|
||||
return -EINVAL;
|
||||
*config = &clsact_config;
|
||||
return 0;
|
||||
case BPF_TC_CUSTOM:
|
||||
return -EOPNOTSUPP;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int tc_get_tcm_parent(enum bpf_tc_attach_point attach_point,
|
||||
__u32 *parent)
|
||||
{
|
||||
switch (attach_point) {
|
||||
case BPF_TC_INGRESS:
|
||||
case BPF_TC_EGRESS:
|
||||
if (*parent)
|
||||
return -EINVAL;
|
||||
*parent = TC_H_MAKE(TC_H_CLSACT,
|
||||
attach_point == BPF_TC_INGRESS ?
|
||||
TC_H_MIN_INGRESS : TC_H_MIN_EGRESS);
|
||||
break;
|
||||
case BPF_TC_CUSTOM:
|
||||
if (!*parent)
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc_qdisc_modify(struct bpf_tc_hook *hook, int cmd, int flags)
|
||||
{
|
||||
qdisc_config_t config;
|
||||
int ret;
|
||||
struct libbpf_nla_req req;
|
||||
|
||||
ret = attach_point_to_config(hook, &config);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
|
||||
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
|
||||
req.nh.nlmsg_type = cmd;
|
||||
req.tc.tcm_family = AF_UNSPEC;
|
||||
req.tc.tcm_ifindex = OPTS_GET(hook, ifindex, 0);
|
||||
|
||||
ret = config(&req);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return libbpf_netlink_send_recv(&req, NETLINK_ROUTE, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static int tc_qdisc_create_excl(struct bpf_tc_hook *hook)
|
||||
{
|
||||
return tc_qdisc_modify(hook, RTM_NEWQDISC, NLM_F_CREATE | NLM_F_EXCL);
|
||||
}
|
||||
|
||||
static int tc_qdisc_delete(struct bpf_tc_hook *hook)
|
||||
{
|
||||
return tc_qdisc_modify(hook, RTM_DELQDISC, 0);
|
||||
}
|
||||
|
||||
int bpf_tc_hook_create(struct bpf_tc_hook *hook)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!hook || !OPTS_VALID(hook, bpf_tc_hook) ||
|
||||
OPTS_GET(hook, ifindex, 0) <= 0)
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
ret = tc_qdisc_create_excl(hook);
|
||||
return libbpf_err(ret);
|
||||
}
|
||||
|
||||
static int __bpf_tc_detach(const struct bpf_tc_hook *hook,
|
||||
const struct bpf_tc_opts *opts,
|
||||
const bool flush);
|
||||
|
||||
int bpf_tc_hook_destroy(struct bpf_tc_hook *hook)
|
||||
{
|
||||
if (!hook || !OPTS_VALID(hook, bpf_tc_hook) ||
|
||||
OPTS_GET(hook, ifindex, 0) <= 0)
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
switch (OPTS_GET(hook, attach_point, 0)) {
|
||||
case BPF_TC_INGRESS:
|
||||
case BPF_TC_EGRESS:
|
||||
return libbpf_err(__bpf_tc_detach(hook, NULL, true));
|
||||
case BPF_TC_INGRESS | BPF_TC_EGRESS:
|
||||
return libbpf_err(tc_qdisc_delete(hook));
|
||||
case BPF_TC_CUSTOM:
|
||||
return libbpf_err(-EOPNOTSUPP);
|
||||
default:
|
||||
return libbpf_err(-EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
struct bpf_cb_ctx {
|
||||
struct bpf_tc_opts *opts;
|
||||
bool processed;
|
||||
};
|
||||
|
||||
static int __get_tc_info(void *cookie, struct tcmsg *tc, struct nlattr **tb,
|
||||
bool unicast)
|
||||
{
|
||||
struct nlattr *tbb[TCA_BPF_MAX + 1];
|
||||
struct bpf_cb_ctx *info = cookie;
|
||||
|
||||
if (!info || !info->opts)
|
||||
return -EINVAL;
|
||||
if (unicast && info->processed)
|
||||
return -EINVAL;
|
||||
if (!tb[TCA_OPTIONS])
|
||||
return NL_CONT;
|
||||
|
||||
libbpf_nla_parse_nested(tbb, TCA_BPF_MAX, tb[TCA_OPTIONS], NULL);
|
||||
if (!tbb[TCA_BPF_ID])
|
||||
return -EINVAL;
|
||||
|
||||
OPTS_SET(info->opts, prog_id, libbpf_nla_getattr_u32(tbb[TCA_BPF_ID]));
|
||||
OPTS_SET(info->opts, handle, tc->tcm_handle);
|
||||
OPTS_SET(info->opts, priority, TC_H_MAJ(tc->tcm_info) >> 16);
|
||||
|
||||
info->processed = true;
|
||||
return unicast ? NL_NEXT : NL_DONE;
|
||||
}
|
||||
|
||||
static int get_tc_info(struct nlmsghdr *nh, libbpf_dump_nlmsg_t fn,
|
||||
void *cookie)
|
||||
{
|
||||
struct tcmsg *tc = NLMSG_DATA(nh);
|
||||
struct nlattr *tb[TCA_MAX + 1];
|
||||
|
||||
libbpf_nla_parse(tb, TCA_MAX,
|
||||
(struct nlattr *)((void *)tc + NLMSG_ALIGN(sizeof(*tc))),
|
||||
NLMSG_PAYLOAD(nh, sizeof(*tc)), NULL);
|
||||
if (!tb[TCA_KIND])
|
||||
return NL_CONT;
|
||||
return __get_tc_info(cookie, tc, tb, nh->nlmsg_flags & NLM_F_ECHO);
|
||||
}
|
||||
|
||||
static int tc_add_fd_and_name(struct libbpf_nla_req *req, int fd)
|
||||
{
|
||||
struct bpf_prog_info info;
|
||||
__u32 info_len = sizeof(info);
|
||||
char name[256];
|
||||
int len, ret;
|
||||
|
||||
memset(&info, 0, info_len);
|
||||
ret = bpf_prog_get_info_by_fd(fd, &info, &info_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = nlattr_add(req, TCA_BPF_FD, &fd, sizeof(fd));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
len = snprintf(name, sizeof(name), "%s:[%u]", info.name, info.id);
|
||||
if (len < 0)
|
||||
return -errno;
|
||||
if (len >= sizeof(name))
|
||||
return -ENAMETOOLONG;
|
||||
return nlattr_add(req, TCA_BPF_NAME, name, len + 1);
|
||||
}
|
||||
|
||||
int bpf_tc_attach(const struct bpf_tc_hook *hook, struct bpf_tc_opts *opts)
|
||||
{
|
||||
__u32 protocol, bpf_flags, handle, priority, parent, prog_id, flags;
|
||||
int ret, ifindex, attach_point, prog_fd;
|
||||
struct bpf_cb_ctx info = {};
|
||||
struct libbpf_nla_req req;
|
||||
struct nlattr *nla;
|
||||
|
||||
if (!hook || !opts ||
|
||||
!OPTS_VALID(hook, bpf_tc_hook) ||
|
||||
!OPTS_VALID(opts, bpf_tc_opts))
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
ifindex = OPTS_GET(hook, ifindex, 0);
|
||||
parent = OPTS_GET(hook, parent, 0);
|
||||
attach_point = OPTS_GET(hook, attach_point, 0);
|
||||
|
||||
handle = OPTS_GET(opts, handle, 0);
|
||||
priority = OPTS_GET(opts, priority, 0);
|
||||
prog_fd = OPTS_GET(opts, prog_fd, 0);
|
||||
prog_id = OPTS_GET(opts, prog_id, 0);
|
||||
flags = OPTS_GET(opts, flags, 0);
|
||||
|
||||
if (ifindex <= 0 || !prog_fd || prog_id)
|
||||
return libbpf_err(-EINVAL);
|
||||
if (priority > UINT16_MAX)
|
||||
return libbpf_err(-EINVAL);
|
||||
if (flags & ~BPF_TC_F_REPLACE)
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
flags = (flags & BPF_TC_F_REPLACE) ? NLM_F_REPLACE : NLM_F_EXCL;
|
||||
protocol = ETH_P_ALL;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
|
||||
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE |
|
||||
NLM_F_ECHO | flags;
|
||||
req.nh.nlmsg_type = RTM_NEWTFILTER;
|
||||
req.tc.tcm_family = AF_UNSPEC;
|
||||
req.tc.tcm_ifindex = ifindex;
|
||||
req.tc.tcm_handle = handle;
|
||||
req.tc.tcm_info = TC_H_MAKE(priority << 16, htons(protocol));
|
||||
|
||||
ret = tc_get_tcm_parent(attach_point, &parent);
|
||||
if (ret < 0)
|
||||
return libbpf_err(ret);
|
||||
req.tc.tcm_parent = parent;
|
||||
|
||||
ret = nlattr_add(&req, TCA_KIND, "bpf", sizeof("bpf"));
|
||||
if (ret < 0)
|
||||
return libbpf_err(ret);
|
||||
nla = nlattr_begin_nested(&req, TCA_OPTIONS);
|
||||
if (!nla)
|
||||
return libbpf_err(-EMSGSIZE);
|
||||
ret = tc_add_fd_and_name(&req, prog_fd);
|
||||
if (ret < 0)
|
||||
return libbpf_err(ret);
|
||||
bpf_flags = TCA_BPF_FLAG_ACT_DIRECT;
|
||||
ret = nlattr_add(&req, TCA_BPF_FLAGS, &bpf_flags, sizeof(bpf_flags));
|
||||
if (ret < 0)
|
||||
return libbpf_err(ret);
|
||||
nlattr_end_nested(&req, nla);
|
||||
|
||||
info.opts = opts;
|
||||
|
||||
ret = libbpf_netlink_send_recv(&req, NETLINK_ROUTE, get_tc_info, NULL,
|
||||
&info);
|
||||
if (ret < 0)
|
||||
return libbpf_err(ret);
|
||||
if (!info.processed)
|
||||
return libbpf_err(-ENOENT);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __bpf_tc_detach(const struct bpf_tc_hook *hook,
|
||||
const struct bpf_tc_opts *opts,
|
||||
const bool flush)
|
||||
{
|
||||
__u32 protocol = 0, handle, priority, parent, prog_id, flags;
|
||||
int ret, ifindex, attach_point, prog_fd;
|
||||
struct libbpf_nla_req req;
|
||||
|
||||
if (!hook ||
|
||||
!OPTS_VALID(hook, bpf_tc_hook) ||
|
||||
!OPTS_VALID(opts, bpf_tc_opts))
|
||||
return -EINVAL;
|
||||
|
||||
ifindex = OPTS_GET(hook, ifindex, 0);
|
||||
parent = OPTS_GET(hook, parent, 0);
|
||||
attach_point = OPTS_GET(hook, attach_point, 0);
|
||||
|
||||
handle = OPTS_GET(opts, handle, 0);
|
||||
priority = OPTS_GET(opts, priority, 0);
|
||||
prog_fd = OPTS_GET(opts, prog_fd, 0);
|
||||
prog_id = OPTS_GET(opts, prog_id, 0);
|
||||
flags = OPTS_GET(opts, flags, 0);
|
||||
|
||||
if (ifindex <= 0 || flags || prog_fd || prog_id)
|
||||
return -EINVAL;
|
||||
if (priority > UINT16_MAX)
|
||||
return -EINVAL;
|
||||
if (!flush) {
|
||||
if (!handle || !priority)
|
||||
return -EINVAL;
|
||||
protocol = ETH_P_ALL;
|
||||
} else {
|
||||
if (handle || priority)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
|
||||
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
req.nh.nlmsg_type = RTM_DELTFILTER;
|
||||
req.tc.tcm_family = AF_UNSPEC;
|
||||
req.tc.tcm_ifindex = ifindex;
|
||||
if (!flush) {
|
||||
req.tc.tcm_handle = handle;
|
||||
req.tc.tcm_info = TC_H_MAKE(priority << 16, htons(protocol));
|
||||
}
|
||||
|
||||
ret = tc_get_tcm_parent(attach_point, &parent);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
req.tc.tcm_parent = parent;
|
||||
|
||||
if (!flush) {
|
||||
ret = nlattr_add(&req, TCA_KIND, "bpf", sizeof("bpf"));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return libbpf_netlink_send_recv(&req, NETLINK_ROUTE, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
int bpf_tc_detach(const struct bpf_tc_hook *hook,
|
||||
const struct bpf_tc_opts *opts)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!opts)
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
ret = __bpf_tc_detach(hook, opts, false);
|
||||
return libbpf_err(ret);
|
||||
}
|
||||
|
||||
int bpf_tc_query(const struct bpf_tc_hook *hook, struct bpf_tc_opts *opts)
|
||||
{
|
||||
__u32 protocol, handle, priority, parent, prog_id, flags;
|
||||
int ret, ifindex, attach_point, prog_fd;
|
||||
struct bpf_cb_ctx info = {};
|
||||
struct libbpf_nla_req req;
|
||||
|
||||
if (!hook || !opts ||
|
||||
!OPTS_VALID(hook, bpf_tc_hook) ||
|
||||
!OPTS_VALID(opts, bpf_tc_opts))
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
ifindex = OPTS_GET(hook, ifindex, 0);
|
||||
parent = OPTS_GET(hook, parent, 0);
|
||||
attach_point = OPTS_GET(hook, attach_point, 0);
|
||||
|
||||
handle = OPTS_GET(opts, handle, 0);
|
||||
priority = OPTS_GET(opts, priority, 0);
|
||||
prog_fd = OPTS_GET(opts, prog_fd, 0);
|
||||
prog_id = OPTS_GET(opts, prog_id, 0);
|
||||
flags = OPTS_GET(opts, flags, 0);
|
||||
|
||||
if (ifindex <= 0 || flags || prog_fd || prog_id ||
|
||||
!handle || !priority)
|
||||
return libbpf_err(-EINVAL);
|
||||
if (priority > UINT16_MAX)
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
protocol = ETH_P_ALL;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
|
||||
req.nh.nlmsg_flags = NLM_F_REQUEST;
|
||||
req.nh.nlmsg_type = RTM_GETTFILTER;
|
||||
req.tc.tcm_family = AF_UNSPEC;
|
||||
req.tc.tcm_ifindex = ifindex;
|
||||
req.tc.tcm_handle = handle;
|
||||
req.tc.tcm_info = TC_H_MAKE(priority << 16, htons(protocol));
|
||||
|
||||
ret = tc_get_tcm_parent(attach_point, &parent);
|
||||
if (ret < 0)
|
||||
return libbpf_err(ret);
|
||||
req.tc.tcm_parent = parent;
|
||||
|
||||
ret = nlattr_add(&req, TCA_KIND, "bpf", sizeof("bpf"));
|
||||
if (ret < 0)
|
||||
return libbpf_err(ret);
|
||||
|
||||
info.opts = opts;
|
||||
|
||||
ret = libbpf_netlink_send_recv(&req, NETLINK_ROUTE, get_tc_info, NULL,
|
||||
&info);
|
||||
if (ret < 0)
|
||||
return libbpf_err(ret);
|
||||
if (!info.processed)
|
||||
return libbpf_err(-ENOENT);
|
||||
return ret;
|
||||
}
|
||||
195
third_party/libbpf/src/nlattr.c
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
|
||||
/*
|
||||
* NETLINK Netlink attributes
|
||||
*
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include "nlattr.h"
|
||||
#include "libbpf_internal.h"
|
||||
|
||||
static uint16_t nla_attr_minlen[LIBBPF_NLA_TYPE_MAX+1] = {
|
||||
[LIBBPF_NLA_U8] = sizeof(uint8_t),
|
||||
[LIBBPF_NLA_U16] = sizeof(uint16_t),
|
||||
[LIBBPF_NLA_U32] = sizeof(uint32_t),
|
||||
[LIBBPF_NLA_U64] = sizeof(uint64_t),
|
||||
[LIBBPF_NLA_STRING] = 1,
|
||||
[LIBBPF_NLA_FLAG] = 0,
|
||||
};
|
||||
|
||||
static struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
|
||||
{
|
||||
int totlen = NLA_ALIGN(nla->nla_len);
|
||||
|
||||
*remaining -= totlen;
|
||||
return (struct nlattr *)((void *)nla + totlen);
|
||||
}
|
||||
|
||||
static int nla_ok(const struct nlattr *nla, int remaining)
|
||||
{
|
||||
return remaining >= (int)sizeof(*nla) &&
|
||||
nla->nla_len >= sizeof(*nla) &&
|
||||
nla->nla_len <= remaining;
|
||||
}
|
||||
|
||||
static int nla_type(const struct nlattr *nla)
|
||||
{
|
||||
return nla->nla_type & NLA_TYPE_MASK;
|
||||
}
|
||||
|
||||
static int validate_nla(struct nlattr *nla, int maxtype,
|
||||
struct libbpf_nla_policy *policy)
|
||||
{
|
||||
struct libbpf_nla_policy *pt;
|
||||
unsigned int minlen = 0;
|
||||
int type = nla_type(nla);
|
||||
|
||||
if (type < 0 || type > maxtype)
|
||||
return 0;
|
||||
|
||||
pt = &policy[type];
|
||||
|
||||
if (pt->type > LIBBPF_NLA_TYPE_MAX)
|
||||
return 0;
|
||||
|
||||
if (pt->minlen)
|
||||
minlen = pt->minlen;
|
||||
else if (pt->type != LIBBPF_NLA_UNSPEC)
|
||||
minlen = nla_attr_minlen[pt->type];
|
||||
|
||||
if (libbpf_nla_len(nla) < minlen)
|
||||
return -1;
|
||||
|
||||
if (pt->maxlen && libbpf_nla_len(nla) > pt->maxlen)
|
||||
return -1;
|
||||
|
||||
if (pt->type == LIBBPF_NLA_STRING) {
|
||||
char *data = libbpf_nla_data(nla);
|
||||
|
||||
if (data[libbpf_nla_len(nla) - 1] != '\0')
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int nlmsg_len(const struct nlmsghdr *nlh)
|
||||
{
|
||||
return nlh->nlmsg_len - NLMSG_HDRLEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create attribute index based on a stream of attributes.
|
||||
* @arg tb Index array to be filled (maxtype+1 elements).
|
||||
* @arg maxtype Maximum attribute type expected and accepted.
|
||||
* @arg head Head of attribute stream.
|
||||
* @arg len Length of attribute stream.
|
||||
* @arg policy Attribute validation policy.
|
||||
*
|
||||
* Iterates over the stream of attributes and stores a pointer to each
|
||||
* attribute in the index array using the attribute type as index to
|
||||
* the array. Attribute with a type greater than the maximum type
|
||||
* specified will be silently ignored in order to maintain backwards
|
||||
* compatibility. If \a policy is not NULL, the attribute will be
|
||||
* validated using the specified policy.
|
||||
*
|
||||
* @see nla_validate
|
||||
* @return 0 on success or a negative error code.
|
||||
*/
|
||||
int libbpf_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head,
|
||||
int len, struct libbpf_nla_policy *policy)
|
||||
{
|
||||
struct nlattr *nla;
|
||||
int rem, err;
|
||||
|
||||
memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
|
||||
|
||||
libbpf_nla_for_each_attr(nla, head, len, rem) {
|
||||
int type = nla_type(nla);
|
||||
|
||||
if (type > maxtype)
|
||||
continue;
|
||||
|
||||
if (policy) {
|
||||
err = validate_nla(nla, maxtype, policy);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (tb[type])
|
||||
pr_warn("Attribute of type %#x found multiple times in message, "
|
||||
"previous attribute is being ignored.\n", type);
|
||||
|
||||
tb[type] = nla;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
errout:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create attribute index based on nested attribute
|
||||
* @arg tb Index array to be filled (maxtype+1 elements).
|
||||
* @arg maxtype Maximum attribute type expected and accepted.
|
||||
* @arg nla Nested Attribute.
|
||||
* @arg policy Attribute validation policy.
|
||||
*
|
||||
* Feeds the stream of attributes nested into the specified attribute
|
||||
* to libbpf_nla_parse().
|
||||
*
|
||||
* @see libbpf_nla_parse
|
||||
* @return 0 on success or a negative error code.
|
||||
*/
|
||||
int libbpf_nla_parse_nested(struct nlattr *tb[], int maxtype,
|
||||
struct nlattr *nla,
|
||||
struct libbpf_nla_policy *policy)
|
||||
{
|
||||
return libbpf_nla_parse(tb, maxtype, libbpf_nla_data(nla),
|
||||
libbpf_nla_len(nla), policy);
|
||||
}
|
||||
|
||||
/* dump netlink extended ack error message */
|
||||
int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh)
|
||||
{
|
||||
struct libbpf_nla_policy extack_policy[NLMSGERR_ATTR_MAX + 1] = {
|
||||
[NLMSGERR_ATTR_MSG] = { .type = LIBBPF_NLA_STRING },
|
||||
[NLMSGERR_ATTR_OFFS] = { .type = LIBBPF_NLA_U32 },
|
||||
};
|
||||
struct nlattr *tb[NLMSGERR_ATTR_MAX + 1], *attr;
|
||||
struct nlmsgerr *err;
|
||||
char *errmsg = NULL;
|
||||
int hlen, alen;
|
||||
|
||||
/* no TLVs, nothing to do here */
|
||||
if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
|
||||
return 0;
|
||||
|
||||
err = (struct nlmsgerr *)NLMSG_DATA(nlh);
|
||||
hlen = sizeof(*err);
|
||||
|
||||
/* if NLM_F_CAPPED is set then the inner err msg was capped */
|
||||
if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
|
||||
hlen += nlmsg_len(&err->msg);
|
||||
|
||||
attr = (struct nlattr *) ((void *) err + hlen);
|
||||
alen = (void *)nlh + nlh->nlmsg_len - (void *)attr;
|
||||
|
||||
if (libbpf_nla_parse(tb, NLMSGERR_ATTR_MAX, attr, alen,
|
||||
extack_policy) != 0) {
|
||||
pr_warn("Failed to parse extended error attributes\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tb[NLMSGERR_ATTR_MSG])
|
||||
errmsg = (char *) libbpf_nla_data(tb[NLMSGERR_ATTR_MSG]);
|
||||
|
||||
pr_warn("Kernel error message: %s\n", errmsg);
|
||||
|
||||
return 0;
|
||||
}
|
||||