mirror of
https://github.com/netdata/libbpf.git
synced 2026-03-18 07:19:07 +08:00
Compare commits
104 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab067ed371 | ||
|
|
9b69fbe4d1 | ||
|
|
04d8fc50ab | ||
|
|
ceff1e0363 | ||
|
|
d28acc595f | ||
|
|
9ef191ea7d | ||
|
|
1add860402 | ||
|
|
c658f21738 | ||
|
|
9f519af7f4 | ||
|
|
b7bdc604ef | ||
|
|
354dd9844e | ||
|
|
9b91dce691 | ||
|
|
83535cb2bf | ||
|
|
3f05b513d4 | ||
|
|
0d0d05de08 | ||
|
|
44409068f7 | ||
|
|
16ecc53e73 | ||
|
|
38f66776db | ||
|
|
e9d33df74d | ||
|
|
05b515de7d | ||
|
|
c2bbeaa900 | ||
|
|
799d153f41 | ||
|
|
69ff3960eb | ||
|
|
b91f53ec5f | ||
|
|
dd8f1bdd45 | ||
|
|
3720f31852 | ||
|
|
c51c492a65 | ||
|
|
d3e68e036e | ||
|
|
6ce8910d4d | ||
|
|
79b1d813f9 | ||
|
|
26954e103d | ||
|
|
c8c02fca3a | ||
|
|
0e2f5f9615 | ||
|
|
b539321838 | ||
|
|
0f15f88443 | ||
|
|
bada95a5f3 | ||
|
|
fb929625dc | ||
|
|
1a828b3d58 | ||
|
|
330f4683e2 | ||
|
|
2ef7f5607c | ||
|
|
4da243c179 | ||
|
|
4d8fc6d438 | ||
|
|
6d4abdda08 | ||
|
|
67ab4c0f82 | ||
|
|
df45cf7a3e | ||
|
|
4438972ccc | ||
|
|
09cd9ff2db | ||
|
|
e7d860d2fc | ||
|
|
ff3d2702d8 | ||
|
|
44f9712f79 | ||
|
|
fe4cb796df | ||
|
|
15de8ad80d | ||
|
|
d7a137510a | ||
|
|
91e4f27dd7 | ||
|
|
1339ef70a3 | ||
|
|
c204e3d610 | ||
|
|
32d0a03332 | ||
|
|
05346cfd90 | ||
|
|
a7a32b899c | ||
|
|
68a051f2d2 | ||
|
|
8e80367637 | ||
|
|
9a5adecc62 | ||
|
|
b923d0e3c6 | ||
|
|
f02e248ae1 | ||
|
|
e152510d72 | ||
|
|
59ac1946b0 | ||
|
|
5150a4a0fb | ||
|
|
2a25957df6 | ||
|
|
e441f55089 | ||
|
|
beb9f88080 | ||
|
|
c7b5116f71 | ||
|
|
2b0cd55bf5 | ||
|
|
188276ca5f | ||
|
|
87c4984da8 | ||
|
|
a5611ba6e8 | ||
|
|
c6e01425b6 | ||
|
|
58e3a8fac1 | ||
|
|
1b27702c14 | ||
|
|
39cf9fc90f | ||
|
|
bc4a6e9709 | ||
|
|
4a50ceb043 | ||
|
|
4d86cae4f0 | ||
|
|
33b374395f | ||
|
|
ade4409352 | ||
|
|
2f9abb2a26 | ||
|
|
fca60960ea | ||
|
|
0db22b01a1 | ||
|
|
807b9d7be1 | ||
|
|
a3d02f9ab4 | ||
|
|
54aac21f7e | ||
|
|
d8dd0beb98 | ||
|
|
e94f57a9ab | ||
|
|
bda436be4a | ||
|
|
a30df5c09f | ||
|
|
e776bf7ec7 | ||
|
|
46688687d5 | ||
|
|
19cbbd8f52 | ||
|
|
c87b3a6065 | ||
|
|
4c55ba2b19 | ||
|
|
104006a054 | ||
|
|
bf83a95dee | ||
|
|
732f598282 | ||
|
|
de3c5a17cb | ||
|
|
1a8a75037b |
14
.lgtm.yml
Normal file
14
.lgtm.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
# vi: set ts=2 sw=2:
|
||||
extraction:
|
||||
cpp:
|
||||
prepare:
|
||||
packages:
|
||||
- libelf-dev
|
||||
- pkg-config
|
||||
after_prepare:
|
||||
# As the buildsystem detection by LGTM is performed _only_ during the
|
||||
# 'configure' phase, we need to trick LGTM we use a supported build
|
||||
# system (configure, meson, cmake, etc.). This way LGTM correctly detects
|
||||
# that our sources are in the src/ subfolder.
|
||||
- touch src/configure
|
||||
- chmod +x src/configure
|
||||
77
.travis.yml
77
.travis.yml
@@ -1,14 +1,24 @@
|
||||
sudo: required
|
||||
dist: xenial
|
||||
dist: bionic
|
||||
services:
|
||||
- docker
|
||||
|
||||
env:
|
||||
global:
|
||||
- AUTHOR_EMAIL="$(git log -1 $TRAVIS_COMMIT --pretty=\"%aE\")"
|
||||
- AUTHOR_EMAIL="$(git log -1 --pretty=\"%aE\")"
|
||||
- CI_MANAGERS="$TRAVIS_BUILD_DIR/travis-ci/managers"
|
||||
- REPO_ROOT="$TRAVIS_BUILD_DIR"
|
||||
|
||||
stages:
|
||||
# Run Coverity periodically instead of for each PR for following reasons:
|
||||
# 1) Coverity jobs are heavily rate-limited
|
||||
# 2) Due to security restrictions of encrypted environment variables
|
||||
# in Travis CI, pull requests made from forks can't access encrypted
|
||||
# env variables, making Coverity unusable
|
||||
# See: https://docs.travis-ci.com/user/pull-requests#pull-requests-and-security-restrictions
|
||||
- name: Coverity
|
||||
if: type = cron
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: Build & test
|
||||
@@ -23,9 +33,7 @@ jobs:
|
||||
install:
|
||||
- $CI_MANAGERS/debian.sh SETUP
|
||||
script:
|
||||
- set -e
|
||||
- $CI_MANAGERS/debian.sh RUN
|
||||
- set +e
|
||||
- $CI_MANAGERS/debian.sh RUN || travis_terminate
|
||||
after_script:
|
||||
- $CI_MANAGERS/debian.sh CLEANUP
|
||||
|
||||
@@ -40,9 +48,7 @@ jobs:
|
||||
install:
|
||||
- $CI_MANAGERS/debian.sh SETUP
|
||||
script:
|
||||
- set -e
|
||||
- $CI_MANAGERS/debian.sh RUN_ASAN
|
||||
- set +e
|
||||
- $CI_MANAGERS/debian.sh RUN_ASAN || travis_terminate
|
||||
after_script:
|
||||
- $CI_MANAGERS/debian.sh CLEANUP
|
||||
|
||||
@@ -57,9 +63,7 @@ jobs:
|
||||
install:
|
||||
- $CI_MANAGERS/debian.sh SETUP
|
||||
script:
|
||||
- set -e
|
||||
- $CI_MANAGERS/debian.sh RUN_CLANG
|
||||
- set +e
|
||||
- $CI_MANAGERS/debian.sh RUN_CLANG || travis_terminate
|
||||
after_script:
|
||||
- $CI_MANAGERS/debian.sh CLEANUP
|
||||
|
||||
@@ -74,9 +78,7 @@ jobs:
|
||||
install:
|
||||
- $CI_MANAGERS/debian.sh SETUP
|
||||
script:
|
||||
- set -e
|
||||
- $CI_MANAGERS/debian.sh RUN_CLANG_ASAN
|
||||
- set +e
|
||||
- $CI_MANAGERS/debian.sh RUN_CLANG_ASAN || travis_terminate
|
||||
after_script:
|
||||
- $CI_MANAGERS/debian.sh CLEANUP
|
||||
|
||||
@@ -91,9 +93,7 @@ jobs:
|
||||
install:
|
||||
- $CI_MANAGERS/debian.sh SETUP
|
||||
script:
|
||||
- set -e
|
||||
- $CI_MANAGERS/debian.sh RUN_GCC8
|
||||
- set +e
|
||||
- $CI_MANAGERS/debian.sh RUN_GCC8 || travis_terminate
|
||||
after_script:
|
||||
- $CI_MANAGERS/debian.sh CLEANUP
|
||||
|
||||
@@ -108,15 +108,44 @@ jobs:
|
||||
install:
|
||||
- $CI_MANAGERS/debian.sh SETUP
|
||||
script:
|
||||
- set -e
|
||||
- $CI_MANAGERS/debian.sh RUN_GCC8_ASAN
|
||||
- set +e
|
||||
- $CI_MANAGERS/debian.sh RUN_GCC8_ASAN || travis_terminate
|
||||
after_script:
|
||||
- $CI_MANAGERS/debian.sh CLEANUP
|
||||
|
||||
- name: Ubuntu Xenial
|
||||
- name: Ubuntu Bionic
|
||||
language: bash
|
||||
script:
|
||||
- set -e
|
||||
- sudo $CI_MANAGERS/xenial.sh
|
||||
- set +e
|
||||
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
||||
|
||||
- name: Ubuntu Bionic (arm)
|
||||
arch: arm64
|
||||
language: bash
|
||||
script:
|
||||
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
||||
|
||||
- name: Ubuntu Bionic (s390x)
|
||||
arch: s390x
|
||||
language: bash
|
||||
script:
|
||||
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
||||
|
||||
- stage: Coverity
|
||||
language: bash
|
||||
env:
|
||||
# Coverity configuration
|
||||
# COVERITY_SCAN_TOKEN=xxx
|
||||
# Encrypted using `travis encrypt --repo libbpf/libbpf COVERITY_SCAN_TOKEN=xxx`
|
||||
- secure: "I9OsMRHbb82IUivDp+I+w/jEQFOJgBDAqYqf1ollqCM1QhocxMcS9bwIAgfPhdXi2hohV7sRrVMZstahY67FAvJLGxNopi4tAPDIAaIFxgO0yDxMhaTMx5xDfMwlIm2FOP/9gB9BQsd6M7CmoQZgXYwBIv7xd1ooxoQrh2rOK1YrRl7UQu3+c3zPTjDfIYZzR3bFttMqZ9/c4U0v8Ry5IFXrel3hCshndHA1TtttJrUSrILlZcmVc1ch7JIy6zCbCU/2lGv0B/7rWXfF8MT7O9jPtFOhJ1DEcd2zhw2n4j9YT3a8OhtnM61LA6ask632mwCOsxpFLTun7AzuR1Cb5mdPHsxhxnCHcXXARa2mJjem0QG1NhwxwJE8sbRDapojexxCvweYlEN40ofwMDSnj/qNt95XIcrk0tiIhGFx0gVNWvAdmZwx+N4mwGPMTAN0AEOFjpgI+ZdB89m+tL/CbEgE1flc8QxUxJhcp5OhH6yR0z9qYOp0nXIbHsIaCiRvt/7LqFRQfheifztWVz4mdQlCdKS9gcOQ09oKicPevKO1L0Ue3cb7Ug7jOpMs+cdh3XokJtUeYEr1NijMHT9+CTAhhO5RToWXIZRon719z3fwoUBNDREATwVFMlVxqSO/pbYgaKminigYbl785S89YYaZ6E5UvaKRHM6KHKMDszs="
|
||||
- COVERITY_SCAN_PROJECT_NAME="libbpf"
|
||||
- COVERITY_SCAN_NOTIFICATION_EMAIL="${AUTHOR_EMAIL}"
|
||||
- COVERITY_SCAN_BRANCH_PATTERN="$TRAVIS_BRANCH"
|
||||
# Note: `make -C src/` as a BUILD_COMMAND will not work here
|
||||
- COVERITY_SCAN_BUILD_COMMAND_PREPEND="cd src/"
|
||||
- COVERITY_SCAN_BUILD_COMMAND="make"
|
||||
install:
|
||||
- sudo echo 'deb-src http://archive.ubuntu.com/ubuntu/ bionic main restricted universe multiverse' >>/etc/apt/sources.list
|
||||
- sudo apt-get update
|
||||
- sudo apt-get -y build-dep libelf-dev
|
||||
- sudo apt-get install -y libelf-dev pkg-config
|
||||
script:
|
||||
- scripts/coverity.sh || travis_terminate
|
||||
|
||||
@@ -1 +1 @@
|
||||
1bd63524593b964934a33afd442df16b8f90e2b5
|
||||
e42617b825f8073569da76dc4510bfa019b1c35a
|
||||
|
||||
@@ -1 +1 @@
|
||||
02dc96ef6c25f990452c114c59d75c368a1f4c8f
|
||||
e7096c131e5161fa3b8e52a650d7719d2857adfd
|
||||
|
||||
32
LICENSE.BSD-2-Clause
Normal file
32
LICENSE.BSD-2-Clause
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) <year> <owner> . 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
LICENSE.LPGL-2.1
Normal file
503
LICENSE.LPGL-2.1
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!
|
||||
13
README.md
13
README.md
@@ -16,7 +16,10 @@ Other header files at this repo (`include/linux/*.h`) are reduced versions of
|
||||
their counterpart files at bpf-next's `tools/include/linux/*.h` to make compilation
|
||||
successful.
|
||||
|
||||
Build [](https://travis-ci.org/libbpf/libbpf)
|
||||
Build
|
||||
[](https://travis-ci.org/libbpf/libbpf)
|
||||
[](https://lgtm.com/projects/g/libbpf/libbpf/alerts/)
|
||||
[](https://scan.coverity.com/projects/libbpf)
|
||||
=====
|
||||
libelf is an internal dependency of libbpf and thus it is required to link
|
||||
against and must be installed on the system for applications to work.
|
||||
@@ -47,3 +50,11 @@ headers in a build directory /build/root/:
|
||||
$ cd src
|
||||
$ PKG_CONFIG_PATH=/build/root/lib64/pkgconfig DESTDIR=/build/root make install
|
||||
```
|
||||
|
||||
License
|
||||
=====
|
||||
|
||||
This work is dual-licensed under BSD 2-clause license and GNU LGPL v2.1 license.
|
||||
You can choose between one of them if you use this work.
|
||||
|
||||
`SPDX-License-Identifier: BSD-2-Clause OR LGPL-2.1`
|
||||
|
||||
@@ -107,5 +107,12 @@
|
||||
.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
|
||||
|
||||
@@ -173,6 +173,7 @@ enum bpf_prog_type {
|
||||
BPF_PROG_TYPE_CGROUP_SYSCTL,
|
||||
BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
|
||||
BPF_PROG_TYPE_CGROUP_SOCKOPT,
|
||||
BPF_PROG_TYPE_TRACING,
|
||||
};
|
||||
|
||||
enum bpf_attach_type {
|
||||
@@ -199,6 +200,9 @@ enum bpf_attach_type {
|
||||
BPF_CGROUP_UDP6_RECVMSG,
|
||||
BPF_CGROUP_GETSOCKOPT,
|
||||
BPF_CGROUP_SETSOCKOPT,
|
||||
BPF_TRACE_RAW_TP,
|
||||
BPF_TRACE_FENTRY,
|
||||
BPF_TRACE_FEXIT,
|
||||
__MAX_BPF_ATTACH_TYPE
|
||||
};
|
||||
|
||||
@@ -344,6 +348,9 @@ enum bpf_attach_type {
|
||||
/* Clone map from listener for newly accepted socket */
|
||||
#define BPF_F_CLONE (1U << 9)
|
||||
|
||||
/* Enable memory-mapping BPF map */
|
||||
#define BPF_F_MMAPABLE (1U << 10)
|
||||
|
||||
/* flags for BPF_PROG_QUERY */
|
||||
#define BPF_F_QUERY_EFFECTIVE (1U << 0)
|
||||
|
||||
@@ -420,6 +427,8 @@ union bpf_attr {
|
||||
__u32 line_info_rec_size; /* userspace bpf_line_info size */
|
||||
__aligned_u64 line_info; /* line info */
|
||||
__u32 line_info_cnt; /* number of bpf_line_info records */
|
||||
__u32 attach_btf_id; /* in-kernel BTF type id to attach to */
|
||||
__u32 attach_prog_fd; /* 0 to attach to vmlinux */
|
||||
};
|
||||
|
||||
struct { /* anonymous struct used by BPF_OBJ_* commands */
|
||||
@@ -560,10 +569,13 @@ union bpf_attr {
|
||||
* Return
|
||||
* 0 on success, or a negative error in case of failure.
|
||||
*
|
||||
* int bpf_probe_read(void *dst, u32 size, const void *src)
|
||||
* int bpf_probe_read(void *dst, u32 size, const void *unsafe_ptr)
|
||||
* Description
|
||||
* For tracing programs, safely attempt to read *size* bytes from
|
||||
* address *src* and store the data in *dst*.
|
||||
* kernel space address *unsafe_ptr* and store the data in *dst*.
|
||||
*
|
||||
* Generally, use bpf_probe_read_user() or bpf_probe_read_kernel()
|
||||
* instead.
|
||||
* Return
|
||||
* 0 on success, or a negative error in case of failure.
|
||||
*
|
||||
@@ -794,7 +806,7 @@ union bpf_attr {
|
||||
* A 64-bit integer containing the current GID and UID, and
|
||||
* created as such: *current_gid* **<< 32 \|** *current_uid*.
|
||||
*
|
||||
* int bpf_get_current_comm(char *buf, u32 size_of_buf)
|
||||
* int bpf_get_current_comm(void *buf, u32 size_of_buf)
|
||||
* Description
|
||||
* Copy the **comm** attribute of the current task into *buf* of
|
||||
* *size_of_buf*. The **comm** attribute contains the name of
|
||||
@@ -1023,7 +1035,7 @@ union bpf_attr {
|
||||
* The realm of the route for the packet associated to *skb*, or 0
|
||||
* if none was found.
|
||||
*
|
||||
* int bpf_perf_event_output(struct pt_regs *ctx, struct bpf_map *map, u64 flags, void *data, u64 size)
|
||||
* int bpf_perf_event_output(void *ctx, struct bpf_map *map, u64 flags, void *data, u64 size)
|
||||
* Description
|
||||
* Write raw *data* blob into a special BPF perf event held by
|
||||
* *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf
|
||||
@@ -1068,7 +1080,7 @@ union bpf_attr {
|
||||
* Return
|
||||
* 0 on success, or a negative error in case of failure.
|
||||
*
|
||||
* int bpf_skb_load_bytes(const struct sk_buff *skb, u32 offset, void *to, u32 len)
|
||||
* int bpf_skb_load_bytes(const void *skb, u32 offset, void *to, u32 len)
|
||||
* Description
|
||||
* This helper was provided as an easy way to load data from a
|
||||
* packet. It can be used to load *len* bytes from *offset* from
|
||||
@@ -1085,7 +1097,7 @@ union bpf_attr {
|
||||
* Return
|
||||
* 0 on success, or a negative error in case of failure.
|
||||
*
|
||||
* int bpf_get_stackid(struct pt_regs *ctx, struct bpf_map *map, u64 flags)
|
||||
* int bpf_get_stackid(void *ctx, struct bpf_map *map, u64 flags)
|
||||
* Description
|
||||
* Walk a user or a kernel stack and return its id. To achieve
|
||||
* this, the helper needs *ctx*, which is a pointer to the context
|
||||
@@ -1154,7 +1166,7 @@ union bpf_attr {
|
||||
* The checksum result, or a negative error code in case of
|
||||
* failure.
|
||||
*
|
||||
* int bpf_skb_get_tunnel_opt(struct sk_buff *skb, u8 *opt, u32 size)
|
||||
* int bpf_skb_get_tunnel_opt(struct sk_buff *skb, void *opt, u32 size)
|
||||
* Description
|
||||
* Retrieve tunnel options metadata for the packet associated to
|
||||
* *skb*, and store the raw tunnel option data to the buffer *opt*
|
||||
@@ -1172,7 +1184,7 @@ union bpf_attr {
|
||||
* Return
|
||||
* The size of the option data retrieved.
|
||||
*
|
||||
* int bpf_skb_set_tunnel_opt(struct sk_buff *skb, u8 *opt, u32 size)
|
||||
* int bpf_skb_set_tunnel_opt(struct sk_buff *skb, void *opt, u32 size)
|
||||
* Description
|
||||
* Set tunnel options metadata for the packet associated to *skb*
|
||||
* to the option data contained in the raw buffer *opt* of *size*.
|
||||
@@ -1425,45 +1437,14 @@ union bpf_attr {
|
||||
* Return
|
||||
* 0 on success, or a negative error in case of failure.
|
||||
*
|
||||
* int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr)
|
||||
* int bpf_probe_read_str(void *dst, u32 size, const void *unsafe_ptr)
|
||||
* Description
|
||||
* Copy a NUL terminated string from an unsafe address
|
||||
* *unsafe_ptr* to *dst*. The *size* should include the
|
||||
* terminating NUL byte. In case the string length is smaller than
|
||||
* *size*, the target is not padded with further NUL bytes. If the
|
||||
* string length is larger than *size*, just *size*-1 bytes are
|
||||
* copied and the last byte is set to NUL.
|
||||
* Copy a NUL terminated string from an unsafe kernel address
|
||||
* *unsafe_ptr* to *dst*. See bpf_probe_read_kernel_str() for
|
||||
* more details.
|
||||
*
|
||||
* On success, the length of the copied string is returned. This
|
||||
* makes this helper useful in tracing programs for reading
|
||||
* strings, and more importantly to get its length at runtime. See
|
||||
* the following snippet:
|
||||
*
|
||||
* ::
|
||||
*
|
||||
* SEC("kprobe/sys_open")
|
||||
* void bpf_sys_open(struct pt_regs *ctx)
|
||||
* {
|
||||
* char buf[PATHLEN]; // PATHLEN is defined to 256
|
||||
* int res = bpf_probe_read_str(buf, sizeof(buf),
|
||||
* ctx->di);
|
||||
*
|
||||
* // Consume buf, for example push it to
|
||||
* // userspace via bpf_perf_event_output(); we
|
||||
* // can use res (the string length) as event
|
||||
* // size, after checking its boundaries.
|
||||
* }
|
||||
*
|
||||
* In comparison, using **bpf_probe_read()** helper here instead
|
||||
* to read the string would require to estimate the length at
|
||||
* compile time, and would often result in copying more memory
|
||||
* than necessary.
|
||||
*
|
||||
* Another useful use case is when parsing individual process
|
||||
* arguments or individual environment variables navigating
|
||||
* *current*\ **->mm->arg_start** and *current*\
|
||||
* **->mm->env_start**: using this helper and the return value,
|
||||
* one can quickly iterate at the right offset of the memory area.
|
||||
* Generally, use bpf_probe_read_user_str() or bpf_probe_read_kernel_str()
|
||||
* instead.
|
||||
* Return
|
||||
* On success, the strictly positive length of the string,
|
||||
* including the trailing NUL character. On error, a negative
|
||||
@@ -1511,7 +1492,7 @@ union bpf_attr {
|
||||
* Return
|
||||
* 0
|
||||
*
|
||||
* int bpf_setsockopt(struct bpf_sock_ops *bpf_socket, int level, int optname, char *optval, int optlen)
|
||||
* int bpf_setsockopt(struct bpf_sock_ops *bpf_socket, int level, int optname, void *optval, int optlen)
|
||||
* Description
|
||||
* Emulate a call to **setsockopt()** on the socket associated to
|
||||
* *bpf_socket*, which must be a full socket. The *level* at
|
||||
@@ -1595,7 +1576,7 @@ union bpf_attr {
|
||||
* Return
|
||||
* **XDP_REDIRECT** on success, or **XDP_ABORTED** on error.
|
||||
*
|
||||
* int bpf_sk_redirect_map(struct bpf_map *map, u32 key, u64 flags)
|
||||
* int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)
|
||||
* Description
|
||||
* Redirect the packet to the socket referenced by *map* (of type
|
||||
* **BPF_MAP_TYPE_SOCKMAP**) at index *key*. Both ingress and
|
||||
@@ -1715,7 +1696,7 @@ union bpf_attr {
|
||||
* Return
|
||||
* 0 on success, or a negative error in case of failure.
|
||||
*
|
||||
* int bpf_getsockopt(struct bpf_sock_ops *bpf_socket, int level, int optname, char *optval, int optlen)
|
||||
* int bpf_getsockopt(struct bpf_sock_ops *bpf_socket, int level, int optname, void *optval, int optlen)
|
||||
* Description
|
||||
* Emulate a call to **getsockopt()** on the socket associated to
|
||||
* *bpf_socket*, which must be a full socket. The *level* at
|
||||
@@ -1947,7 +1928,7 @@ union bpf_attr {
|
||||
* Return
|
||||
* 0 on success, or a negative error in case of failure.
|
||||
*
|
||||
* int bpf_get_stack(struct pt_regs *regs, void *buf, u32 size, u64 flags)
|
||||
* int bpf_get_stack(void *ctx, void *buf, u32 size, u64 flags)
|
||||
* Description
|
||||
* Return a user or a kernel stack in bpf program provided buffer.
|
||||
* To achieve this, the helper needs *ctx*, which is a pointer
|
||||
@@ -1980,7 +1961,7 @@ union bpf_attr {
|
||||
* A non-negative value equal to or less than *size* on success,
|
||||
* or a negative error in case of failure.
|
||||
*
|
||||
* int bpf_skb_load_bytes_relative(const struct sk_buff *skb, u32 offset, void *to, u32 len, u32 start_header)
|
||||
* int bpf_skb_load_bytes_relative(const void *skb, u32 offset, void *to, u32 len, u32 start_header)
|
||||
* Description
|
||||
* This helper is similar to **bpf_skb_load_bytes**\ () in that
|
||||
* it provides an easy way to load *len* bytes from *offset*
|
||||
@@ -2033,7 +2014,7 @@ union bpf_attr {
|
||||
* * > 0 one of **BPF_FIB_LKUP_RET_** codes explaining why the
|
||||
* packet is not forwarded or needs assist from full stack
|
||||
*
|
||||
* int bpf_sock_hash_update(struct bpf_sock_ops_kern *skops, struct bpf_map *map, void *key, u64 flags)
|
||||
* int bpf_sock_hash_update(struct bpf_sock_ops *skops, struct bpf_map *map, void *key, u64 flags)
|
||||
* Description
|
||||
* Add an entry to, or update a sockhash *map* referencing sockets.
|
||||
* The *skops* is used as a new value for the entry associated to
|
||||
@@ -2392,7 +2373,7 @@ union bpf_attr {
|
||||
* Return
|
||||
* 0 on success, or a negative error in case of failure.
|
||||
*
|
||||
* int bpf_msg_push_data(struct sk_buff *skb, u32 start, u32 len, u64 flags)
|
||||
* int bpf_msg_push_data(struct sk_msg_buff *msg, u32 start, u32 len, u64 flags)
|
||||
* Description
|
||||
* For socket policies, insert *len* bytes into *msg* at offset
|
||||
* *start*.
|
||||
@@ -2408,9 +2389,9 @@ union bpf_attr {
|
||||
* Return
|
||||
* 0 on success, or a negative error in case of failure.
|
||||
*
|
||||
* int bpf_msg_pop_data(struct sk_msg_buff *msg, u32 start, u32 pop, u64 flags)
|
||||
* int bpf_msg_pop_data(struct sk_msg_buff *msg, u32 start, u32 len, u64 flags)
|
||||
* Description
|
||||
* Will remove *pop* bytes from a *msg* starting at byte *start*.
|
||||
* Will remove *len* bytes from a *msg* starting at byte *start*.
|
||||
* This may result in **ENOMEM** errors under certain situations if
|
||||
* an allocation and copy are required due to a full ring buffer.
|
||||
* However, the helper will try to avoid doing the allocation
|
||||
@@ -2505,7 +2486,7 @@ union bpf_attr {
|
||||
* A **struct bpf_tcp_sock** pointer on success, or **NULL** in
|
||||
* case of failure.
|
||||
*
|
||||
* int bpf_skb_ecn_set_ce(struct sk_buf *skb)
|
||||
* int bpf_skb_ecn_set_ce(struct sk_buff *skb)
|
||||
* Description
|
||||
* Set ECN (Explicit Congestion Notification) field of IP header
|
||||
* to **CE** (Congestion Encountered) if current value is **ECT**
|
||||
@@ -2750,6 +2731,96 @@ union bpf_attr {
|
||||
* **-EOPNOTSUPP** kernel configuration does not enable SYN cookies
|
||||
*
|
||||
* **-EPROTONOSUPPORT** IP packet version is not 4 or 6
|
||||
*
|
||||
* int bpf_skb_output(void *ctx, struct bpf_map *map, u64 flags, void *data, u64 size)
|
||||
* Description
|
||||
* Write raw *data* blob into a special BPF perf event held by
|
||||
* *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf
|
||||
* event must have the following attributes: **PERF_SAMPLE_RAW**
|
||||
* as **sample_type**, **PERF_TYPE_SOFTWARE** as **type**, and
|
||||
* **PERF_COUNT_SW_BPF_OUTPUT** as **config**.
|
||||
*
|
||||
* The *flags* are used to indicate the index in *map* for which
|
||||
* the value must be put, masked with **BPF_F_INDEX_MASK**.
|
||||
* Alternatively, *flags* can be set to **BPF_F_CURRENT_CPU**
|
||||
* to indicate that the index of the current CPU core should be
|
||||
* used.
|
||||
*
|
||||
* The value to write, of *size*, is passed through eBPF stack and
|
||||
* pointed by *data*.
|
||||
*
|
||||
* *ctx* is a pointer to in-kernel struct sk_buff.
|
||||
*
|
||||
* This helper is similar to **bpf_perf_event_output**\ () but
|
||||
* restricted to raw_tracepoint bpf programs.
|
||||
* Return
|
||||
* 0 on success, or a negative error in case of failure.
|
||||
*
|
||||
* int bpf_probe_read_user(void *dst, u32 size, const void *unsafe_ptr)
|
||||
* Description
|
||||
* Safely attempt to read *size* bytes from user space address
|
||||
* *unsafe_ptr* and store the data in *dst*.
|
||||
* Return
|
||||
* 0 on success, or a negative error in case of failure.
|
||||
*
|
||||
* int bpf_probe_read_kernel(void *dst, u32 size, const void *unsafe_ptr)
|
||||
* Description
|
||||
* Safely attempt to read *size* bytes from kernel space address
|
||||
* *unsafe_ptr* and store the data in *dst*.
|
||||
* Return
|
||||
* 0 on success, or a negative error in case of failure.
|
||||
*
|
||||
* int bpf_probe_read_user_str(void *dst, u32 size, const void *unsafe_ptr)
|
||||
* Description
|
||||
* Copy a NUL terminated string from an unsafe user address
|
||||
* *unsafe_ptr* to *dst*. The *size* should include the
|
||||
* terminating NUL byte. In case the string length is smaller than
|
||||
* *size*, the target is not padded with further NUL bytes. If the
|
||||
* string length is larger than *size*, just *size*-1 bytes are
|
||||
* copied and the last byte is set to NUL.
|
||||
*
|
||||
* On success, the length of the copied string is returned. This
|
||||
* makes this helper useful in tracing programs for reading
|
||||
* strings, and more importantly to get its length at runtime. See
|
||||
* the following snippet:
|
||||
*
|
||||
* ::
|
||||
*
|
||||
* SEC("kprobe/sys_open")
|
||||
* void bpf_sys_open(struct pt_regs *ctx)
|
||||
* {
|
||||
* char buf[PATHLEN]; // PATHLEN is defined to 256
|
||||
* int res = bpf_probe_read_user_str(buf, sizeof(buf),
|
||||
* ctx->di);
|
||||
*
|
||||
* // Consume buf, for example push it to
|
||||
* // userspace via bpf_perf_event_output(); we
|
||||
* // can use res (the string length) as event
|
||||
* // size, after checking its boundaries.
|
||||
* }
|
||||
*
|
||||
* In comparison, using **bpf_probe_read_user()** helper here
|
||||
* instead to read the string would require to estimate the length
|
||||
* at compile time, and would often result in copying more memory
|
||||
* than necessary.
|
||||
*
|
||||
* Another useful use case is when parsing individual process
|
||||
* arguments or individual environment variables navigating
|
||||
* *current*\ **->mm->arg_start** and *current*\
|
||||
* **->mm->env_start**: using this helper and the return value,
|
||||
* one can quickly iterate at the right offset of the memory area.
|
||||
* Return
|
||||
* On success, the strictly positive length of the string,
|
||||
* including the trailing NUL character. On error, a negative
|
||||
* value.
|
||||
*
|
||||
* int bpf_probe_read_kernel_str(void *dst, u32 size, const void *unsafe_ptr)
|
||||
* Description
|
||||
* Copy a NUL terminated string from an unsafe kernel address *unsafe_ptr*
|
||||
* to *dst*. Same semantics as with bpf_probe_read_user_str() apply.
|
||||
* Return
|
||||
* On success, the strictly positive length of the string, including
|
||||
* the trailing NUL character. On error, a negative value.
|
||||
*/
|
||||
#define __BPF_FUNC_MAPPER(FN) \
|
||||
FN(unspec), \
|
||||
@@ -2862,7 +2933,12 @@ union bpf_attr {
|
||||
FN(sk_storage_get), \
|
||||
FN(sk_storage_delete), \
|
||||
FN(send_signal), \
|
||||
FN(tcp_gen_syncookie),
|
||||
FN(tcp_gen_syncookie), \
|
||||
FN(skb_output), \
|
||||
FN(probe_read_user), \
|
||||
FN(probe_read_kernel), \
|
||||
FN(probe_read_user_str), \
|
||||
FN(probe_read_kernel_str),
|
||||
|
||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||
* function eBPF program intends to call
|
||||
|
||||
@@ -167,6 +167,8 @@ enum {
|
||||
IFLA_NEW_IFINDEX,
|
||||
IFLA_MIN_MTU,
|
||||
IFLA_MAX_MTU,
|
||||
IFLA_PROP_LIST,
|
||||
IFLA_ALT_IFNAME, /* Alternative ifname */
|
||||
__IFLA_MAX
|
||||
};
|
||||
|
||||
|
||||
105
scripts/coverity.sh
Executable file
105
scripts/coverity.sh
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
|
||||
@@ -51,13 +51,13 @@ PATH_MAP=( \
|
||||
|
||||
LIBBPF_PATHS="${!PATH_MAP[@]}"
|
||||
LIBBPF_VIEW_PATHS="${PATH_MAP[@]}"
|
||||
LIBBPF_VIEW_EXCLUDE_REGEX='^src/(Makefile|Build|test_libbpf.cpp|\.gitignore)$'
|
||||
LIBBPF_VIEW_EXCLUDE_REGEX='^src/(Makefile|Build|test_libbpf\.c|bpf_helper_defs\.h|\.gitignore)$'
|
||||
|
||||
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.cpp,.gitignore} >/dev/null"
|
||||
LIBBPF_TREE_FILTER+="git rm --ignore-unmatch -f __libbpf/src/{Makefile,Build,test_libbpf.c,.gitignore} >/dev/null"
|
||||
|
||||
cd_to()
|
||||
{
|
||||
@@ -191,6 +191,7 @@ cherry_pick_commits()
|
||||
}
|
||||
|
||||
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
|
||||
@@ -198,6 +199,7 @@ 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})
|
||||
@@ -273,6 +275,24 @@ for patch in $(ls -1 ${TMP_DIR}/patches | tail -n +2); do
|
||||
fi
|
||||
done
|
||||
|
||||
# Generate bpf_helper_defs.h and commit, if anything changed
|
||||
# restore Linux tip to use bpf_helpers_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_helpers_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 -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)
|
||||
@@ -296,14 +316,12 @@ echo "SUCCESS! ${COMMIT_CNT} commits synced."
|
||||
echo "Verifying Linux's and Github's libbpf state"
|
||||
|
||||
cd_to ${LINUX_REPO}
|
||||
LINUX_ABS_DIR=$(pwd)
|
||||
git checkout -b ${VIEW_TAG} ${TIP_COMMIT}
|
||||
git filter-branch -f --tree-filter "${LIBBPF_TREE_FILTER}" ${VIEW_TAG}^..${VIEW_TAG}
|
||||
git filter-branch -f --subdirectory-filter __libbpf ${VIEW_TAG}^..${VIEW_TAG}
|
||||
git ls-files -- ${LIBBPF_VIEW_PATHS[@]} > ${TMP_DIR}/linux-view.ls
|
||||
|
||||
cd_to ${LIBBPF_REPO}
|
||||
GITHUB_ABS_DIR=$(pwd)
|
||||
git ls-files -- ${LIBBPF_VIEW_PATHS[@]} | grep -v -E "${LIBBPF_VIEW_EXCLUDE_REGEX}" > ${TMP_DIR}/github-view.ls
|
||||
|
||||
echo "Comparing list of files..."
|
||||
|
||||
@@ -18,7 +18,7 @@ endif
|
||||
SHARED_CFLAGS += -fPIC -fvisibility=hidden -DSHARED
|
||||
|
||||
CFLAGS ?= -g -O2 -Werror -Wall
|
||||
ALL_CFLAGS += $(CFLAGS)
|
||||
ALL_CFLAGS += $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
|
||||
ALL_LDFLAGS += $(LDFLAGS)
|
||||
ifdef NO_PKG_CONFIG
|
||||
ALL_LDFLAGS += -lelf
|
||||
@@ -45,7 +45,9 @@ ifndef BUILD_STATIC_ONLY
|
||||
VERSION_SCRIPT := libbpf.map
|
||||
endif
|
||||
|
||||
HEADERS := bpf.h libbpf.h btf.h xsk.h libbpf_util.h
|
||||
HEADERS := bpf.h libbpf.h btf.h xsk.h libbpf_util.h \
|
||||
bpf_helpers.h bpf_helper_defs.h bpf_tracing.h \
|
||||
bpf_endian.h bpf_core_read.h
|
||||
UAPI_HEADERS := $(addprefix $(TOPDIR)/include/uapi/linux/,\
|
||||
bpf.h bpf_common.h btf.h)
|
||||
|
||||
|
||||
11
src/bpf.c
11
src/bpf.c
@@ -189,7 +189,7 @@ static void *
|
||||
alloc_zero_tailing_info(const void *orecord, __u32 cnt,
|
||||
__u32 actual_rec_size, __u32 expected_rec_size)
|
||||
{
|
||||
__u64 info_len = actual_rec_size * cnt;
|
||||
__u64 info_len = (__u64)actual_rec_size * cnt;
|
||||
void *info, *nrecord;
|
||||
int i;
|
||||
|
||||
@@ -228,6 +228,13 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
attr.prog_type = load_attr->prog_type;
|
||||
attr.expected_attach_type = load_attr->expected_attach_type;
|
||||
if (attr.prog_type == BPF_PROG_TYPE_TRACING) {
|
||||
attr.attach_btf_id = load_attr->attach_btf_id;
|
||||
attr.attach_prog_fd = load_attr->attach_prog_fd;
|
||||
} else {
|
||||
attr.prog_ifindex = load_attr->prog_ifindex;
|
||||
attr.kern_version = load_attr->kern_version;
|
||||
}
|
||||
attr.insn_cnt = (__u32)load_attr->insns_cnt;
|
||||
attr.insns = ptr_to_u64(load_attr->insns);
|
||||
attr.license = ptr_to_u64(load_attr->license);
|
||||
@@ -241,8 +248,6 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
|
||||
attr.log_size = 0;
|
||||
}
|
||||
|
||||
attr.kern_version = load_attr->kern_version;
|
||||
attr.prog_ifindex = load_attr->prog_ifindex;
|
||||
attr.prog_btf_fd = load_attr->prog_btf_fd;
|
||||
attr.func_info_rec_size = load_attr->func_info_rec_size;
|
||||
attr.func_info_cnt = load_attr->func_info_cnt;
|
||||
|
||||
10
src/bpf.h
10
src/bpf.h
@@ -77,8 +77,14 @@ struct bpf_load_program_attr {
|
||||
const struct bpf_insn *insns;
|
||||
size_t insns_cnt;
|
||||
const char *license;
|
||||
__u32 kern_version;
|
||||
__u32 prog_ifindex;
|
||||
union {
|
||||
__u32 kern_version;
|
||||
__u32 attach_prog_fd;
|
||||
};
|
||||
union {
|
||||
__u32 prog_ifindex;
|
||||
__u32 attach_btf_id;
|
||||
};
|
||||
__u32 prog_btf_fd;
|
||||
__u32 func_info_rec_size;
|
||||
const void *func_info;
|
||||
|
||||
263
src/bpf_core_read.h
Normal file
263
src/bpf_core_read.h
Normal file
@@ -0,0 +1,263 @@
|
||||
/* 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,
|
||||
};
|
||||
|
||||
#define __CORE_RELO(src, field, info) \
|
||||
__builtin_preserve_field_info((src)->field, BPF_FIELD_##info)
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define __CORE_BITFIELD_PROBE_READ(dst, src, fld) \
|
||||
bpf_probe_read((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((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() to read underlying integer
|
||||
* storage. Macro functions as an expression and its return type is
|
||||
* bpf_probe_read()'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; \
|
||||
\
|
||||
switch (__CORE_RELO(s, field, BYTE_SIZE)) { \
|
||||
case 1: val = *(const unsigned char *)p; \
|
||||
case 2: val = *(const unsigned short *)p; \
|
||||
case 4: val = *(const unsigned int *)p; \
|
||||
case 8: val = *(const unsigned long long *)p; \
|
||||
} \
|
||||
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; \
|
||||
})
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#define bpf_core_field_exists(field) \
|
||||
__builtin_preserve_field_info(field, BPF_FIELD_EXISTS)
|
||||
|
||||
/*
|
||||
* Convenience macro to get byte size of a field. Works for integers,
|
||||
* struct/unions, pointers, arrays, and enums.
|
||||
*/
|
||||
#define bpf_core_field_size(field) \
|
||||
__builtin_preserve_field_info(field, BPF_FIELD_BYTE_SIZE)
|
||||
|
||||
/*
|
||||
* bpf_core_read() abstracts away bpf_probe_read() 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(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_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(src, a) ___read(bpf_core_read, &__t, ___type(src), src, a);
|
||||
#define ___rd_last(...) \
|
||||
___read(bpf_core_read, &__t, \
|
||||
___type(___nolast(__VA_ARGS__)), __t, ___last(__VA_ARGS__));
|
||||
#define ___rd_p1(...) const void *__t; ___rd_first(__VA_ARGS__)
|
||||
#define ___rd_p2(...) ___rd_p1(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
|
||||
#define ___rd_p3(...) ___rd_p2(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
|
||||
#define ___rd_p4(...) ___rd_p3(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
|
||||
#define ___rd_p5(...) ___rd_p4(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
|
||||
#define ___rd_p6(...) ___rd_p5(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
|
||||
#define ___rd_p7(...) ___rd_p6(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
|
||||
#define ___rd_p8(...) ___rd_p7(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
|
||||
#define ___rd_p9(...) ___rd_p8(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
|
||||
#define ___read_ptrs(src, ...) \
|
||||
___apply(___rd_p, ___narg(__VA_ARGS__))(src, __VA_ARGS__)
|
||||
|
||||
#define ___core_read0(fn, dst, src, a) \
|
||||
___read(fn, dst, ___type(src), src, a);
|
||||
#define ___core_readN(fn, dst, src, ...) \
|
||||
___read_ptrs(src, ___nolast(__VA_ARGS__)) \
|
||||
___read(fn, dst, ___type(src, ___nolast(__VA_ARGS__)), __t, \
|
||||
___last(__VA_ARGS__));
|
||||
#define ___core_read(fn, dst, src, a, ...) \
|
||||
___apply(___core_read, ___empty(__VA_ARGS__))(fn, 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, 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, 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() 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()
|
||||
* 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; \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
||||
72
src/bpf_endian.h
Normal file
72
src/bpf_endian.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
#ifndef __BPF_ENDIAN__
|
||||
#define __BPF_ENDIAN__
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/swab.h>
|
||||
|
||||
/* 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) ___constant_swab16(x)
|
||||
# define __bpf_constant_htons(x) ___constant_swab16(x)
|
||||
# define __bpf_ntohl(x) __builtin_bswap32(x)
|
||||
# define __bpf_htonl(x) __builtin_bswap32(x)
|
||||
# define __bpf_constant_ntohl(x) ___constant_swab32(x)
|
||||
# define __bpf_constant_htonl(x) ___constant_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) ___constant_swab64(x)
|
||||
# define __bpf_constant_cpu_to_be64(x) ___constant_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__ */
|
||||
2759
src/bpf_helper_defs.h
Normal file
2759
src/bpf_helper_defs.h
Normal file
File diff suppressed because it is too large
Load Diff
47
src/bpf_helpers.h
Normal file
47
src/bpf_helpers.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
#ifndef __BPF_HELPERS__
|
||||
#define __BPF_HELPERS__
|
||||
|
||||
#include "bpf_helper_defs.h"
|
||||
|
||||
#define __uint(name, val) int (*name)[val]
|
||||
#define __type(name, val) typeof(val) *name
|
||||
|
||||
/* Helper macro to print out debug messages */
|
||||
#define bpf_printk(fmt, ...) \
|
||||
({ \
|
||||
char ____fmt[] = fmt; \
|
||||
bpf_trace_printk(____fmt, sizeof(____fmt), \
|
||||
##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
/*
|
||||
* Helper macro to place programs, maps, license in
|
||||
* different sections in elf_bpf file. Section names
|
||||
* are interpreted by elf_bpf loader
|
||||
*/
|
||||
#define SEC(NAME) __attribute__((section(NAME), used))
|
||||
|
||||
#ifndef __always_inline
|
||||
#define __always_inline __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper structure used by eBPF C program
|
||||
* to describe BPF map attributes to libbpf loader
|
||||
*/
|
||||
struct bpf_map_def {
|
||||
unsigned int type;
|
||||
unsigned int key_size;
|
||||
unsigned int value_size;
|
||||
unsigned int max_entries;
|
||||
unsigned int map_flags;
|
||||
};
|
||||
|
||||
enum libbpf_pin_type {
|
||||
LIBBPF_PIN_NONE,
|
||||
/* PIN_BY_NAME: pin maps by name (in /sys/fs/bpf by default) */
|
||||
LIBBPF_PIN_BY_NAME,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -101,6 +101,7 @@ 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;
|
||||
|
||||
@@ -122,11 +123,11 @@ struct bpf_prog_linfo *bpf_prog_linfo__new(const struct bpf_prog_info *info)
|
||||
/* Copy xlated line_info */
|
||||
prog_linfo->nr_linfo = nr_linfo;
|
||||
prog_linfo->rec_size = info->line_info_rec_size;
|
||||
prog_linfo->raw_linfo = malloc(nr_linfo * prog_linfo->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,
|
||||
nr_linfo * prog_linfo->rec_size);
|
||||
memcpy(prog_linfo->raw_linfo, (void *)(long)info->line_info, data_sz);
|
||||
|
||||
nr_jited_func = info->nr_jited_ksyms;
|
||||
if (!nr_jited_func ||
|
||||
@@ -142,13 +143,12 @@ struct bpf_prog_linfo *bpf_prog_linfo__new(const struct bpf_prog_info *info)
|
||||
/* Copy jited_line_info */
|
||||
prog_linfo->nr_jited_func = nr_jited_func;
|
||||
prog_linfo->jited_rec_size = info->jited_line_info_rec_size;
|
||||
prog_linfo->raw_jited_linfo = malloc(nr_linfo *
|
||||
prog_linfo->jited_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,
|
||||
nr_linfo * prog_linfo->jited_rec_size);
|
||||
(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 *
|
||||
|
||||
195
src/bpf_tracing.h
Normal file
195
src/bpf_tracing.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
#ifndef __BPF_TRACING_H__
|
||||
#define __BPF_TRACING_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
|
||||
#else
|
||||
#undef bpf_target_defined
|
||||
#endif
|
||||
|
||||
/* Fall back to what the compiler says */
|
||||
#ifndef bpf_target_defined
|
||||
#if defined(__x86_64__)
|
||||
#define bpf_target_x86
|
||||
#elif defined(__s390__)
|
||||
#define bpf_target_s390
|
||||
#elif defined(__arm__)
|
||||
#define bpf_target_arm
|
||||
#elif defined(__aarch64__)
|
||||
#define bpf_target_arm64
|
||||
#elif defined(__mips__)
|
||||
#define bpf_target_mips
|
||||
#elif defined(__powerpc__)
|
||||
#define bpf_target_powerpc
|
||||
#elif defined(__sparc__)
|
||||
#define bpf_target_sparc
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(bpf_target_x86)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define PT_REGS_PARM1(x) ((x)->di)
|
||||
#define PT_REGS_PARM2(x) ((x)->si)
|
||||
#define PT_REGS_PARM3(x) ((x)->dx)
|
||||
#define PT_REGS_PARM4(x) ((x)->cx)
|
||||
#define PT_REGS_PARM5(x) ((x)->r8)
|
||||
#define PT_REGS_RET(x) ((x)->sp)
|
||||
#define PT_REGS_FP(x) ((x)->bp)
|
||||
#define PT_REGS_RC(x) ((x)->ax)
|
||||
#define PT_REGS_SP(x) ((x)->sp)
|
||||
#define PT_REGS_IP(x) ((x)->ip)
|
||||
#else
|
||||
#ifdef __i386__
|
||||
/* i386 kernel is built with -mregparm=3 */
|
||||
#define PT_REGS_PARM1(x) ((x)->eax)
|
||||
#define PT_REGS_PARM2(x) ((x)->edx)
|
||||
#define PT_REGS_PARM3(x) ((x)->ecx)
|
||||
#define PT_REGS_PARM4(x) 0
|
||||
#define PT_REGS_PARM5(x) 0
|
||||
#define PT_REGS_RET(x) ((x)->esp)
|
||||
#define PT_REGS_FP(x) ((x)->ebp)
|
||||
#define PT_REGS_RC(x) ((x)->eax)
|
||||
#define PT_REGS_SP(x) ((x)->esp)
|
||||
#define PT_REGS_IP(x) ((x)->eip)
|
||||
#else
|
||||
#define PT_REGS_PARM1(x) ((x)->rdi)
|
||||
#define PT_REGS_PARM2(x) ((x)->rsi)
|
||||
#define PT_REGS_PARM3(x) ((x)->rdx)
|
||||
#define PT_REGS_PARM4(x) ((x)->rcx)
|
||||
#define PT_REGS_PARM5(x) ((x)->r8)
|
||||
#define PT_REGS_RET(x) ((x)->rsp)
|
||||
#define PT_REGS_FP(x) ((x)->rbp)
|
||||
#define PT_REGS_RC(x) ((x)->rax)
|
||||
#define PT_REGS_SP(x) ((x)->rsp)
|
||||
#define PT_REGS_IP(x) ((x)->rip)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif defined(bpf_target_s390)
|
||||
|
||||
/* s390 provides user_pt_regs instead of struct pt_regs to userspace */
|
||||
struct pt_regs;
|
||||
#define PT_REGS_S390 const volatile user_pt_regs
|
||||
#define PT_REGS_PARM1(x) (((PT_REGS_S390 *)(x))->gprs[2])
|
||||
#define PT_REGS_PARM2(x) (((PT_REGS_S390 *)(x))->gprs[3])
|
||||
#define PT_REGS_PARM3(x) (((PT_REGS_S390 *)(x))->gprs[4])
|
||||
#define PT_REGS_PARM4(x) (((PT_REGS_S390 *)(x))->gprs[5])
|
||||
#define PT_REGS_PARM5(x) (((PT_REGS_S390 *)(x))->gprs[6])
|
||||
#define PT_REGS_RET(x) (((PT_REGS_S390 *)(x))->gprs[14])
|
||||
/* Works only with CONFIG_FRAME_POINTER */
|
||||
#define PT_REGS_FP(x) (((PT_REGS_S390 *)(x))->gprs[11])
|
||||
#define PT_REGS_RC(x) (((PT_REGS_S390 *)(x))->gprs[2])
|
||||
#define PT_REGS_SP(x) (((PT_REGS_S390 *)(x))->gprs[15])
|
||||
#define PT_REGS_IP(x) (((PT_REGS_S390 *)(x))->psw.addr)
|
||||
|
||||
#elif defined(bpf_target_arm)
|
||||
|
||||
#define PT_REGS_PARM1(x) ((x)->uregs[0])
|
||||
#define PT_REGS_PARM2(x) ((x)->uregs[1])
|
||||
#define PT_REGS_PARM3(x) ((x)->uregs[2])
|
||||
#define PT_REGS_PARM4(x) ((x)->uregs[3])
|
||||
#define PT_REGS_PARM5(x) ((x)->uregs[4])
|
||||
#define PT_REGS_RET(x) ((x)->uregs[14])
|
||||
#define PT_REGS_FP(x) ((x)->uregs[11]) /* Works only with CONFIG_FRAME_POINTER */
|
||||
#define PT_REGS_RC(x) ((x)->uregs[0])
|
||||
#define PT_REGS_SP(x) ((x)->uregs[13])
|
||||
#define PT_REGS_IP(x) ((x)->uregs[12])
|
||||
|
||||
#elif defined(bpf_target_arm64)
|
||||
|
||||
/* arm64 provides struct user_pt_regs instead of struct pt_regs to userspace */
|
||||
struct pt_regs;
|
||||
#define PT_REGS_ARM64 const volatile struct user_pt_regs
|
||||
#define PT_REGS_PARM1(x) (((PT_REGS_ARM64 *)(x))->regs[0])
|
||||
#define PT_REGS_PARM2(x) (((PT_REGS_ARM64 *)(x))->regs[1])
|
||||
#define PT_REGS_PARM3(x) (((PT_REGS_ARM64 *)(x))->regs[2])
|
||||
#define PT_REGS_PARM4(x) (((PT_REGS_ARM64 *)(x))->regs[3])
|
||||
#define PT_REGS_PARM5(x) (((PT_REGS_ARM64 *)(x))->regs[4])
|
||||
#define PT_REGS_RET(x) (((PT_REGS_ARM64 *)(x))->regs[30])
|
||||
/* Works only with CONFIG_FRAME_POINTER */
|
||||
#define PT_REGS_FP(x) (((PT_REGS_ARM64 *)(x))->regs[29])
|
||||
#define PT_REGS_RC(x) (((PT_REGS_ARM64 *)(x))->regs[0])
|
||||
#define PT_REGS_SP(x) (((PT_REGS_ARM64 *)(x))->sp)
|
||||
#define PT_REGS_IP(x) (((PT_REGS_ARM64 *)(x))->pc)
|
||||
|
||||
#elif defined(bpf_target_mips)
|
||||
|
||||
#define PT_REGS_PARM1(x) ((x)->regs[4])
|
||||
#define PT_REGS_PARM2(x) ((x)->regs[5])
|
||||
#define PT_REGS_PARM3(x) ((x)->regs[6])
|
||||
#define PT_REGS_PARM4(x) ((x)->regs[7])
|
||||
#define PT_REGS_PARM5(x) ((x)->regs[8])
|
||||
#define PT_REGS_RET(x) ((x)->regs[31])
|
||||
#define PT_REGS_FP(x) ((x)->regs[30]) /* Works only with CONFIG_FRAME_POINTER */
|
||||
#define PT_REGS_RC(x) ((x)->regs[1])
|
||||
#define PT_REGS_SP(x) ((x)->regs[29])
|
||||
#define PT_REGS_IP(x) ((x)->cp0_epc)
|
||||
|
||||
#elif defined(bpf_target_powerpc)
|
||||
|
||||
#define PT_REGS_PARM1(x) ((x)->gpr[3])
|
||||
#define PT_REGS_PARM2(x) ((x)->gpr[4])
|
||||
#define PT_REGS_PARM3(x) ((x)->gpr[5])
|
||||
#define PT_REGS_PARM4(x) ((x)->gpr[6])
|
||||
#define PT_REGS_PARM5(x) ((x)->gpr[7])
|
||||
#define PT_REGS_RC(x) ((x)->gpr[3])
|
||||
#define PT_REGS_SP(x) ((x)->sp)
|
||||
#define PT_REGS_IP(x) ((x)->nip)
|
||||
|
||||
#elif defined(bpf_target_sparc)
|
||||
|
||||
#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0])
|
||||
#define PT_REGS_PARM2(x) ((x)->u_regs[UREG_I1])
|
||||
#define PT_REGS_PARM3(x) ((x)->u_regs[UREG_I2])
|
||||
#define PT_REGS_PARM4(x) ((x)->u_regs[UREG_I3])
|
||||
#define PT_REGS_PARM5(x) ((x)->u_regs[UREG_I4])
|
||||
#define PT_REGS_RET(x) ((x)->u_regs[UREG_I7])
|
||||
#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0])
|
||||
#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP])
|
||||
|
||||
/* Should this also be a bpf_target check for the sparc case? */
|
||||
#if defined(__arch64__)
|
||||
#define PT_REGS_IP(x) ((x)->tpc)
|
||||
#else
|
||||
#define PT_REGS_IP(x) ((x)->pc)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#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(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); })
|
||||
#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) \
|
||||
({ bpf_probe_read(&(ip), sizeof(ip), \
|
||||
(void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
|
||||
#endif
|
||||
|
||||
#endif
|
||||
97
src/btf.c
97
src/btf.c
@@ -269,10 +269,9 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
|
||||
t = btf__type_by_id(btf, type_id);
|
||||
}
|
||||
|
||||
done:
|
||||
if (size < 0)
|
||||
return -EINVAL;
|
||||
|
||||
done:
|
||||
if (nelems && size > UINT32_MAX / nelems)
|
||||
return -E2BIG;
|
||||
|
||||
@@ -317,6 +316,28 @@ __s32 btf__find_by_name(const struct btf *btf, const char *type_name)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
__s32 btf__find_by_name_kind(const struct btf *btf, const char *type_name,
|
||||
__u32 kind)
|
||||
{
|
||||
__u32 i;
|
||||
|
||||
if (kind == BTF_KIND_UNKN || !strcmp(type_name, "void"))
|
||||
return 0;
|
||||
|
||||
for (i = 1; i <= btf->nr_types; i++) {
|
||||
const struct btf_type *t = btf->types[i];
|
||||
const char *name;
|
||||
|
||||
if (btf_kind(t) != kind)
|
||||
continue;
|
||||
name = btf__name_by_offset(btf, t->name_off);
|
||||
if (name && !strcmp(type_name, name))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
void btf__free(struct btf *btf)
|
||||
{
|
||||
if (!btf)
|
||||
@@ -390,14 +411,14 @@ struct btf *btf__parse_elf(const char *path, struct btf_ext **btf_ext)
|
||||
GElf_Ehdr ehdr;
|
||||
|
||||
if (elf_version(EV_CURRENT) == EV_NONE) {
|
||||
pr_warning("failed to init libelf for %s\n", path);
|
||||
pr_warn("failed to init libelf for %s\n", path);
|
||||
return ERR_PTR(-LIBBPF_ERRNO__LIBELF);
|
||||
}
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
err = -errno;
|
||||
pr_warning("failed to open %s: %s\n", path, strerror(errno));
|
||||
pr_warn("failed to open %s: %s\n", path, strerror(errno));
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
@@ -405,19 +426,19 @@ struct btf *btf__parse_elf(const char *path, struct btf_ext **btf_ext)
|
||||
|
||||
elf = elf_begin(fd, ELF_C_READ, NULL);
|
||||
if (!elf) {
|
||||
pr_warning("failed to open %s as ELF file\n", path);
|
||||
pr_warn("failed to open %s as ELF file\n", path);
|
||||
goto done;
|
||||
}
|
||||
if (!gelf_getehdr(elf, &ehdr)) {
|
||||
pr_warning("failed to get EHDR from %s\n", path);
|
||||
pr_warn("failed to get EHDR from %s\n", path);
|
||||
goto done;
|
||||
}
|
||||
if (!btf_check_endianness(&ehdr)) {
|
||||
pr_warning("non-native ELF endianness is not supported\n");
|
||||
pr_warn("non-native ELF endianness is not supported\n");
|
||||
goto done;
|
||||
}
|
||||
if (!elf_rawdata(elf_getscn(elf, ehdr.e_shstrndx), NULL)) {
|
||||
pr_warning("failed to get e_shstrndx from %s\n", path);
|
||||
pr_warn("failed to get e_shstrndx from %s\n", path);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -427,29 +448,29 @@ struct btf *btf__parse_elf(const char *path, struct btf_ext **btf_ext)
|
||||
|
||||
idx++;
|
||||
if (gelf_getshdr(scn, &sh) != &sh) {
|
||||
pr_warning("failed to get section(%d) header from %s\n",
|
||||
idx, path);
|
||||
pr_warn("failed to get section(%d) header from %s\n",
|
||||
idx, path);
|
||||
goto done;
|
||||
}
|
||||
name = elf_strptr(elf, ehdr.e_shstrndx, sh.sh_name);
|
||||
if (!name) {
|
||||
pr_warning("failed to get section(%d) name from %s\n",
|
||||
idx, path);
|
||||
pr_warn("failed to get section(%d) name from %s\n",
|
||||
idx, path);
|
||||
goto done;
|
||||
}
|
||||
if (strcmp(name, BTF_ELF_SEC) == 0) {
|
||||
btf_data = elf_getdata(scn, 0);
|
||||
if (!btf_data) {
|
||||
pr_warning("failed to get section(%d, %s) data from %s\n",
|
||||
idx, name, path);
|
||||
pr_warn("failed to get section(%d, %s) data from %s\n",
|
||||
idx, name, path);
|
||||
goto done;
|
||||
}
|
||||
continue;
|
||||
} else if (btf_ext && strcmp(name, BTF_EXT_ELF_SEC) == 0) {
|
||||
btf_ext_data = elf_getdata(scn, 0);
|
||||
if (!btf_ext_data) {
|
||||
pr_warning("failed to get section(%d, %s) data from %s\n",
|
||||
idx, name, path);
|
||||
pr_warn("failed to get section(%d, %s) data from %s\n",
|
||||
idx, name, path);
|
||||
goto done;
|
||||
}
|
||||
continue;
|
||||
@@ -600,9 +621,9 @@ int btf__load(struct btf *btf)
|
||||
log_buf, log_buf_size, false);
|
||||
if (btf->fd < 0) {
|
||||
err = -errno;
|
||||
pr_warning("Error loading BTF: %s(%d)\n", strerror(errno), errno);
|
||||
pr_warn("Error loading BTF: %s(%d)\n", strerror(errno), errno);
|
||||
if (*log_buf)
|
||||
pr_warning("%s\n", log_buf);
|
||||
pr_warn("%s\n", log_buf);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -707,8 +728,8 @@ int btf__get_map_kv_tids(const struct btf *btf, const char *map_name,
|
||||
|
||||
if (snprintf(container_name, max_name, "____btf_map_%s", map_name) ==
|
||||
max_name) {
|
||||
pr_warning("map:%s length of '____btf_map_%s' is too long\n",
|
||||
map_name, map_name);
|
||||
pr_warn("map:%s length of '____btf_map_%s' is too long\n",
|
||||
map_name, map_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -721,14 +742,14 @@ int btf__get_map_kv_tids(const struct btf *btf, const char *map_name,
|
||||
|
||||
container_type = btf__type_by_id(btf, container_id);
|
||||
if (!container_type) {
|
||||
pr_warning("map:%s cannot find BTF type for container_id:%u\n",
|
||||
map_name, container_id);
|
||||
pr_warn("map:%s cannot find BTF type for container_id:%u\n",
|
||||
map_name, container_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!btf_is_struct(container_type) || btf_vlen(container_type) < 2) {
|
||||
pr_warning("map:%s container_name:%s is an invalid container struct\n",
|
||||
map_name, container_name);
|
||||
pr_warn("map:%s container_name:%s is an invalid container struct\n",
|
||||
map_name, container_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -737,25 +758,25 @@ int btf__get_map_kv_tids(const struct btf *btf, const char *map_name,
|
||||
|
||||
key_size = btf__resolve_size(btf, key->type);
|
||||
if (key_size < 0) {
|
||||
pr_warning("map:%s invalid BTF key_type_size\n", map_name);
|
||||
pr_warn("map:%s invalid BTF key_type_size\n", map_name);
|
||||
return key_size;
|
||||
}
|
||||
|
||||
if (expected_key_size != key_size) {
|
||||
pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n",
|
||||
map_name, (__u32)key_size, expected_key_size);
|
||||
pr_warn("map:%s btf_key_type_size:%u != map_def_key_size:%u\n",
|
||||
map_name, (__u32)key_size, expected_key_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
value_size = btf__resolve_size(btf, value->type);
|
||||
if (value_size < 0) {
|
||||
pr_warning("map:%s invalid BTF value_type_size\n", map_name);
|
||||
pr_warn("map:%s invalid BTF value_type_size\n", map_name);
|
||||
return value_size;
|
||||
}
|
||||
|
||||
if (expected_value_size != value_size) {
|
||||
pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n",
|
||||
map_name, (__u32)value_size, expected_value_size);
|
||||
pr_warn("map:%s btf_value_type_size:%u != map_def_value_size:%u\n",
|
||||
map_name, (__u32)value_size, expected_value_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -888,14 +909,14 @@ static int btf_ext_setup_line_info(struct btf_ext *btf_ext)
|
||||
return btf_ext_setup_info(btf_ext, ¶m);
|
||||
}
|
||||
|
||||
static int btf_ext_setup_offset_reloc(struct btf_ext *btf_ext)
|
||||
static int btf_ext_setup_field_reloc(struct btf_ext *btf_ext)
|
||||
{
|
||||
struct btf_ext_sec_setup_param param = {
|
||||
.off = btf_ext->hdr->offset_reloc_off,
|
||||
.len = btf_ext->hdr->offset_reloc_len,
|
||||
.min_rec_size = sizeof(struct bpf_offset_reloc),
|
||||
.ext_info = &btf_ext->offset_reloc_info,
|
||||
.desc = "offset_reloc",
|
||||
.off = btf_ext->hdr->field_reloc_off,
|
||||
.len = btf_ext->hdr->field_reloc_len,
|
||||
.min_rec_size = sizeof(struct bpf_field_reloc),
|
||||
.ext_info = &btf_ext->field_reloc_info,
|
||||
.desc = "field_reloc",
|
||||
};
|
||||
|
||||
return btf_ext_setup_info(btf_ext, ¶m);
|
||||
@@ -975,9 +996,9 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size)
|
||||
goto done;
|
||||
|
||||
if (btf_ext->hdr->hdr_len <
|
||||
offsetofend(struct btf_ext_header, offset_reloc_len))
|
||||
offsetofend(struct btf_ext_header, field_reloc_len))
|
||||
goto done;
|
||||
err = btf_ext_setup_offset_reloc(btf_ext);
|
||||
err = btf_ext_setup_field_reloc(btf_ext);
|
||||
if (err)
|
||||
goto done;
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@ struct btf_ext_header {
|
||||
__u32 line_info_len;
|
||||
|
||||
/* optional part of .BTF.ext header */
|
||||
__u32 offset_reloc_off;
|
||||
__u32 offset_reloc_len;
|
||||
__u32 field_reloc_off;
|
||||
__u32 field_reloc_len;
|
||||
};
|
||||
|
||||
LIBBPF_API void btf__free(struct btf *btf);
|
||||
@@ -72,6 +72,8 @@ LIBBPF_API int btf__finalize_data(struct bpf_object *obj, struct btf *btf);
|
||||
LIBBPF_API int btf__load(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__get_nr_types(const struct btf *btf);
|
||||
LIBBPF_API const struct btf_type *btf__type_by_id(const struct btf *btf,
|
||||
__u32 id);
|
||||
|
||||
@@ -428,7 +428,7 @@ static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr)
|
||||
/* type loop, but resolvable through fwd declaration */
|
||||
if (btf_is_composite(t) && through_ptr && t->name_off != 0)
|
||||
return 0;
|
||||
pr_warning("unsatisfiable type cycle, id:[%u]\n", id);
|
||||
pr_warn("unsatisfiable type cycle, id:[%u]\n", id);
|
||||
return -ELOOP;
|
||||
}
|
||||
|
||||
@@ -636,8 +636,8 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id)
|
||||
if (id == cont_id)
|
||||
return;
|
||||
if (t->name_off == 0) {
|
||||
pr_warning("anonymous struct/union loop, id:[%u]\n",
|
||||
id);
|
||||
pr_warn("anonymous struct/union loop, id:[%u]\n",
|
||||
id);
|
||||
return;
|
||||
}
|
||||
btf_dump_emit_struct_fwd(d, id, t);
|
||||
@@ -782,7 +782,7 @@ static int btf_align_of(const struct btf *btf, __u32 id)
|
||||
return align;
|
||||
}
|
||||
default:
|
||||
pr_warning("unsupported BTF_KIND:%u\n", btf_kind(t));
|
||||
pr_warn("unsupported BTF_KIND:%u\n", btf_kind(t));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -876,7 +876,6 @@ static void btf_dump_emit_struct_def(struct btf_dump *d,
|
||||
__u16 vlen = btf_vlen(t);
|
||||
|
||||
packed = is_struct ? btf_is_struct_packed(d->btf, id, t) : 0;
|
||||
align = packed ? 1 : btf_align_of(d->btf, id);
|
||||
|
||||
btf_dump_printf(d, "%s%s%s {",
|
||||
is_struct ? "struct" : "union",
|
||||
@@ -906,6 +905,13 @@ static void btf_dump_emit_struct_def(struct btf_dump *d,
|
||||
btf_dump_printf(d, ";");
|
||||
}
|
||||
|
||||
/* pad at the end, if necessary */
|
||||
if (is_struct) {
|
||||
align = packed ? 1 : btf_align_of(d->btf, id);
|
||||
btf_dump_emit_bit_padding(d, off, t->size * 8, 0, align,
|
||||
lvl + 1);
|
||||
}
|
||||
|
||||
if (vlen)
|
||||
btf_dump_printf(d, "\n");
|
||||
btf_dump_printf(d, "%s}", pfx(lvl));
|
||||
@@ -969,6 +975,17 @@ static void btf_dump_emit_typedef_def(struct btf_dump *d, __u32 id,
|
||||
{
|
||||
const char *name = btf_dump_ident_name(d, id);
|
||||
|
||||
/*
|
||||
* Old GCC versions are emitting invalid typedef for __gnuc_va_list
|
||||
* pointing to VOID. This generates warnings from btf_dump() and
|
||||
* results in uncompilable header file, so we are fixing it up here
|
||||
* with valid typedef into __builtin_va_list.
|
||||
*/
|
||||
if (t->type == 0 && strcmp(name, "__gnuc_va_list") == 0) {
|
||||
btf_dump_printf(d, "typedef __builtin_va_list __gnuc_va_list");
|
||||
return;
|
||||
}
|
||||
|
||||
btf_dump_printf(d, "typedef ");
|
||||
btf_dump_emit_type_decl(d, t->type, name, lvl);
|
||||
}
|
||||
@@ -1050,7 +1067,7 @@ static void btf_dump_emit_type_decl(struct btf_dump *d, __u32 id,
|
||||
* chain, restore stack, emit warning, and try to
|
||||
* proceed nevertheless
|
||||
*/
|
||||
pr_warning("not enough memory for decl stack:%d", err);
|
||||
pr_warn("not enough memory for decl stack:%d", err);
|
||||
d->decl_stack_cnt = stack_start;
|
||||
return;
|
||||
}
|
||||
@@ -1079,8 +1096,8 @@ static void btf_dump_emit_type_decl(struct btf_dump *d, __u32 id,
|
||||
case BTF_KIND_TYPEDEF:
|
||||
goto done;
|
||||
default:
|
||||
pr_warning("unexpected type in decl chain, kind:%u, id:[%u]\n",
|
||||
btf_kind(t), id);
|
||||
pr_warn("unexpected type in decl chain, kind:%u, id:[%u]\n",
|
||||
btf_kind(t), id);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@@ -1306,8 +1323,8 @@ static void btf_dump_emit_type_chain(struct btf_dump *d,
|
||||
return;
|
||||
}
|
||||
default:
|
||||
pr_warning("unexpected type in decl chain, kind:%u, id:[%u]\n",
|
||||
kind, id);
|
||||
pr_warn("unexpected type in decl chain, kind:%u, id:[%u]\n",
|
||||
kind, id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
2137
src/libbpf.c
2137
src/libbpf.c
File diff suppressed because it is too large
Load Diff
99
src/libbpf.h
99
src/libbpf.h
@@ -67,18 +67,80 @@ struct bpf_object_open_attr {
|
||||
enum bpf_prog_type prog_type;
|
||||
};
|
||||
|
||||
/* 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 DECLARE_LIBBPF_OPTS(TYPE, NAME, ...) \
|
||||
struct TYPE NAME = ({ \
|
||||
memset(&NAME, 0, sizeof(struct TYPE)); \
|
||||
(struct TYPE) { \
|
||||
.sz = sizeof(struct TYPE), \
|
||||
__VA_ARGS__ \
|
||||
}; \
|
||||
})
|
||||
|
||||
struct bpf_object_open_opts {
|
||||
/* size of this struct, for forward/backward compatiblity */
|
||||
size_t sz;
|
||||
/* object name override, if provided:
|
||||
* - for object open from file, this will override setting object
|
||||
* name from file path's base name;
|
||||
* - for object open from memory buffer, this will specify an object
|
||||
* name and will override default "<addr>-<buf-size>" name;
|
||||
*/
|
||||
const char *object_name;
|
||||
/* parse map definitions non-strictly, allowing extra attributes/data */
|
||||
bool relaxed_maps;
|
||||
/* process CO-RE relocations non-strictly, allowing them to fail */
|
||||
bool relaxed_core_relocs;
|
||||
/* maps that set the 'pinning' attribute in their definition will have
|
||||
* their pin_path attribute set to a file in this directory, and be
|
||||
* auto-pinned to that path on load; defaults to "/sys/fs/bpf".
|
||||
*/
|
||||
const char *pin_root_path;
|
||||
__u32 attach_prog_fd;
|
||||
};
|
||||
#define bpf_object_open_opts__last_field attach_prog_fd
|
||||
|
||||
LIBBPF_API struct bpf_object *bpf_object__open(const char *path);
|
||||
LIBBPF_API struct bpf_object *
|
||||
bpf_object__open_file(const char *path, struct bpf_object_open_opts *opts);
|
||||
LIBBPF_API struct bpf_object *
|
||||
bpf_object__open_mem(const void *obj_buf, size_t obj_buf_sz,
|
||||
struct bpf_object_open_opts *opts);
|
||||
|
||||
/* deprecated bpf_object__open variants */
|
||||
LIBBPF_API struct bpf_object *
|
||||
bpf_object__open_buffer(const void *obj_buf, size_t obj_buf_sz,
|
||||
const char *name);
|
||||
LIBBPF_API struct bpf_object *
|
||||
bpf_object__open_xattr(struct bpf_object_open_attr *attr);
|
||||
struct bpf_object *__bpf_object__open_xattr(struct bpf_object_open_attr *attr,
|
||||
int flags);
|
||||
LIBBPF_API struct bpf_object *bpf_object__open_buffer(void *obj_buf,
|
||||
size_t obj_buf_sz,
|
||||
const char *name);
|
||||
|
||||
int bpf_object__section_size(const struct bpf_object *obj, const char *name,
|
||||
__u32 *size);
|
||||
int bpf_object__variable_offset(const struct bpf_object *obj, const char *name,
|
||||
__u32 *off);
|
||||
|
||||
enum libbpf_pin_type {
|
||||
LIBBPF_PIN_NONE,
|
||||
/* PIN_BY_NAME: pin maps by name (in /sys/fs/bpf by default) */
|
||||
LIBBPF_PIN_BY_NAME,
|
||||
};
|
||||
|
||||
/* pin_maps and unpin_maps can both be called with a NULL path, in which case
|
||||
* they will use the pin_path attribute of each map (and ignore all maps that
|
||||
* don't have a pin_path set).
|
||||
*/
|
||||
LIBBPF_API int bpf_object__pin_maps(struct bpf_object *obj, const char *path);
|
||||
LIBBPF_API int bpf_object__unpin_maps(struct bpf_object *obj,
|
||||
const char *path);
|
||||
@@ -127,6 +189,8 @@ libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
|
||||
enum bpf_attach_type *expected_attach_type);
|
||||
LIBBPF_API int libbpf_attach_type_by_name(const char *name,
|
||||
enum bpf_attach_type *attach_type);
|
||||
LIBBPF_API int libbpf_find_vmlinux_btf_id(const char *name,
|
||||
enum bpf_attach_type attach_type);
|
||||
|
||||
/* Accessors of bpf_program */
|
||||
struct bpf_program;
|
||||
@@ -153,6 +217,9 @@ LIBBPF_API void bpf_program__set_ifindex(struct bpf_program *prog,
|
||||
LIBBPF_API const char *bpf_program__title(const struct bpf_program *prog,
|
||||
bool needs_copy);
|
||||
|
||||
/* returns program size in bytes */
|
||||
LIBBPF_API size_t bpf_program__size(const struct bpf_program *prog);
|
||||
|
||||
LIBBPF_API int bpf_program__load(struct bpf_program *prog, char *license,
|
||||
__u32 kern_version);
|
||||
LIBBPF_API int bpf_program__fd(const struct bpf_program *prog);
|
||||
@@ -187,6 +254,8 @@ LIBBPF_API struct bpf_link *
|
||||
bpf_program__attach_raw_tracepoint(struct bpf_program *prog,
|
||||
const char *tp_name);
|
||||
|
||||
LIBBPF_API struct bpf_link *
|
||||
bpf_program__attach_trace(struct bpf_program *prog);
|
||||
struct bpf_insn;
|
||||
|
||||
/*
|
||||
@@ -262,8 +331,14 @@ LIBBPF_API int bpf_program__set_sched_cls(struct bpf_program *prog);
|
||||
LIBBPF_API int bpf_program__set_sched_act(struct bpf_program *prog);
|
||||
LIBBPF_API int bpf_program__set_xdp(struct bpf_program *prog);
|
||||
LIBBPF_API int bpf_program__set_perf_event(struct bpf_program *prog);
|
||||
LIBBPF_API int bpf_program__set_tracing(struct bpf_program *prog);
|
||||
|
||||
LIBBPF_API enum bpf_prog_type bpf_program__get_type(struct bpf_program *prog);
|
||||
LIBBPF_API void bpf_program__set_type(struct bpf_program *prog,
|
||||
enum bpf_prog_type type);
|
||||
|
||||
LIBBPF_API enum bpf_attach_type
|
||||
bpf_program__get_expected_attach_type(struct bpf_program *prog);
|
||||
LIBBPF_API void
|
||||
bpf_program__set_expected_attach_type(struct bpf_program *prog,
|
||||
enum bpf_attach_type type);
|
||||
@@ -276,6 +351,7 @@ LIBBPF_API bool bpf_program__is_sched_cls(const struct bpf_program *prog);
|
||||
LIBBPF_API bool bpf_program__is_sched_act(const struct bpf_program *prog);
|
||||
LIBBPF_API bool bpf_program__is_xdp(const struct bpf_program *prog);
|
||||
LIBBPF_API bool bpf_program__is_perf_event(const struct bpf_program *prog);
|
||||
LIBBPF_API bool bpf_program__is_tracing(const struct bpf_program *prog);
|
||||
|
||||
/*
|
||||
* No need for __attribute__((packed)), all members of 'bpf_map_def'
|
||||
@@ -335,6 +411,9 @@ LIBBPF_API int bpf_map__resize(struct bpf_map *map, __u32 max_entries);
|
||||
LIBBPF_API bool bpf_map__is_offload_neutral(const struct bpf_map *map);
|
||||
LIBBPF_API bool bpf_map__is_internal(const struct bpf_map *map);
|
||||
LIBBPF_API void bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex);
|
||||
LIBBPF_API int bpf_map__set_pin_path(struct bpf_map *map, const char *path);
|
||||
LIBBPF_API const char *bpf_map__get_pin_path(const struct bpf_map *map);
|
||||
LIBBPF_API bool bpf_map__is_pinned(const struct bpf_map *map);
|
||||
LIBBPF_API int bpf_map__pin(struct bpf_map *map, const char *path);
|
||||
LIBBPF_API int bpf_map__unpin(struct bpf_map *map, const char *path);
|
||||
|
||||
@@ -356,8 +435,18 @@ LIBBPF_API int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
|
||||
LIBBPF_API int bpf_prog_load(const char *file, enum bpf_prog_type type,
|
||||
struct bpf_object **pobj, int *prog_fd);
|
||||
|
||||
struct xdp_link_info {
|
||||
__u32 prog_id;
|
||||
__u32 drv_prog_id;
|
||||
__u32 hw_prog_id;
|
||||
__u32 skb_prog_id;
|
||||
__u8 attach_mode;
|
||||
};
|
||||
|
||||
LIBBPF_API int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags);
|
||||
LIBBPF_API int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags);
|
||||
LIBBPF_API int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
|
||||
size_t info_size, __u32 flags);
|
||||
|
||||
struct perf_buffer;
|
||||
|
||||
|
||||
@@ -190,3 +190,21 @@ LIBBPF_0.0.5 {
|
||||
global:
|
||||
bpf_btf_get_next_id;
|
||||
} LIBBPF_0.0.4;
|
||||
|
||||
LIBBPF_0.0.6 {
|
||||
global:
|
||||
bpf_get_link_xdp_info;
|
||||
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;
|
||||
bpf_program__is_tracing;
|
||||
bpf_program__set_tracing;
|
||||
bpf_program__size;
|
||||
btf__find_by_name_kind;
|
||||
libbpf_find_vmlinux_btf_id;
|
||||
} LIBBPF_0.0.5;
|
||||
|
||||
@@ -59,10 +59,42 @@ do { \
|
||||
libbpf_print(level, "libbpf: " fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define pr_warning(fmt, ...) __pr(LIBBPF_WARN, fmt, ##__VA_ARGS__)
|
||||
#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__)
|
||||
|
||||
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 (user_sz > opts_sz) {
|
||||
size_t i;
|
||||
|
||||
for (i = opts_sz; i < user_sz; i++) {
|
||||
if (opts[i]) {
|
||||
pr_warn("%s has non-zero extra bytes",
|
||||
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)
|
||||
|
||||
int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
|
||||
const char *str_sec, size_t str_len);
|
||||
|
||||
@@ -94,7 +126,7 @@ struct btf_ext {
|
||||
};
|
||||
struct btf_ext_info func_info;
|
||||
struct btf_ext_info line_info;
|
||||
struct btf_ext_info offset_reloc_info;
|
||||
struct btf_ext_info field_reloc_info;
|
||||
__u32 data_size;
|
||||
};
|
||||
|
||||
@@ -119,13 +151,27 @@ struct bpf_line_info_min {
|
||||
__u32 line_col;
|
||||
};
|
||||
|
||||
/* The minimum bpf_offset_reloc checked by the loader
|
||||
/* bpf_field_info_kind encodes which aspect of captured field has to be
|
||||
* adjusted by relocations. Currently supported values are:
|
||||
* - BPF_FIELD_BYTE_OFFSET: field offset (in bytes);
|
||||
* - BPF_FIELD_EXISTS: field existence (1, if field exists; 0, otherwise);
|
||||
*/
|
||||
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,
|
||||
};
|
||||
|
||||
/* The minimum bpf_field_reloc checked by the loader
|
||||
*
|
||||
* Offset relocation captures the following data:
|
||||
* Field relocation captures the following data:
|
||||
* - insn_off - instruction offset (in bytes) within a BPF program that needs
|
||||
* its insn->imm field to be relocated with actual offset;
|
||||
* its insn->imm field to be relocated with actual field info;
|
||||
* - type_id - BTF type ID of the "root" (containing) entity of a relocatable
|
||||
* offset;
|
||||
* field;
|
||||
* - access_str_off - offset into corresponding .BTF string section. String
|
||||
* itself encodes an accessed field using a sequence of field and array
|
||||
* indicies, separated by colon (:). It's conceptually very close to LLVM's
|
||||
@@ -156,15 +202,16 @@ struct bpf_line_info_min {
|
||||
* bpf_probe_read(&dst, sizeof(dst),
|
||||
* __builtin_preserve_access_index(&src->a.b.c));
|
||||
*
|
||||
* In this case Clang will emit offset relocation recording necessary data to
|
||||
* In this case Clang will emit field relocation recording necessary data to
|
||||
* be able to find offset of embedded `a.b.c` field within `src` struct.
|
||||
*
|
||||
* [0] https://llvm.org/docs/LangRef.html#getelementptr-instruction
|
||||
*/
|
||||
struct bpf_offset_reloc {
|
||||
struct bpf_field_reloc {
|
||||
__u32 insn_off;
|
||||
__u32 type_id;
|
||||
__u32 access_str_off;
|
||||
enum bpf_field_info_kind kind;
|
||||
};
|
||||
|
||||
#endif /* __LIBBPF_LIBBPF_INTERNAL_H */
|
||||
|
||||
@@ -102,6 +102,7 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
|
||||
case BPF_PROG_TYPE_FLOW_DISSECTOR:
|
||||
case BPF_PROG_TYPE_CGROUP_SYSCTL:
|
||||
case BPF_PROG_TYPE_CGROUP_SOCKOPT:
|
||||
case BPF_PROG_TYPE_TRACING:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "bpf.h"
|
||||
#include "libbpf.h"
|
||||
#include "libbpf_internal.h"
|
||||
#include "nlattr.h"
|
||||
|
||||
#ifndef SOL_NETLINK
|
||||
@@ -24,7 +25,7 @@ typedef int (*__dump_nlmsg_t)(struct nlmsghdr *nlmsg, libbpf_dump_nlmsg_t,
|
||||
struct xdp_id_md {
|
||||
int ifindex;
|
||||
__u32 flags;
|
||||
__u32 id;
|
||||
struct xdp_link_info info;
|
||||
};
|
||||
|
||||
int libbpf_netlink_open(__u32 *nl_pid)
|
||||
@@ -43,7 +44,7 @@ int libbpf_netlink_open(__u32 *nl_pid)
|
||||
|
||||
if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK,
|
||||
&one, sizeof(one)) < 0) {
|
||||
fprintf(stderr, "Netlink error reporting not supported\n");
|
||||
pr_warn("Netlink error reporting not supported\n");
|
||||
}
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
|
||||
@@ -202,26 +203,11 @@ static int __dump_link_nlmsg(struct nlmsghdr *nlh,
|
||||
return dump_link_nlmsg(cookie, ifi, tb);
|
||||
}
|
||||
|
||||
static unsigned char get_xdp_id_attr(unsigned char mode, __u32 flags)
|
||||
{
|
||||
if (mode != XDP_ATTACHED_MULTI)
|
||||
return IFLA_XDP_PROG_ID;
|
||||
if (flags & XDP_FLAGS_DRV_MODE)
|
||||
return IFLA_XDP_DRV_PROG_ID;
|
||||
if (flags & XDP_FLAGS_HW_MODE)
|
||||
return IFLA_XDP_HW_PROG_ID;
|
||||
if (flags & XDP_FLAGS_SKB_MODE)
|
||||
return IFLA_XDP_SKB_PROG_ID;
|
||||
|
||||
return IFLA_XDP_UNSPEC;
|
||||
}
|
||||
|
||||
static int get_xdp_id(void *cookie, void *msg, struct nlattr **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;
|
||||
unsigned char mode, xdp_attr;
|
||||
int ret;
|
||||
|
||||
if (xdp_id->ifindex && xdp_id->ifindex != ifinfo->ifi_index)
|
||||
@@ -237,27 +223,40 @@ static int get_xdp_id(void *cookie, void *msg, struct nlattr **tb)
|
||||
if (!xdp_tb[IFLA_XDP_ATTACHED])
|
||||
return 0;
|
||||
|
||||
mode = libbpf_nla_getattr_u8(xdp_tb[IFLA_XDP_ATTACHED]);
|
||||
if (mode == XDP_ATTACHED_NONE)
|
||||
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;
|
||||
|
||||
xdp_attr = get_xdp_id_attr(mode, xdp_id->flags);
|
||||
if (!xdp_attr || !xdp_tb[xdp_attr])
|
||||
return 0;
|
||||
if (xdp_tb[IFLA_XDP_PROG_ID])
|
||||
xdp_id->info.prog_id = libbpf_nla_getattr_u32(
|
||||
xdp_tb[IFLA_XDP_PROG_ID]);
|
||||
|
||||
xdp_id->id = libbpf_nla_getattr_u32(xdp_tb[xdp_attr]);
|
||||
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;
|
||||
}
|
||||
|
||||
int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags)
|
||||
int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
|
||||
size_t info_size, __u32 flags)
|
||||
{
|
||||
struct xdp_id_md xdp_id = {};
|
||||
int sock, ret;
|
||||
__u32 nl_pid;
|
||||
__u32 mask;
|
||||
|
||||
if (flags & ~XDP_FLAGS_MASK)
|
||||
if (flags & ~XDP_FLAGS_MASK || !info_size)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check whether the single {HW,DRV,SKB} mode is set */
|
||||
@@ -273,14 +272,44 @@ int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags)
|
||||
xdp_id.ifindex = ifindex;
|
||||
xdp_id.flags = flags;
|
||||
|
||||
ret = libbpf_nl_get_link(sock, nl_pid, get_xdp_id, &xdp_id);
|
||||
if (!ret)
|
||||
*prog_id = xdp_id.id;
|
||||
ret = libbpf_nl_get_link(sock, nl_pid, get_xdp_info, &xdp_id);
|
||||
if (!ret) {
|
||||
size_t sz = min(info_size, sizeof(xdp_id.info));
|
||||
|
||||
memcpy(info, &xdp_id.info, sz);
|
||||
memset((void *) info + sz, 0, info_size - sz);
|
||||
}
|
||||
|
||||
close(sock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __u32 get_xdp_id(struct xdp_link_info *info, __u32 flags)
|
||||
{
|
||||
if (info->attach_mode != XDP_ATTACHED_MULTI)
|
||||
return info->prog_id;
|
||||
if (flags & XDP_FLAGS_DRV_MODE)
|
||||
return info->drv_prog_id;
|
||||
if (flags & XDP_FLAGS_HW_MODE)
|
||||
return info->hw_prog_id;
|
||||
if (flags & XDP_FLAGS_SKB_MODE)
|
||||
return info->skb_prog_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags)
|
||||
{
|
||||
struct xdp_link_info info;
|
||||
int ret;
|
||||
|
||||
ret = bpf_get_link_xdp_info(ifindex, &info, sizeof(info), flags);
|
||||
if (!ret)
|
||||
*prog_id = get_xdp_id(&info, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int libbpf_nl_get_link(int sock, unsigned int nl_pid,
|
||||
libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie)
|
||||
{
|
||||
|
||||
10
src/nlattr.c
10
src/nlattr.c
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include "nlattr.h"
|
||||
#include "libbpf_internal.h"
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@@ -121,8 +122,8 @@ int libbpf_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head,
|
||||
}
|
||||
|
||||
if (tb[type])
|
||||
fprintf(stderr, "Attribute of type %#x found multiple times in message, "
|
||||
"previous attribute is being ignored.\n", type);
|
||||
pr_warn("Attribute of type %#x found multiple times in message, "
|
||||
"previous attribute is being ignored.\n", type);
|
||||
|
||||
tb[type] = nla;
|
||||
}
|
||||
@@ -181,15 +182,14 @@ int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh)
|
||||
|
||||
if (libbpf_nla_parse(tb, NLMSGERR_ATTR_MAX, attr, alen,
|
||||
extack_policy) != 0) {
|
||||
fprintf(stderr,
|
||||
"Failed to parse extended error attributes\n");
|
||||
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]);
|
||||
|
||||
fprintf(stderr, "Kernel error message: %s\n", errmsg);
|
||||
pr_warn("Kernel error message: %s\n", errmsg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
177
src/xsk.c
177
src/xsk.c
@@ -73,6 +73,21 @@ struct xsk_nl_info {
|
||||
int fd;
|
||||
};
|
||||
|
||||
/* Up until and including Linux 5.3 */
|
||||
struct xdp_ring_offset_v1 {
|
||||
__u64 producer;
|
||||
__u64 consumer;
|
||||
__u64 desc;
|
||||
};
|
||||
|
||||
/* Up until and including Linux 5.3 */
|
||||
struct xdp_mmap_offsets_v1 {
|
||||
struct xdp_ring_offset_v1 rx;
|
||||
struct xdp_ring_offset_v1 tx;
|
||||
struct xdp_ring_offset_v1 fr;
|
||||
struct xdp_ring_offset_v1 cr;
|
||||
};
|
||||
|
||||
int xsk_umem__fd(const struct xsk_umem *umem)
|
||||
{
|
||||
return umem ? umem->fd : -EINVAL;
|
||||
@@ -133,6 +148,58 @@ static int xsk_set_xdp_socket_config(struct xsk_socket_config *cfg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xsk_mmap_offsets_v1(struct xdp_mmap_offsets *off)
|
||||
{
|
||||
struct xdp_mmap_offsets_v1 off_v1;
|
||||
|
||||
/* getsockopt on a kernel <= 5.3 has no flags fields.
|
||||
* Copy over the offsets to the correct places in the >=5.4 format
|
||||
* and put the flags where they would have been on that kernel.
|
||||
*/
|
||||
memcpy(&off_v1, off, sizeof(off_v1));
|
||||
|
||||
off->rx.producer = off_v1.rx.producer;
|
||||
off->rx.consumer = off_v1.rx.consumer;
|
||||
off->rx.desc = off_v1.rx.desc;
|
||||
off->rx.flags = off_v1.rx.consumer + sizeof(__u32);
|
||||
|
||||
off->tx.producer = off_v1.tx.producer;
|
||||
off->tx.consumer = off_v1.tx.consumer;
|
||||
off->tx.desc = off_v1.tx.desc;
|
||||
off->tx.flags = off_v1.tx.consumer + sizeof(__u32);
|
||||
|
||||
off->fr.producer = off_v1.fr.producer;
|
||||
off->fr.consumer = off_v1.fr.consumer;
|
||||
off->fr.desc = off_v1.fr.desc;
|
||||
off->fr.flags = off_v1.fr.consumer + sizeof(__u32);
|
||||
|
||||
off->cr.producer = off_v1.cr.producer;
|
||||
off->cr.consumer = off_v1.cr.consumer;
|
||||
off->cr.desc = off_v1.cr.desc;
|
||||
off->cr.flags = off_v1.cr.consumer + sizeof(__u32);
|
||||
}
|
||||
|
||||
static int xsk_get_mmap_offsets(int fd, struct xdp_mmap_offsets *off)
|
||||
{
|
||||
socklen_t optlen;
|
||||
int err;
|
||||
|
||||
optlen = sizeof(*off);
|
||||
err = getsockopt(fd, SOL_XDP, XDP_MMAP_OFFSETS, off, &optlen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (optlen == sizeof(*off))
|
||||
return 0;
|
||||
|
||||
if (optlen == sizeof(struct xdp_mmap_offsets_v1)) {
|
||||
xsk_mmap_offsets_v1(off);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int xsk_umem__create_v0_0_4(struct xsk_umem **umem_ptr, void *umem_area,
|
||||
__u64 size, struct xsk_ring_prod *fill,
|
||||
struct xsk_ring_cons *comp,
|
||||
@@ -141,7 +208,6 @@ int xsk_umem__create_v0_0_4(struct xsk_umem **umem_ptr, void *umem_area,
|
||||
struct xdp_mmap_offsets off;
|
||||
struct xdp_umem_reg mr;
|
||||
struct xsk_umem *umem;
|
||||
socklen_t optlen;
|
||||
void *map;
|
||||
int err;
|
||||
|
||||
@@ -163,6 +229,7 @@ int xsk_umem__create_v0_0_4(struct xsk_umem **umem_ptr, void *umem_area,
|
||||
umem->umem_area = umem_area;
|
||||
xsk_set_umem_config(&umem->config, usr_config);
|
||||
|
||||
memset(&mr, 0, sizeof(mr));
|
||||
mr.addr = (uintptr_t)umem_area;
|
||||
mr.len = size;
|
||||
mr.chunk_size = umem->config.frame_size;
|
||||
@@ -189,8 +256,7 @@ int xsk_umem__create_v0_0_4(struct xsk_umem **umem_ptr, void *umem_area,
|
||||
goto out_socket;
|
||||
}
|
||||
|
||||
optlen = sizeof(off);
|
||||
err = getsockopt(umem->fd, SOL_XDP, XDP_MMAP_OFFSETS, &off, &optlen);
|
||||
err = xsk_get_mmap_offsets(umem->fd, &off);
|
||||
if (err) {
|
||||
err = -errno;
|
||||
goto out_socket;
|
||||
@@ -273,33 +339,55 @@ static int xsk_load_xdp_prog(struct xsk_socket *xsk)
|
||||
/* This is the C-program:
|
||||
* SEC("xdp_sock") int xdp_sock_prog(struct xdp_md *ctx)
|
||||
* {
|
||||
* int index = ctx->rx_queue_index;
|
||||
* int ret, index = ctx->rx_queue_index;
|
||||
*
|
||||
* // A set entry here means that the correspnding queue_id
|
||||
* // has an active AF_XDP socket bound to it.
|
||||
* ret = bpf_redirect_map(&xsks_map, index, XDP_PASS);
|
||||
* if (ret > 0)
|
||||
* return ret;
|
||||
*
|
||||
* // Fallback for pre-5.3 kernels, not supporting default
|
||||
* // action in the flags parameter.
|
||||
* if (bpf_map_lookup_elem(&xsks_map, &index))
|
||||
* return bpf_redirect_map(&xsks_map, index, 0);
|
||||
*
|
||||
* return XDP_PASS;
|
||||
* }
|
||||
*/
|
||||
struct bpf_insn prog[] = {
|
||||
/* r1 = *(u32 *)(r1 + 16) */
|
||||
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 16),
|
||||
/* *(u32 *)(r10 - 4) = r1 */
|
||||
BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_1, -4),
|
||||
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4),
|
||||
/* r2 = *(u32 *)(r1 + 16) */
|
||||
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 16),
|
||||
/* *(u32 *)(r10 - 4) = r2 */
|
||||
BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, -4),
|
||||
/* r1 = xskmap[] */
|
||||
BPF_LD_MAP_FD(BPF_REG_1, xsk->xsks_map_fd),
|
||||
/* r3 = XDP_PASS */
|
||||
BPF_MOV64_IMM(BPF_REG_3, 2),
|
||||
/* call bpf_redirect_map */
|
||||
BPF_EMIT_CALL(BPF_FUNC_redirect_map),
|
||||
/* if w0 != 0 goto pc+13 */
|
||||
BPF_JMP32_IMM(BPF_JSGT, BPF_REG_0, 0, 13),
|
||||
/* r2 = r10 */
|
||||
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
||||
/* r2 += -4 */
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4),
|
||||
/* r1 = xskmap[] */
|
||||
BPF_LD_MAP_FD(BPF_REG_1, xsk->xsks_map_fd),
|
||||
/* call bpf_map_lookup_elem */
|
||||
BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
|
||||
/* r1 = r0 */
|
||||
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
||||
BPF_MOV32_IMM(BPF_REG_0, 2),
|
||||
/* if r1 == 0 goto +5 */
|
||||
/* r0 = XDP_PASS */
|
||||
BPF_MOV64_IMM(BPF_REG_0, 2),
|
||||
/* if r1 == 0 goto pc+5 */
|
||||
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 5),
|
||||
/* r2 = *(u32 *)(r10 - 4) */
|
||||
BPF_LD_MAP_FD(BPF_REG_1, xsk->xsks_map_fd),
|
||||
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_10, -4),
|
||||
BPF_MOV32_IMM(BPF_REG_3, 0),
|
||||
/* r1 = xskmap[] */
|
||||
BPF_LD_MAP_FD(BPF_REG_1, xsk->xsks_map_fd),
|
||||
/* r3 = 0 */
|
||||
BPF_MOV64_IMM(BPF_REG_3, 0),
|
||||
/* call bpf_redirect_map */
|
||||
BPF_EMIT_CALL(BPF_FUNC_redirect_map),
|
||||
/* The jumps are to this instruction */
|
||||
BPF_EXIT_INSN(),
|
||||
@@ -310,7 +398,7 @@ static int xsk_load_xdp_prog(struct xsk_socket *xsk)
|
||||
"LGPL-2.1 or BSD-2-Clause", 0, log_buf,
|
||||
log_buf_size);
|
||||
if (prog_fd < 0) {
|
||||
pr_warning("BPF log buffer:\n%s", log_buf);
|
||||
pr_warn("BPF log buffer:\n%s", log_buf);
|
||||
return prog_fd;
|
||||
}
|
||||
|
||||
@@ -343,13 +431,18 @@ static int xsk_get_max_queues(struct xsk_socket *xsk)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (err || channels.max_combined == 0)
|
||||
if (err) {
|
||||
/* If the device says it has no channels, then all traffic
|
||||
* is sent to a single stream, so max queues = 1.
|
||||
*/
|
||||
ret = 1;
|
||||
else
|
||||
ret = channels.max_combined;
|
||||
} else {
|
||||
/* Take the max of rx, tx, combined. Drivers return
|
||||
* the number of channels in different ways.
|
||||
*/
|
||||
ret = max(channels.max_rx, channels.max_tx);
|
||||
ret = max(ret, (int)channels.max_combined);
|
||||
}
|
||||
|
||||
out:
|
||||
close(fd);
|
||||
@@ -465,6 +558,8 @@ static int xsk_setup_xdp_prog(struct xsk_socket *xsk)
|
||||
}
|
||||
} else {
|
||||
xsk->prog_fd = bpf_prog_get_fd_by_id(prog_id);
|
||||
if (xsk->prog_fd < 0)
|
||||
return -errno;
|
||||
err = xsk_lookup_bpf_maps(xsk);
|
||||
if (err) {
|
||||
close(xsk->prog_fd);
|
||||
@@ -472,7 +567,8 @@ static int xsk_setup_xdp_prog(struct xsk_socket *xsk)
|
||||
}
|
||||
}
|
||||
|
||||
err = xsk_set_bpf_maps(xsk);
|
||||
if (xsk->rx)
|
||||
err = xsk_set_bpf_maps(xsk);
|
||||
if (err) {
|
||||
xsk_delete_bpf_maps(xsk);
|
||||
close(xsk->prog_fd);
|
||||
@@ -491,21 +587,26 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
||||
struct sockaddr_xdp sxdp = {};
|
||||
struct xdp_mmap_offsets off;
|
||||
struct xsk_socket *xsk;
|
||||
socklen_t optlen;
|
||||
int err;
|
||||
|
||||
if (!umem || !xsk_ptr || !rx || !tx)
|
||||
if (!umem || !xsk_ptr || !(rx || tx))
|
||||
return -EFAULT;
|
||||
|
||||
if (umem->refcount) {
|
||||
pr_warning("Error: shared umems not supported by libbpf.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
xsk = calloc(1, sizeof(*xsk));
|
||||
if (!xsk)
|
||||
return -ENOMEM;
|
||||
|
||||
err = xsk_set_xdp_socket_config(&xsk->config, usr_config);
|
||||
if (err)
|
||||
goto out_xsk_alloc;
|
||||
|
||||
if (umem->refcount &&
|
||||
!(xsk->config.libbpf_flags & XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) {
|
||||
pr_warn("Error: shared umems not supported by libbpf supplied XDP program.\n");
|
||||
err = -EBUSY;
|
||||
goto out_xsk_alloc;
|
||||
}
|
||||
|
||||
if (umem->refcount++ > 0) {
|
||||
xsk->fd = socket(AF_XDP, SOCK_RAW, 0);
|
||||
if (xsk->fd < 0) {
|
||||
@@ -527,10 +628,6 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
||||
memcpy(xsk->ifname, ifname, IFNAMSIZ - 1);
|
||||
xsk->ifname[IFNAMSIZ - 1] = '\0';
|
||||
|
||||
err = xsk_set_xdp_socket_config(&xsk->config, usr_config);
|
||||
if (err)
|
||||
goto out_socket;
|
||||
|
||||
if (rx) {
|
||||
err = setsockopt(xsk->fd, SOL_XDP, XDP_RX_RING,
|
||||
&xsk->config.rx_size,
|
||||
@@ -550,8 +647,7 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
||||
}
|
||||
}
|
||||
|
||||
optlen = sizeof(off);
|
||||
err = getsockopt(xsk->fd, SOL_XDP, XDP_MMAP_OFFSETS, &off, &optlen);
|
||||
err = xsk_get_mmap_offsets(xsk->fd, &off);
|
||||
if (err) {
|
||||
err = -errno;
|
||||
goto out_socket;
|
||||
@@ -599,7 +695,12 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
||||
sxdp.sxdp_family = PF_XDP;
|
||||
sxdp.sxdp_ifindex = xsk->ifindex;
|
||||
sxdp.sxdp_queue_id = xsk->queue_id;
|
||||
sxdp.sxdp_flags = xsk->config.bind_flags;
|
||||
if (umem->refcount > 1) {
|
||||
sxdp.sxdp_flags = XDP_SHARED_UMEM;
|
||||
sxdp.sxdp_shared_umem_fd = umem->fd;
|
||||
} else {
|
||||
sxdp.sxdp_flags = xsk->config.bind_flags;
|
||||
}
|
||||
|
||||
err = bind(xsk->fd, (struct sockaddr *)&sxdp, sizeof(sxdp));
|
||||
if (err) {
|
||||
@@ -637,7 +738,6 @@ out_xsk_alloc:
|
||||
int xsk_umem__delete(struct xsk_umem *umem)
|
||||
{
|
||||
struct xdp_mmap_offsets off;
|
||||
socklen_t optlen;
|
||||
int err;
|
||||
|
||||
if (!umem)
|
||||
@@ -646,8 +746,7 @@ int xsk_umem__delete(struct xsk_umem *umem)
|
||||
if (umem->refcount)
|
||||
return -EBUSY;
|
||||
|
||||
optlen = sizeof(off);
|
||||
err = getsockopt(umem->fd, SOL_XDP, XDP_MMAP_OFFSETS, &off, &optlen);
|
||||
err = xsk_get_mmap_offsets(umem->fd, &off);
|
||||
if (!err) {
|
||||
munmap(umem->fill->ring - off.fr.desc,
|
||||
off.fr.desc + umem->config.fill_size * sizeof(__u64));
|
||||
@@ -665,7 +764,6 @@ void xsk_socket__delete(struct xsk_socket *xsk)
|
||||
{
|
||||
size_t desc_sz = sizeof(struct xdp_desc);
|
||||
struct xdp_mmap_offsets off;
|
||||
socklen_t optlen;
|
||||
int err;
|
||||
|
||||
if (!xsk)
|
||||
@@ -676,8 +774,7 @@ void xsk_socket__delete(struct xsk_socket *xsk)
|
||||
close(xsk->prog_fd);
|
||||
}
|
||||
|
||||
optlen = sizeof(off);
|
||||
err = getsockopt(xsk->fd, SOL_XDP, XDP_MMAP_OFFSETS, &off, &optlen);
|
||||
err = xsk_get_mmap_offsets(xsk->fd, &off);
|
||||
if (!err) {
|
||||
if (xsk->rx) {
|
||||
munmap(xsk->rx->ring - off.rx.desc,
|
||||
|
||||
@@ -48,6 +48,8 @@ for phase in "${PHASES[@]}"; do
|
||||
elif [[ "$phase" = *"GCC8"* ]]; then
|
||||
ENV_VARS="-e CC=gcc-8 -e CXX=g++-8"
|
||||
CC="gcc-8"
|
||||
else
|
||||
CFLAGS="${CFLAGS} -Wno-stringop-truncation"
|
||||
fi
|
||||
if [[ "$phase" = *"ASAN"* ]]; then
|
||||
CFLAGS="${CFLAGS} -fsanitize=address,undefined"
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
set -e
|
||||
set -x
|
||||
|
||||
RELEASE="bionic"
|
||||
|
||||
echo "deb-src http://archive.ubuntu.com/ubuntu/ $RELEASE main restricted universe multiverse" >>/etc/apt/sources.list
|
||||
|
||||
apt-get update
|
||||
apt-get -y build-dep libelf-dev
|
||||
apt-get install -y libelf-dev
|
||||
apt-get install -y libelf-dev pkg-config
|
||||
|
||||
source "$(dirname $0)/travis_wait.bash"
|
||||
|
||||
Reference in New Issue
Block a user