mirror of
https://github.com/eunomia-bpf/bpf-developer-tutorial.git
synced 2026-02-10 13:45:07 +08:00
Deploying to gh-pages from @ eunomia-bpf/bpf-developer-tutorial@c120bb4912 🚀
This commit is contained in:
@@ -186,7 +186,7 @@
|
||||
<h2 id="示例程序"><a class="header" href="#示例程序">示例程序</a></h2>
|
||||
<p>此示例程序从发送者的套接字(出口)重定向流量至接收者的套接字(入口),<strong>跳过 TCP/IP 内核网络栈</strong>。在这个示例中,我们假定发送者和接收者都在<strong>同一台</strong>机器上运行。这个示例程序有两个部分,它们共享一个 map 定义:</p>
|
||||
<p>bpf_sockmap.h</p>
|
||||
<pre><code class="language-c">#include "vmlinux.h"
|
||||
<pre><code class="language-c">#include "vmlinux.h"
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
@@ -205,7 +205,7 @@ struct {
|
||||
__uint(max_entries, 65535);
|
||||
__type(key, struct sock_key);
|
||||
__type(value, int);
|
||||
} sock_ops_map SEC(".maps");
|
||||
} sock_ops_map SEC(".maps");
|
||||
</code></pre>
|
||||
<p>这个示例程序中的 BPF 程序被分为两个部分 <code>bpf_redirect.bpf.c</code> 和 <code>bpf_contrack.bpf.c</code>。</p>
|
||||
<ul>
|
||||
@@ -227,11 +227,11 @@ struct {
|
||||
</ol>
|
||||
<p>这个示例程序就是通过 BPF 实现了在本地通信时,快速将消息从发送者的套接字重定向到接收者的套接字,从而绕过了内核网络栈,以提高传输效率。</p>
|
||||
<p>bpf_redirect.bpf.c</p>
|
||||
<pre><code class="language-c">#include "bpf_sockmap.h"
|
||||
<pre><code class="language-c">#include "bpf_sockmap.h"
|
||||
|
||||
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
||||
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
||||
|
||||
SEC("sk_msg")
|
||||
SEC("sk_msg")
|
||||
int bpf_redir(struct sk_msg_md *msg)
|
||||
{
|
||||
if(msg->remote_ip4 != LOCALHOST_IPV4 || msg->local_ip4!= LOCALHOST_IPV4)
|
||||
@@ -248,11 +248,11 @@ int bpf_redir(struct sk_msg_md *msg)
|
||||
}
|
||||
</code></pre>
|
||||
<p>bpf_contrack.bpf.c</p>
|
||||
<pre><code class="language-c">#include "bpf_sockmap.h"
|
||||
<pre><code class="language-c">#include "bpf_sockmap.h"
|
||||
|
||||
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
||||
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
||||
|
||||
SEC("sockops")
|
||||
SEC("sockops")
|
||||
int bpf_sockops_handler(struct bpf_sock_ops *skops){
|
||||
u32 family, op;
|
||||
|
||||
@@ -275,7 +275,7 @@ int bpf_sockops_handler(struct bpf_sock_ops *skops){
|
||||
.family = skops->family,
|
||||
};
|
||||
|
||||
bpf_printk(">>> new connection: OP:%d, PORT:%d --> %d\n", op, bpf_ntohl(key.sport), bpf_ntohl(key.dport));
|
||||
bpf_printk(">>> new connection: OP:%d, PORT:%d --> %d\n", op, bpf_ntohl(key.sport), bpf_ntohl(key.dport));
|
||||
|
||||
bpf_sock_hash_update(skops, &sock_ops_map, &key, BPF_NOEXIST);
|
||||
return BPF_OK;
|
||||
@@ -298,28 +298,28 @@ set -e
|
||||
sudo mount -t bpf bpf /sys/fs/bpf/
|
||||
|
||||
# check if old program already loaded
|
||||
if [ -e "/sys/fs/bpf/bpf_sockops" ]; then
|
||||
echo ">>> bpf_sockops already loaded, uninstalling..."
|
||||
if [ -e "/sys/fs/bpf/bpf_sockops" ]; then
|
||||
echo ">>> bpf_sockops already loaded, uninstalling..."
|
||||
./unload.sh
|
||||
echo ">>> old program already deleted..."
|
||||
echo ">>> old program already deleted..."
|
||||
fi
|
||||
|
||||
# load and attach sock_ops program
|
||||
sudo bpftool prog load bpf_contrack.bpf.o /sys/fs/bpf/bpf_sockops type sockops pinmaps /sys/fs/bpf/
|
||||
sudo bpftool cgroup attach "/sys/fs/cgroup/" sock_ops pinned "/sys/fs/bpf/bpf_sockops"
|
||||
sudo bpftool cgroup attach "/sys/fs/cgroup/" sock_ops pinned "/sys/fs/bpf/bpf_sockops"
|
||||
|
||||
# load and attach sk_msg program
|
||||
sudo bpftool prog load bpf_redirect.bpf.o "/sys/fs/bpf/bpf_redir" map name sock_ops_map pinned "/sys/fs/bpf/sock_ops_map"
|
||||
sudo bpftool prog load bpf_redirect.bpf.o "/sys/fs/bpf/bpf_redir" map name sock_ops_map pinned "/sys/fs/bpf/sock_ops_map"
|
||||
sudo bpftool prog attach pinned /sys/fs/bpf/bpf_redir msg_verdict pinned /sys/fs/bpf/sock_ops_map
|
||||
</code></pre>
|
||||
<p>这是一个 BPF 的加载脚本。它的主要功能是加载和附加 BPF 程序到内核系统中,并将关联的 BPF map 一并存储(pin)到 BPF 文件系统中,以便 BPF 程序能访问和操作这些 map。</p>
|
||||
<p>让我们详细地看一下脚本的每一行是做什么的。</p>
|
||||
<ol>
|
||||
<li><code>sudo mount -t bpf bpf /sys/fs/bpf/</code> 这一行用于挂载 BPF 文件系统,使得 BPF 程序和相关的 map 可以被系统访问和操作。</li>
|
||||
<li>判断条件 <code>[ -e "/sys/fs/bpf/bpf_sockops" ]</code> 是检查是否已经存在 <code>/sys/fs/bpf/bpf_sockops</code> 文件,如果存在,则说明 <code>bpf_sockops</code> 程序已经被加载到系统中,那么将会通过 <code>./unload.sh</code> 脚本将其卸载。</li>
|
||||
<li>判断条件 <code>[ -e "/sys/fs/bpf/bpf_sockops" ]</code> 是检查是否已经存在 <code>/sys/fs/bpf/bpf_sockops</code> 文件,如果存在,则说明 <code>bpf_sockops</code> 程序已经被加载到系统中,那么将会通过 <code>./unload.sh</code> 脚本将其卸载。</li>
|
||||
<li><code>sudo bpftool prog load bpf_contrack.bpf.o /sys/fs/bpf/bpf_sockops type sockops pinmaps /sys/fs/bpf/</code> 这一行是加载上文中 <code>bpf_contrack.bpf.c</code> 编译得到的 BPF 对象文件 <code>bpf_contrack.bpf.o</code> 到 BPF 文件系统中,存储至 <code>/sys/fs/bpf/bpf_sockops</code>,并且指定它的类型为 <code>sockops</code>。<code>pinmaps /sys/fs/bpf/</code> 是指定将加载的 BPF 程序相关的 map 存储在 <code>/sys/fs/bpf/</code> 下。</li>
|
||||
<li><code>sudo bpftool cgroup attach "/sys/fs/cgroup/" sock_ops pinned "/sys/fs/bpf/bpf_sockops"</code> 这一行是将已经加载到 BPF 文件系统的 <code>bpf_sockops</code> 程序附加到 cgroup(此路径为"/sys/fs/cgroup/")。附加后,所有属于这个 cgroup 的套接字操作都会受到 <code>bpf_sockops</code> 的影响。</li>
|
||||
<li><code>sudo bpftool prog load bpf_redirect.bpf.o "/sys/fs/bpf/bpf_redir" map name sock_ops_map pinned "/sys/fs/bpf/sock_ops_map"</code> 这一行是加载 <code>bpf_redirect.bpf.c</code> 编译得到的 BPF 对象文件 <code>bpf_redirect.bpf.o</code> 到 BPF 文件系统中,存储至 <code>/sys/fs/bpf/bpf_redir</code> ,并且指定它的相关 map为 <code>sock_ops_map</code>,这个map在 <code>/sys/fs/bpf/sock_ops_map</code> 中。</li>
|
||||
<li><code>sudo bpftool cgroup attach "/sys/fs/cgroup/" sock_ops pinned "/sys/fs/bpf/bpf_sockops"</code> 这一行是将已经加载到 BPF 文件系统的 <code>bpf_sockops</code> 程序附加到 cgroup(此路径为"/sys/fs/cgroup/")。附加后,所有属于这个 cgroup 的套接字操作都会受到 <code>bpf_sockops</code> 的影响。</li>
|
||||
<li><code>sudo bpftool prog load bpf_redirect.bpf.o "/sys/fs/bpf/bpf_redir" map name sock_ops_map pinned "/sys/fs/bpf/sock_ops_map"</code> 这一行是加载 <code>bpf_redirect.bpf.c</code> 编译得到的 BPF 对象文件 <code>bpf_redirect.bpf.o</code> 到 BPF 文件系统中,存储至 <code>/sys/fs/bpf/bpf_redir</code> ,并且指定它的相关 map为 <code>sock_ops_map</code>,这个map在 <code>/sys/fs/bpf/sock_ops_map</code> 中。</li>
|
||||
<li><code>sudo bpftool prog attach pinned /sys/fs/bpf/bpf_redir msg_verdict pinned /sys/fs/bpf/sock_ops_map</code> 这一行是将已经加载的 <code>bpf_redir</code> 附加到 <code>sock_ops_map</code> 上,附加方式为 <code>msg_verdict</code>,表示当该 map 对应的套接字收到消息时,将会调用 <code>bpf_redir</code> 程序处理。</li>
|
||||
</ol>
|
||||
<p>综上,此脚本的主要作用就是将两个用于处理本地套接字流量的 BPF 程序分别加载到系统并附加到正确的位置,以便它们能被正确地调用,并且确保它们可以访问和操作相关的 BPF map。</p>
|
||||
|
||||
Reference in New Issue
Block a user