diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..ebf309a --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,5 @@ +[build] +target = "x86_64-unknown-linux-gnu" + +[target.x86_64-unknown-linux-gnu] +rustflags = ["-C", "target-feature=+crt-static"] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..f259114 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,246 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anstream" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "btf-rs" +version = "0.1.0" +source = "git+https://github.com/retis-org/btf-rs?rev=78cbe9edd750#78cbe9edd750d310cc60251d0768e3985416c47c" +dependencies = [ + "anyhow", + "byteorder", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "clap" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "drdump" +version = "0.1.0" +dependencies = [ + "anyhow", + "btf-rs", + "clap", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "2.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..cb3976c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "drdump" +version = "0.1.0" +edition = "2021" +description = "Small utility to work with skb drop reasons given a set of BTF files (defaulting to the running kernel ones)" +repository = "https://github.com/retis-org/drdump" +homepage = "https://github.com/retis-org/drdump" +readme = "README.md" + +[dependencies] +anyhow = "1.0" +btf-rs = { git = "https://github.com/retis-org/btf-rs", rev = "78cbe9edd750" } +clap = { version = "4.4", features = ["derive"] } diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), 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 Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; 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. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d872f42 --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# Drop reasons dump (drdump) + +Small utility to dump drop reasons from BTF files (by default using the running +kernel ones), which can also resolve reasons (raw value to enum variant) and +generate bpftrace and stap scripts to dump drop reasons from the `skb:kfree_skb` +tracepoint. + +## Installing + +`drdump` is configured to be build as a static binary when building for x86_64. + +``` +$ git clone https://github.com/retis-org/drdump.git +$ cd drdump +$ cargo build --release +``` + +A pre-build binaries are available on the +[release page](https://github.com/retis-org/drdump/releases/). + +## Usage + +See the below examples and the `drdump --help` output. + +## Examples + +Dumping all known drop reasons, + +``` +$ drdump + 0 = RX_QUEUED + 1 = RX_CONTINUE + 2 = SKB_DROP_REASON_NOT_SPECIFIED + 3 = SKB_DROP_REASON_NO_SOCKET + 4 = SKB_DROP_REASON_PKT_TOO_SMALL +... +``` + +Resolving a specific raw drop reason, + +``` +$ drdump -r 65538 +RX_DROP_U_REPLAY +$ drdump -r 65900` +Unknown reason 65900 (sub-system: SKB_DROP_REASON_SUBSYS_MAC80211_UNUSABLE) +``` + +Generating a bpftrace script to dump drop reasons, + +``` +$ drdump -f bpftrace > drop.bt +$ chmod +x drop.bt +$ ./drop.bt +... +``` + +Generating a stap script to dump drop reasons, + +``` +$ drdump -f stap > drop.stp +$ stap-prep +$ stap --all-modules drop.stp +... +``` diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b23c0e5 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,244 @@ +use std::{collections::BTreeMap, fmt::Write, path::PathBuf}; + +use anyhow::{bail, Result}; +use btf_rs::{utils::BtfCollection, Type}; +use clap::{builder::PossibleValuesParser, Parser}; + +// Keep this in-sync with the kernel definition in include/net/dropreason.h +// +// Used to detect if the kernel supports more drop reasons than we know of. +const SKB_DROP_REASON_SUBSYS_NUM: usize = 5; + +// Known drop reason definitions in the kernel (except for core that is +// mandatory). +const NON_CORE_DROP_REASONS: &[&str] = &["mac80211_drop_reason", "ovs_drop_reason"]; + +#[derive(Parser)] +#[command( + author, + version, + about = "Dumps and translates skb drop reasons given a set of BTF files", + long_about = None, +)] +struct Args { + #[arg( + long, + default_value = "/sys/kernel/btf", + help = "Directory where BTF files are stored" + )] + btf: PathBuf, + #[arg( + short, + long, + help = "Resolve given value into a drop reason enum value" + )] + resolve: Option, + #[arg( + short, + long, + value_parser = PossibleValuesParser::new(["raw", "bpftrace", "stap"]), + default_value = "raw", + help = "Format to output the drop reason values: +- raw: output on stdout all the drop reasons that were found +- bpftrace: construct a bpftrace monitoring script +- stap: construct a system-tap monitoring script +", + )] + format: String, + #[arg( + short, + long, + help = "Increase verbosity (eg. display sub-system for drop reasons)" + )] + verbose: bool, +} + +fn main() -> Result<()> { + let args = Args::parse(); + + let btf = + BtfCollection::from_dir(args.btf).or_else(|e| bail!("Could not parse BTF files: {e}"))?; + + // First parse core drop reasons. If not found, the kernel doesn't support + // drop reasons. + let mut reasons = match parse_enum(&btf, "skb_drop_reason") { + Ok(Some(reasons)) => reasons, + Ok(None) => bail!("Drop reasons are not supported by this kernel"), + Err(e) => bail!(e), + }; + + // Special case the drop reason mask (SKB_DROP_REASON_SUBSYS_MASK). + reasons.remove(&0xffff0000); + + // Parse non-core drop reasons. + for r#enum in NON_CORE_DROP_REASONS { + if let Some(mut subsys_reasons) = parse_enum(&btf, r#enum)? { + while let Some((val, reason)) = subsys_reasons.pop_first() { + // Do not overwrite known values. Some sub-system do this for + // reusing some of the very generic core reasons. Eg. + // SKB_CONSUMED. + reasons.entry(val).or_insert(reason); + } + } + } + + // Get a list of all the known subsystems that can register non-core drop + // reasons. This might return more elements than the ones we know of (if we + // haven't added support for those yet). + let subsys = parse_enum(&btf, "skb_drop_reason_subsys")?; + if let Some(ref subsys) = subsys { + if subsys.len() > SKB_DROP_REASON_SUBSYS_NUM { + eprint!("INFO: found more drop reasons than we know of. Drdump will still be able to resolve raw values into a sub-system when using --resolve.\n\n"); + } + } + + // Handle the output. Depends on which operation was requested. + if let Some(resolve) = args.resolve { + println!( + "{}", + format_reason(resolve, &reasons, subsys.as_ref(), args.verbose) + ); + } else { + match args.format.as_str() { + "raw" => { + let width = (reasons + .keys() + .max() + .unwrap_or(&0) + .checked_ilog10() + .unwrap_or(0) + + 1) as usize; + reasons.keys().for_each(|i| { + println!( + "{i:width$} = {}", + format_reason(*i, &reasons, subsys.as_ref(), args.verbose) + ) + }); + } + "bpftrace" => println!("{}", format_bpftrace(&reasons)), + "stap" => println!("{}", format_stap(&reasons)), + _ => (), + } + } + + Ok(()) +} + +// Formats a reason for pretty printing. If verbose is set, prints the subsystem +// enum variant corresponding to a reason. If a reason is not known, try to +// always print its subsystem if we have a match. +fn format_reason( + val: u32, + reasons: &BTreeMap, + subsys: Option<&BTreeMap>, + verbose: bool, +) -> String { + let format = |s: &str, verbose: bool| -> String { + if verbose && subsys.is_some() { + let subsys_id = val >> 16; + + // Unwrap as we just made sure it's Some<>. + if let Some(name) = subsys.unwrap().get(&subsys_id) { + return format!("{s} (sub-system: {name})"); + } + } + s.to_string() + }; + + match reasons.get(&val) { + Some(name) => format(name, verbose), + None => format(&format!("Unknown reason {val}"), true), + } +} + +// Parses a kernel enum into an ordered BTreeMap of (val <> name). +fn parse_enum(btf: &BtfCollection, name: &str) -> Result>> { + let mut values = BTreeMap::new(); + + let types = match btf.resolve_types_by_name(name) { + Ok(types) => types, + Err(_) => return Ok(None), + }; + + let (btf, r#enum) = match types.iter().find(|(_, t)| matches!(t, &Type::Enum(_))) { + Some((btf, Type::Enum(r#enum))) => (btf, r#enum), + _ => return Ok(None), + }; + + for member in r#enum.members.iter() { + let val = member.val() as u32; + values.insert(val, btf.resolve_name(member)?); + } + + Ok(Some(values)) +} + +// Construct a bpftrace script to monitor drop reasons. +fn format_bpftrace(reasons: &BTreeMap) -> String { + let reasons_def = reasons.iter().fold(String::new(), |mut out, (val, name)| { + write!(out, " @drop_reasons[{val}] = \"{name}\";\n").unwrap(); + out + }); + + format!( + "#!/usr/bin/bpftrace + +BEGIN +{{ + printf(\"Tracing dropped skbs... Hit Ctrl-C to end.\\n\"); +}} + +tracepoint:skb:kfree_skb +{{ +{reasons_def} + @stack[ksym(args->location),@drop_reasons[args->reason]] = count(); + clear(@drop_reasons); +}} + +interval:s:5 +{{ + time(\"%F %T %z (%Z)\\n\"); + print(@stack); + printf(\"\\n\"); + clear(@stack); +}} + +END +{{ + clear(@stack); +}}" + ) +} + +// Construct a stap script to monitor drop reasons. +fn format_stap(reasons: &BTreeMap) -> String { + let reasons_def = reasons.iter().fold(String::new(), |mut out, (val, name)| { + write!(out, " drop_reasons[{val}] = \"{name}\";\n").unwrap(); + out + }); + + format!("#! /usr/bin/env stap + +global skb_drop_reason +global drop_reasons + +probe kernel.trace(\"kfree_skb\") {{ + skb_drop_reason[$location, $reason] <<< 1; +}} + +probe begin {{ + printf(\"Tracing dropped skbs... Hit Ctrl-C to end.\\n\"); +}} + +# Report every 5 seconds +probe timer.sec(5) +{{ + printf(\"\\n%s\", tz_ctime(gettimeofday_s())) +{reasons_def} + printf(\"\\n%-35s%-35s%10s\\n\",\"Drop\",\"Location\",\"Count\"); + foreach([location, reason] in skb_drop_reason) {{ + printf(\"%-35s%-35s%10d\\n\",symname(location),drop_reasons[reason],@count(skb_drop_reason[location, reason])) + }} + delete skb_drop_reason +}}") +}