<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>mozillazg's Blog</title><link href="https://mozillazg.com/" rel="alternate"></link><link href="https://mozillazg.com/feeds/all.atom.xml" rel="self"></link><id>https://mozillazg.com/</id><updated>2025-11-29T00:00:00+00:00</updated><entry><title>ptcpdump v0.33 ~ v0.37 的主要变更内容</title><link href="https://mozillazg.com/2025/11/whats-new-ptcpdump-v0.33-v0.37.html" rel="alternate"></link><published>2025-11-29T00:00:00+00:00</published><updated>2025-11-29T00:00:00+00:00</updated><author><name>mozillazg</name></author><id>tag:mozillazg.com,2025-11-29:2025/11/whats-new-ptcpdump-v0.33-v0.37.html</id><summary type="html">&lt;div class="section" id="section-1"&gt;
&lt;h2 id="hidsection-1"&gt;前言&lt;a class="headerlink" href="#hidsection-1" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;本文将按变更顺序介绍一下 &lt;a class="reference external" href="https://github.com/mozillazg/ptcpdump"&gt;ptcpdump&lt;/a&gt;
从上次的 &lt;a class="reference external" href="https://mozillazg.com/2025/01/whats-new-ptcpdump-v0.27-v0.32.html"&gt;v0.32&lt;/a&gt;
之后的 v0.33 版本到最新的 v0.37 版本期间所发布的主要变更内容。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="section-2"&gt;
&lt;h2 id="hidsection-2"&gt;主要变更内容&lt;a class="headerlink" href="#hidsection-2" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="bpf-ringbuf-bpf-perfbuf"&gt;
&lt;h3 id="hidbpf-ringbuf-bpf-perfbuf"&gt;优先使用 BPF ringbuf 代替 BPF perfbuf&lt;a class="headerlink" href="#hidbpf-ringbuf-bpf-perfbuf" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;如果当前系统使用的 Linux 内核支持 BPF ringbuf 的话，
ptcpdump 将优先使用 BPF ringbuf 技术优化程序性能。
关于 BPF ringbuf 的更多信息，详见 &lt;a class="reference external" href="https://nakryiko.com/posts/bpf-ringbuf/"&gt;BPF ring buffer&lt;/a&gt; 。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="cgroup-skb"&gt;
&lt;h3 id="hidcgroup-skb"&gt;修复使用 cgroup-skb 后端时按进程过滤数据包功能失效的问题&lt;a class="headerlink" href="#hidcgroup-skb" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;修复之前的版本中，通过 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--backend=cgroup-skb&lt;/span&gt;&lt;/tt&gt; 参数指定使用 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;cgroup-skb&lt;/span&gt;&lt;/tt&gt; 后端时，
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--pid&lt;/span&gt;&lt;/tt&gt; 或 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--pname&lt;/span&gt;&lt;/tt&gt; 参数对应的功能失效的问题。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="pcapng"&gt;
&lt;h3 id="hidpcapng"&gt;支持从标准输入中读取 PcapNG 格式的数据&lt;a class="headerlink" href="#hidpcapng" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;现已支持通过 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-r&lt;/span&gt; -&lt;/tt&gt; 从标准输入中读取 PcapNG 格式的数据:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ cat data.pcapng | ptcpdump -r -
$ ptcpdump -r - &amp;lt; data.pcapng
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="c-w"&gt;
&lt;h3 id="hidc-w"&gt;支持 -C 和 -W 参数实现文件轮转功能&lt;a class="headerlink" href="#hidc-w" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;现已支持在使用 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-w&lt;/span&gt;&lt;/tt&gt; 保存数据到文件中时，使用 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-C&lt;/span&gt;&lt;/tt&gt; 或 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-W&lt;/span&gt;&lt;/tt&gt; 参数实现文件轮转功能:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sudo ptcpdump -i any -w data.pcapng -C 1mb
sudo ptcpdump -i any -w data.pcapng -C 1mb -W 5
&lt;/pre&gt;
&lt;p&gt;其中:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-C&lt;/span&gt;&lt;/tt&gt; 指定文件的最大大小，当超过该大小时，将在旧的文件名后面追加数字（比如 &lt;tt class="docutils literal"&gt;data.pcapng1&lt;/tt&gt; ），来保存历史数据。&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-W&lt;/span&gt;&lt;/tt&gt; 自定保存的文件数量，需要与 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-C&lt;/span&gt;&lt;/tt&gt; 一起使用，用于限制文件数量。&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="f-expression-file-pcap-fitler"&gt;
&lt;h3 id="hidf-expression-file-pcap-fitler"&gt;支持 -F/--expression-file 参数实现从文件中读取 pcap fitler 表达式&lt;a class="headerlink" href="#hidf-expression-file-pcap-fitler" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;现已支持使用 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-F&lt;/span&gt;&lt;/tt&gt; 或者 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--expression-file&lt;/span&gt;&lt;/tt&gt; 参数从文件中读取 pcap filter 包过滤表达式:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sudo ptcpdump -i any -c 10 -F filter.txt
sudo ptcpdump -i any -c 10 --expression-file filter.txt
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="tt-ttt-tttt-ttttt"&gt;
&lt;h3 id="hidtt-ttt-tttt-ttttt"&gt;支持 -tt, -ttt, -tttt, -ttttt 参数实现指定输出的时间格式&lt;a class="headerlink" href="#hidtt-ttt-tttt-ttttt" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;现已支持使用 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-tt&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-ttt&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-tttt&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-ttttt&lt;/span&gt;&lt;/tt&gt; 指定输出包信息时的时间信息格式。&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-tt&lt;/span&gt;&lt;/tt&gt; : 显示时间戳格式，比如 &lt;tt class="docutils literal"&gt;1764417816.346098 ens33 sshd.183127 Out IP xx.xx.xx.xx.22 &amp;gt; &lt;span class="pre"&gt;xx.xx.xx.xx.64755:...&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-ttt&lt;/span&gt;&lt;/tt&gt; : 显示两条记录的时间间隔, 比如 &lt;tt class="docutils literal"&gt;00:00:00.000265 ens33 sshd.183127 Out IP xx.xx.xx.xx.22 &amp;gt; &lt;span class="pre"&gt;xx.xx.xx.xx.64755:...&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-tttt&lt;/span&gt;&lt;/tt&gt; : 显示日期和时间，比如 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;2025-11-29&lt;/span&gt; 20:03:36.346098 ens33 sshd.183127 Out IP xx.xx.xx.xx.22 &amp;gt; &lt;span class="pre"&gt;xx.xx.xx.xx.64755:...&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-ttttt&lt;/span&gt;&lt;/tt&gt; : 显示距离第一条记录的时间间隔，比如 &lt;tt class="docutils literal"&gt;00:00:00.002708 ens33 sshd.183127 Out IP xx.xx.xx.xx.22 &amp;gt; &lt;span class="pre"&gt;xx.xx.xx.xx.64755:...&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="libpcap"&gt;
&lt;h3 id="hidlibpcap"&gt;支持通过动态链接的方式使用系统安装的 libpcap&lt;a class="headerlink" href="#hidlibpcap" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;之前的版本只支持以静态链接的方式编译依赖的 libpcap 库，
现已支持通过动态链接的方式使用系统安装的 libpcap 库，满足简化系统库管理的需求。&lt;/p&gt;
&lt;p&gt;可以通过下面任一编译方式使用动态链接库:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ CGO_ENABLED=1 go build -tags dynamic
$ make build-dynamic-link
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="s-0"&gt;
&lt;h3 id="hids-0"&gt;修复 -s 0 参数会导致程序崩溃的问题&lt;a class="headerlink" href="#hids-0" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在之前的版本中，如果使用 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-s&lt;/span&gt; 0&lt;/tt&gt; 参数会导致 ptcpdump 程序崩溃，这个问题现已修复。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="section-3"&gt;
&lt;h3 id="hidsection-3"&gt;修复终端输出中的时间信息不准确的问题&lt;a class="headerlink" href="#hidsection-3" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在之前的版本中，终端输出的包信息的时间信息随着时间的推移会与实践的事件时间差距越来越大，
这个问题现已修复。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="armv7-cpu"&gt;
&lt;h3 id="hidarmv7-cpu"&gt;实验性支持 armv7 CPU 架构&lt;a class="headerlink" href="#hidarmv7-cpu" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在新版本中已实验性支持 armv7 CPU 架构。
因为缺少支持 armv7 架构的 CI 环境， 因此只能作为实验性支持，
没法保证未来版本的兼容性。如果某个版本不再支持 armv7 了，
欢迎反馈。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="tp-btf"&gt;
&lt;h3 id="hidtp-btf"&gt;新增 tp-btf 后端&lt;a class="headerlink" href="#hidtp-btf" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;新版本增加了一个新的后端 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;tp-btf&lt;/span&gt;&lt;/tt&gt; ，
当指定使用该后端时，ptcpdump 将使用 &lt;tt class="docutils literal"&gt;BPF_PROG_TYPE_TRACING&lt;/tt&gt; 类型的 eBPF 程序来捕获数据包。
该后端与 &lt;tt class="docutils literal"&gt;tc&lt;/tt&gt; 后端的主要区别是：&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;tp-btf&lt;/span&gt;&lt;/tt&gt; 默认将能捕获所有网络命名空间下的数据，
而 &lt;tt class="docutils literal"&gt;tc&lt;/tt&gt; 后端默认只捕获当前网络命名空间下的数据（可以通过 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--netns&lt;/span&gt;&lt;/tt&gt; 命令指定捕获特定网络命名空间下的数据）。
关于该后端与其他后端的区别，详见 &lt;a class="reference external" href="https://github.com/mozillazg/ptcpdump?tab=readme-ov-file#backend"&gt;Backend&lt;/a&gt; 。&lt;/p&gt;
&lt;p&gt;可以通过 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--backend&lt;/span&gt; &lt;span class="pre"&gt;tp-btf&lt;/span&gt;&lt;/tt&gt; 使用新增的 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;tp-btf&lt;/span&gt;&lt;/tt&gt; 后端。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="socket-filter"&gt;
&lt;h3 id="hidsocket-filter"&gt;新增 socket-filter 后端&lt;a class="headerlink" href="#hidsocket-filter" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;新版本增加了另一个新的后端 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;socket-filter&lt;/span&gt;&lt;/tt&gt; ，
当指定使用该后端时，ptcpdump 将使用 &lt;tt class="docutils literal"&gt;BPF_PROG_TYPE_SOCKET_FILTER&lt;/tt&gt; 类型的 eBPF 程序来捕获数据包。
使用该后端时，ptcpdump 的输出结果将更接近 tcpdump 的输出结果，因为此时它们两个捕获数据包的时机会更接近。
关于该后端与其他后端的区别，详见 &lt;a class="reference external" href="https://github.com/mozillazg/ptcpdump?tab=readme-ov-file#backend"&gt;Backend&lt;/a&gt; 。&lt;/p&gt;
&lt;p&gt;可以通过 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--backend&lt;/span&gt; &lt;span class="pre"&gt;socket-filter&lt;/span&gt;&lt;/tt&gt; 使用新增的 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;socket-filter&lt;/span&gt;&lt;/tt&gt; 后端。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="inode-id"&gt;
&lt;h3 id="hidinode-id"&gt;在跨网络命名空间的数据结果中显示 inode ID 信息&lt;a class="headerlink" href="#hidinode-id" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;从新版本开始，当输出结果中包含非当前网络命名空间的数据时，程序将会尝试在输出网络接口信息时，显示对应网络命名空间的 inode ID 信息:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
12:20:31.336316 eth0&amp;#64;4026533097 curl.405939 Out IP 172.17.0.4.38670 &amp;gt; 1.1.1.1.80: Flags [S], seq 3064539219, win 64240, options [mss 1460,sackOK,TS val 1731159046 ecr 0,nop,wscale 7], length 0, ParentProc [bash.405653]
12:20:31.336382 veth1d387b0 curl.405939 In IP 172.17.0.4.38670 &amp;gt; 1.1.1.1.80: Flags [S], seq 3064539219, win 64240, options [mss 1460,sackOK,TS val 1731159046 ecr 0,nop,wscale 7], length 0, ParentProc [bash.405653]
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="v-ip-options"&gt;
&lt;h3 id="hidv-ip-options"&gt;-v 的输出中增加 IP Options 信息&lt;a class="headerlink" href="#hidv-ip-options" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;新版本在使用 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-v&lt;/span&gt;&lt;/tt&gt; 参数输出详情时，将输出 IP Options 信息:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
09:48:31.908813 IP (tos 0x0, ttl 64, id 39183, offset 0, flags [none], proto TCP (6), length 80, options (RR 1.2.3.4, 1.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0,EOL))
    ${IP}.1373 &amp;gt; 1.1.1.1.80: Flags [S], cksum 0xbfb4, seq 122218745, win 512, length 0
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="http"&gt;
&lt;h3 id="hidhttp"&gt;新增输出 HTTP 信息&lt;a class="headerlink" href="#hidhttp" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;如果某一行的数据包是 HTTP 数据，新版本将默认输出基本的 HTTP 信息:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
13:27:02.285015 IP ${IP}.57166 &amp;gt; ${IP}.80: Flags [P.], ..., length 73: HTTP: GET / HTTP/1.1
13:27:02.516911 IP ${IP}.80 &amp;gt; ${IP}.57166: Flags [P.], ..., length 349: HTTP: HTTP/1.1 301 Moved Permanently
&lt;/pre&gt;
&lt;p&gt;如果使用 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-v&lt;/span&gt;&lt;/tt&gt; 参数输出详情，则会包含详细的 HTTP 信息:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
13:27:02.285015 IP (tos 0x0, ttl 64, id 8683, offset 0, flags [DF], proto TCP (6), length 113)
    ..., length 73: HTTP: GET / HTTP/1.1
        GET / HTTP/1.1
        Host: kernel.org
        User-Agent: curl/8.5.0
        Accept: */*

13:27:02.516911 IP (tos 0x0, ttl 128, id 62994, offset 0, flags [none], proto TCP (6), length 389)
    ..., length 349: HTTP: HTTP/1.1 301 Moved Permanently
        HTTP/1.1 301 Moved Permanently
        Server: nginx
        Date: Sat, 05 Jul 2025 13:27:02 GMT
        Content-Type: text/html
        Content-Length: 162
        Connection: keep-alive
        Location: https://kernel.org/

        &amp;lt;html&amp;gt;
        &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;301 Moved Permanently&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;
        &amp;lt;body&amp;gt;
        &amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;301 Moved Permanently&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt;
        &amp;lt;hr&amp;gt;&amp;lt;center&amp;gt;nginx&amp;lt;/center&amp;gt;
        &amp;lt;/body&amp;gt;
        &amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="tls"&gt;
&lt;h3 id="hidtls"&gt;新增输出 TLS 信息&lt;a class="headerlink" href="#hidtls" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;如果某一行的数据包是 TLS 数据，新版本将默认输出 TLS Client Hello 或 Server Hello 信息:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
13:48:40.371849 IP ${IP}.47812 &amp;gt; ${IP}.443: Flags [P.], ..., length 517: TLSv1.0: Client Hello (SNI=kernel.org)
13:48:40.606677 IP ${IP}.443 &amp;gt; ${IP}.47812: Flags [P.], ..., length 1412: TLSv1.3: Server Hello
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="l3"&gt;
&lt;h3 id="hidl3"&gt;新增支持对 L3 网络接口设备抓包&lt;a class="headerlink" href="#hidl3" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;之前的版本只支持对 L2 网络接口设备抓包，新版本已增加对 L3 网络接口（比如 TUN 设备）的支持。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="tcp"&gt;
&lt;h3 id="hidtcp"&gt;改为默认以相对数字显示 TCP 序列号&lt;a class="headerlink" href="#hidtcp" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在之前的版本中，默认会显示 TCP 序列号的原始数字，比较难阅读:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
20:03:36.346098 ens33 sshd.183127 Out IP ${IP}.22 &amp;gt; ${IP}.64755: Flags [P.], seq 1457857145:1457857369, ack 1966040526, win 65535, length 224, ParentProc [sshd.16678]
20:03:36.346909 ens33 sshd.183127 In IP ${IP}.64755 &amp;gt; ${IP}.22: Flags [.], seq 1966040526, ack 1457857369, win 64240, length 0, ParentProc [sshd.16678]
20:03:36.348807 ens33 sshd.183127 Out IP ${IP}.22 &amp;gt; ${IP}.64755: Flags [P.], seq 1457857369:1457857593, ack 1966040526, win 65535, length 224, ParentProc [sshd.16678]
&lt;/pre&gt;
&lt;p&gt;新版本将默认以相对数字的形式显示 TCP 序列号信息:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
20:03:36.346098 ens33 sshd.183127 Out IP ${IP}.22 &amp;gt; ${IP}.64755: Flags [P.], seq 1457857145:1457857369, ack 1966040526, win 65535, length 224, ParentProc [sshd.16678]
20:03:36.346909 ens33 sshd.183127 In IP ${IP}.64755 &amp;gt; ${IP}.22: Flags [.], ack 224, win 64240, length 0, ParentProc [sshd.16678]
20:03:36.348807 ens33 sshd.183127 Out IP ${IP}.22 &amp;gt; ${IP}.64755: Flags [P.], seq 224:448, ack 0, win 65535, length 224, ParentProc [sshd.16678]
&lt;/pre&gt;
&lt;p&gt;同时新增 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-S&lt;/span&gt;&lt;/tt&gt; 和 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--absolute-tcp-sequence-numbers&lt;/span&gt;&lt;/tt&gt; 参数用于控制恢复之前的显示原始数字的模式。&lt;/p&gt;
&lt;p&gt;如果你对 ptcpdump 有额外的改进或新功能建议，欢迎在评论区或项目 issues 中留言。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</summary><category term="ptcpdump"></category></entry><entry><title>Major Changes in ptcpdump versions 0.33 to 0.37</title><link href="https://mozillazg.com/2025/11/whats-new-ptcpdump-v0.33-v0.37-en.html" rel="alternate"></link><published>2025-11-29T00:00:00+00:00</published><updated>2025-11-29T00:00:00+00:00</updated><author><name>mozillazg</name></author><id>tag:mozillazg.com,2025-11-29:2025/11/whats-new-ptcpdump-v0.33-v0.37-en.html</id><summary type="html">&lt;div class="section" id="preface"&gt;
&lt;h2 id="hidpreface"&gt;Preface&lt;a class="headerlink" href="#hidpreface" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This article introduces the main changes in &lt;a class="reference external" href="https://github.com/mozillazg/ptcpdump"&gt;ptcpdump&lt;/a&gt;
from v0.33 (after &lt;a class="reference external" href="https://mozillazg.com/2025/01/whats-new-ptcpdump-v0.27-v0.32-en.html"&gt;v0.32&lt;/a&gt; )
to the latest v0.37, in chronological order.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="main-changes"&gt;
&lt;h2 id="hidmain-changes"&gt;Main changes&lt;a class="headerlink" href="#hidmain-changes" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="prefer-using-bpf-ringbuf-instead-of-bpf-perfbuf"&gt;
&lt;h3 id="hidprefer-using-bpf-ringbuf-instead-of-bpf-perfbuf"&gt;Prefer using BPF ringbuf instead of BPF perfbuf&lt;a class="headerlink" href="#hidprefer-using-bpf-ringbuf-instead-of-bpf-perfbuf" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If the Linux kernel on the current system supports BPF ringbuf,
ptcpdump will prioritize using BPF ringbuf to optimize program performance.
For more information about BPF ringbuf, please refer to
&lt;a class="reference external" href="https://nakryiko.com/posts/bpf-ringbuf/"&gt;BPF ring buffer&lt;/a&gt; .&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="fix-the-issue-where-packet-filtering-by-process-failed-when-using-the-cgroup-skb-backend"&gt;
&lt;h3 id="hidfix-the-issue-where-packet-filtering-by-process-failed-when-using-the-cgroup-skb-backend"&gt;Fix the issue where packet filtering by process failed when using the cgroup-skb backend&lt;a class="headerlink" href="#hidfix-the-issue-where-packet-filtering-by-process-failed-when-using-the-cgroup-skb-backend" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Fixed an issue in previous versions where the features corresponding to
the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--pid&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--pname&lt;/span&gt;&lt;/tt&gt; parameters failed when the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;cgroup-skb&lt;/span&gt;&lt;/tt&gt; backend
was specified via &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--backend=cgroup-skb&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="support-reading-pcapng-format-data-from-standard-input"&gt;
&lt;h3 id="hidsupport-reading-pcapng-format-data-from-standard-input"&gt;Support reading PcapNG format data from standard input&lt;a class="headerlink" href="#hidsupport-reading-pcapng-format-data-from-standard-input" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It now supports reading PcapNG format data from standard input using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-r&lt;/span&gt; -&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ cat data.pcapng | ptcpdump -r -
$ ptcpdump -r - &amp;lt; data.pcapng
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="support-file-rotation-using-c-and-w-options"&gt;
&lt;h3 id="hidsupport-file-rotation-using-c-and-w-options"&gt;Support file rotation using -C and -W options&lt;a class="headerlink" href="#hidsupport-file-rotation-using-c-and-w-options" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It now supports file rotation when saving data to a file using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-w&lt;/span&gt;&lt;/tt&gt;,
by using the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-C&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-W&lt;/span&gt;&lt;/tt&gt; options:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sudo ptcpdump -i any -w data.pcapng -C 1mb
sudo ptcpdump -i any -w data.pcapng -C 1mb -W 5
&lt;/pre&gt;
&lt;p&gt;Where:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-C&lt;/span&gt;&lt;/tt&gt; specifies the maximum file size. When this size is exceeded, a number will be
appended to the old filename (e.g., &lt;tt class="docutils literal"&gt;data.pcapng1&lt;/tt&gt;) to save historical data.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-W&lt;/span&gt;&lt;/tt&gt; specifies the number of files to keep. It must be used with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-C&lt;/span&gt;&lt;/tt&gt; to limit the number of files.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="support-reading-pcap-filter-expressions-from-a-file-using-f-expression-file"&gt;
&lt;h3 id="hidsupport-reading-pcap-filter-expressions-from-a-file-using-f-expression-file"&gt;Support reading pcap filter expressions from a file using -F/--expression-file&lt;a class="headerlink" href="#hidsupport-reading-pcap-filter-expressions-from-a-file-using-f-expression-file" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It now supports reading pcap filter expressions from a file using the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-F&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--expression-file&lt;/span&gt;&lt;/tt&gt; option:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sudo ptcpdump -i any -c 10 -F filter.txt
sudo ptcpdump -i any -c 10 --expression-file filter.txt
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="support-specifying-output-time-format-using-tt-ttt-tttt-ttttt"&gt;
&lt;h3 id="hidsupport-specifying-output-time-format-using-tt-ttt-tttt-ttttt"&gt;Support specifying output time format using -tt, -ttt, -tttt, -ttttt&lt;a class="headerlink" href="#hidsupport-specifying-output-time-format-using-tt-ttt-tttt-ttttt" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It now supports using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-tt&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-ttt&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-tttt&lt;/span&gt;&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-ttttt&lt;/span&gt;&lt;/tt&gt; to
specify the time format when outputting packet information.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-tt&lt;/span&gt;&lt;/tt&gt; : Displays timestamp format, e.g., &lt;tt class="docutils literal"&gt;1764417816.346098 ens33 sshd.183127 Out IP xx.xx.xx.xx.22 &amp;gt; &lt;span class="pre"&gt;xx.xx.xx.xx.64755:...&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-ttt&lt;/span&gt;&lt;/tt&gt; : Displays the time interval between two records, e.g., &lt;tt class="docutils literal"&gt;00:00:00.000265 ens33 sshd.183127 Out IP xx.xx.xx.xx.22 &amp;gt; &lt;span class="pre"&gt;xx.xx.xx.xx.64755:...&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-tttt&lt;/span&gt;&lt;/tt&gt; : Displays date and time, e.g., &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;2025-11-29&lt;/span&gt; 20:03:36.346098 ens33 sshd.183127 Out IP xx.xx.xx.xx.22 &amp;gt; &lt;span class="pre"&gt;xx.xx.xx.xx.64755:...&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-ttttt&lt;/span&gt;&lt;/tt&gt; : Displays the time interval since the first record, e.g., &lt;tt class="docutils literal"&gt;00:00:00.002708 ens33 sshd.183127 Out IP xx.xx.xx.xx.22 &amp;gt; &lt;span class="pre"&gt;xx.xx.xx.xx.64755:...&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="support-using-system-installed-libpcap-via-dynamic-linking"&gt;
&lt;h3 id="hidsupport-using-system-installed-libpcap-via-dynamic-linking"&gt;Support using system-installed libpcap via dynamic linking&lt;a class="headerlink" href="#hidsupport-using-system-installed-libpcap-via-dynamic-linking" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Previous versions only supported compiling the dependent libpcap library via static linking.
It now supports using the system-installed libpcap library via dynamic linking to
meet the needs of simplified system library management.&lt;/p&gt;
&lt;p&gt;You can use the dynamic link library through either of the following compilation methods:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ CGO_ENABLED=1 go build -tags dynamic
$ make build-dynamic-link
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="fix-the-issue-where-using-s-0-caused-the-program-to-crash"&gt;
&lt;h3 id="hidfix-the-issue-where-using-s-0-caused-the-program-to-crash"&gt;Fix the issue where using -s 0 caused the program to crash&lt;a class="headerlink" href="#hidfix-the-issue-where-using-s-0-caused-the-program-to-crash" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In previous versions, using the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-s&lt;/span&gt; 0&lt;/tt&gt; option caused the ptcpdump program to crash. This issue is now fixed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="fix-the-issue-of-inaccurate-timestamps-in-terminal-output"&gt;
&lt;h3 id="hidfix-the-issue-of-inaccurate-timestamps-in-terminal-output"&gt;Fix the issue of inaccurate timestamps in terminal output&lt;a class="headerlink" href="#hidfix-the-issue-of-inaccurate-timestamps-in-terminal-output" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In previous versions, the timestamps of packet information in the terminal
output drifted further from the actual event time over time.
This issue is now fixed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="experimental-support-for-armv7-cpu-architecture"&gt;
&lt;h3 id="hidexperimental-support-for-armv7-cpu-architecture"&gt;Experimental support for armv7 CPU architecture&lt;a class="headerlink" href="#hidexperimental-support-for-armv7-cpu-architecture" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Experimental support for the armv7 CPU architecture has been added in the new version.
Since there is no CI environment supporting the armv7 architecture, this is only experimental support,
and compatibility in future versions cannot be guaranteed. If a version no longer supports armv7,
feedback is welcome.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="add-tp-btf-backend"&gt;
&lt;h3 id="hidadd-tp-btf-backend"&gt;Add tp-btf backend&lt;a class="headerlink" href="#hidadd-tp-btf-backend" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A new backend &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;tp-btf&lt;/span&gt;&lt;/tt&gt; has been added.
When this backend is used, ptcpdump uses &lt;tt class="docutils literal"&gt;BPF_PROG_TYPE_TRACING&lt;/tt&gt; eBPF programs to capture packets.
The main difference from the &lt;tt class="docutils literal"&gt;tc&lt;/tt&gt; backend is that &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;tp-btf&lt;/span&gt;&lt;/tt&gt; captures data from all network namespaces by default,
while the &lt;tt class="docutils literal"&gt;tc&lt;/tt&gt; backend defaults to capturing data only from the current
network namespace (use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--netns&lt;/span&gt;&lt;/tt&gt; to specify a specific network namespace).
For differences between backends, see &lt;a class="reference external" href="https://github.com/mozillazg/ptcpdump?tab=readme-ov-file#backend"&gt;Backend&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;You can use the new &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;tp-btf&lt;/span&gt;&lt;/tt&gt; backend via &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--backend&lt;/span&gt; &lt;span class="pre"&gt;tp-btf&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="add-socket-filter-backend"&gt;
&lt;h3 id="hidadd-socket-filter-backend"&gt;Add socket-filter backend&lt;a class="headerlink" href="#hidadd-socket-filter-backend" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Another new backend &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;socket-filter&lt;/span&gt;&lt;/tt&gt; has been added.
When this backend is used, ptcpdump uses &lt;tt class="docutils literal"&gt;BPF_PROG_TYPE_SOCKET_FILTER&lt;/tt&gt; eBPF programs to capture packets.
When using this backend, the output of ptcpdump is closer to the output
of tcpdump because the packet capture timing is more similar.
For differences between backends, see &lt;a class="reference external" href="https://github.com/mozillazg/ptcpdump?tab=readme-ov-file#backend"&gt;Backend&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;You can use the new &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;socket-filter&lt;/span&gt;&lt;/tt&gt; backend via &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--backend&lt;/span&gt; &lt;span class="pre"&gt;socket-filter&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="display-inode-id-in-cross-network-namespace-results"&gt;
&lt;h3 id="hiddisplay-inode-id-in-cross-network-namespace-results"&gt;Display inode ID in cross-network namespace results&lt;a class="headerlink" href="#hiddisplay-inode-id-in-cross-network-namespace-results" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Starting from the new version, when the output contains data from a non-current network namespace,
the program will attempt to display the inode ID of that network
namespace when showing network interface information:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
12:20:31.336316 eth0&amp;#64;4026533097 curl.405939 Out IP 172.17.0.4.38670 &amp;gt; 1.1.1.1.80: Flags [S], seq 3064539219, win 64240, options [mss 1460,sackOK,TS val 1731159046 ecr 0,nop,wscale 7], length 0, ParentProc [bash.405653]
12:20:31.336382 veth1d387b0 curl.405939 In IP 172.17.0.4.38670 &amp;gt; 1.1.1.1.80: Flags [S], seq 3064539219, win 64240, options [mss 1460,sackOK,TS val 1731159046 ecr 0,nop,wscale 7], length 0, ParentProc [bash.405653]
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="add-ip-options-information-to-v-output"&gt;
&lt;h3 id="hidadd-ip-options-information-to-v-output"&gt;Add IP Options information to -v output&lt;a class="headerlink" href="#hidadd-ip-options-information-to-v-output" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The new version will output IP Options information when using the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-v&lt;/span&gt;&lt;/tt&gt; option for details:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
09:48:31.908813 IP (tos 0x0, ttl 64, id 39183, offset 0, flags [none], proto TCP (6), length 80, options (RR 1.2.3.4, 1.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0,EOL))
    ${IP}.1373 &amp;gt; 1.1.1.1.80: Flags [S], cksum 0xbfb4, seq 122218745, win 512, length 0
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="add-output-for-http-information"&gt;
&lt;h3 id="hidadd-output-for-http-information"&gt;Add output for HTTP information&lt;a class="headerlink" href="#hidadd-output-for-http-information" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If a packet contains HTTP data, the new version will output basic HTTP information by default:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
13:27:02.285015 IP ${IP}.57166 &amp;gt; ${IP}.80: Flags [P.], ..., length 73: HTTP: GET / HTTP/1.1
13:27:02.516911 IP ${IP}.80 &amp;gt; ${IP}.57166: Flags [P.], ..., length 349: HTTP: HTTP/1.1 301 Moved Permanently
&lt;/pre&gt;
&lt;p&gt;If &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-v&lt;/span&gt;&lt;/tt&gt; is used for detailed output, detailed HTTP information will be included:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
13:27:02.285015 IP (tos 0x0, ttl 64, id 8683, offset 0, flags [DF], proto TCP (6), length 113)
    ..., length 73: HTTP: GET / HTTP/1.1
        GET / HTTP/1.1
        Host: kernel.org
        User-Agent: curl/8.5.0
        Accept: */*

13:27:02.516911 IP (tos 0x0, ttl 128, id 62994, offset 0, flags [none], proto TCP (6), length 389)
    ..., length 349: HTTP: HTTP/1.1 301 Moved Permanently
        HTTP/1.1 301 Moved Permanently
        Server: nginx
        Date: Sat, 05 Jul 2025 13:27:02 GMT
        Content-Type: text/html
        Content-Length: 162
        Connection: keep-alive
        Location: https://kernel.org/

        &amp;lt;html&amp;gt;
        &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;301 Moved Permanently&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;
        &amp;lt;body&amp;gt;
        &amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;301 Moved Permanently&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt;
        &amp;lt;hr&amp;gt;&amp;lt;center&amp;gt;nginx&amp;lt;/center&amp;gt;
        &amp;lt;/body&amp;gt;
        &amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="add-output-for-tls-information"&gt;
&lt;h3 id="hidadd-output-for-tls-information"&gt;Add output for TLS information&lt;a class="headerlink" href="#hidadd-output-for-tls-information" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If a packet contains TLS data, the new version will output TLS Client Hello
or Server Hello information by default:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
13:48:40.371849 IP ${IP}.47812 &amp;gt; ${IP}.443: Flags [P.], ..., length 517: TLSv1.0: Client Hello (SNI=kernel.org)
13:48:40.606677 IP ${IP}.443 &amp;gt; ${IP}.47812: Flags [P.], ..., length 1412: TLSv1.3: Server Hello
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="add-support-for-capturing-on-l3-network-interface-devices"&gt;
&lt;h3 id="hidadd-support-for-capturing-on-l3-network-interface-devices"&gt;Add support for capturing on L3 network interface devices&lt;a class="headerlink" href="#hidadd-support-for-capturing-on-l3-network-interface-devices" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Previous versions only supported capturing on L2 network interface devices.
The new version adds support for L3 network interfaces (such as TUN devices).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="change-to-display-tcp-sequence-numbers-as-relative-numbers-by-default"&gt;
&lt;h3 id="hidchange-to-display-tcp-sequence-numbers-as-relative-numbers-by-default"&gt;Change to display TCP sequence numbers as relative numbers by default&lt;a class="headerlink" href="#hidchange-to-display-tcp-sequence-numbers-as-relative-numbers-by-default" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In previous versions, raw TCP sequence numbers were displayed by default, which was hard to read:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
20:03:36.346098 ens33 sshd.183127 Out IP ${IP}.22 &amp;gt; ${IP}.64755: Flags [P.], seq 1457857145:1457857369, ack 1966040526, win 65535, length 224, ParentProc [sshd.16678]
20:03:36.346909 ens33 sshd.183127 In IP ${IP}.64755 &amp;gt; ${IP}.22: Flags [.], seq 1966040526, ack 1457857369, win 64240, length 0, ParentProc [sshd.16678]
20:03:36.348807 ens33 sshd.183127 Out IP ${IP}.22 &amp;gt; ${IP}.64755: Flags [P.], seq 1457857369:1457857593, ack 1966040526, win 65535, length 224, ParentProc [sshd.16678]
&lt;/pre&gt;
&lt;p&gt;The new version displays TCP sequence numbers as relative numbers by default:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
20:03:36.346098 ens33 sshd.183127 Out IP ${IP}.22 &amp;gt; ${IP}.64755: Flags [P.], seq 1457857145:1457857369, ack 1966040526, win 65535, length 224, ParentProc [sshd.16678]
20:03:36.346909 ens33 sshd.183127 In IP ${IP}.64755 &amp;gt; ${IP}.22: Flags [.], ack 224, win 64240, length 0, ParentProc [sshd.16678]
20:03:36.348807 ens33 sshd.183127 Out IP ${IP}.22 &amp;gt; ${IP}.64755: Flags [P.], seq 224:448, ack 0, win 65535, length 224, ParentProc [sshd.16678]
&lt;/pre&gt;
&lt;p&gt;It also adds the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-S&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--absolute-tcp-sequence-numbers&lt;/span&gt;&lt;/tt&gt; options to
switch back to displaying raw numbers.&lt;/p&gt;
&lt;p&gt;If you have any additional improvements or new feature suggestions for ptcpdump,
feel free to leave a comment in the comments section or project issues.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</summary><category term="ptcpdump"></category></entry><entry><title>使用 elibpcap 为网络相关 eBPF 程序实现 pcap-filter 包过滤语法支持</title><link href="https://mozillazg.com/2025/05/ebpf-let-any-network-ebpf-programs-to-support-pcap-filter-with-elibpcap.html" rel="alternate"></link><published>2025-05-03T00:00:00+00:00</published><updated>2025-05-03T00:00:00+00:00</updated><author><name>mozillazg</name></author><id>tag:mozillazg.com,2025-05-03:2025/05/ebpf-let-any-network-ebpf-programs-to-support-pcap-filter-with-elibpcap.html</id><summary type="html">&lt;div class="section" id="section-1"&gt;
&lt;h2 id="hidsection-1"&gt;前言&lt;a class="headerlink" href="#hidsection-1" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;我们常用的 tcpdump 抓包工具的一个核心能力是支持使用
&lt;a class="reference external" href="https://www.tcpdump.org/manpages/pcap-filter.7.html"&gt;pcap-filter&lt;/a&gt;
包过滤语法对流量进行过滤，只对符合条件的特定流量进行抓包。&lt;/p&gt;
&lt;p&gt;当我们使用 eBPF 技术开发网络相关的工具的时候，如果也能支持 pcap-filter 包过滤语法的话，
想必会极大的提升用户体验。
因此，我开发的 &lt;a class="reference external" href="https://github.com/mozillazg/ptcpdump"&gt;ptcpdump&lt;/a&gt; 工具也内置了对 pcap-filter 包过滤语法的支持。&lt;/p&gt;
&lt;p&gt;使用常规方法为 eBPF 程序增加 pcap-filter 支持会需要实现复杂的逻辑。
但是，如果你的项目正在使用 &lt;a class="reference external" href="https://github.com/cilium/ebpf"&gt;cilium/ebpf&lt;/a&gt; 作为 eBPF Loader，
通过使用本文介绍的 elibpcap 这个 Go package ，
你只需要增加几行代码就能为你的项目内置支持 pcap-filter 包过滤语法的能力。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="section-2"&gt;
&lt;h2 id="hidsection-2"&gt;项目介绍&lt;a class="headerlink" href="#hidsection-2" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;如前面所说，通过使用 elibpcap，只需几行代码就可以为 eBPF 项目增加支持 pcap-filter 的能力。&lt;/p&gt;
&lt;p&gt;下面是 &lt;a class="reference external" href="https://deepwiki.com/jschwinger233/elibpcap"&gt;AI&lt;/a&gt; 总结的项目介绍：&lt;/p&gt;
&lt;blockquote&gt;
elibpcap 是一个 Go 语言包，它提供的功能是：将 pcap 过滤表达式编译为 eBPF 字节码，
并将这些过滤器注入到现有的 eBPF 程序中。它将人类可读的 pcap 过滤表达式
（例如 tcpdump 等工具中使用的那些表达式）的世界与在 Linux 内核中运行的 eBPF 程序的强大能力和高效率连接了起来。&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class="section" id="section-3"&gt;
&lt;h2 id="hidsection-3"&gt;项目地址&lt;a class="headerlink" href="#hidsection-3" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/jschwinger233/elibpcap"&gt;https://github.com/jschwinger233/elibpcap&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="section-4"&gt;
&lt;h2 id="hidsection-4"&gt;使用示例&lt;a class="headerlink" href="#hidsection-4" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="section-5"&gt;
&lt;h3 id="hidsection-5"&gt;使用模式&lt;a class="headerlink" href="#hidsection-5" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;为了使用 elibpcap ，我们需要做三方面的修改：&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;一个是，需要修改 eBPF 程序，在需要实现数据包过滤的位置增加类似如下的 placeholder 逻辑：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__noinline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;_skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;__skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;___skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_skb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__skb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__skb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;___skb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tc&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sample_prog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;__sk_buff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;bpf_printk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter not match&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;另一个是，需要修改 Go 程序，调用 elibpcap package 增加集成 pcap-filter 包过滤能力的逻辑：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;
&lt;span class="nx"&gt;newInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;AtBpf2Bpf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;PacketAccessMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Direct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;L2Skb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;其中：&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;AtBpf2Bpf&lt;/tt&gt; 用于指定是我们在 eBPF 程序中定义的 &lt;tt class="docutils literal"&gt;static __noinline bool &lt;span class="pre"&gt;pcap_filter(...)&lt;/span&gt;&lt;/tt&gt; 函数的名称。&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;PacketAccessMode&lt;/tt&gt; 用于指定 elibpcap 在生成的字节码时，应当使用哪种方式读取我们在 eBPF 程序中向 &lt;tt class="docutils literal"&gt;pcap_filter&lt;/tt&gt; 函数所传入的 skb 数据。
取值如下：&lt;ul&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;elibpcap.Direct&lt;/tt&gt; ：使用 &lt;a class="reference external" href="https://docs.kernel.org/bpf/verifier.html#direct-packet-access"&gt;direct access&lt;/a&gt;
的方式读取数据，即，直接通过指针操作读取数据。&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;elibpcap.BpfProbeReadKernel&lt;/tt&gt; ：使用辅助函数 &lt;tt class="docutils literal"&gt;bpf_probe_read_kernel&lt;/tt&gt; 读取数据。&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;elibpcap.BpfSkbLoadBytes&lt;/tt&gt; ：使用辅助函数 &lt;tt class="docutils literal"&gt;bpf_skb_load_bytes&lt;/tt&gt; 读取数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;L2Skb&lt;/tt&gt; 用于指定我们的 eBPF 程序中 &lt;tt class="docutils literal"&gt;pcap_filter&lt;/tt&gt; 函数传入的 skb 数据是否包含 L2（链路层） 相关的数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic" start="3"&gt;
&lt;li&gt;&lt;p class="first"&gt;最后是，因为 elibpcap 依赖了 libpcap ，因此需要在编译时启用 CGO：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;静态链接编译示例：&lt;/p&gt;
&lt;pre class="literal-block"&gt;
CGO_CFLAGS=&amp;quot;-I/path/to/libpcap/include&amp;quot; \
CGO_LDFLAGS=&amp;quot;-L/path/to/libpcap/lib -lpcap /path/to/libpcap.a&amp;quot; \
CGO_ENABLED=1 go build -o main \
-tags static -ldflags &amp;quot;-linkmode 'external' -extldflags '-static'&amp;quot;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;动态链接编译示例：&lt;/p&gt;
&lt;pre class="literal-block"&gt;
CGO_ENABLED=1 go build -o main -tags dynamic
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下面将以常见的不同 eBPF 程序类型为例介绍如何集成 elibpcap。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="tc-tcx"&gt;
&lt;h3 id="hidtc-tcx"&gt;tc/tcx&lt;a class="headerlink" href="#hidtc-tcx" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;下面是 tc eBPF 程序中需要做的修改：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__noinline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;_skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;__skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;___skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_skb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__skb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__skb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;___skb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tc&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sample_prog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;__sk_buff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bpf_skb_pull_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;bpf_printk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter not match&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bpf_printk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello from tc after pcap filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TC_ACT_UNSPEC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;可以看到主要的修改点是：&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;新增了一个 &lt;tt class="docutils literal"&gt;pcap_filter&lt;/tt&gt; 函数。&lt;/li&gt;
&lt;li&gt;新增了一个 &lt;tt class="docutils literal"&gt;if &lt;span class="pre"&gt;(!pcap_filter((void&lt;/span&gt; *)skb, (void *)skb, (void *)skb, data, data_end))&lt;/tt&gt; 的判断。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下面是对应的 Go 程序所需要做的修改：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;injectFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ebpf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CollectionSpec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;inject pcap filter: %s&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;AtBpf2Bpf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;PacketAccessMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Direct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;L2Skb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// end&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;injectFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LoadAndAssign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;objs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;完整的示例程序详见：&lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/tc"&gt;tc&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="xdp"&gt;
&lt;h3 id="hidxdp"&gt;xdp&lt;a class="headerlink" href="#hidxdp" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;xdp 程序集成 pcap-filter 能力所需要做的修改与 tc/tcx 程序基本一致。&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;c 程序:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;xdp&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sample_prog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;xdp_md&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;bpf_printk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter not match&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;go 程序:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;injectFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ebpf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CollectionSpec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;AtBpf2Bpf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;PacketAccessMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Direct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;L2Skb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;完整的示例程序详见：&lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/xdp"&gt;xdp&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="cgroup-skb"&gt;
&lt;h3 id="hidcgroup-skb"&gt;cgroup-skb&lt;a class="headerlink" href="#hidcgroup-skb" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;cgroup-skb 程序与前面 tc/tcx/xdp 程序所需要做的修改也是基本一致。&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;c 程序:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cgroup_skb/egress&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sample_prog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;__sk_buff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;go 程序:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;injectFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ebpf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CollectionSpec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;AtBpf2Bpf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;PacketAccessMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Direct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;L2Skb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这里有一个需要注意的点： 因为 cgroup-skb 程序中 skb 的数据里未包含 L2 的数据，因此这里需要设置 &lt;tt class="docutils literal"&gt;L2Skb: false&lt;/tt&gt; 。&lt;/p&gt;
&lt;p&gt;完整的示例程序详见：&lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/cgroup-skb"&gt;cgroup-skb&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="kprobe-fentry-tracepoint"&gt;
&lt;h3 id="hidkprobe-fentry-tracepoint"&gt;kprobe/fentry/tracepoint&lt;a class="headerlink" href="#hidkprobe-fentry-tracepoint" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;elibpcap 帮助我们屏蔽了 kprobe/fentry/tracepoint 程序与前面的 tc/tcx/xdp 程序
在数据读取方面的差异，让我们可以以基本一致的方式进行集成。&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;c 程序:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;kprobe/__dev_queue_xmit&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BPF_KPROBE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sample_prog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;sk_buff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;skb_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BPF_CORE_READ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;skb_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BPF_CORE_READ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;network_header&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;skb_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BPF_CORE_READ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;go 程序:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;injectFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ebpf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CollectionSpec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;AtBpf2Bpf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;PacketAccessMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BpfProbeReadKernel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;L2Skb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这里有两个需要注意的点：&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;因为在 kprobe 程序中无法通过 “direct packet access“ 的方式读取 skb 中的包数据，
因此我们选择设置 &lt;tt class="docutils literal"&gt;PacketAccessMode: elibpcap.BpfProbeReadKernel&lt;/tt&gt; 使用 &lt;tt class="docutils literal"&gt;bpf_probe_read_kernel&lt;/tt&gt; 读取数据。&lt;/li&gt;
&lt;li&gt;因为我们的 kprobe 程序中检查的是 L3 的数据，因此这里需要设置 &lt;tt class="docutils literal"&gt;L2Skb: false&lt;/tt&gt; 。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;完整的示例程序详见：
&lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/kprobe"&gt;kprobe&lt;/a&gt; ,
&lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/fentry"&gt;fentry&lt;/a&gt; ,
&lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/tracepoint"&gt;tracepoint&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="socket-filter"&gt;
&lt;h3 id="hidsocket-filter"&gt;socket filter&lt;a class="headerlink" href="#hidsocket-filter" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;socket filter 程序的一个限制是无法使用 direct access 或 bpf_probe_read_kernel 的方式读取数据包，
只能使用类似 bpf_skb_load_bytes 的方式读取数据包。&lt;/p&gt;
&lt;p&gt;下面是使用 socket filter 程序集成 elibpcap 的示例代码：&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;c 程序:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;socket&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sample_prog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;__sk_buff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bpf_skb_load_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;go 程序:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;injectFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ebpf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CollectionSpec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;AtBpf2Bpf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;PacketAccessMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BpfSkbLoadBytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;L2Skb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这里有三个需要注意的点：&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;我们需要使用 &lt;tt class="docutils literal"&gt;bpf_skb_load_bytes&lt;/tt&gt; 读取数据，因此 &lt;tt class="docutils literal"&gt;PacketAccessMode&lt;/tt&gt; 被设置为 &lt;tt class="docutils literal"&gt;elibpcap.BpfSkbLoadBytes&lt;/tt&gt; 。&lt;/li&gt;
&lt;li&gt;在 socket filter 程序中，我们是直接从 skb 而不是从 skb-&amp;gt;data 中读取的数据，因此 data 被设置为 skb。&lt;/li&gt;
&lt;li&gt;在 socket filter 程序中，我们无法直接获取 skb-&amp;gt;data_end，
并且 pcap_filter 中的 data_end 在使用 &lt;tt class="docutils literal"&gt;BpfSkbLoadBytes&lt;/tt&gt; 访问方式时只是一个用于申请一个栈变量的 placeholder 变量，
因此我们可以直接使用一个 dummy 变量作为 date_end。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;完整的示例程序详见：
&lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/socket-filter"&gt;socket-filter&lt;/a&gt; 。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="section-6"&gt;
&lt;h2 id="hidsection-6"&gt;结束语&lt;a class="headerlink" href="#hidsection-6" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;如果你的使用 Go 和 eBPF 技术开发的网络项目想要集成 pcap-filter 的能力，但却苦于无从下手，
推荐尝试集成 elibpcap 这个巧妙而强大的项目。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="section-7"&gt;
&lt;h2 id="hidsection-7"&gt;参考资料&lt;a class="headerlink" href="#hidsection-7" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/jschwinger233/elibpcap"&gt;jschwinger233/elibpcap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/mozillazg/ptcpdump"&gt;mozillazg/ptcpdump: Process-aware, eBPF-based tcpdump&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples"&gt;mozillazg/elibpcap-examples: usage of github.com/jschwinger233/elibpcap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/jschwinger233/ktcpdump"&gt;jschwinger233/ktcpdump&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</summary><category term="elibpcap"></category><category term="cilium/ebpf"></category><category term="pcap-filter"></category></entry><entry><title>Implement pcap-filter syntax support for network eBPF programs using elibpcap</title><link href="https://mozillazg.com/2025/05/ebpf-let-any-network-ebpf-programs-to-support-pcap-filter-with-elibpcap-en.html" rel="alternate"></link><published>2025-05-03T00:00:00+00:00</published><updated>2025-05-03T00:00:00+00:00</updated><author><name>mozillazg</name></author><id>tag:mozillazg.com,2025-05-03:2025/05/ebpf-let-any-network-ebpf-programs-to-support-pcap-filter-with-elibpcap-en.html</id><summary type="html">&lt;div class="section" id="preface"&gt;
&lt;h2 id="hidpreface"&gt;Preface&lt;a class="headerlink" href="#hidpreface" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A core feature of the common &lt;tt class="docutils literal"&gt;tcpdump&lt;/tt&gt; packet capture tool is its support for the
&lt;a class="reference external" href="https://www.tcpdump.org/manpages/pcap-filter.7.html"&gt;pcap-filter&lt;/a&gt;
syntax. This lets it filter traffic and capture only specific packets matching the filter.&lt;/p&gt;
&lt;p&gt;When developing network-related tools with eBPF, supporting the pcap-filter syntax
would greatly improve user experience.
That's why the &lt;a class="reference external" href="https://github.com/mozillazg/ptcpdump"&gt;ptcpdump&lt;/a&gt; tool I developed
includes built-in support for the pcap-filter syntax.&lt;/p&gt;
&lt;p&gt;Adding pcap-filter support to eBPF programs the usual way involves complex logic.
However, if your project uses &lt;a class="reference external" href="https://github.com/cilium/ebpf"&gt;cilium/ebpf&lt;/a&gt; as its eBPF loader,
you can use the elibpcap Go package introduced in this article.
This lets you add built-in pcap-filter syntax support to your project with just a few lines of code.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="project-introduction"&gt;
&lt;h2 id="hidproject-introduction"&gt;Project Introduction&lt;a class="headerlink" href="#hidproject-introduction" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As mentioned before, using elibpcap allows you to add pcap-filter support to an eBPF project with just a few lines of code.&lt;/p&gt;
&lt;p&gt;Here is a project introduction summarized by &lt;a class="reference external" href="https://deepwiki.com/jschwinger233/elibpcap"&gt;AI&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
elibpcap is a Go package that provides functionality for compiling pcap filter expressions into
eBPF bytecode and injecting these filters into existing eBPF programs.
It bridges the world of human-readable pcap filter expressions
(like those used in tools such as tcpdump) with the power and efficiency
of eBPF programs running in the Linux kernel.&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class="section" id="project-repository"&gt;
&lt;h2 id="hidproject-repository"&gt;Project Repository&lt;a class="headerlink" href="#hidproject-repository" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/jschwinger233/elibpcap"&gt;https://github.com/jschwinger233/elibpcap&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="usage-example"&gt;
&lt;h2 id="hidusage-example"&gt;Usage Example&lt;a class="headerlink" href="#hidusage-example" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="usage-pattern"&gt;
&lt;h3 id="hidusage-pattern"&gt;Usage Pattern&lt;a class="headerlink" href="#hidusage-pattern" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To use elibpcap, we need to make changes in three areas:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;First, modify the eBPF program. Add placeholder logic like the following where packet filtering is needed:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__noinline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;_skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;__skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;___skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_skb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__skb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__skb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;___skb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tc&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sample_prog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;__sk_buff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;bpf_printk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter not match&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;Second, modify the Go program. Call the elibpcap package to add the logic for integrating pcap-filter capability:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;
&lt;span class="nx"&gt;newInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;AtBpf2Bpf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;PacketAccessMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Direct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;L2Skb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Where:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;AtBpf2Bpf&lt;/tt&gt; specifies the name of the &lt;tt class="docutils literal"&gt;static __noinline bool &lt;span class="pre"&gt;pcap_filter(...)&lt;/span&gt;&lt;/tt&gt; function defined in our eBPF program.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;PacketAccessMode&lt;/tt&gt; specifies how elibpcap should read the skb data passed to the &lt;tt class="docutils literal"&gt;pcap_filter&lt;/tt&gt; function in our eBPF program when generating bytecode.
Values are:&lt;ul&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;elibpcap.Direct&lt;/tt&gt;: Uses &lt;a class="reference external" href="https://docs.kernel.org/bpf/verifier.html#direct-packet-access"&gt;direct access&lt;/a&gt;
to read data, i.e., direct pointer operations.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;elibpcap.BpfProbeReadKernel&lt;/tt&gt;: Uses the helper function &lt;tt class="docutils literal"&gt;bpf_probe_read_kernel&lt;/tt&gt; to read data.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;elibpcap.BpfSkbLoadBytes&lt;/tt&gt;: Uses the helper function &lt;tt class="docutils literal"&gt;bpf_skb_load_bytes&lt;/tt&gt; to read data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;L2Skb&lt;/tt&gt; specifies if the skb data passed to the &lt;tt class="docutils literal"&gt;pcap_filter&lt;/tt&gt; function in our eBPF program includes L2 (link layer) related data.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic" start="3"&gt;
&lt;li&gt;&lt;p class="first"&gt;Finally, because elibpcap depends on libpcap, you need to enable CGO during compilation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Static linking example:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
CGO_CFLAGS=&amp;quot;-I/path/to/libpcap/include&amp;quot; \
CGO_LDFLAGS=&amp;quot;-L/path/to/libpcap/lib -lpcap /path/to/libpcap.a&amp;quot; \
CGO_ENABLED=1 go build -o main \
-tags static -ldflags &amp;quot;-linkmode 'external' -extldflags '-static'&amp;quot;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Dynamic linking example:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
CGO_ENABLED=1 go build -o main -tags dynamic
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The following sections will show how to integrate elibpcap with examples for different common eBPF program types.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="tc-tcx"&gt;
&lt;h3 id="hidtc-tcx"&gt;tc/tcx&lt;a class="headerlink" href="#hidtc-tcx" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Below are the changes required in the tc eBPF program:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__noinline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;_skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;__skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;___skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_skb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__skb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__skb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;___skb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tc&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sample_prog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;__sk_buff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bpf_skb_pull_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;bpf_printk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter not match&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bpf_printk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello from tc after pcap filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TC_ACT_UNSPEC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The main changes are:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Added a &lt;tt class="docutils literal"&gt;pcap_filter&lt;/tt&gt; function.&lt;/li&gt;
&lt;li&gt;Added an &lt;tt class="docutils literal"&gt;if &lt;span class="pre"&gt;(!pcap_filter((void&lt;/span&gt; *)skb, (void *)skb, (void *)skb, data, data_end))&lt;/tt&gt; check.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Below are the corresponding changes required in the Go program:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;injectFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ebpf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CollectionSpec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;inject pcap filter: %s&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;AtBpf2Bpf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;PacketAccessMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Direct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;L2Skb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// end&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;injectFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LoadAndAssign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;objs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See the complete example program: &lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/tc"&gt;tc&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="xdp"&gt;
&lt;h3 id="hidxdp"&gt;xdp&lt;a class="headerlink" href="#hidxdp" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The modifications needed to integrate pcap-filter capability into XDP programs are basically the same as for tc/tcx programs.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;c program:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;xdp&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sample_prog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;xdp_md&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;bpf_printk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter not match&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;go program:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;injectFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ebpf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CollectionSpec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;AtBpf2Bpf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;PacketAccessMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Direct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;L2Skb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See the complete example program: &lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/xdp"&gt;xdp&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="cgroup-skb"&gt;
&lt;h3 id="hidcgroup-skb"&gt;cgroup-skb&lt;a class="headerlink" href="#hidcgroup-skb" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The modifications needed for cgroup-skb programs are also basically the same as those for the previous tc/tcx/xdp programs.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;c program:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cgroup_skb/egress&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sample_prog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;__sk_buff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;go program:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;injectFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ebpf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CollectionSpec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;AtBpf2Bpf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;PacketAccessMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Direct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;L2Skb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;One point to note: Because the skb data in cgroup-skb programs does not contain L2 data, set &lt;tt class="docutils literal"&gt;L2Skb: false&lt;/tt&gt; here.&lt;/p&gt;
&lt;p&gt;See the complete example program: &lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/cgroup-skb"&gt;cgroup-skb&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="kprobe-fentry-tracepoint"&gt;
&lt;h3 id="hidkprobe-fentry-tracepoint"&gt;kprobe/fentry/tracepoint&lt;a class="headerlink" href="#hidkprobe-fentry-tracepoint" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;elibpcap hides the data reading differences between kprobe/fentry/tracepoint programs and
the tc/tcx/xdp programs mentioned earlier. This allows us to integrate them in a mostly consistent way.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;c program:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;kprobe/__dev_queue_xmit&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BPF_KPROBE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sample_prog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;sk_buff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;skb_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BPF_CORE_READ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;skb_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BPF_CORE_READ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;network_header&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;skb_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BPF_CORE_READ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;go program:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;injectFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ebpf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CollectionSpec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;AtBpf2Bpf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;PacketAccessMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BpfProbeReadKernel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;L2Skb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here are two things to note:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Because kprobe programs cannot read packet data from &lt;cite&gt;skb&lt;/cite&gt; using &amp;quot;direct packet access&amp;quot;,
So we set &lt;tt class="docutils literal"&gt;PacketAccessMode: elibpcap.BpfProbeReadKernel&lt;/tt&gt; to read data using &lt;tt class="docutils literal"&gt;bpf_probe_read_kernel&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Because our kprobe program checks L3 data,
we need to set &lt;tt class="docutils literal"&gt;L2Skb: false&lt;/tt&gt; here.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;See the complete example program:
&lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/kprobe"&gt;kprobe&lt;/a&gt; ,
&lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/fentry"&gt;fentry&lt;/a&gt; ,
&lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/tracepoint"&gt;tracepoint&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="socket-filter"&gt;
&lt;h3 id="hidsocket-filter"&gt;socket filter&lt;a class="headerlink" href="#hidsocket-filter" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A limitation of socket filter programs is they cannot read packets using direct access or bpf_probe_read_kernel.
They can only read packets using methods similar to bpf_skb_load_bytes.&lt;/p&gt;
&lt;p&gt;Below is example code for integrating elibpcap with socket filter programs:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;c program:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;socket&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sample_prog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;__sk_buff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bpf_skb_load_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pcap_filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;go program:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;injectFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ebpf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CollectionSpec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oldInsts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;AtBpf2Bpf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pcap_filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;PacketAccessMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elibpcap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BpfSkbLoadBytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;L2Skb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Programs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sample_prog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Instructions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newInsts&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here are three points to note:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;We need to use &lt;tt class="docutils literal"&gt;bpf_skb_load_bytes&lt;/tt&gt; to read data, so &lt;tt class="docutils literal"&gt;PacketAccessMode&lt;/tt&gt; is set to &lt;tt class="docutils literal"&gt;elibpcap.BpfSkbLoadBytes&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;In socket filter programs, we read data directly from skb, not from skb-&amp;gt;data. So, data is set to skb.&lt;/li&gt;
&lt;li&gt;In socket filter programs, we cannot directly get skb-&amp;gt;data_end.
Also, data_end in pcap_filter is just a placeholder variable for allocating a stack variable
when using the &lt;tt class="docutils literal"&gt;BpfSkbLoadBytes&lt;/tt&gt; access mode.
So, we can directly use a dummy variable as data_end.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;See the complete example program:
&lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples/tree/master/socket-filter"&gt;socket-filter&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2 id="hidconclusion"&gt;Conclusion&lt;a class="headerlink" href="#hidconclusion" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you want to add pcap-filter support to your Go and eBPF network project but don't know where to start,
try integrating the clever and powerful elibpcap project.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="references"&gt;
&lt;h2 id="hidreferences"&gt;References&lt;a class="headerlink" href="#hidreferences" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/jschwinger233/elibpcap"&gt;jschwinger233/elibpcap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/mozillazg/ptcpdump"&gt;mozillazg/ptcpdump: Process-aware, eBPF-based tcpdump&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/mozillazg/elibpcap-examples"&gt;mozillazg/elibpcap-examples: usage of github.com/jschwinger233/elibpcap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/jschwinger233/ktcpdump"&gt;jschwinger233/ktcpdump&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</summary><category term="elibpcap"></category><category term="cilium/ebpf"></category><category term="pcap-filter"></category><category term="en-version"></category></entry><entry><title>ptcpdump v0.27 ~ v0.32 的主要变更内容</title><link href="https://mozillazg.com/2025/01/whats-new-ptcpdump-v0.27-v0.32.html" rel="alternate"></link><published>2025-01-25T00:00:00+00:00</published><updated>2025-01-25T00:00:00+00:00</updated><author><name>mozillazg</name></author><id>tag:mozillazg.com,2025-01-25:2025/01/whats-new-ptcpdump-v0.27-v0.32.html</id><summary type="html">&lt;div class="section" id="section-1"&gt;
&lt;h2 id="hidsection-1"&gt;前言&lt;a class="headerlink" href="#hidsection-1" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;本文将按变更顺序介绍一下 &lt;a class="reference external" href="https://github.com/mozillazg/ptcpdump"&gt;ptcpdump&lt;/a&gt;
从上次的 &lt;a class="reference external" href="https://mozillazg.com/2024/11/whats-new-ptcpdump-v1.16-v1.26.html"&gt;v0.26&lt;/a&gt;
之后的 v0.27 版本到最新的 v0.32 版本期间所发布的主要变更内容。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="section-2"&gt;
&lt;h2 id="hidsection-2"&gt;主要变更内容&lt;a class="headerlink" href="#hidsection-2" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="q-quiet"&gt;
&lt;h3 id="hidq-quiet"&gt;新增 -q/--quiet 参数&lt;a class="headerlink" href="#hidq-quiet" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;新增 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-q/--quiet&lt;/span&gt;&lt;/tt&gt; 参数用于精简输出内容:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
13:50:35.524360 lo curl.345650 Out IP 127.0.0.1.58694 &amp;gt; 127.0.0.1.8000: tcp 0, ParentProc [bash.345626]
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="context"&gt;
&lt;h3 id="hidcontext"&gt;新增 --context 参数&lt;a class="headerlink" href="#hidcontext" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;新增 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--context&lt;/span&gt;&lt;/tt&gt; 参数用于指定输出中包含的上下文信息，可以通过这个参数控制只显示特定的上下文信息。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;通过 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--context=process&lt;/span&gt;&lt;/tt&gt; 限制只输出进程信息:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
# --context=process
09:32:09.718892 vethee2a302f wget.3553008 In IP 10.244.0.2.33426 &amp;gt; 139.178.84.217.80: Flags [S], seq 4113492822, win 64240, length 0

# -v --context=process
13:44:41.529003 eth0 In IP (tos 0x4, ttl 45, id 45428, offset 0, flags [DF], proto TCP (6), length 52)
    139.178.84.217.443 &amp;gt; 172.19.0.2.42606: Flags [.], cksum 0x5284, seq 3173118145, ack 1385712707, win 118, options [nop,nop,TS val 134560683 ecr 1627716996], length 0
    Process (pid 553587, cmd /usr/bin/wget, args wget kernel.org)
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;该参数既支持通过英文逗号分割多个值，也支持多次指定参数的方式指定多个值:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
# -v --context=process,parentproc
# -v --context=process --context=parentproc

13:44:41.529003 eth0 In IP (tos 0x4, ttl 45, id 45428, offset 0, flags [DF], proto TCP (6), length 52)
    139.178.84.217.443 &amp;gt; 172.19.0.2.42606: Flags [.], cksum 0x5284, seq 3173118145, ack 1385712707, win 118, options [nop,nop,TS val 134560683 ecr 1627716996], length 0
    Process (pid 553587, cmd /usr/bin/wget, args wget kernel.org)
    ParentProc (pid 553296, cmd /bin/sh, args sh)

# -v --context=process,parentproc,container
# -v --context=process --context=parentproc --context=container

13:44:41.529003 eth0 In IP (tos 0x4, ttl 45, id 45428, offset 0, flags [DF], proto TCP (6), length 52)
    139.178.84.217.443 &amp;gt; 172.19.0.2.42606: Flags [.], cksum 0x5284, seq 3173118145, ack 1385712707, win 118, options [nop,nop,TS val 134560683 ecr 1627716996], length 0
    Process (pid 553587, cmd /usr/bin/wget, args wget kernel.org)
    ParentProc (pid 553296, cmd /bin/sh, args sh)
    Container (name test, id d9028334568bf75a5a084963a8f98f78c56bba7f45f823b3780a135b71b91e95, image docker.io/library/alpine:3.18, labels {&amp;quot;io.cri-containerd.kind&amp;quot;:&amp;quot;container&amp;quot;,&amp;quot;io.kubernetes.container.name&amp;quot;:&amp;quot;test&amp;quot;,&amp;quot;io.kubernetes.pod.name&amp;quot;:&amp;quot;test&amp;quot;,&amp;quot;io.kubernetes.pod.namespace&amp;quot;:&amp;quot;default&amp;quot;,&amp;quot;io.kubernetes.pod.uid&amp;quot;:&amp;quot;9e4bc54b-de48-4b1c-8b9e-54709f67ed0c&amp;quot;})
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="fentry-btf-raw-tracepoint-tcx-ebpf"&gt;
&lt;h3 id="hidfentry-btf-raw-tracepoint-tcx-ebpf"&gt;在高版本内核中使用 fentry, btf raw tracepoint 以及 tcx ebpf 特性&lt;a class="headerlink" href="#hidfentry-btf-raw-tracepoint-tcx-ebpf" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;当在高版本内核中执行 ptcpdump 程序时，程序将自动使用 fentry 代替 kprobe，
使用 btf raw tracepoint 代替 raw tracepoint, 使用 tcx 代替 tc，
通过使用这些新的 ebpf 特性，优化程序在高版本内核下的性能。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="backend"&gt;
&lt;h3 id="hidbackend"&gt;新增 --backend 参数&lt;a class="headerlink" href="#hidbackend" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;新增 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--backend&lt;/span&gt;&lt;/tt&gt; 参数用于指定抓包时使用的技术，默认是使用的 tc/tcx 技术。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="backend-cgroup-skb"&gt;
&lt;h3 id="hidbackend-cgroup-skb"&gt;支持 --backend=cgroup-skb&lt;a class="headerlink" href="#hidbackend-cgroup-skb" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;支持通过 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--backend=cgroup-skb&lt;/span&gt;&lt;/tt&gt; 参数指定使用 cgroup-skb ebpf 程序进行抓包。
使用该方式抓取的流量将不包含链路层信息，ptcpdump 输出中的链路层信息将是一个固定的 fake 数据。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="openwrt-24-10-x86-64"&gt;
&lt;h3 id="hidopenwrt-24-10-x86-64"&gt;支持 OpenWrt 24.10 x86-64 系统&lt;a class="headerlink" href="#hidopenwrt-24-10-x86-64" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;根据用户的需求反馈，提升程序兼容性，支持在 OpenWrt 24.10 x86-64 系统中使用 ptcpdump （前提是系统内核在编译时启用 ebpf 和 BTF 相关参数）。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="section-3"&gt;
&lt;h3 id="hidsection-3"&gt;支持在输出中显示线程信息&lt;a class="headerlink" href="#hidsection-3" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;当通过 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--backend=cgroup-skb&lt;/span&gt;&lt;/tt&gt; 进行抓包时，新增在输出中显示线程信息:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo ptcpdump -i any --backend cgroup-skb -v port 80

10:18:26.846884 ens33 Out IP (tos 0x0, ttl 64, id 57734, offset 0, flags [DF], proto TCP (6), length 478)
    xxx.xxx.xxx.35102 &amp;gt; xxx.xxx.xxx.80: Flags [P.], cksum 0x3381, seq xx:xx, ack xx, win 64240, length 438
    Process (pid 113278, cmd /snap/firefox/5437/usr/lib/firefox/firefox, args /snap/firefox/5437/usr/lib/firefox/firefox)
    Thread (tid 113438, name Socket Thread)
    ParentProc (pid 49607, cmd /usr/bin/xfce4-panel, args xfce4-panel --display :0.0 --sm-client-id xxxx)
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="uid-uid"&gt;
&lt;h3 id="hiduid-uid"&gt;支持在输出中显示 uid 以及按 uid 抓包&lt;a class="headerlink" href="#hiduid-uid" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;新增在输出中显示 uid 信息:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
12:37:40.051539 ens33 Out IP (tos 0x0, ttl 64, id 48697, offset 0, flags [DF], proto TCP (6), length 60)
    10.0.x.x.42906 &amp;gt; 139.x.x.x.443: Flags [S], cksum 0xecc8, seq 940329637, win 64240, options [mss 1460,sackOK,TS val 3421262256 ecr 0,nop,wscale 7], length 0
    Process (pid 99722, cmd /usr/bin/curl, args curl https://kernel.org)
    User (uid 1000)
    ParentProc (pid 18840, cmd /usr/bin/bash, args -bash)
&lt;/pre&gt;
&lt;p&gt;新增支持指定 uid 进行抓包:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo ptcpdump -i any --uid 100 -v port 80
&lt;/pre&gt;
&lt;p&gt;如果你对 ptcpdump 有额外的改进或新功能建议，欢迎在评论区或项目 issues 中留言。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</summary><category term="ptcpdump"></category></entry><entry><title>ptcpdump v0.27 ~ v0.32 的主要变更内容</title><link href="https://mozillazg.com/2025/01/whats-new-ptcpdump-v0.27-v0.32-en.html" rel="alternate"></link><published>2025-01-25T00:00:00+00:00</published><updated>2025-01-25T00:00:00+00:00</updated><author><name>mozillazg</name></author><id>tag:mozillazg.com,2025-01-25:2025/01/whats-new-ptcpdump-v0.27-v0.32-en.html</id><summary type="html">&lt;div class="section" id="introduction"&gt;
&lt;h2 id="hidintroduction"&gt;Introduction&lt;a class="headerlink" href="#hidintroduction" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This article introduces the main changes in &lt;a class="reference external" href="https://github.com/mozillazg/ptcpdump"&gt;ptcpdump&lt;/a&gt;
from v0.27 (after &lt;a class="reference external" href="https://mozillazg.com/2024/11/whats-new-ptcpdump-v1.16-v1.26-en.html"&gt;v0.26&lt;/a&gt;)
to the latest v0.32, in chronological order.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="main-changes"&gt;
&lt;h2 id="hidmain-changes"&gt;Main Changes&lt;a class="headerlink" href="#hidmain-changes" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="add-q-quiet-option"&gt;
&lt;h3 id="hidadd-q-quiet-option"&gt;Add -q/--quiet option&lt;a class="headerlink" href="#hidadd-q-quiet-option" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Added the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-q/--quiet&lt;/span&gt;&lt;/tt&gt; option to simplify the output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
13:50:35.524360 lo curl.345650 Out IP 127.0.0.1.58694 &amp;gt; 127.0.0.1.8000: tcp 0, ParentProc [bash.345626]
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="add-context-option"&gt;
&lt;h3 id="hidadd-context-option"&gt;Add --context option&lt;a class="headerlink" href="#hidadd-context-option" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Added the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--context&lt;/span&gt;&lt;/tt&gt; option to specify the context information included in the output. This option controls showing only specific context information.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--context=process&lt;/span&gt;&lt;/tt&gt; to restrict output to process information only:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
# --context=process
09:32:09.718892 vethee2a302f wget.3553008 In IP 10.244.0.2.33426 &amp;gt; 139.178.84.217.80: Flags [S], seq 4113492822, win 64240, length 0

# -v --context=process
13:44:41.529003 eth0 In IP (tos 0x4, ttl 45, id 45428, offset 0, flags [DF], proto TCP (6), length 52)
    139.178.84.217.443 &amp;gt; 172.19.0.2.42606: Flags [.], cksum 0x5284, seq 3173118145, ack 1385712707, win 118, options [nop,nop,TS val 134560683 ecr 1627716996], length 0
    Process (pid 553587, cmd /usr/bin/wget, args wget kernel.org)
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;This option supports specifying multiple values either by separating them with commas or by specifying the option multiple times:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
# -v --context=process,parentproc
# -v --context=process --context=parentproc

13:44:41.529003 eth0 In IP (tos 0x4, ttl 45, id 45428, offset 0, flags [DF], proto TCP (6), length 52)
    139.178.84.217.443 &amp;gt; 172.19.0.2.42606: Flags [.], cksum 0x5284, seq 3173118145, ack 1385712707, win 118, options [nop,nop,TS val 134560683 ecr 1627716996], length 0
    Process (pid 553587, cmd /usr/bin/wget, args wget kernel.org)
    ParentProc (pid 553296, cmd /bin/sh, args sh)

# -v --context=process,parentproc,container
# -v --context=process --context=parentproc --context=container

13:44:41.529003 eth0 In IP (tos 0x4, ttl 45, id 45428, offset 0, flags [DF], proto TCP (6), length 52)
    139.178.84.217.443 &amp;gt; 172.19.0.2.42606: Flags [.], cksum 0x5284, seq 3173118145, ack 1385712707, win 118, options [nop,nop,TS val 134560683 ecr 1627716996], length 0
    Process (pid 553587, cmd /usr/bin/wget, args wget kernel.org)
    ParentProc (pid 553296, cmd /bin/sh, args sh)
    Container (name test, id d9028334568bf75a5a084963a8f98f78c56bba7f45f823b3780a135b71b91e95, image docker.io/library/alpine:3.18, labels {&amp;quot;io.cri-containerd.kind&amp;quot;:&amp;quot;container&amp;quot;,&amp;quot;io.kubernetes.container.name&amp;quot;:&amp;quot;test&amp;quot;,&amp;quot;io.kubernetes.pod.name&amp;quot;:&amp;quot;test&amp;quot;,&amp;quot;io.kubernetes.pod.namespace&amp;quot;:&amp;quot;default&amp;quot;,&amp;quot;io.kubernetes.pod.uid&amp;quot;:&amp;quot;9e4bc54b-de48-4b1c-8b9e-54709f67ed0c&amp;quot;})
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="use-fentry-btf-raw-tracepoint-and-tcx-ebpf-features-on-newer-kernels"&gt;
&lt;h3 id="hiduse-fentry-btf-raw-tracepoint-and-tcx-ebpf-features-on-newer-kernels"&gt;Use fentry, btf raw tracepoint, and tcx ebpf features on newer kernels&lt;a class="headerlink" href="#hiduse-fentry-btf-raw-tracepoint-and-tcx-ebpf-features-on-newer-kernels" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When running ptcpdump on newer kernels, the program will automatically use fentry instead of kprobe,
btf raw tracepoint instead of raw tracepoint, and tcx instead of tc.
Using these new ebpf features optimizes performance on newer kernels.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="add-backend-option"&gt;
&lt;h3 id="hidadd-backend-option"&gt;Add --backend option&lt;a class="headerlink" href="#hidadd-backend-option" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Added the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--backend&lt;/span&gt;&lt;/tt&gt; option to specify the technology used for packet capturing. The default is tc/tcx.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="support-backend-cgroup-skb"&gt;
&lt;h3 id="hidsupport-backend-cgroup-skb"&gt;Support --backend=cgroup-skb&lt;a class="headerlink" href="#hidsupport-backend-cgroup-skb" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It now supports using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--backend=cgroup-skb&lt;/span&gt;&lt;/tt&gt; to capture packets using cgroup-skb ebpf programs.
Traffic captured this way will not contain link-layer information; the link-layer information in ptcpdump output will be fixed fake data.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="support-openwrt-24-10-x86-64-system"&gt;
&lt;h3 id="hidsupport-openwrt-24-10-x86-64-system"&gt;Support OpenWrt 24.10 x86-64 system&lt;a class="headerlink" href="#hidsupport-openwrt-24-10-x86-64-system" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Based on user feedback, program compatibility has been improved to support using ptcpdump on OpenWrt 24.10 x86-64 systems (provided the system kernel was compiled with ebpf and BTF parameters enabled).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="support-displaying-thread-information-in-output"&gt;
&lt;h3 id="hidsupport-displaying-thread-information-in-output"&gt;Support displaying thread information in output&lt;a class="headerlink" href="#hidsupport-displaying-thread-information-in-output" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When capturing packets using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--backend=cgroup-skb&lt;/span&gt;&lt;/tt&gt;, thread information is now displayed in the output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo ptcpdump -i any --backend cgroup-skb -v port 80

10:18:26.846884 ens33 Out IP (tos 0x0, ttl 64, id 57734, offset 0, flags [DF], proto TCP (6), length 478)
    xxx.xxx.xxx.35102 &amp;gt; xxx.xxx.xxx.80: Flags [P.], cksum 0x3381, seq xx:xx, ack xx, win 64240, length 438
    Process (pid 113278, cmd /snap/firefox/5437/usr/lib/firefox/firefox, args /snap/firefox/5437/usr/lib/firefox/firefox)
    Thread (tid 113438, name Socket Thread)
    ParentProc (pid 49607, cmd /usr/bin/xfce4-panel, args xfce4-panel --display :0.0 --sm-client-id xxxx)
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="support-displaying-uid-in-output-and-capturing-by-uid"&gt;
&lt;h3 id="hidsupport-displaying-uid-in-output-and-capturing-by-uid"&gt;Support displaying UID in output and capturing by UID&lt;a class="headerlink" href="#hidsupport-displaying-uid-in-output-and-capturing-by-uid" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It now supports displaying UID information in the output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
12:37:40.051539 ens33 Out IP (tos 0x0, ttl 64, id 48697, offset 0, flags [DF], proto TCP (6), length 60)
    10.0.x.x.42906 &amp;gt; 139.x.x.x.443: Flags [S], cksum 0xecc8, seq 940329637, win 64240, options [mss 1460,sackOK,TS val 3421262256 ecr 0,nop,wscale 7], length 0
    Process (pid 99722, cmd /usr/bin/curl, args curl https://kernel.org)
    User (uid 1000)
    ParentProc (pid 18840, cmd /usr/bin/bash, args -bash)
&lt;/pre&gt;
&lt;p&gt;It now supports specifying a UID for packet capturing:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo ptcpdump -i any --uid 100 -v port 80
&lt;/pre&gt;
&lt;p&gt;If you have additional improvements or new feature suggestions for ptcpdump,
feel free to leave a message in the comments or project issues.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</summary><category term="ptcpdump"></category></entry><entry><title>Workload Identity Federation for GKE 特性探索</title><link href="https://mozillazg.com/2025/01/security-deep-dive-into-gcp-workload-identity-federation-for-gke-feature.html" rel="alternate"></link><published>2025-01-05T00:00:00+00:00</published><updated>2025-01-05T00:00:00+00:00</updated><author><name>mozillazg</name></author><id>tag:mozillazg.com,2025-01-05:2025/01/security-deep-dive-into-gcp-workload-identity-federation-for-gke-feature.html</id><summary type="html">&lt;p&gt;本文将简单探索一下前段时间 GKE 官宣的名为 &lt;a class="reference external" href="https://cloud.google.com/blog/products/identity-security/make-iam-for-gke-easier-to-use-with-workload-identity-federation"&gt;Workload Identity Federation for GKE&lt;/a&gt; 的特性。&lt;/p&gt;
&lt;div class="section" id="section-1"&gt;
&lt;h2 id="hidsection-1"&gt;功能介绍&lt;a class="headerlink" href="#hidsection-1" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Workload Identity Federation for GKE 是原有的 GKE Workload Identity 特性的改进版本,
核心的改进是减少了需要配置的信息，提升了用户体验。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="section-2"&gt;
&lt;h2 id="hidsection-2"&gt;使用方法&lt;a class="headerlink" href="#hidsection-2" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;可以通过下面几个步骤体验该特性：&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;创建一个启用 Workload Identity Federation for GKE 特性的 GKE 集群。具体启用位置是：创建集群 - 安全 - 启用 Workload Identity。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;为测试应用使用的 service account 关联 iam 角色，一个 service account 可以关联多个角色。比如:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ kubectl create ns demo-ns
$ kubectl -n demo-ns create serviceaccount demo-sa

$ gcloud projects add-iam-policy-binding projects/test-gke-XXX \
    --role=roles/container.clusterViewer \
    --member=principal://iam.googleapis.com/projects/23182XXXXXXX/locations/global/workloadIdentityPools/test-gke-XXXXXX.svc.id.goog/subject/ns/&amp;lt;namespace-name&amp;gt;/sa/&amp;lt;service-account-name&amp;gt; \
    --condition=None

$ gcloud storage buckets add-iam-policy-binding gs://&amp;lt;bucket-name&amp;gt; \
--role=roles/storage.objectViewer \
--member=principal://iam.googleapis.com/projects/23182XXXXXXX/locations/global/workloadIdentityPools/test-gke-XXXXXX.svc.id.goog/subject/ns/&amp;lt;namespace-name&amp;gt;/sa/&amp;lt;service-account-name&amp;gt; \
--condition=None
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;部署测试应用，测试应用的 pod 需要使用第 2 步对应的 namespace 和 service account 以及增加 nodeSelector 确保调度到启用了 Workload Identity Federation for GKE 特性的节点上:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  namespace: demo-ns
spec:
  nodeSelector:
    iam.gke.io/gke-metadata-server-enabled: &amp;quot;true&amp;quot;
  serviceAccountName: demo-sa
  containers:
  - name: test-pod
    image: google/cloud-sdk:slim
    command: [&amp;quot;sleep&amp;quot;,&amp;quot;infinity&amp;quot;]
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;待 pod running 后, 进入 test-pod 容器内，访问实例元数据服务获取 sts token，实际的业务应用使用的官方 SDK 也将使用类似的方式访问实例元数据服务获取用于请求云产品 API 的 sts token。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;gcloud&lt;span class="w"&gt; &lt;/span&gt;auth&lt;span class="w"&gt; &lt;/span&gt;print-access-token
&lt;span class="w"&gt; &lt;/span&gt;ya29.d.XXX
$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Metadata-Flavor: Google&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;access_token&amp;quot;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;quot;ya29.d.XXX&amp;quot;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;quot;expires_in&amp;quot;&lt;/span&gt;:3423,&lt;span class="s2"&gt;&amp;quot;token_type&amp;quot;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;quot;Bearer&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol class="arabic simple" start="5"&gt;
&lt;li&gt;获取的 sts token 将具有前面第 2 步所关联的所有角色的权限.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;gcloud&lt;span class="w"&gt; &lt;/span&gt;container&lt;span class="w"&gt; &lt;/span&gt;node-pools&lt;span class="w"&gt; &lt;/span&gt;list&lt;span class="w"&gt; &lt;/span&gt;--zone&lt;span class="w"&gt; &lt;/span&gt;us-central1&lt;span class="w"&gt; &lt;/span&gt;--cluster&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;NAME&lt;span class="w"&gt;          &lt;/span&gt;MACHINE_TYPE&lt;span class="w"&gt;  &lt;/span&gt;DISK_SIZE_GB&lt;span class="w"&gt;  &lt;/span&gt;NODE_VERSION
&lt;span class="w"&gt; &lt;/span&gt;default-pool&lt;span class="w"&gt;  &lt;/span&gt;e2-medium&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.30.6-gke.1125000

$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;GET&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Authorization: Bearer &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;gcloud&lt;span class="w"&gt; &lt;/span&gt;auth&lt;span class="w"&gt; &lt;/span&gt;print-access-token&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://storage.googleapis.com/storage/v1/b/demo-gke-workload-identity-federation/o&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;kind&amp;quot;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;storage#objects&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="section-3"&gt;
&lt;h2 id="hidsection-3"&gt;工作流程&lt;a class="headerlink" href="#hidsection-3" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Workload Identity Federation for GKE 特性的工作流程如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="/static/images/security/gke-workload-identity-federation-for-gke.png" /&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;当应用 Pod 容器内的程序请求实例元数据服务（访问 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;http://metadata.google.internal&lt;/span&gt;&lt;/tt&gt; ，实际是访问 &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;http://169.254.169.254:80&lt;/span&gt;&lt;/tt&gt; ）
获取 sts token 时, 该请求将被重定向到 169.254.169.252:988。
169.254.169.252:988 是节点上部署的 gke-metadata-server 服务所监听的端口。&lt;/li&gt;
&lt;li&gt;gke-metadata-server 服务在收到请求后，将根据请求的 client ip 确定请求来自哪个 Pod，
然后再请求 apiserver 生成一个该 Pod 所使用的 service account 对应的 token。&lt;/li&gt;
&lt;li&gt;gke-metadata-server 将使用获取的 service account token 访问 GCP 的
&lt;a class="reference external" href="https://cloud.google.com/iam/docs/reference/sts/rest/v1/TopLevel/token"&gt;STS API&lt;/a&gt; 获取一个 sts token，
最后 gke-metadata-server 将获取到的 sts token 返回给客户端。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这个流程中有几个关键的组件和信息需要重点关注，下面将逐个说明。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="gke-metadata-server"&gt;
&lt;h2 id="hidgke-metadata-server"&gt;gke-metadata-server&lt;a class="headerlink" href="#hidgke-metadata-server" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;当在集群维度或节点池维度启用 Workload Identity Federation for GKE 特性时，集群内将自动部署一个名为 gke-metadata-server 的组件。
该组件的工作负载 YAML 如下:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
apiVersion: apps/v1
kind: DaemonSet
metadata:
  annotations:
    deprecated.daemonset.template.generation: &amp;quot;1&amp;quot;
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
    k8s-app: gke-metadata-server
  name: gke-metadata-server
  namespace: kube-system
spec:
  minReadySeconds: 90
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: gke-metadata-server
  template:
    metadata:
      annotations:
        components.gke.io/component-name: gke-metadata-server
        components.gke.io/component-version: 0.4.301
        monitoring.gke.io/path: /metricz
      creationTimestamp: null
      labels:
        addonmanager.kubernetes.io/mode: Reconcile
        k8s-app: gke-metadata-server
    spec:
      containers:
      - command:
        - /gke-metadata-server
        - --logtostderr
        - --token-exchange-endpoint=https://securetoken.googleapis.com/v1/identitybindingtoken
        - --workload-pool=test-gke-XXXXXX.svc.id.goog
        - --alts-service-suffixes-using-node-identity=storage.googleapis.com,bigtable.googleapis.com,bigtable2.googleapis.com,bigtablerls.googleapis.com,spanner.googleapis.com,spanner2.googleapis.com,spanner-rls.googleapis.com,grpclb.directpath.google.internal,grpclb-dualstack.directpath.google.internal,staging-wrenchworks.sandbox.googleapis.com,preprod-spanner.sandbox.googleapis.com,wrenchworks-loadtest.googleapis.com,wrenchworks-nonprod.googleapis.com
        - --identity-provider=https://container.googleapis.com/v1/projects/test-gke-XXXXXX/locations/us-central1/clusters/test
        - --passthrough-ksa-list=anthos-identity-service:gke-oidc-envoy-sa,anthos-identity-service:gke-oidc-service-sa,gke-managed-dpv2-observability:hubble-relay,kube-system:antrea-controller,kube-system:container-watcher-pod-reader,kube-system:coredns,kube-system:egress-nat-controller,kube-system:event-exporter-sa,kube-system:fluentd-gcp-scaler,kube-system:gke-metrics-agent,kube-system:gke-spiffe-node-agent,kube-system:heapster,kube-system:konnectivity-agent,kube-system:kube-dns,kube-system:maintenance-handler,kube-system:metadata-agent,kube-system:network-metering-agent,kube-system:node-local-dns,kube-system:pkgextract-service,kube-system:pkgextract-cleanup-service,kube-system:securityprofile-controller,istio-system:istio-ingressgateway-service-account,istio-system:cluster-local-gateway-service-account,csm:csm-sync-agent,knative-serving:controller,kube-system:pdcsi-node-sa,kube-system:gcsfusecsi-node-sa,gmp-system:collector,gke-gmp-system:collector,gke-managed-cim:kube-state-metrics
        - --attributes=cluster-name=test,cluster-uid=392f63049deXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,cluster-location=us-central1
        - --cluster-uid=392f63049ded410XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        - --sts-endpoint=https://sts.googleapis.com
        - --token-exchange-mode=sts
        - --cloud-monitoring-endpoint=monitoring.googleapis.com:443
        - --iam-cred-service-endpoint=https://iamcredentials.googleapis.com
        - --cluster-project-number=2318XXXXXXXX
        - --cluster-location=us-central1
        - --cluster-name=test
        - --component-version=0.4.301
        - --ksa-cache-mode=watchchecker
        - --kcp-allow-watch-checker=true
        - --enable-mds-csi-driver=true
        - --csi-socket=/csi/csi.sock
        - --volumes-db=/var/run/gkemds.gke.io/csi/volumes.boltdb
        env:
        - name: GOMEMLIMIT
          value: &amp;quot;94371840&amp;quot;
        image: us-central1-artifactregistry.gcr.io/gke-release/gke-release/gke-metadata-server:gke_metadata_server_20240702.00_p0&amp;#64;sha256:aea9cc887c91b9a05e5bb4bb604180772594a01f0828bbfacf30c77562ac7205
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            host: 127.0.0.1
            path: /healthz
            port: 989
            scheme: HTTP
          initialDelaySeconds: 30
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 3
        name: gke-metadata-server
        ports:
        - containerPort: 987
          name: alts
          protocol: TCP
        - containerPort: 988
          name: metadata-server
          protocol: TCP
        - containerPort: 989
          name: debug-port
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            host: 127.0.0.1
            path: /healthz
            port: 989
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        resources:
          limits:
            memory: 100Mi
          requests:
            cpu: 100m
            memory: 100Mi
        securityContext:
          privileged: true
          readOnlyRootFilesystem: true
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /var/lib/kubelet/kubeconfig
          name: kubelet-credentials
          readOnly: true
        - mountPath: /var/lib/kubelet/pki/
          name: kubelet-certs
          readOnly: true
        - mountPath: /var/run/
          name: container-runtime-interface
        - mountPath: /etc/srv/kubernetes/pki
          name: kubelet-pki
          readOnly: true
        - mountPath: /etc/ssl/certs/
          name: ca-certificates
          readOnly: true
        - mountPath: /home/kubernetes/bin/gke-exec-auth-plugin
          name: gke-exec-auth-plugin
          readOnly: true
        - mountPath: /sys/firmware/efi/efivars/
          name: efivars
          readOnly: true
        - mountPath: /dev/tpm0
          name: vtpm
          readOnly: true
        - mountPath: /csi
          name: csi-socket-dir
        - mountPath: /var/run/gkemds.gke.io/csi
          name: state-dir
        - mountPath: /var/lib/kubelet/pods
          mountPropagation: Bidirectional
          name: pods-dir
        - mountPath: /registration
          name: kubelet-registration-dir
      dnsPolicy: Default
      hostNetwork: true
      nodeSelector:
        iam.gke.io/gke-metadata-server-enabled: &amp;quot;true&amp;quot;
        kubernetes.io/os: linux
      priorityClassName: system-node-critical
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      serviceAccount: gke-metadata-server
      serviceAccountName: gke-metadata-server
      terminationGracePeriodSeconds: 30
      tolerations:
      - effect: NoExecute
        operator: Exists
      - effect: NoSchedule
        operator: Exists
      - key: components.gke.io/gke-managed-components
        operator: Exists
      volumes:
      - hostPath:
          path: /var/lib/kubelet/pki/
          type: Directory
        name: kubelet-certs
      - hostPath:
          path: /var/lib/kubelet/kubeconfig
          type: File
        name: kubelet-credentials
      - hostPath:
          path: /var/run/
          type: Directory
        name: container-runtime-interface
      - hostPath:
          path: /etc/srv/kubernetes/pki/
          type: Directory
        name: kubelet-pki
      - hostPath:
          path: /etc/ssl/certs/
          type: Directory
        name: ca-certificates
      - hostPath:
          path: /home/kubernetes/bin/gke-exec-auth-plugin
          type: File
        name: gke-exec-auth-plugin
      - hostPath:
          path: /sys/firmware/efi/efivars/
          type: Directory
        name: efivars
      - hostPath:
          path: /dev/tpm0
          type: CharDevice
        name: vtpm
      - hostPath:
          path: /var/lib/kubelet/plugins/gkemds.gke.io
          type: DirectoryOrCreate
        name: csi-socket-dir
      - hostPath:
          path: /var/lib/kubelet/pods
          type: Directory
        name: pods-dir
      - hostPath:
          path: /var/lib/kubelet/plugins_registry
          type: Directory
        name: kubelet-registration-dir
      - hostPath:
          path: /var/lib/kubelet/plugins
          type: Directory
        name: kubelet-plugins-dir
      - hostPath:
          path: /var/run/gkemds.gke.io/csi
          type: DirectoryOrCreate
        name: state-dir
&lt;/pre&gt;
&lt;p&gt;gke-metadata-server 组件具有如下特点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;组件的工作负载是一个 DaemonSet。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;组件 Pod 使用 &lt;tt class="docutils literal"&gt;hostNetwork: true&lt;/tt&gt; 以及 &lt;tt class="docutils literal"&gt;privileged: true&lt;/tt&gt; 。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;组件内的服务将监听 987, 988 以及 989 端口, 其中 988 端口将用于接收重定向过来的访问实例元数据服务的请求:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ ss -atnlp |grep gke
LISTEN 0      1024               *:987              *:*    users:((&amp;quot;gke-metadata-se&amp;quot;,pid=183706,fd=10))
LISTEN 0      1024               *:989              *:*    users:((&amp;quot;gke-metadata-se&amp;quot;,pid=183706,fd=12))
LISTEN 0      1024               *:988              *:*    users:((&amp;quot;gke-metadata-se&amp;quot;,pid=183706,fd=15))
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;前面所说的 169.254.169.252 这个 IP 是本机 lo 的 IP 地址，所以 gke-metadata-server 监听的 988 端口
就包含了前面所说的 &lt;tt class="docutils literal"&gt;169.254.169.252:988&lt;/tt&gt; 端口:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet 169.254.169.252/32 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;所有启用了 Workload Identity Federation for GKE 特性的节点在初始化的时候都会配置如下 nftables 规则，
确保从业务容器内发起的请求元数据服务 (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;http://metadata.google.internal&lt;/span&gt;&lt;/tt&gt; , 169.254.169.254:80)
的流量都会被重定向到组件所监听的 &lt;tt class="docutils literal"&gt;169.254.169.252:988&lt;/tt&gt; 端口:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
table ip nat {
        chain PREROUTING {
                type nat hook prerouting priority dstnat; policy accept;
                 counter packets 2143 bytes 169432 jump KUBE-SERVICES
                iifname != &amp;quot;eth0&amp;quot; meta l4proto tcp ip daddr 169.254.169.254 tcp dport 8080  counter packets 0 bytes 0 dnat to 169.254.169.252:987
                iifname != &amp;quot;eth0&amp;quot; meta l4proto tcp ip daddr 169.254.169.254 tcp dport 80  counter packets 181 bytes 10860 dnat to 169.254.169.252:988
        }
}
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;前面说到组件将通过 client ip 确定请求的来源 pod 以及会请求 apiserver 获取 service account，这里就涉及到组件是使用的什么凭证来访问 apiserver。
组件使用的是节点上 kubelet 的凭证来访问的 apiserver（前面的组件 YAML 中包含了挂载 kubelet kubeconfig 的配置）。
同时在部署组件时，将额外为 kubelet 的凭证授予 pods 和 serviceaccounts 的 get/list/watch RBAC 权限，
用于获取当前节点的 pod 以及 service account 信息:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    components.gke.io/component-name: gke-metadata-server
    components.gke.io/component-version: 0.4.301
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
  name: gce:gke-metadata-server-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: gce:gke-metadata-server-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:nodes
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    components.gke.io/component-name: gke-metadata-server
    components.gke.io/component-version: 0.4.301
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
  name: gce:gke-metadata-server-reader
rules:
- apiGroups:
  - &amp;quot;&amp;quot;
  resources:
  - pods
  - serviceaccounts
  verbs:
  - get
  - watch
  - list
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;如果 pod 使用的 service account 没有绑定 IAM 角色，pod 内应用访问元数据服务获取的 sts token 将会是节点默认的 google serivce account 的 sts token。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="service-account-token"&gt;
&lt;h2 id="hidservice-account-token"&gt;service account token&lt;a class="headerlink" href="#hidservice-account-token" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;对于每个 pod 内程序发起的请求，gke-metadata-server 组件不是直接使用 pod 容器所挂载 service account token，
而是请求 apiserver 生成了一份新的 service account token。&lt;/p&gt;
&lt;p&gt;容器所挂载的 service account token 的 payload 示例如下:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
{
  &amp;quot;aud&amp;quot;: [
    &amp;quot;https://container.googleapis.com/v1/projects/test-gke-XXXXXX/locations/us-central1/clusters/test&amp;quot;
  ],
  &amp;quot;exp&amp;quot;: ...,
  &amp;quot;iat&amp;quot;: ...,
  &amp;quot;iss&amp;quot;: &amp;quot;https://container.googleapis.com/v1/projects/test-gke-XXXXXX/locations/us-central1/clusters/test&amp;quot;,
  &amp;quot;jti&amp;quot;: &amp;quot;...&amp;quot;,
  &amp;quot;kubernetes.io&amp;quot;: {...},
  &amp;quot;nbf&amp;quot;: ...,
  &amp;quot;sub&amp;quot;: &amp;quot;system:serviceaccount:demo-ns:demo-sa&amp;quot;
}
&lt;/pre&gt;
&lt;p&gt;组件请求 apiserver 所生成的 service account token 的 payload 示例如下:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
{
  &amp;quot;aud&amp;quot;: [
    &amp;quot;test-gke-XXXXXX.svc.id.goog&amp;quot;
  ],
  &amp;quot;exp&amp;quot;: ...,
  &amp;quot;iat&amp;quot;: ...,
  &amp;quot;iss&amp;quot;: &amp;quot;https://container.googleapis.com/v1/projects/test-gke-XXXXXX/locations/us-central1/clusters/test&amp;quot;,
  &amp;quot;jti&amp;quot;: &amp;quot;...&amp;quot;,
  &amp;quot;kubernetes.io&amp;quot;: {...},
  &amp;quot;nbf&amp;quot;: ...,
  &amp;quot;sub&amp;quot;: &amp;quot;system:serviceaccount:demo-ns:demo-sa&amp;quot;
}
&lt;/pre&gt;
&lt;p&gt;可以看到，主要的区别是 aud 的内容不一样。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="sts-token"&gt;
&lt;h2 id="hidsts-token"&gt;sts token&lt;a class="headerlink" href="#hidsts-token" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;gke-metadata-server 组件将使用获取到的 service account token 访问 STS 的
&lt;a class="reference external" href="https://cloud.google.com/iam/docs/reference/sts/rest/v1/TopLevel/token"&gt;token API&lt;/a&gt; 获取一份 sts token。&lt;/p&gt;
&lt;p&gt;对应的请求示例如下:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
:authority: sts.googleapis.com
:method: POST
:path: /v1/token?alt=json&amp;amp;prettyPrint=false
:scheme: https
x-goog-api-client: gl-go/1.23.0--20240626-RC01 cl/646990413 +5a18e79687 X:fieldtrack,boringcrypto gdcl/0.177.0
user-agent: google-api-go-client/0.5 gke-metadata-server
content-type: application/json
content-length: 1673
accept-encoding: gzip

{&amp;quot;audience&amp;quot;:&amp;quot;identitynamespace:test-gke-XXXXXX.svc.id.goog:https://container.googleapis.com/v1/projects/test-gke-XXXXXX/locations/us-central1/clusters/test&amp;quot;,&amp;quot;grantType&amp;quot;:&amp;quot;urn:ietf:params:oauth:grant-type:token-exchange&amp;quot;,&amp;quot;requestedTokenType&amp;quot;:&amp;quot;urn:ietf:params:oauth:token-type:access_token&amp;quot;,&amp;quot;scope&amp;quot;:&amp;quot;https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/userinfo.email&amp;quot;,&amp;quot;subjectToken&amp;quot;:&amp;quot;XXX.XXX.XXX&amp;quot;,&amp;quot;subjectTokenType&amp;quot;:&amp;quot;urn:ietf:params:oauth:token-type:jwt&amp;quot;}

:status: 200
content-type: application/json; charset=UTF-8
vary: Origin
vary: X-Origin
vary: Referer
content-encoding: gzip
date: ...
server: scaffolding on HTTPServer2
content-length: 1061
x-xss-protection: 0
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff

{&amp;quot;access_token&amp;quot;:&amp;quot;ya29.d.XXX&amp;quot;,&amp;quot;issued_token_type&amp;quot;:&amp;quot;urn:ietf:params:oauth:token-type:access_token&amp;quot;,&amp;quot;token_type&amp;quot;:&amp;quot;Bearer&amp;quot;,&amp;quot;expires_in&amp;quot;:3599}
&lt;/pre&gt;
&lt;p&gt;其中请求 body 格式化后的内容如下:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
{
  &amp;quot;audience&amp;quot;: &amp;quot;identitynamespace:test-gke-XXXXXX.svc.id.goog:https://container.googleapis.com/v1/projects/test-gke-XXXXXX/locations/us-central1/clusters/test&amp;quot;,
  &amp;quot;grantType&amp;quot;: &amp;quot;urn:ietf:params:oauth:grant-type:token-exchange&amp;quot;,
  &amp;quot;requestedTokenType&amp;quot;: &amp;quot;urn:ietf:params:oauth:token-type:access_token&amp;quot;,
  &amp;quot;scope&amp;quot;: &amp;quot;https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/userinfo.email&amp;quot;,
  &amp;quot;subjectToken&amp;quot;: &amp;quot;XXX.XXX.XXX&amp;quot;,
  &amp;quot;subjectTokenType&amp;quot;: &amp;quot;urn:ietf:params:oauth:token-type:jwt&amp;quot;
}
&lt;/pre&gt;
&lt;p&gt;响应 body 格式化后的内容如下:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
{
  &amp;quot;access_token&amp;quot;: &amp;quot;ya29.d.XXX&amp;quot;,
  &amp;quot;issued_token_type&amp;quot;: &amp;quot;urn:ietf:params:oauth:token-type:access_token&amp;quot;,
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,
  &amp;quot;expires_in&amp;quot;: 3599
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="gke-workload-identity"&gt;
&lt;h2 id="hidgke-workload-identity"&gt;与 GKE Workload Identity 的区别&lt;a class="headerlink" href="#hidgke-workload-identity" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Workload Identity Federation for GKE 与 GKE Workload Identity 特性（又叫 link Kubernetes ServiceAccounts to IAM）的区别如下：&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;colgroup&gt;
&lt;col width="29%" /&gt;
&lt;col width="26%" /&gt;
&lt;col width="45%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;比较项&lt;/th&gt;
&lt;th class="head"&gt;GKE Workload Identity&lt;/th&gt;
&lt;th class="head"&gt;Workload Identity Federation for GKE&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;需要创建 Google service account (GSA)&lt;/td&gt;
&lt;td&gt;需要&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;不需要&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;需要配置 GSA 绑定的 IAM 角色&lt;/td&gt;
&lt;td&gt;需要&lt;/td&gt;
&lt;td&gt;需要配置 k8s service account (KSA) 绑定的角色&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;需要配置允许使用 KSA 扮演 GSA&lt;/td&gt;
&lt;td&gt;需要&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;不需要&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;需要在集群内配置 KSA 的 GSA 信息&lt;/td&gt;
&lt;td&gt;需要&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;不需要&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;绑定角色时支持指定多个 KSA/GSA&lt;/td&gt;
&lt;td&gt;不支持&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;支持&lt;/strong&gt; 指定多个，比如某个命名空间下的所有SA, 某个集群内的所有SA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;支持 project + namespace + KSA 维度授权&lt;/td&gt;
&lt;td&gt;支持&lt;/td&gt;
&lt;td&gt;支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;支持 cluster + namespace + KSA 维度授权&lt;/td&gt;
&lt;td&gt;不支持&lt;/td&gt;
&lt;td&gt;不支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;支持使用 hostNetwork 的应用&lt;/td&gt;
&lt;td&gt;不支持&lt;/td&gt;
&lt;td&gt;不支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;依赖部署 gke-metadata-server 组件&lt;/td&gt;
&lt;td&gt;依赖&lt;/td&gt;
&lt;td&gt;依赖&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;云产品API对获取的 sts token 的支持情况&lt;/td&gt;
&lt;td&gt;几乎所有云产品 API 都支持&lt;/td&gt;
&lt;td&gt;大部分云产品API都支持，部分云产品有限支持，少量云产品不支持&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;BTW, 虽然 Workload Identity Federation for GKE 方案的官方教程和文档中都是说的需要依赖 gke-metadata-server 这个组件，
但是从前面的内容中我们也可以看到：我们其实也可以在不安装 gke-metadata-server 组件的情况下，使用该方案。
具体来说就是，我们可以通过为应用 Pod 挂载所需的 service account token 然后在应用程序内直接访问
STS 提供的 Token API 的方式来解除对该组件的依赖。&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="section-4"&gt;
&lt;h2 id="hidsection-4"&gt;参考资料&lt;a class="headerlink" href="#hidsection-4" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://cloud.google.com/blog/products/identity-security/make-iam-for-gke-easier-to-use-with-workload-identity-federation"&gt;Make IAM for GKE easier to use with Workload Identity Federation | Google Cloud Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity"&gt;Authenticate to Google Cloud APIs from GKE workloads &amp;nbsp;|&amp;nbsp; Google Kubernetes Engine (GKE)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://cloud.google.com/kubernetes-engine/docs/concepts/workload-identity"&gt;About Workload Identity Federation for GKE &amp;nbsp;|&amp;nbsp; Google Kubernetes Engine (GKE) &amp;nbsp;|&amp;nbsp; Google Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://cloud.google.com/iam/docs/federated-identity-supported-services"&gt;Identity federation: products and limitations &amp;nbsp;|&amp;nbsp; IAM Documentation &amp;nbsp;|&amp;nbsp; Google Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://cloud.google.com/iam/docs/reference/sts/rest/v1/TopLevel/token"&gt;Method: token &amp;nbsp;|&amp;nbsp; IAM Documentation &amp;nbsp;|&amp;nbsp; Google Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://cloud.google.com/compute/docs/metadata/overview"&gt;About VM metadata &amp;nbsp;|&amp;nbsp; Compute Engine Documentation &amp;nbsp;|&amp;nbsp; Google Cloud&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</summary><category term="kubernetes"></category><category term="k8s"></category><category term="gcp"></category><category term="gke"></category><category term="Workload Identity Federation for GKE"></category><category term="cloud-security"></category></entry><entry><title>Exploring Workload Identity Federation for GKE</title><link href="https://mozillazg.com/2025/01/security-deep-dive-into-gcp-workload-identity-federation-for-gke-feature-en.html" rel="alternate"></link><published>2025-01-05T00:00:00+00:00</published><updated>2025-01-05T00:00:00+00:00</updated><author><name>mozillazg</name></author><id>tag:mozillazg.com,2025-01-05:2025/01/security-deep-dive-into-gcp-workload-identity-federation-for-gke-feature-en.html</id><summary type="html">&lt;p&gt;In this article, we will briefly explore a feature called &amp;quot;&lt;a class="reference external" href="https://cloud.google.com/blog/products/identity-security/make-iam-for-gke-easier-to-use-with-workload-identity-federation"&gt;Workload Identity Federation for GKE&lt;/a&gt;&amp;quot;
that was recently announced by GKE in their official blog.&lt;/p&gt;
&lt;div class="section" id="features-overview"&gt;
&lt;h2 id="hidfeatures-overview"&gt;Features Overview&lt;a class="headerlink" href="#hidfeatures-overview" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Workload Identity Federation for GKE is an improved version of the original GKE Workload Identity feature.
The main improvement is that it needs less configuration and offers better user experience.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="how-to-use"&gt;
&lt;h2 id="hidhow-to-use"&gt;How to Use&lt;a class="headerlink" href="#hidhow-to-use" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Follow these steps to try this feature:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Create a GKE cluster with Workload Identity Federation for GKE enabled. You can find this option at:
Create Cluster - Security - Enable Workload Identity.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Link IAM roles to the service account used by your test application. One service account can have multiple roles.
For example:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ kubectl create ns demo-ns
$ kubectl -n demo-ns create serviceaccount demo-sa

$ gcloud projects add-iam-policy-binding projects/test-gke-XXX \
    --role=roles/container.clusterViewer \
    --member=principal://iam.googleapis.com/projects/23182XXXXXXX/locations/global/workloadIdentityPools/test-gke-XXXXXX.svc.id.goog/subject/ns/&amp;lt;namespace-name&amp;gt;/sa/&amp;lt;service-account-name&amp;gt; \
    --condition=None

$ gcloud storage buckets add-iam-policy-binding gs://&amp;lt;bucket-name&amp;gt; \
--role=roles/storage.objectViewer \
--member=principal://iam.googleapis.com/projects/23182XXXXXXX/locations/global/workloadIdentityPools/test-gke-XXXXXX.svc.id.goog/subject/ns/&amp;lt;namespace-name&amp;gt;/sa/&amp;lt;service-account-name&amp;gt; \
--condition=None
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Deploy the test application. The application pod needs to use the namespace and service account from step 2,
and add nodeSelector to ensure scheduling on nodes with the Workload Identity Federation for GKE feature enabled&lt;/p&gt;
&lt;pre class="literal-block"&gt;
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  namespace: demo-ns
spec:
  nodeSelector:
    iam.gke.io/gke-metadata-server-enabled: &amp;quot;true&amp;quot;
  serviceAccountName: demo-sa
  containers:
  - name: test-pod
    image: google/cloud-sdk:slim
    command: [&amp;quot;sleep&amp;quot;,&amp;quot;infinity&amp;quot;]
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;After the pod is running, enter the test-pod container and access the instance metadata service to obtain the STS token.
The official SDK used by actual business applications will use a similar method to access the instance metadata service to
obtain STS tokens for requesting cloud product APIs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;gcloud&lt;span class="w"&gt; &lt;/span&gt;auth&lt;span class="w"&gt; &lt;/span&gt;print-access-token
&lt;span class="w"&gt; &lt;/span&gt;ya29.d.XXX
$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Metadata-Flavor: Google&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;access_token&amp;quot;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;quot;ya29.d.XXX&amp;quot;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;quot;expires_in&amp;quot;&lt;/span&gt;:3423,&lt;span class="s2"&gt;&amp;quot;token_type&amp;quot;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;quot;Bearer&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol class="arabic simple" start="5"&gt;
&lt;li&gt;The obtained STS token will have all the permissions of the roles associated in step 2.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;gcloud&lt;span class="w"&gt; &lt;/span&gt;container&lt;span class="w"&gt; &lt;/span&gt;node-pools&lt;span class="w"&gt; &lt;/span&gt;list&lt;span class="w"&gt; &lt;/span&gt;--zone&lt;span class="w"&gt; &lt;/span&gt;us-central1&lt;span class="w"&gt; &lt;/span&gt;--cluster&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;NAME&lt;span class="w"&gt;          &lt;/span&gt;MACHINE_TYPE&lt;span class="w"&gt;  &lt;/span&gt;DISK_SIZE_GB&lt;span class="w"&gt;  &lt;/span&gt;NODE_VERSION
&lt;span class="w"&gt; &lt;/span&gt;default-pool&lt;span class="w"&gt;  &lt;/span&gt;e2-medium&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.30.6-gke.1125000

$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;GET&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Authorization: Bearer &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;gcloud&lt;span class="w"&gt; &lt;/span&gt;auth&lt;span class="w"&gt; &lt;/span&gt;print-access-token&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://storage.googleapis.com/storage/v1/b/demo-gke-workload-identity-federation/o&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;kind&amp;quot;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;storage#objects&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="workflow-explained"&gt;
&lt;h2 id="hidworkflow-explained"&gt;Workflow Explained&lt;a class="headerlink" href="#hidworkflow-explained" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The workflow of Workload Identity Federation for GKE feature is as follows:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="/static/images/security/gke-workload-identity-federation-for-gke-en.png" /&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;When a program in the application Pod container requests the instance metadata service
(accessing &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;http://metadata.google.internal&lt;/span&gt;&lt;/tt&gt;, which actually accesses &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;http://169.254.169.254:80&lt;/span&gt;&lt;/tt&gt;)
to get an STS token, the request will be redirected to 169.254.169.252:988.
169.254.169.252:988 is the port listened to by the gke-metadata-server service deployed on the node.&lt;/li&gt;
&lt;li&gt;When the gke-metadata-server service receives the request, it will determine which Pod the request came from based on the client IP,
then request the apiserver to generate a token corresponding to the service account used by that Pod.&lt;/li&gt;
&lt;li&gt;gke-metadata-server will use the obtained service account token to access GCP's
&lt;a class="reference external" href="https://cloud.google.com/iam/docs/reference/sts/rest/v1/TopLevel/token"&gt;STS API&lt;/a&gt; to get an STS token,
finally gke-metadata-server returns the obtained STS token to the client.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are several key components and information that need special attention in this workflow, which will be explained one by one below.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="gke-metadata-server"&gt;
&lt;h2 id="hidgke-metadata-server"&gt;gke-metadata-server&lt;a class="headerlink" href="#hidgke-metadata-server" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When enabling the Workload Identity Federation for GKE feature at the cluster or node pool level,
a component named gke-metadata-server will be automatically deployed in the cluster.
The workload YAML for this component is as follows:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
apiVersion: apps/v1
kind: DaemonSet
metadata:
  annotations:
    deprecated.daemonset.template.generation: &amp;quot;1&amp;quot;
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
    k8s-app: gke-metadata-server
  name: gke-metadata-server
  namespace: kube-system
spec:
  minReadySeconds: 90
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: gke-metadata-server
  template:
    metadata:
      annotations:
        components.gke.io/component-name: gke-metadata-server
        components.gke.io/component-version: 0.4.301
        monitoring.gke.io/path: /metricz
      creationTimestamp: null
      labels:
        addonmanager.kubernetes.io/mode: Reconcile
        k8s-app: gke-metadata-server
    spec:
      containers:
      - command:
        - /gke-metadata-server
        - --logtostderr
        - --token-exchange-endpoint=https://securetoken.googleapis.com/v1/identitybindingtoken
        - --workload-pool=test-gke-XXXXXX.svc.id.goog
        - --alts-service-suffixes-using-node-identity=storage.googleapis.com,bigtable.googleapis.com,bigtable2.googleapis.com,bigtablerls.googleapis.com,spanner.googleapis.com,spanner2.googleapis.com,spanner-rls.googleapis.com,grpclb.directpath.google.internal,grpclb-dualstack.directpath.google.internal,staging-wrenchworks.sandbox.googleapis.com,preprod-spanner.sandbox.googleapis.com,wrenchworks-loadtest.googleapis.com,wrenchworks-nonprod.googleapis.com
        - --identity-provider=https://container.googleapis.com/v1/projects/test-gke-XXXXXX/locations/us-central1/clusters/test
        - --passthrough-ksa-list=anthos-identity-service:gke-oidc-envoy-sa,anthos-identity-service:gke-oidc-service-sa,gke-managed-dpv2-observability:hubble-relay,kube-system:antrea-controller,kube-system:container-watcher-pod-reader,kube-system:coredns,kube-system:egress-nat-controller,kube-system:event-exporter-sa,kube-system:fluentd-gcp-scaler,kube-system:gke-metrics-agent,kube-system:gke-spiffe-node-agent,kube-system:heapster,kube-system:konnectivity-agent,kube-system:kube-dns,kube-system:maintenance-handler,kube-system:metadata-agent,kube-system:network-metering-agent,kube-system:node-local-dns,kube-system:pkgextract-service,kube-system:pkgextract-cleanup-service,kube-system:securityprofile-controller,istio-system:istio-ingressgateway-service-account,istio-system:cluster-local-gateway-service-account,csm:csm-sync-agent,knative-serving:controller,kube-system:pdcsi-node-sa,kube-system:gcsfusecsi-node-sa,gmp-system:collector,gke-gmp-system:collector,gke-managed-cim:kube-state-metrics
        - --attributes=cluster-name=test,cluster-uid=392f63049deXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,cluster-location=us-central1
        - --cluster-uid=392f63049ded410XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        - --sts-endpoint=https://sts.googleapis.com
        - --token-exchange-mode=sts
        - --cloud-monitoring-endpoint=monitoring.googleapis.com:443
        - --iam-cred-service-endpoint=https://iamcredentials.googleapis.com
        - --cluster-project-number=2318XXXXXXXX
        - --cluster-location=us-central1
        - --cluster-name=test
        - --component-version=0.4.301
        - --ksa-cache-mode=watchchecker
        - --kcp-allow-watch-checker=true
        - --enable-mds-csi-driver=true
        - --csi-socket=/csi/csi.sock
        - --volumes-db=/var/run/gkemds.gke.io/csi/volumes.boltdb
        env:
        - name: GOMEMLIMIT
          value: &amp;quot;94371840&amp;quot;
        image: us-central1-artifactregistry.gcr.io/gke-release/gke-release/gke-metadata-server:gke_metadata_server_20240702.00_p0&amp;#64;sha256:aea9cc887c91b9a05e5bb4bb604180772594a01f0828bbfacf30c77562ac7205
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            host: 127.0.0.1
            path: /healthz
            port: 989
            scheme: HTTP
          initialDelaySeconds: 30
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 3
        name: gke-metadata-server
        ports:
        - containerPort: 987
          name: alts
          protocol: TCP
        - containerPort: 988
          name: metadata-server
          protocol: TCP
        - containerPort: 989
          name: debug-port
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            host: 127.0.0.1
            path: /healthz
            port: 989
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        resources:
          limits:
            memory: 100Mi
          requests:
            cpu: 100m
            memory: 100Mi
        securityContext:
          privileged: true
          readOnlyRootFilesystem: true
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /var/lib/kubelet/kubeconfig
          name: kubelet-credentials
          readOnly: true
        - mountPath: /var/lib/kubelet/pki/
          name: kubelet-certs
          readOnly: true
        - mountPath: /var/run/
          name: container-runtime-interface
        - mountPath: /etc/srv/kubernetes/pki
          name: kubelet-pki
          readOnly: true
        - mountPath: /etc/ssl/certs/
          name: ca-certificates
          readOnly: true
        - mountPath: /home/kubernetes/bin/gke-exec-auth-plugin
          name: gke-exec-auth-plugin
          readOnly: true
        - mountPath: /sys/firmware/efi/efivars/
          name: efivars
          readOnly: true
        - mountPath: /dev/tpm0
          name: vtpm
          readOnly: true
        - mountPath: /csi
          name: csi-socket-dir
        - mountPath: /var/run/gkemds.gke.io/csi
          name: state-dir
        - mountPath: /var/lib/kubelet/pods
          mountPropagation: Bidirectional
          name: pods-dir
        - mountPath: /registration
          name: kubelet-registration-dir
      dnsPolicy: Default
      hostNetwork: true
      nodeSelector:
        iam.gke.io/gke-metadata-server-enabled: &amp;quot;true&amp;quot;
        kubernetes.io/os: linux
      priorityClassName: system-node-critical
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      serviceAccount: gke-metadata-server
      serviceAccountName: gke-metadata-server
      terminationGracePeriodSeconds: 30
      tolerations:
      - effect: NoExecute
        operator: Exists
      - effect: NoSchedule
        operator: Exists
      - key: components.gke.io/gke-managed-components
        operator: Exists
      volumes:
      - hostPath:
          path: /var/lib/kubelet/pki/
          type: Directory
        name: kubelet-certs
      - hostPath:
          path: /var/lib/kubelet/kubeconfig
          type: File
        name: kubelet-credentials
      - hostPath:
          path: /var/run/
          type: Directory
        name: container-runtime-interface
      - hostPath:
          path: /etc/srv/kubernetes/pki/
          type: Directory
        name: kubelet-pki
      - hostPath:
          path: /etc/ssl/certs/
          type: Directory
        name: ca-certificates
      - hostPath:
          path: /home/kubernetes/bin/gke-exec-auth-plugin
          type: File
        name: gke-exec-auth-plugin
      - hostPath:
          path: /sys/firmware/efi/efivars/
          type: Directory
        name: efivars
      - hostPath:
          path: /dev/tpm0
          type: CharDevice
        name: vtpm
      - hostPath:
          path: /var/lib/kubelet/plugins/gkemds.gke.io
          type: DirectoryOrCreate
        name: csi-socket-dir
      - hostPath:
          path: /var/lib/kubelet/pods
          type: Directory
        name: pods-dir
      - hostPath:
          path: /var/lib/kubelet/plugins_registry
          type: Directory
        name: kubelet-registration-dir
      - hostPath:
          path: /var/lib/kubelet/plugins
          type: Directory
        name: kubelet-plugins-dir
      - hostPath:
          path: /var/run/gkemds.gke.io/csi
          type: DirectoryOrCreate
        name: state-dir
&lt;/pre&gt;
&lt;p&gt;The gke-metadata-server component has the following characteristics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The component's workload is a DaemonSet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The component Pod uses &lt;tt class="docutils literal"&gt;hostNetwork: true&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;privileged: true&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The service inside the component will listen on ports 987, 988, and 989, where port 988 will be used to
receive redirected requests for accessing the instance metadata service:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ ss -atnlp |grep gke
LISTEN 0      1024               *:987              *:*    users:((&amp;quot;gke-metadata-se&amp;quot;,pid=183706,fd=10))
LISTEN 0      1024               *:989              *:*    users:((&amp;quot;gke-metadata-se&amp;quot;,pid=183706,fd=12))
LISTEN 0      1024               *:988              *:*    users:((&amp;quot;gke-metadata-se&amp;quot;,pid=183706,fd=15))
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The previously mentioned IP 169.254.169.252 is the local loopback (lo) IP address,
so the port 988 listened to by gke-metadata-server
includes the previously mentioned &lt;tt class="docutils literal"&gt;169.254.169.252:988&lt;/tt&gt; port:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet 169.254.169.252/32 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;All nodes with the Workload Identity Federation for GKE feature enabled will be configured with the following
nftables rules during initialization, ensuring that traffic from business containers requesting
the metadata service (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;http://metadata.google.internal&lt;/span&gt;&lt;/tt&gt;, 169.254.169.254:80)
will be redirected to the &lt;tt class="docutils literal"&gt;169.254.169.252:988&lt;/tt&gt; port listened to by the component:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
table ip nat {
        chain PREROUTING {
                type nat hook prerouting priority dstnat; policy accept;
                 counter packets 2143 bytes 169432 jump KUBE-SERVICES
                iifname != &amp;quot;eth0&amp;quot; meta l4proto tcp ip daddr 169.254.169.254 tcp dport 8080  counter packets 0 bytes 0 dnat to 169.254.169.252:987
                iifname != &amp;quot;eth0&amp;quot; meta l4proto tcp ip daddr 169.254.169.254 tcp dport 80  counter packets 181 bytes 10860 dnat to 169.254.169.252:988
        }
}
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;As mentioned earlier, the component will determine the source pod through the client IP
and request the apiserver to get the service account. This involves what credentials the component uses to access the apiserver.
The component uses the kubelet's credentials on the node to access the apiserver
(the component YAML shown earlier includes the configuration for mounting kubelet kubeconfig).
Additionally, when deploying the component, extra RBAC permissions for get/list/watch on pods
and serviceaccounts will be granted to the kubelet's credentials,
used for obtaining information about pods and service accounts on the current node:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    components.gke.io/component-name: gke-metadata-server
    components.gke.io/component-version: 0.4.301
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
  name: gce:gke-metadata-server-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: gce:gke-metadata-server-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:nodes
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    components.gke.io/component-name: gke-metadata-server
    components.gke.io/component-version: 0.4.301
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
  name: gce:gke-metadata-server-reader
rules:
- apiGroups:
  - &amp;quot;&amp;quot;
  resources:
  - pods
  - serviceaccounts
  verbs:
  - get
  - watch
  - list
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;If the service account used by the pod is not bound to any IAM role,
the STS token obtained by the application in the pod when accessing the metadata service will
be the STS token of the node's default Google service account.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="service-account-token"&gt;
&lt;h2 id="hidservice-account-token"&gt;service account token&lt;a class="headerlink" href="#hidservice-account-token" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For requests initiated by programs within each pod, the gke-metadata-server component
doesn't directly use the service account token mounted in the pod container,
but instead requests the apiserver to generate a new service account token.&lt;/p&gt;
&lt;p&gt;Here's an example of the payload for a service account token mounted in the container:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
{
  &amp;quot;aud&amp;quot;: [
    &amp;quot;https://container.googleapis.com/v1/projects/test-gke-XXXXXX/locations/us-central1/clusters/test&amp;quot;
  ],
  &amp;quot;exp&amp;quot;: ...,
  &amp;quot;iat&amp;quot;: ...,
  &amp;quot;iss&amp;quot;: &amp;quot;https://container.googleapis.com/v1/projects/test-gke-XXXXXX/locations/us-central1/clusters/test&amp;quot;,
  &amp;quot;jti&amp;quot;: &amp;quot;...&amp;quot;,
  &amp;quot;kubernetes.io&amp;quot;: {...},
  &amp;quot;nbf&amp;quot;: ...,
  &amp;quot;sub&amp;quot;: &amp;quot;system:serviceaccount:demo-ns:demo-sa&amp;quot;
}
&lt;/pre&gt;
&lt;p&gt;Here's an example of the payload for a service account token generated by the apiserver when requested by the component:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
{
  &amp;quot;aud&amp;quot;: [
    &amp;quot;test-gke-XXXXXX.svc.id.goog&amp;quot;
  ],
  &amp;quot;exp&amp;quot;: ...,
  &amp;quot;iat&amp;quot;: ...,
  &amp;quot;iss&amp;quot;: &amp;quot;https://container.googleapis.com/v1/projects/test-gke-XXXXXX/locations/us-central1/clusters/test&amp;quot;,
  &amp;quot;jti&amp;quot;: &amp;quot;...&amp;quot;,
  &amp;quot;kubernetes.io&amp;quot;: {...},
  &amp;quot;nbf&amp;quot;: ...,
  &amp;quot;sub&amp;quot;: &amp;quot;system:serviceaccount:demo-ns:demo-sa&amp;quot;
}
&lt;/pre&gt;
&lt;p&gt;As we can see, the main difference is in the content of the &lt;tt class="docutils literal"&gt;aud&lt;/tt&gt; field.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="sts-token"&gt;
&lt;h2 id="hidsts-token"&gt;sts token&lt;a class="headerlink" href="#hidsts-token" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The gke-metadata-server component will use the obtained service account token to access the STS
&lt;a class="reference external" href="https://cloud.google.com/iam/docs/reference/sts/rest/v1/TopLevel/token"&gt;token API&lt;/a&gt; to get an STS token.&lt;/p&gt;
&lt;p&gt;Here's an example of the corresponding request:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
:authority: sts.googleapis.com
:method: POST
:path: /v1/token?alt=json&amp;amp;prettyPrint=false
:scheme: https
x-goog-api-client: gl-go/1.23.0--20240626-RC01 cl/646990413 +5a18e79687 X:fieldtrack,boringcrypto gdcl/0.177.0
user-agent: google-api-go-client/0.5 gke-metadata-server
content-type: application/json
content-length: 1673
accept-encoding: gzip

{&amp;quot;audience&amp;quot;:&amp;quot;identitynamespace:test-gke-XXXXXX.svc.id.goog:https://container.googleapis.com/v1/projects/test-gke-XXXXXX/locations/us-central1/clusters/test&amp;quot;,&amp;quot;grantType&amp;quot;:&amp;quot;urn:ietf:params:oauth:grant-type:token-exchange&amp;quot;,&amp;quot;requestedTokenType&amp;quot;:&amp;quot;urn:ietf:params:oauth:token-type:access_token&amp;quot;,&amp;quot;scope&amp;quot;:&amp;quot;https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/userinfo.email&amp;quot;,&amp;quot;subjectToken&amp;quot;:&amp;quot;XXX.XXX.XXX&amp;quot;,&amp;quot;subjectTokenType&amp;quot;:&amp;quot;urn:ietf:params:oauth:token-type:jwt&amp;quot;}

:status: 200
content-type: application/json; charset=UTF-8
vary: Origin
vary: X-Origin
vary: Referer
content-encoding: gzip
date: ...
server: scaffolding on HTTPServer2
content-length: 1061
x-xss-protection: 0
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff

{&amp;quot;access_token&amp;quot;:&amp;quot;ya29.d.XXX&amp;quot;,&amp;quot;issued_token_type&amp;quot;:&amp;quot;urn:ietf:params:oauth:token-type:access_token&amp;quot;,&amp;quot;token_type&amp;quot;:&amp;quot;Bearer&amp;quot;,&amp;quot;expires_in&amp;quot;:3599}
&lt;/pre&gt;
&lt;p&gt;The formatted content of the request body is as follows:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
{
  &amp;quot;audience&amp;quot;: &amp;quot;identitynamespace:test-gke-XXXXXX.svc.id.goog:https://container.googleapis.com/v1/projects/test-gke-XXXXXX/locations/us-central1/clusters/test&amp;quot;,
  &amp;quot;grantType&amp;quot;: &amp;quot;urn:ietf:params:oauth:grant-type:token-exchange&amp;quot;,
  &amp;quot;requestedTokenType&amp;quot;: &amp;quot;urn:ietf:params:oauth:token-type:access_token&amp;quot;,
  &amp;quot;scope&amp;quot;: &amp;quot;https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/userinfo.email&amp;quot;,
  &amp;quot;subjectToken&amp;quot;: &amp;quot;XXX.XXX.XXX&amp;quot;,
  &amp;quot;subjectTokenType&amp;quot;: &amp;quot;urn:ietf:params:oauth:token-type:jwt&amp;quot;
}
&lt;/pre&gt;
&lt;p&gt;The formatted content of the response body is as follows:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
{
  &amp;quot;access_token&amp;quot;: &amp;quot;ya29.d.XXX&amp;quot;,
  &amp;quot;issued_token_type&amp;quot;: &amp;quot;urn:ietf:params:oauth:token-type:access_token&amp;quot;,
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,
  &amp;quot;expires_in&amp;quot;: 3599
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="differences-from-gke-workload-identity"&gt;
&lt;h2 id="hiddifferences-from-gke-workload-identity"&gt;Differences from GKE Workload Identity&lt;a class="headerlink" href="#hiddifferences-from-gke-workload-identity" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here are the differences between Workload Identity Federation for GKE and GKE Workload Identity feature
(also known as linking Kubernetes ServiceAccounts to IAM):&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;colgroup&gt;
&lt;col width="29%" /&gt;
&lt;col width="26%" /&gt;
&lt;col width="45%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;Comparison Item&lt;/th&gt;
&lt;th class="head"&gt;GKE Workload Identity&lt;/th&gt;
&lt;th class="head"&gt;Workload Identity Federation for GKE&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;Requires Google service account (GSA)&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Not Required&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;IAM role binding configuration&lt;/td&gt;
&lt;td&gt;Requires GSA role binding&lt;/td&gt;
&lt;td&gt;Requires k8s service account (KSA) role binding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;KSA impersonating GSA configuration&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Not Required&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;GSA info configuration for KSA in cluster&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Not Required&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Multiple KSA/GSA binding support&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Supported&lt;/strong&gt; (e.g., all SAs in namespace, all SAs in cluster)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Authorization at project + namespace + KSA&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Authorization at cluster + namespace + KSA&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Support for hostNetwork applications&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Depends on gke-metadata-server component&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Cloud API support for obtained STS token&lt;/td&gt;
&lt;td&gt;Almost all cloud product APIs&lt;/td&gt;
&lt;td&gt;Most cloud APIs supported, some limited support, few unsupported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;By the way, although the official tutorials and documentation for Workload Identity Federation for GKE mention that it requires the gke-metadata-server component,
from what we discussed earlier, we can see that: we can actually use this solution without installing the gke-metadata-server component.
Specifically, we can remove the dependency on this component by mounting the required service account token to the application Pod and then directly accessing
the Token API provided by STS within our applications.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="references"&gt;
&lt;h2 id="hidreferences"&gt;References&lt;a class="headerlink" href="#hidreferences" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://cloud.google.com/blog/products/identity-security/make-iam-for-gke-easier-to-use-with-workload-identity-federation"&gt;Make IAM for GKE easier to use with Workload Identity Federation | Google Cloud Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity"&gt;Authenticate to Google Cloud APIs from GKE workloads &amp;nbsp;|&amp;nbsp; Google Kubernetes Engine (GKE)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://cloud.google.com/kubernetes-engine/docs/concepts/workload-identity"&gt;About Workload Identity Federation for GKE &amp;nbsp;|&amp;nbsp; Google Kubernetes Engine (GKE) &amp;nbsp;|&amp;nbsp; Google Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://cloud.google.com/iam/docs/federated-identity-supported-services"&gt;Identity federation: products and limitations &amp;nbsp;|&amp;nbsp; IAM Documentation &amp;nbsp;|&amp;nbsp; Google Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://cloud.google.com/iam/docs/reference/sts/rest/v1/TopLevel/token"&gt;Method: token &amp;nbsp;|&amp;nbsp; IAM Documentation &amp;nbsp;|&amp;nbsp; Google Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://cloud.google.com/compute/docs/metadata/overview"&gt;About VM metadata &amp;nbsp;|&amp;nbsp; Compute Engine Documentation &amp;nbsp;|&amp;nbsp; Google Cloud&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</summary><category term="kubernetes"></category><category term="k8s"></category><category term="gcp"></category><category term="gke"></category><category term="Workload Identity Federation for GKE"></category><category term="cloud-security"></category><category term="en-version"></category></entry></feed>