Files
nexus/sreweekly/articles/303/09-day-23-what-is-ebpf.html
2026-09-12 17:23:01 +08:00

1575 lines
56 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html dir='ltr' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'>
<head>
<link href='https://www.blogger.com/static/v1/widgets/4165133002-widget_css_bundle.css' rel='stylesheet' type='text/css'/>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/>
<meta content='blogger' name='generator'/>
<link href='https://sysadvent.blogspot.com/favicon.ico' rel='icon' type='image/x-icon'/>
<link href='https://sysadvent.blogspot.com/2021/12/day-23-what-is-ebpf.html' rel='canonical'/>
<link rel="alternate" type="application/atom+xml" title="sysadvent - Atom" href="https://sysadvent.blogspot.com/feeds/posts/default" />
<link rel="alternate" type="application/rss+xml" title="sysadvent - RSS" href="https://sysadvent.blogspot.com/feeds/posts/default?alt=rss" />
<link rel="service.post" type="application/atom+xml" title="sysadvent - Atom" href="https://www.blogger.com/feeds/3615332969083650973/posts/default" />
<link rel="alternate" type="application/atom+xml" title="sysadvent - Atom" href="https://sysadvent.blogspot.com/feeds/8352453746970378361/comments/default" />
<!--Can't find substitution for tag [blog.ieCssRetrofitLinks]-->
<meta content='https://sysadvent.blogspot.com/2021/12/day-23-what-is-ebpf.html' property='og:url'/>
<meta content='Day 23 - What is eBPF?' property='og:title'/>
<meta content=' By: Ania Kapuścińska ( @lambdanis ) Edited by: Shaun Mouton ( @sdmouton ) Like many engineers, for a long time I’ve thought ...' property='og:description'/>
<title>
sysadvent: Day 23 - What is eBPF?
</title>
<style type='text/css'>@font-face{font-family:'Allerta';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/allerta/v19/TwMO-IAHRlkbx940YnYXSCiN9uc.woff2)format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}@font-face{font-family:'Arimo';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/arimo/v36/P5sfzZCDf9_T_3cV7NCUECyoxNk37cxcDRrBdwcoaaQwpBQ.woff2)format('woff2');unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;}@font-face{font-family:'Arimo';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/arimo/v36/P5sfzZCDf9_T_3cV7NCUECyoxNk37cxcBBrBdwcoaaQwpBQ.woff2)format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;}@font-face{font-family:'Arimo';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/arimo/v36/P5sfzZCDf9_T_3cV7NCUECyoxNk37cxcDBrBdwcoaaQwpBQ.woff2)format('woff2');unicode-range:U+1F00-1FFF;}@font-face{font-family:'Arimo';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/arimo/v36/P5sfzZCDf9_T_3cV7NCUECyoxNk37cxcAxrBdwcoaaQwpBQ.woff2)format('woff2');unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;}@font-face{font-family:'Arimo';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/arimo/v36/P5sfzZCDf9_T_3cV7NCUECyoxNk37cxcAhrBdwcoaaQwpBQ.woff2)format('woff2');unicode-range:U+0307-0308,U+0590-05FF,U+200C-2010,U+20AA,U+25CC,U+FB1D-FB4F;}@font-face{font-family:'Arimo';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/arimo/v36/P5sfzZCDf9_T_3cV7NCUECyoxNk37cxcDxrBdwcoaaQwpBQ.woff2)format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;}@font-face{font-family:'Arimo';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/arimo/v36/P5sfzZCDf9_T_3cV7NCUECyoxNk37cxcDhrBdwcoaaQwpBQ.woff2)format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}@font-face{font-family:'Arimo';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/arimo/v36/P5sfzZCDf9_T_3cV7NCUECyoxNk37cxcABrBdwcoaaQw.woff2)format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}</style>
<style id='page-skin-1' type='text/css'><!--
/*
-----------------------------------------------
Blogger Template Style
Name: Minima
Designer: Douglas Bowman
URL: www.stopdesign.com
Date: 26 Feb 2004
Updated by: Blogger Team
----------------------------------------------- */
/* Variable definitions
====================
<Variable name="bgcolor" description="Page Background Color"
type="color" default="#fff">
<Variable name="textcolor" description="Text Color"
type="color" default="#333">
<Variable name="linkcolor" description="Link Color"
type="color" default="#58a">
<Variable name="pagetitlecolor" description="Blog Title Color"
type="color" default="#666">
<Variable name="descriptioncolor" description="Blog Description Color"
type="color" default="#999">
<Variable name="titlecolor" description="Post Title Color"
type="color" default="#c60">
<Variable name="bordercolor" description="Border Color"
type="color" default="#ccc">
<Variable name="sidebarcolor" description="Sidebar Title Color"
type="color" default="#999">
<Variable name="sidebartextcolor" description="Sidebar Text Color"
type="color" default="#666">
<Variable name="visitedlinkcolor" description="Visited Link Color"
type="color" default="#999">
<Variable name="bodyfont" description="Text Font"
type="font" default="normal normal 100% Georgia, Serif">
<Variable name="headerfont" description="Sidebar Title Font"
type="font"
default="normal normal 78% 'Trebuchet MS',Trebuchet,Arial,Verdana,Sans-serif">
<Variable name="pagetitlefont" description="Blog Title Font"
type="font"
default="normal normal 200% Georgia, Serif">
<Variable name="descriptionfont" description="Blog Description Font"
type="font"
default="normal normal 78% 'Trebuchet MS', Trebuchet, Arial, Verdana, Sans-serif">
<Variable name="postfooterfont" description="Post Footer Font"
type="font"
default="normal normal 78% 'Trebuchet MS', Trebuchet, Arial, Verdana, Sans-serif">
<Variable name="startSide" description="Side where text starts in blog language"
type="automatic" default="left">
<Variable name="endSide" description="Side where text ends in blog language"
type="automatic" default="right">
*/
/* Use this with templates/template-twocol.html */
body {
background:#ffffff;
margin:0;
color:#333333;
font:x-small Georgia Serif;
font-size/* */:/**/small;
font-size: /**/small;
text-align: center;
}
a:link {
color:#5588aa;
text-decoration:none;
}
a:visited {
color:#999999;
text-decoration:none;
}
a:hover {
color:#cc6600;
text-decoration:underline;
}
a img {
border-width:0;
}
/* Header
-----------------------------------------------
*/
#header-wrapper {
width:760px;
margin:0 auto 10px;
/*border:1px solid #cccccc;*/
}
#header-inner {
background-position: center;
margin-left: auto;
margin-right: auto;
}
#header {
margin: 5px;
/*border: 1px solid #cccccc;*/
text-align: center;
color:#666666;
}
#header h1 {
margin:5px 5px 0;
padding:15px 20px .25em;
line-height:1.2em;
text-transform:uppercase;
letter-spacing:.2em;
font: normal normal 200% Georgia, Serif;
}
#header a {
color:#666666;
text-decoration:none;
}
#header a:hover {
color:#666666;
}
#header .description {
margin:0 5px 5px;
padding:0 20px 15px;
max-width:800px;
text-transform:uppercase;
letter-spacing:.2em;
line-height: 1.4em;
font: normal normal 78% 'Trebuchet MS', Trebuchet, Arial, Verdana, Sans-serif;
color: #999999;
}
#header img {
margin-left: auto;
margin-right: auto;
}
/* Outer-Wrapper
----------------------------------------------- */
#outer-wrapper {
width: 760px;
margin:0 auto;
padding:10px;
text-align:left;
font: normal normal 100% Arimo;
}
#main-wrapper {
width: 510px;
float: left;
word-wrap: break-word; /* fix for long text breaking sidebar float in IE */
overflow: hidden; /* fix for long non-text content breaking IE sidebar float */
}
#sidebar-wrapper {
width: 220px;
float: right;
word-wrap: break-word; /* fix for long text breaking sidebar float in IE */
overflow: hidden; /* fix for long non-text content breaking IE sidebar float */
}
/* Headings
----------------------------------------------- */
h2 {
margin:1.5em 0 .75em;
font:normal normal 130% Allerta;
line-height: 1.4em;
text-transform:uppercase;
letter-spacing:.2em;
color:#999999;
}
/* Posts
-----------------------------------------------
*/
h2.date-header {
margin:1.5em 0 .5em;
}
.post {
margin:.5em 0 1.5em;
border-bottom:1px dotted #cccccc;
padding-bottom:1.5em;
}
.post h3 {
margin:.25em 0 0;
padding:0 0 4px;
font-size:140%;
font-weight:normal;
line-height:1.4em;
color:#cc6600;
}
.post h3 a, .post h3 a:visited, .post h3 strong {
display:block;
text-decoration:none;
color:#cc6600;
font-weight:normal;
}
.post h3 strong, .post h3 a:hover {
color:#333333;
}
.post-body {
margin:0 0 .75em;
line-height:1.6em;
}
.post-body blockquote {
line-height:1.3em;
}
.post-footer {
margin: .75em 0;
color:#999999;
text-transform:uppercase;
letter-spacing:.1em;
font: normal normal 78% 'Trebuchet MS', Trebuchet, Arial, Verdana, Sans-serif;
line-height: 1.4em;
}
.comment-link {
margin-left:.6em;
}
.post img {
padding:4px;
border:1px solid #cccccc;
}
.post blockquote {
margin:1em 20px;
}
.post blockquote p {
margin:.75em 0;
}
.post pre {
overflow: auto;
padding-left: 5px;
padding-right: 5px;
border: 1px solid #CCCCFF !important;
}
.post pre a {
text-decoration: underline;
}
/* Comments
----------------------------------------------- */
#comments h4 {
margin:1em 0;
font-weight: bold;
line-height: 1.4em;
text-transform:uppercase;
letter-spacing:.2em;
color: #999999;
}
#comments-block {
margin:1em 0 1.5em;
line-height:1.6em;
}
#comments-block .comment-author {
margin:.5em 0;
}
#comments-block .comment-body {
margin:.25em 0 0;
}
#comments-block .comment-footer {
margin:-.25em 0 2em;
line-height: 1.4em;
text-transform:uppercase;
letter-spacing:.1em;
}
#comments-block .comment-body p {
margin:0 0 .75em;
}
.deleted-comment {
font-style:italic;
color:gray;
}
#blog-pager-newer-link {
float: left;
}
#blog-pager-older-link {
float: right;
}
#blog-pager {
text-align: center;
}
.feed-links {
clear: both;
line-height: 2.5em;
}
/* Sidebar Content
----------------------------------------------- */
.sidebar {
color: #666666;
line-height: 1.5em;
}
.sidebar ul {
list-style:none;
margin:0 0 0;
padding:0 0 0;
}
.sidebar li {
margin:0;
padding-top:0;
padding-right:0;
padding-bottom:.25em;
padding-left:15px;
text-indent:-15px;
line-height:1.5em;
}
.sidebar .widget, .main .widget {
border-bottom:1px dotted #cccccc;
margin:0 0 1.5em;
padding:0 0 1.5em;
}
.main .Blog {
border-bottom-width: 0;
}
/* Profile
----------------------------------------------- */
.profile-img {
float: left;
margin-top: 0;
margin-right: 5px;
margin-bottom: 5px;
margin-left: 0;
padding: 4px;
border: 1px solid #cccccc;
}
.profile-data {
margin:0;
text-transform:uppercase;
letter-spacing:.1em;
font: normal normal 78% 'Trebuchet MS', Trebuchet, Arial, Verdana, Sans-serif;
color: #999999;
font-weight: bold;
line-height: 1.6em;
}
.profile-datablock {
margin:.5em 0 .5em;
}
.profile-textblock {
margin: 0.5em 0;
line-height: 1.6em;
}
.profile-link {
font: normal normal 78% 'Trebuchet MS', Trebuchet, Arial, Verdana, Sans-serif;
text-transform: uppercase;
letter-spacing: .1em;
}
/* Footer
----------------------------------------------- */
#footer {
width:760px;
clear:both;
margin:0 auto;
padding-top:15px;
line-height: 1.6em;
text-transform:uppercase;
letter-spacing:.1em;
text-align: center;
}
@media only screen and (max-width:480px) {
a:link {
color: #d12a39;
}
.mobile-link-button {
background-color: #d12a39;
}
.mobile-link-button a:link, .mobile-link-button a:visited {
color: #ffffff;
}
}
--></style>
<link href='https://www.blogger.com/dyncss/3615332969083650973/authorization.css?zx=24cd04b2-38ff-45f4-a3f0-f0a07f75ec8f' media='none' onload='if(media!=&#39;all&#39;)media=&#39;all&#39;' rel='stylesheet'/><noscript><link href='https://www.blogger.com/dyncss/3615332969083650973/authorization.css?zx=24cd04b2-38ff-45f4-a3f0-f0a07f75ec8f' rel='stylesheet'/></noscript>
<meta name='google-adsense-platform-account' content='ca-host-pub-1556223355139109'/>
<meta name='google-adsense-platform-domain' content='blogspot.com'/>
<!-- data-ad-client=ca-pub-6194074709963145 -->
</head>
<body>
<div class='navbar section' id='navbar'><div class='widget Navbar' data-version='1' id='Navbar1'><script type="text/javascript">
function setAttributeOnload(object, attribute, val) {
if(window.addEventListener) {
window.addEventListener('load',
function(){ object[attribute] = val; }, false);
} else {
window.attachEvent('onload', function(){ object[attribute] = val; });
}
}
</script>
<div id="navbar-iframe-container"></div>
<script type="text/javascript" src="https://apis.google.com/js/platform.js"></script>
<script type="text/javascript">
gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() {
if (gapi.iframes && gapi.iframes.getContext) {
gapi.iframes.getContext().openChild({
url: 'https://www.blogger.com/navbar/3615332969083650973?po\x3d8352453746970378361\x26origin\x3dhttps://sysadvent.blogspot.com',
where: document.getElementById("navbar-iframe-container"),
id: "navbar-iframe"
});
}
});
</script><script type="text/javascript">
(function() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '//pagead2.googlesyndication.com/pagead/js/google_top_exp.js';
var head = document.getElementsByTagName('head')[0];
if (head) {
head.appendChild(script);
}})();
</script>
</div></div>
<div id='outer-wrapper'>
<div id='wrap2'>
<!-- skip links for text browsers -->
<span id='skiplinks' style='display:none;'>
<a href='#main'>
skip to main
</a>
|
<a href='#sidebar'>
skip to sidebar
</a>
</span>
<div id='header-wrapper'>
<div class='header section' id='header'><div class='widget Header' data-version='1' id='Header1'>
<div id='header-inner'>
<a href='https://sysadvent.blogspot.com/' style='display: block'>
<img alt='sysadvent' height='240px; ' id='Header1_headerimg' src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYVlIMEU0sXvTBtcY5iFj5QtiT3Klf0S3sgSamkTPsjU1QGvOWHA-6yq173iHys3-ImrIFY26KIPuKEoSNSbitvtnXsZU6b8YPGQ48ir-8Jo2NFrTsaiO_Nl9W9XLt_wyWhTM_16_HeN0/s750/sys-advent-long.png' style='display: block' width='750px; '/>
</a>
</div>
</div></div>
</div>
<div id='content-wrapper'>
<div id='crosscol-wrapper' style='text-align:center'>
<div class='crosscol no-items section' id='crosscol'></div>
</div>
<div id='main-wrapper'>
<div class='main section' id='main'><div class='widget Blog' data-version='1' id='Blog1'>
<div class='blog-posts hfeed'>
<!--Can't find substitution for tag [defaultAdStart]-->
<div class="date-outer">
<h2 class='date-header'>
<span>
December 23, 2021
</span>
</h2>
<div class="date-posts">
<div class='post-outer'>
<div class='post hentry'>
<a name='8352453746970378361'></a>
<h3 class='post-title entry-title'>
<a href='https://sysadvent.blogspot.com/2021/12/day-23-what-is-ebpf.html'>
Day 23 - What is eBPF?
</a>
</h3>
<div class='post-header-line-1'></div>
<div class='post-body entry-content'>
<p>
By: Ania Kapuścińska (<a href="https://twitter.com/lambdanis">@lambdanis</a>)<br />
Edited by: Shaun Mouton (<a href="https://twitter.com/sdmouton">@sdmouton</a> )
</p>
<p>
Like many engineers, for a long time I&#8217;ve thought of the Linux kernel as a black
box. I've been using Linux daily for many years - but my usage was mostly
limited to following the installation guide, interacting with the command line
interface and writing bash scripts.
</p>
<p>
Some time ago I heard about eBPF (extended BPF). The first thing I heard was
that it&#8217;s a programmable interface for the Linux kernel. Wait a second. Does
that mean I can now inject my code into Linux without fully understanding all
the internals and compiling the kernel? The answer turns out to be approximately
yes!
</p>
<p>
An eBPF (or BPF - these acronyms are used practically interchangeably) program
is written in a restricted version of C. Restricted, because a dedicated
verifier checks that the program is safe to run in an BPF VM - it can&#8217;t crash,
loop infinitely, or access arbitrary memory. If the program passes the check, it
can be attached to some kind of event in the Linux kernel, and run every time
this event happens.
</p>
<p>
A growing ecosystem makes it easier to create tools on top of BPF. One very
popular framework is <a href="https://github.com/iovisor/bcc">BCC</a> (BPF
Compiler Collection), containing a Python interface for writing BPF programs.
Python is a very popular scripting language, for a good reason - simple syntax,
dynamic typing and rich standard library make writing even complex scripts quick
and fun. On top of that, bcc provides easy compilation, events attachment and
output processing of BPF programs. That makes it the perfect tool to start
experimenting with writing BPF code.
</p>
<p>
To run code examples from this article, you will need a Linux machine with a
fairly recent kernel version (supporting eBPF). If you don&#8217;t have a Linux
machine available, you can experiment in a Vagrant box. You will also need to <a href="https://github.com/iovisor/bcc/blob/master/INSTALL.md">install Python bcc
package</a>.
</p>
<h2>Very complicated hello</h2>
<p>
Let&#8217;s start in a very unoriginal way - with a &#8220;hello world&#8221; program. As I
mentioned before, BPF programs are written in (restricted) C. A BPF program
printing &#8220;Hello World!&#8221; can look like that:
</p>
<p>
hello.c
</p>
<pre
class="prettyprint">#define HELLO_LENGTH 13
BPF_PERF_OUTPUT(output);
struct message_t {
char hello[HELLO_LENGTH];
};
static int strcp(char *src, char *dest) {
for (int i = 0; src[i] != '\0'; i++) {
dest[i] = src[i];
}
return 0;
};
int hello_world(struct pt_regs *ctx) {
struct message_t message = {};
strcp("Hello World!", message.hello);
output.perf_submit(ctx, &message, sizeof(message));
return 0;
}
</pre>
<p>
The main piece here is the hello_world function - later we will attach it to a
kernel event. We don&#8217;t have access to many common libraries, so we are
implementing strcp (string copy) functionality ourselves. Extra functions are
allowed in BPF code, but have to be defined as static. Loops are also allowed,
but the verifier will check that they are guaranteed to complete.
</p>
<p>
The way we output data might look unusual. First, we define a perf ring buffer
called &#8220;output&#8221; using the BPF_PERF_OUTPUT macro. Then we define a data structure
that we will put in this buffer - message_t. Finally, we write to the &#8220;output&#8221;
buffer using perf_submit function.
</p>
<p>
Now it&#8217;s time to write some Python:
</p>
<p>
hello.py
</p>
<pre
class="prettyprint">from bcc import BPF
b = BPF(src_file="hello.c")
b.attach_kprobe(
event=b.get_syscall_fnname("clone"),
fn_name="hello_world"
)
def print_message(_cpu, data, _size):
message = b["output"].event(data)
print(message.hello)
b["output"].open_perf_buffer(print_message)
while True:
try:
b.perf_buffer_poll()
except KeyboardInterrupt:
exit()
</pre>
<p>
We import BPF from bcc as BPF is the core of the Python interface with eBPF in
the bcc package. It loads our C program, compiles it, and gives us a Python
object to operate on. The program has to be attached to a Linux kernel event -
in this case it will be the clone system call, used to create a new process. The
attach_kprobe method hooks the hello_world C function to the start of a clone
system call.
</p>
<p>
The rest of Python code is reading and printing output. A great functionality
provided by bcc is automatic translation of C structures (in this case &#8220;output&#8221;
perf ring buffer) into Python objects. We access the buffer with a simple
b[&#8220;output&#8221;], and use open_perf_buffer method to associate it with the
print_message function. In this function we read incoming messages with the
event method. The C structure we used to send them gets automatically converted
into a Python object, so we can read &#8220;Hello World!&#8221; by accessing the hello
attribute.
</p>
<p>
To see it in action, run the script with root privileges:
</p>
<div><pre><code class="language-none">
> sudo python hello.py
</code></pre></div>
<p>
In a different terminal window run any commands, e.g. ls. &#8220;Hello World!&#8221;
messages will start popping up.
</p>
<p>
Does it look awfully complicated for a &#8220;hello world&#8221; example? Yes, it does :)
But it covers a lot, and most of the complexity comes from the fact that we are
sending data to user space via a perf ring buffer.
</p>
<p>
In fact, similar functionality can be achieved with much simpler code. We can
get rid of the complex printing logic by using the bpf_trace_printk function to
write a message to the shared trace_pipe. Then, in Python script we can read
from this pipe using trace_print method. It&#8217;s not recommended for real world
tools, as trace_pipe is global and the output format is limited - but for
experiments or debugging it&#8217;s perfectly fine.
</p>
<p>
Additionally, bcc allows us to write C code inline in the Python script. We can
also use a shortcut for attaching C functions to kernel events - if we name the
C function kprobe__&lt;kernel function name&gt;, it will get hooked to the desired
kernel function automatically. In this case we want to hook into the sys_clone
function.
</p>
<p>
So, hello world, the simplest version, can look like this:
</p>
<pre
class="prettyprint">from bcc import BPF
BPF(text='int kprobe__sys_clone(void *ctx) { bpf_trace_printk("Hello World!\\n"); return 0; }').trace_print()
</pre>
<p>
The output will be different, but what doesn&#8217;t change is that while the script
is running, custom code will run whenever a clone system call is starting.
</p>
<h2>What even is an event?</h2>
<p>
Code compilation and attaching functions to events are greatly simplified by the
bcc interface. But a lot of its power lies in the fact that we can glue many BPF
programs together with Python. Nothing prevents us from defining multiple C
functions in one Python script and attaching them to multiple different hook
points.
</p>
<p>
Let&#8217;s talk about these &#8220;hook points&#8221;. What we used in the &#8220;hello world&#8221; example
is a kprobe (kernel probe). It&#8217;s a way to dynamically run code at the beginning
of Linux kernel functions. We can also define a kretprobe to run code when a
kernel function returns. Similarly, for programs running in user space, there
are uprobes and uretprobes.
</p>
<p>
Probes are extremely useful for dynamic tracing use cases. They can be attached
almost anywhere, but that can cause stability problems - a function rename could
break our program. Better stability can be achieved by using predefined static
tracepoints wherever possible. Linux kernel provides many of those, and for user
space tracing you can define them too (<a href="https://lwn.net/Articles/753601/">user statically defined tracepoints</a>
- USDTs).
</p>
<p>
Network events are very interesting hook points. BPF can be used to inspect,
filter and route packets, opening a whole sea of possibilities for very
performant networking and security tools. In this category, XDP (eXpress Data
Path) is a BPF framework that allows running BPF programs not only in Linux
kernel, but also on supported network devices.
</p>
<h2>We need to store data</h2>
<p>
So far I&#8217;ve mentioned functions attached to other functions many times. But
interesting computer programs generally have something more than functions - a
state that can be shared between function calls. That can be a database or a
filesystem, and in the BPF world that&#8217;s BPF maps.
</p>
<p>
BPF maps are key/value pairs stored in Linux kernel. They can be accessed by
both kernel and user space programs, allowing communication between them.
Usually BPF maps are defined with C macros, and read or modified with <a href="https://man7.org/linux/man-pages/man7/bpf-helpers.7.html">BPF helpers</a>.
There are several different types of BPF maps, e.g.: hash tables, histograms,
arrays, queues and stacks. In newer kernel versions, some types of maps let you
protect concurrent access with spin locks.
</p>
<p>
In fact, we&#8217;ve seen a BPF map in action already. The perf ring buffer we&#8217;ve
created with BPF_PERF_OUTPUT macro is nothing more than a BPF map of type
BPF_MAP_TYPE_PERF_EVENT_ARRAY. We also saw that it can be accessed from Python
bcc script, including automatic translation of items structure into Python
objects.
</p>
<p>
</p>
<p>
A good, but still simple example of using a hash table BPF map for communication
between different BPF programs can be found in <a href="https://www.oreilly.com/library/view/linux-observability-with/9781492050193/">&#8220;Linux
Observability with BPF&#8221; book</a> (or in the <a href="https://github.com/bpftools/linux-observability-with-bpf/blob/master/code/chapter-4/uretprobes/example.py">accompanying
repo</a>). It&#8217;s a script using uprobe and uretprobe to measure duration of a Go
binary execution:
</p>
<pre
class="prettyprint">from bcc import BPF
bpf_source = """
BPF_HASH(cache, u64, u64);
int trace_start_time(struct pt_regs *ctx) {
u64 pid = bpf_get_current_pid_tgid();
u64 start_time_ns = bpf_ktime_get_ns();
cache.update(&pid, &start_time_ns);
return 0;
}
"""
bpf_source += """
int print_duration(struct pt_regs *ctx) {
u64 pid = bpf_get_current_pid_tgid();
u64 *start_time_ns = cache.lookup(&pid);
if (start_time_ns == 0) {
return 0;
}
u64 duration_ns = bpf_ktime_get_ns() - *start_time_ns;
bpf_trace_printk("Function call duration: %d\\n", duration_ns);
return 0;
}
"""
bpf = BPF(text = bpf_source)
bpf.attach_uprobe(name = "./hello-bpf", sym = "main.main", fn_name = "trace_start_time")
bpf.attach_uretprobe(name = "./hello-bpf", sym = "main.main", fn_name = "print_duration")
bpf.trace_print()
</pre>
<p>
First, a hash table called &#8220;cache&#8221; is defined with the BPF_HASH macro. Then we
have two C functions: trace_start_time writing the process start time to the map
using cache.update(), and print_duration reading this value using
cache.lookup(). The former is attached to a uprobe, and the latter to uretprobe
for the same function - main.main in hello-bpf binary. That allows
print_duration to, well, print duration of the Go program execution.
</p>
<h2>Sounds great! Now what?</h2>
<p>
To start using the bcc framework, visit its Github repo. There is a <a href="https://github.com/iovisor/bcc/blob/master/docs/tutorial_bcc_python_developer.md">developer
tutorial</a> and a <a href="https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md">reference
guide</a>. Many tools have been built on the bcc framework - you can learn them
from a <a href="https://github.com/iovisor/bcc/blob/master/docs/tutorial.md">tutorial</a>
or check <a href="https://github.com/iovisor/bcc/tree/master/tools">their
code</a>. It&#8217;s a great inspiration and a great way to learn - code of a single
tool is usually not extremely complicated.
</p>
<p>
Two goldmines of eBPF resources are <a href="https://ebpf.io/">ebpf.io</a> and
<a href="https://project-awesome.org/zoidbergwill/awesome-ebpf">eBPF awesome
list</a>. Start browsing any of those, and you have all your winter evenings
sorted :)
</p>
<p>
Have fun!
</p>
<div style='clear: both;'></div>
</div>
<div class='post-footer'>
<div class='post-footer-line post-footer-line-1'>
<span class='post-author vcard'>
Posted by
<span class='fn'>
sigje
</span>
</span>
<span class='post-timestamp'>
</span>
<span class='post-comment-link'>
</span>
<span class='post-icons'>
<span class='item-action'>
<a href='https://www.blogger.com/email-post/3615332969083650973/8352453746970378361' title='Email Post'>
<img alt="" class="icon-action" height="13" src="//www.blogger.com/img/icon18_email.gif" width="18">
</a>
</span>
<span class='item-control blog-admin pid-1271197227'>
<a href='https://www.blogger.com/post-edit.g?blogID=3615332969083650973&postID=8352453746970378361&from=pencil' title='Edit Post'>
<img alt="" class="icon-action" height="18" src="//img2.blogblog.com/img/icon18_edit_allbkg.gif" width="18">
</a>
</span>
</span>
</div>
<div class='post-footer-line post-footer-line-2'>
<span class='post-labels'>
Labels:
<a href='https://sysadvent.blogspot.com/search/label/bcc' rel='tag'>
bcc
</a>
,
<a href='https://sysadvent.blogspot.com/search/label/ebpf' rel='tag'>
ebpf
</a>
,
<a href='https://sysadvent.blogspot.com/search/label/linux' rel='tag'>
linux
</a>
</span>
</div>
<div class='post-footer-line post-footer-line-3'></div>
</div>
</div>
<div class='comments' id='comments'>
<a name='comments'></a>
<h4>
No comments
:
</h4>
<div id='Blog1_comments-block-wrapper'>
<dl class='' id='comments-block'>
</dl>
</div>
<p class='comment-footer'>
<a href='https://www.blogger.com/comment/fullpage/post/3615332969083650973/8352453746970378361' onclick=''>
Post a Comment
</a>
</p>
<div id='backlinks-container'>
<div id='Blog1_backlinks-container'>
</div>
</div>
</div>
</div>
</div></div>
<!--Can't find substitution for tag [adEnd]-->
</div>
<div class='blog-pager' id='blog-pager'>
<span id='blog-pager-older-link'>
<a class='blog-pager-older-link' href='https://sysadvent.blogspot.com/2021/12/day-22-so-youre-incident-commander-now.html' id='Blog1_blog-pager-older-link' title='Older Post'>
Older Post
</a>
</span>
<a class='home-link' href='https://sysadvent.blogspot.com/'>
Home
</a>
</div>
<div class='clear'></div>
<div class='post-feeds'>
<div class='feed-links'>
Subscribe to:
<a class='feed-link' href='https://sysadvent.blogspot.com/feeds/8352453746970378361/comments/default' target='_blank' type='application/atom+xml'>
Post Comments
(
Atom
)
</a>
</div>
</div>
</div></div>
</div>
<div id='sidebar-wrapper'>
<div class='sidebar section' id='sidebar'><div class='widget HTML' data-version='1' id='HTML2'>
<h2 class='title'>
What is sysadvent?
</h2>
<div class='widget-content'>
<p>
One article for each day of December, ending on the 25th article.
</p><p>
With the goals of sharing, openness, and mentoring, we aim to provide great articles about systems administration topics written by fellow sysadmins.
</p><p>
Want to get involved? Join the <a href="http://groups.google.com/group/sysadvent">mailing list</a>!
<p></p></p>
</div>
<div class='clear'></div>
</div><div class='widget Subscribe' data-version='1' id='Subscribe1'>
<div style='white-space:nowrap'>
<h2 class='title'>
Subscribe
</h2>
<div class='widget-content'>
<div class='subscribe-wrapper subscribe-type-POST'>
<div class='subscribe expanded subscribe-type-POST' id='SW_READER_LIST_Subscribe1POST' style='display:none;'>
<div class='top'>
<span class='inner' onclick='return(_SW_toggleReaderList(event, "Subscribe1POST"));'>
<img class='subscribe-dropdown-arrow' src='https://resources.blogblog.com/img/widgets/arrow_dropdown.gif'/>
<img align='absmiddle' alt='' border='0' class='feed-icon' src='https://resources.blogblog.com/img/icon_feed12.png'/>
Posts
</span>
<div class='feed-reader-links'>
<a class='feed-reader-link' href='http://www.netvibes.com/subscribe.php?url=https%3A%2F%2Fsysadvent.blogspot.com%2Ffeeds%2Fposts%2Fdefault' target='_blank'>
<img src='https://resources.blogblog.com/img/widgets/subscribe-netvibes.png'/>
</a>
<a class='feed-reader-link' href='http://add.my.yahoo.com/content?url=https%3A%2F%2Fsysadvent.blogspot.com%2Ffeeds%2Fposts%2Fdefault' target='_blank'>
<img src='https://resources.blogblog.com/img/widgets/subscribe-yahoo.png'/>
</a>
<a class='feed-reader-link' href='https://sysadvent.blogspot.com/feeds/posts/default' target='_blank'>
<img align='absmiddle' class='feed-icon' src='https://resources.blogblog.com/img/icon_feed12.png'/>
Atom
</a>
</div>
</div>
<div class='bottom'></div>
</div>
<div class='subscribe' id='SW_READER_LIST_CLOSED_Subscribe1POST' onclick='return(_SW_toggleReaderList(event, "Subscribe1POST"));'>
<div class='top'>
<span class='inner'>
<img class='subscribe-dropdown-arrow' src='https://resources.blogblog.com/img/widgets/arrow_dropdown.gif'/>
<span onclick='return(_SW_toggleReaderList(event, "Subscribe1POST"));'>
<img align='absmiddle' alt='' border='0' class='feed-icon' src='https://resources.blogblog.com/img/icon_feed12.png'/>
Posts
</span>
</span>
</div>
<div class='bottom'></div>
</div>
</div>
<div class='subscribe-wrapper subscribe-type-PER_POST'>
<div class='subscribe expanded subscribe-type-PER_POST' id='SW_READER_LIST_Subscribe1PER_POST' style='display:none;'>
<div class='top'>
<span class='inner' onclick='return(_SW_toggleReaderList(event, "Subscribe1PER_POST"));'>
<img class='subscribe-dropdown-arrow' src='https://resources.blogblog.com/img/widgets/arrow_dropdown.gif'/>
<img align='absmiddle' alt='' border='0' class='feed-icon' src='https://resources.blogblog.com/img/icon_feed12.png'/>
Comments
</span>
<div class='feed-reader-links'>
<a class='feed-reader-link' href='http://www.netvibes.com/subscribe.php?url=https%3A%2F%2Fsysadvent.blogspot.com%2Ffeeds%2F8352453746970378361%2Fcomments%2Fdefault' target='_blank'>
<img src='https://resources.blogblog.com/img/widgets/subscribe-netvibes.png'/>
</a>
<a class='feed-reader-link' href='http://add.my.yahoo.com/content?url=https%3A%2F%2Fsysadvent.blogspot.com%2Ffeeds%2F8352453746970378361%2Fcomments%2Fdefault' target='_blank'>
<img src='https://resources.blogblog.com/img/widgets/subscribe-yahoo.png'/>
</a>
<a class='feed-reader-link' href='https://sysadvent.blogspot.com/feeds/8352453746970378361/comments/default' target='_blank'>
<img align='absmiddle' class='feed-icon' src='https://resources.blogblog.com/img/icon_feed12.png'/>
Atom
</a>
</div>
</div>
<div class='bottom'></div>
</div>
<div class='subscribe' id='SW_READER_LIST_CLOSED_Subscribe1PER_POST' onclick='return(_SW_toggleReaderList(event, "Subscribe1PER_POST"));'>
<div class='top'>
<span class='inner'>
<img class='subscribe-dropdown-arrow' src='https://resources.blogblog.com/img/widgets/arrow_dropdown.gif'/>
<span onclick='return(_SW_toggleReaderList(event, "Subscribe1PER_POST"));'>
<img align='absmiddle' alt='' border='0' class='feed-icon' src='https://resources.blogblog.com/img/icon_feed12.png'/>
Comments
</span>
</span>
</div>
<div class='bottom'></div>
</div>
</div>
<div style='clear:both'></div>
</div>
</div>
<div class='clear'></div>
</div><div class='widget BlogArchive' data-version='1' id='BlogArchive2'>
<h2>
Blog Archive
</h2>
<div class='widget-content'>
<div id='ArchiveList'>
<div id='BlogArchive2_ArchiveList'>
<ul class='hierarchy'>
<li class='archivedate expanded'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy toggle-open'>
&#9660;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2021/'>
2021
</a>
<span class='post-count' dir='ltr'>
(
22
)
</span>
<ul class='hierarchy'>
<li class='archivedate expanded'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy toggle-open'>
&#9660;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2021/12/'>
December
</a>
<span class='post-count' dir='ltr'>
(
22
)
</span>
<ul class='posts'>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-23-what-is-ebpf.html'>
Day 23 - What is eBPF?
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-22-so-youre-incident-commander-now.html'>
Day 22 - So, You&#39;re Incident Commander, Now What?
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-20-to-deploy-or-not-to-deploy-that.html'>
Day 20 - To Deploy or Not to Deploy? That is the q...
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-19-into-world-of-chaos-engineering.html'>
Day 19 - Into the World of Chaos Engineering
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-18-minimizing-false-positive.html'>
Day 18 - Minimizing False Positive Monitoring Aler...
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-17-death-to-localhost-benefits-of.html'>
Day 17 - Death to Localhost: The Benefits of Devel...
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-16-setting-up-k3s-in-your-home-lab.html'>
Day 16 - Setting up k3s in your home lab
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-15-introduction-to-pagerduty-api.html'>
Day 15 - Introduction to the PagerDuty API
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-14-whats-in-job-description-and-who.html'>
Day 14 - What&#39;s in a job description (and who does...
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-13-ephemeral-pr-environments.html'>
Day 13 - Ephemeral PR Environments: Enabling autom...
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-12-terraform-refactoring.html'>
Day 12 - Terraform Refactoring
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-11-moving-from-engineering-manager.html'>
Day 11 - Moving from Engineering Manager to IC
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-10-assembling-your-year-in-review.html'>
Day 10 - Assembling Your Year In Review
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/3-things-parenting-taught-me-about.html'>
Day 9 - 3 things parenting taught me about system ...
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-8-d-for-sres.html'>
Day 8 - D&amp;D for SREs
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-7-baking-multi-architecture-docker.html'>
Day 7 - Baking Multi-architecture Docker Images
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/day-6-more-to-come-tomorrow.html'>
Day 6 - More to come tomorrow!
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/least-privilege-using-strace.html'>
Day 5 - Least Privilege using strace
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/gwlb-panacea-for-cloud-dmz-on-aws.html'>
Day 4 - GWLB: Panacea for Cloud DMZ on AWS
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/keeping-config-management-simple-with.html'>
Day 3 - Keeping Config Management Simple with Itamae
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/reliability-as-product-feature.html'>
Day 2 - Reliability as a Product Feature
</a>
</li>
<li>
<a href='https://sysadvent.blogspot.com/2021/12/the-myths-and-magic-in-my-search-for.html'>
Day 1 - The Myths and the Magic in My Search for A...
</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2019/'>
2019
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2019/12/'>
December
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
</li>
</ul>
</li>
</ul>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2017/'>
2017
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2017/12/'>
December
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
</li>
</ul>
</li>
</ul>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2016/'>
2016
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2016/12/'>
December
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
</li>
</ul>
</li>
</ul>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2015/'>
2015
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2015/12/'>
December
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
</li>
</ul>
</li>
</ul>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2014/'>
2014
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2014/12/'>
December
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
</li>
</ul>
</li>
</ul>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2013/'>
2013
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2013/12/'>
December
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
</li>
</ul>
</li>
</ul>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2012/'>
2012
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2012/12/'>
December
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
</li>
</ul>
</li>
</ul>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2011/'>
2011
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2011/12/'>
December
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
</li>
</ul>
</li>
</ul>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2010/'>
2010
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2010/12/'>
December
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
</li>
</ul>
</li>
</ul>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2009/'>
2009
</a>
<span class='post-count' dir='ltr'>
(
26
)
</span>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2009/12/'>
December
</a>
<span class='post-count' dir='ltr'>
(
26
)
</span>
</li>
</ul>
</li>
</ul>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2008/'>
2008
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
<ul class='hierarchy'>
<li class='archivedate collapsed'>
<a class='toggle' href='javascript:void(0)'>
<span class='zippy'>
&#9658;&#160;
</span>
</a>
<a class='post-count-link' href='https://sysadvent.blogspot.com/2008/12/'>
December
</a>
<span class='post-count' dir='ltr'>
(
25
)
</span>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div class='clear'></div>
</div>
</div></div>
</div>
<!-- spacer for skins that want sidebar and main to be the same height-->
<div class='clear'>
&#160;
</div>
</div>
<!-- end content-wrapper -->
<div id='footer-wrapper'>
<div class='footer no-items section' id='footer'></div>
</div>
</div>
</div>
<!-- end outer-wrapper -->
<script type='text/javascript'>
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type='text/javascript'>
try {
var pageTracker = _gat._getTracker("UA-6522917-1");
pageTracker._trackPageview();
} catch(err) {}</script>
<script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/1363620594-widgets.js"></script>
<script type='text/javascript'>
window['__wavt'] = 'AAPvtVlj4iV_14v5SiI0tIizNlNI:1789190002955';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d3615332969083650973','//sysadvent.blogspot.com/2021/12/day-23-what-is-ebpf.html','3615332969083650973');
_WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '3615332969083650973', 'title': 'sysadvent', 'url': 'https://sysadvent.blogspot.com/2021/12/day-23-what-is-ebpf.html', 'canonicalUrl': 'https://sysadvent.blogspot.com/2021/12/day-23-what-is-ebpf.html', 'homepageUrl': 'https://sysadvent.blogspot.com/', 'searchUrl': 'https://sysadvent.blogspot.com/search', 'canonicalHomepageUrl': 'https://sysadvent.blogspot.com/', 'blogspotFaviconUrl': 'https://sysadvent.blogspot.com/favicon.ico', 'bloggerUrl': 'https://www.blogger.com', 'hasCustomDomain': false, 'httpsEnabled': true, 'enabledCommentProfileImages': false, 'gPlusViewType': 'FILTERED_POSTMOD', 'adultContent': false, 'analyticsAccountNumber': '', 'encoding': 'UTF-8', 'locale': 'en', 'localeUnderscoreDelimited': 'en', 'languageDirection': 'ltr', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'isDynamicViewsAvailable': true, 'feedLinks': '\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22sysadvent - Atom\x22 href\x3d\x22https://sysadvent.blogspot.com/feeds/posts/default\x22 /\x3e\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/rss+xml\x22 title\x3d\x22sysadvent - RSS\x22 href\x3d\x22https://sysadvent.blogspot.com/feeds/posts/default?alt\x3drss\x22 /\x3e\n\x3clink rel\x3d\x22service.post\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22sysadvent - Atom\x22 href\x3d\x22https://www.blogger.com/feeds/3615332969083650973/posts/default\x22 /\x3e\n\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22sysadvent - Atom\x22 href\x3d\x22https://sysadvent.blogspot.com/feeds/8352453746970378361/comments/default\x22 /\x3e\n', 'meTag': '', 'adsenseClientId': 'ca-pub-6194074709963145', 'adsenseHostId': 'ca-host-pub-1556223355139109', 'adsenseHasAds': false, 'adsenseAutoAds': false, 'boqCommentIframeForm': true, 'loginRedirectParam': '', 'isGoogleEverywhereLinkTooltipEnabled': true, 'view': '', 'dynamicViewsCommentsSrc': '//www.blogblog.com/dynamicviews/4224c15c4e7c9321/js/comments.js', 'dynamicViewsScriptSrc': '//www.blogblog.com/dynamicviews/1890a9484e710b1c', 'plusOneApiSrc': 'https://apis.google.com/js/platform.js', 'disableGComments': true, 'interstitialAccepted': false, 'sharing': {'platforms': [{'name': 'Get link', 'key': 'link', 'shareMessage': 'Get link', 'target': ''}, {'name': 'Facebook', 'key': 'facebook', 'shareMessage': 'Share to Facebook', 'target': 'facebook'}, {'name': 'BlogThis!', 'key': 'blogThis', 'shareMessage': 'BlogThis!', 'target': 'blog'}, {'name': 'X', 'key': 'twitter', 'shareMessage': 'Share to X', 'target': 'twitter'}, {'name': 'Pinterest', 'key': 'pinterest', 'shareMessage': 'Share to Pinterest', 'target': 'pinterest'}, {'name': 'Email', 'key': 'email', 'shareMessage': 'Email', 'target': 'email'}], 'disableGooglePlus': true, 'googlePlusShareButtonWidth': 0, 'googlePlusBootstrap': '\x3cscript type\x3d\x22text/javascript\x22\x3ewindow.___gcfg \x3d {\x27lang\x27: \x27en\x27};\x3c/script\x3e'}, 'hasCustomJumpLinkMessage': false, 'jumpLinkMessage': 'Read more', 'pageType': 'item', 'postId': '8352453746970378361', 'pageName': 'Day 23 - What is eBPF?', 'pageTitle': 'sysadvent: Day 23 - What is eBPF?'}}, {'name': 'features', 'data': {}}, {'name': 'messages', 'data': {'edit': 'Edit', 'linkCopiedToClipboard': 'Link copied to clipboard!', 'ok': 'Ok', 'postLink': 'Post Link'}}, {'name': 'template', 'data': {'name': 'custom', 'localizedName': 'Custom', 'isResponsive': false, 'isAlternateRendering': false, 'isCustom': true}}, {'name': 'view', 'data': {'classic': {'name': 'classic', 'url': '?view\x3dclassic'}, 'flipcard': {'name': 'flipcard', 'url': '?view\x3dflipcard'}, 'magazine': {'name': 'magazine', 'url': '?view\x3dmagazine'}, 'mosaic': {'name': 'mosaic', 'url': '?view\x3dmosaic'}, 'sidebar': {'name': 'sidebar', 'url': '?view\x3dsidebar'}, 'snapshot': {'name': 'snapshot', 'url': '?view\x3dsnapshot'}, 'timeslide': {'name': 'timeslide', 'url': '?view\x3dtimeslide'}, 'isMobile': false, 'title': 'Day 23 - What is eBPF?', 'description': ' By: Ania Kapu\u015bci\u0144ska ( @lambdanis ) Edited by: Shaun Mouton ( @sdmouton ) Like many engineers, for a long time I\u2019ve thought ...', 'url': 'https://sysadvent.blogspot.com/2021/12/day-23-what-is-ebpf.html', 'type': 'item', 'isSingleItem': true, 'isMultipleItems': false, 'isError': false, 'isPage': false, 'isPost': true, 'isHomepage': false, 'isArchive': false, 'isLabelSearch': false, 'postId': 8352453746970378361}}]);
_WidgetManager._RegisterWidget('_NavbarView', new _WidgetInfo('Navbar1', 'navbar', document.getElementById('Navbar1'), {}, 'displayModeFull'));
_WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', document.getElementById('Header1'), {}, 'displayModeFull'));
_WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false, 'lightboxEnabled': true, 'lightboxModuleUrl': 'https://www.blogger.com/static/v1/jsbin/700075392-lbx.js', 'lightboxCssUrl': 'https://www.blogger.com/static/v1/v-css/828616780-lightbox_bundle.css'}, 'displayModeFull'));
_WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML2', 'sidebar', document.getElementById('HTML2'), {}, 'displayModeFull'));
_WidgetManager._RegisterWidget('_SubscribeView', new _WidgetInfo('Subscribe1', 'sidebar', document.getElementById('Subscribe1'), {}, 'displayModeFull'));
_WidgetManager._RegisterWidget('_BlogArchiveView', new _WidgetInfo('BlogArchive2', 'sidebar', document.getElementById('BlogArchive2'), {'languageDirection': 'ltr', 'loadingMessage': 'Loading\x26hellip;'}, 'displayModeFull'));
</script>
</body>
</html>