{"id":10008359,"date":"2024-02-17T16:01:19","date_gmt":"2024-02-17T08:01:19","guid":{"rendered":"https:\/\/blog.itmax.cn\/?p=10008359"},"modified":"2024-02-17T16:01:19","modified_gmt":"2024-02-17T08:01:19","slug":"ebpf-go-%e5%88%9d%e4%bd%93%e9%aa%8c","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10008359","title":{"rendered":"ebpf-go \u521d\u4f53\u9a8c"},"content":{"rendered":"<h2>\u524d\u8a00<\/h2>\n<p>\u6211\u4eec\u5728<a target=\"_blank\" href=\"https:\/\/link.segmentfault.com\/?enc=ycc4co7VP0WbochG%2BXFWNQ%3D%3D.LfNIt10YrC5RUpnG%2BO1tMO43ondFysC5J%2B95qSwxFt2etzni9YwQmbihgXC4ywrjw36mW57fcTm0%2F0C4GBa29A%3D%3D\" rel=\"noopener noreferrer\">\u300a\u7528eBPF\/XDP\u6765\u66ff\u4ee3LVS\u300b<\/a>\u7cfb\u5217\u3001<a target=\"_blank\" href=\"https:\/\/link.segmentfault.com\/?enc=b7YY2ZCi%2BvhaZgOVJ08now%3D%3D.pV1cWBR8wfBb%2FdNNr8r%2F9NjZnhDHlab7nUHBUIyqp9qYsJSOlhsaeXrkBv6yiH%2B%2Fam3F9%2FxyYvnkRZhC25B26A%3D%3D\" rel=\"noopener noreferrer\">\u300a\u4e00\u5f20\u56fe\u611f\u53d7\u771f\u5b9e\u7684 TCP \u72b6\u6001\u8f6c\u79fb\u300b<\/a>\u7cfb\u5217\uff0c\u4ee5\u53ca<a target=\"_blank\" href=\"https:\/\/link.segmentfault.com\/?enc=%2BQbE%2FavonjQkgmG1iLKBQg%3D%3D.SAmck6%2BGxuqNGXkyAwORv4d%2BmA1hFNMGR7W6BF6Eky1VFgfoeVe7wZBy7rYy91h8i6yOXpEJkXC9%2BLzCGHjE7g%3D%3D\" rel=\"noopener noreferrer\">\u300a\u5982\u4f55\u7ec8\u7ed3\u5df2\u5b58\u5728\u7684TCP\u8fde\u63a5?\u300b<\/a>\u7cfb\u5217\u6587\u7ae0\u4e2d\uff0c\u5747\u901a\u8fc7\u7eaf C \u8bed\u8a00\u548c libbpf<sup id=\"fnref-1\"><a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fn-1\" rel=\"noopener noreferrer\">1<\/a><\/sup> \u8fd9\u4e2a\u5e93\u6765\u8fd0\u7528 eBPF\u3002<\/p>\n<p>\u4f46\u662f\u5f88\u591a\u7684\u573a\u666f\u4e2d\uff08\u5c24\u5176\u662f\u4e91\u539f\u751f\u573a\u666f\uff09\uff0c\u6211\u4eec\u51fa\u4e8e\u907f\u514d\u91cd\u590d\u9020\u8f6e\u5b50\u3001\u66f4\u5feb\u7684\u8fed\u4ee3\u901f\u5ea6\u3001\u8fd0\u884c\u65f6\u5b89\u5168\u7b49\u539f\u56e0\uff0c\u4f1a\u9009\u62e9 go \u8bed\u8a00\u6765\u8fdb\u884c\u5f00\u53d1\uff0cebpf-go<sup id=\"fnref-2\"><a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fn-2\" rel=\"noopener noreferrer\">2<\/a><\/sup> \u8fd9\u4e2a\u5e93\u5c31\u662f\u5f53\u524d\u6700\u597d\u7684\u9009\u62e9\u3002 <\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"291\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVda2Z9\" alt=\"\" title=\"\"><\/p>\n<p>\u4eca\u5929\uff0c\u6211\u4eec\u5c31\u5bf9 ebpf-go \u8fdb\u884c\u4e00\u4e2a\u521d\u4f53\u9a8c\uff0c\u8fd9\u4e2a\u4f53\u9a8c\u4e0d\u662f\u6309\u90e8\u5c31\u73ed\u7684 API \u6587\u6863\uff0c\u800c\u662f\u901a\u8fc7\u4e00\u4e2a\u7b80\u5355\u7684\u9700\u6c42\uff0c\u8ba9\u5927\u5bb6\u5f97\u5230\u4e00\u4e2a\u771f\u5207\u7684\u611f\u53d7\uff0c\u8fd9\u4e2a\u9700\u6c42\u5c31\u662f\uff1a\u7edf\u8ba1\u53d1\u5411\u672c\u673a\u7684\u6bcf\u4e2a <em>\u201c\u8fde\u63a5\u201d<\/em> \u7684\u5305\u6570\u91cf\uff0c\u5e76\u4e14\u6bcf\u65b0\u589e 5 \u4e2a <em>\u201c\u8fde\u63a5\u201d<\/em> \u5c31\u8fdb\u884c\u4e00\u6b21\u6570\u636e\u5c55\u793a\u3002<\/p>\n<h2>\u4f53\u9a8c<\/h2>\n<h3>\u4f9d\u8d56<\/h3>\n<p>\u672c\u6b21\u4f53\u9a8c\u9700\u8981\u8bb8\u591a\u524d\u7f6e\u6761\u4ef6\uff1a<\/p>\n<ul>\n<li>Linux kernel \u7248\u672c 5.7 \u4ee5\u4e0a\uff0c\u4ee5\u652f\u6301 bpf_link\uff08\u6211\u662f 6.6.5\uff09<\/li>\n<li>LLVM \u7248\u672c 11 \u4ee5\u4e0a (clang and llvm-strip\uff0c\u68c0\u67e5\u547d\u4ee4 <code>clang --version<\/code> )<\/li>\n<li>libbpf headers (Debian\/Ubuntu \u662f libbpf-dev\uff0cFedora \u662f libbpf-devel )<\/li>\n<li>Linux kernel headers (Debian\/Ubuntu \u662f linux-headers-amd64\uff0cFedora \u662f kernel-devel )<\/li>\n<li>Go compiler \u7248\u672c\u9700\u8981\u652f\u6301 ebpf-go (\u6211\u5b89\u88c5\u4e86 GO 1.21\uff0c\u68c0\u67e5\u547d\u4ee4 <code>go version<\/code>)<\/li>\n<\/ul>\n<h3>\u9879\u76ee\u521d\u59cb\u5316<\/h3>\n<pre><code class=\"shell\"># \u521b\u5efa\u9879\u76ee\nmkdir ebpf-go-exp &amp;&amp; cd ebpf-go-exp\ngo mod init ebpf-go-exp\ngo mod tidy\n# \u624b\u52a8\u5f15\u5165\u4f9d\u8d56\ngo get github.com\/cilium\/ebpf\/cmd\/bpf2go<\/code><\/pre>\n<blockquote><p>\u5982\u679c\u4f9d\u8d56\u4e0b\u8f7d\u8d85\u65f6\u7684\u8bdd\uff0c\u53ef\u4ee5\u8bbe\u7f6e\u4e0b\u4ee3\u7406\uff1a<code>go env -w  GOPROXY=https:\/\/goproxy.cn,direct<\/code><\/p><\/blockquote>\n<h3>\u4ee3\u7801<\/h3>\n<h4>C \u4ee3\u7801<\/h4>\n<pre><code class=\"c\">...\n\n\/\/go:build ignore\n\nstruct event {\n    __u32 count;\n};\nconst struct event *unused __attribute__((unused));\n\nSEC(&quot;xdp&quot;) \nint count_packets(struct xdp_md *ctx) {\n    __u32 ip;\n    __u16 sport;\n    __u16 dport;\n    if (!parse_ip_src_addr(ctx, &amp;ip, &amp;sport, &amp;dport)){\n        goto done;\n    }\n    __u16 r_sport = bpf_ntohs(sport);\n    bpf_printk(&quot;Process a packet of tuple from %u|%pI4n:%u|%u&quot;,ip,&amp;ip,sport,r_sport);\n    if(8080 != bpf_ntohs(dport)){\n        goto done;\n    }\n    \n    struct tuple key;\n    __builtin_memset(&amp;key,0,sizeof(key));\n    key.addr = ip;\n    key.port = sport;\n\n    __u32 *pkt_count = bpf_map_lookup_elem(&amp;pkt_count_map, &amp;key);\n    if (!pkt_count) {\n        __u32 init_pkt_count = 1;\n        bpf_map_update_elem(&amp;pkt_count_map, &amp;key, &amp;init_pkt_count, BPF_NOEXIST);\n        __u32 key    = 0; \n        __u64 *count = bpf_map_lookup_elem(&amp;tuple_num, &amp;key); \n        if (count) { \n            __sync_fetch_and_add(count, 1); \n            if(*count % 5 == 0){\n                struct event *e;\n                e = bpf_ringbuf_reserve(&amp;events, sizeof(struct event), 0);\n                if (e){\n                    e-&gt;count = *count;\n                    bpf_ringbuf_submit(e, 0);\n                }\n            }\n        }\n    } else {\n        __sync_fetch_and_add(pkt_count, 1);\n    }\n\ndone:\n    return XDP_PASS; \n}\n\n...<\/code><\/pre>\n<h4>Go \u4ee3\u7801<\/h4>\n<pre><code class=\"golang\">...\n\n\/\/go:generate go run github.com\/cilium\/ebpf\/cmd\/bpf2go -type event counter counter.c -- -I headers\n\nfunc main() {\n    \/\/ Load the compiled eBPF ELF and load it into the kernel.\n    var objs counterObjects\n    if err := loadCounterObjects(&amp;objs, nil); err != nil {\n        log.Fatal(&quot;Loading eBPF objects:&quot;, err)\n    }\n    defer objs.Close()\n\n    ifname := &quot;lo&quot;\n    iface, err := net.InterfaceByName(ifname)\n    if err != nil {\n        log.Fatalf(&quot;Getting interface %s: %s&quot;, ifname, err)\n    }\n\n    \/\/ Attach count_packets to the network interface.\n    link, err := link.AttachXDP(link.XDPOptions{\n        Program:   objs.CountPackets,\n        Interface: iface.Index,\n    })\n    if err != nil {\n        log.Fatal(&quot;Attaching XDP:&quot;, err)\n    }\n    defer link.Close()\n\n    rd, err := ringbuf.NewReader(objs.Events)\n    if err != nil {\n        log.Fatalf(&quot;opening ringbuf reader: %s&quot;, err)\n    }\n    defer rd.Close()\n\n    stopper := make(chan os.Signal, 1)\n    signal.Notify(stopper, os.Interrupt, syscall.SIGTERM)\n    go func() {\n        &lt;-stopper\n        if err := rd.Close(); err != nil {\n            log.Fatalf(&quot;closing ringbuf reader: %s&quot;, err)\n        }\n    }()\n\n    log.Println(&quot;Waiting for events..&quot;)\n\n    \/\/ counterEvent is generated by bpf2go.\n    var event counterEvent\n    for {\n        record, err := rd.Read()\n        if err != nil {\n            if errors.Is(err, ringbuf.ErrClosed) {\n                log.Println(&quot;Received signal, exiting..&quot;)\n                return\n            }\n            log.Printf(&quot;reading from reader: %s&quot;, err)\n            continue\n        }\n        if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &amp;event); err != nil {\n            log.Printf(&quot;parsing ringbuf event: %s&quot;, err)\n            continue\n        }\n        log.Printf(&quot;tuple num: %d&quot;, event.Count)\n\n        var (\n            key counterTuple\n            val uint32\n        )\n        iter := objs.PktCountMap.Iterate()\n        for iter.Next(&amp;key, &amp;val) {\n            sourceIP := key.Addr\n            sourcePort := key.Port\n            packetCount := val\n            log.Printf(&quot;%d\/%s:%d =&gt; %d\/n&quot;, sourceIP, int2ip(sourceIP), sourcePort, packetCount)\n        }\n    }\n}\n\n...<\/code><\/pre>\n<p>\u5b8c\u6574\u4ee3\u7801\u5728\uff1a<a target=\"_blank\" href=\"https:\/\/link.segmentfault.com\/?enc=SMb2Ev18Ie5%2FkcLyM1dSnQ%3D%3D.%2Fa5UMF%2Fw%2BlE%2FO0aLqTgt8n%2FX7LSjDJkpA7BY05Ast7KgPljfHIpajTxN8tiwKrRM\" rel=\"noopener noreferrer\">https:\/\/github.com\/MageekChiu\/epbf-go-exp<\/a><\/p>\n<h3>\u8fd0\u884c<\/h3>\n<pre><code class=\"shell\"># \u751f\u6210\u811a\u624b\u67b6\u4ee3\u7801\ngo generate\n\n# \u5229\u7528\u751f\u6210\u7684 GO \u4ee3\u7801\uff0c\u8fdb\u884c\u7f16\u8bd1\u548c\u8fd0\u884c\ngo build &amp;&amp; sudo .\/ebpf-go-exp\n<\/code><\/pre>\n<p>\u672c\u673a\u8fd0\u884c\u4e00\u4e2a openresty \u5e76\u76d1\u542c 8080 \u7aef\u53e3\uff0c\u7136\u540e\u53cd\u590d\u8bbf\u95ee\u6d4b\u8bd5<\/p>\n<pre><code>openresty\n\ncurl localhost:8080\ncurl localhost:8080\n...<\/code><\/pre>\n<p>\u67e5\u770b\u65e5\u5fd7<\/p>\n<pre><code># bpf \u8f93\u51fa\nbpftool prog tracelog\n bpf_trace_printk: Process a packet of tuple from 16777343|127.0.0.1:31876|33916\n ...\n bpf_trace_printk: Process a packet of tuple from 16777343|127.0.0.1:56449|33244\n ...\n\n# go \u8f93\u51fa\nWaiting for events..\ntuple num: 5\n16777343\/127.0.0.1:31876 =&gt; 7\n16777343\/127.0.0.1:31364 =&gt; 7\n16777343\/127.0.0.1:56449 =&gt; 1\n16777343\/127.0.0.1:10909 =&gt; 7\n16777343\/127.0.0.1:30340 =&gt; 7\n...<\/code><\/pre>\n<p>\u82e5\u8fed\u4ee3\u8fc7\u7a0b\u4e2d\uff0cC \u4ee3\u7801\u6709\u53d8\u5316\uff0c\u5219\u9700\u8981\u6267\u884c <code>go generate<\/code>\uff0c\u5426\u5219\u4ec5\u6267\u884c Go \u7f16\u8bd1\u90e8\u5206\u5373\u53ef\u3002<\/p>\n<h3>\u91cd\u70b9\u89e3\u6790<\/h3>\n<ol>\n<li>c \u4ee3\u7801\u4e3b\u4f53\u548c\u6211\u4eec\u4e4b\u524d\u7cfb\u5217\u7684\u6587\u7ae0\u7c7b\u4f3c\uff0c\u5c31\u662f\u5728 xdp hook \u70b9\u89e3\u6790\u51fa\u6bcf\u4e2a\u62a5\u6587\u7684\u56db\u5143\u7ec4\uff0c\u7136\u540e\u5b58\u5165 <code>pkt_count_map<\/code>\u3002<code>tuple_num<\/code> \u8fd9\u4e2a map \u4f5c\u4e3a\u5168\u5c40\u53d8\u91cf\uff0c\u901a\u8fc7 <code>__sync_fetch_and_add<\/code> \u5b89\u5168\u5730\u5e76\u53d1\uff0c\u6bcf\u5f53\u65b0\u589e 5 \u4e2a <em>\u201c\u8fde\u63a5\u201d<\/em> \u5c31\u5411\u7528\u6237\u7a7a\u95f4\u53d1\u9001\u4e8b\u4ef6\u3002<\/li>\n<li>c \u4ee3\u7801\u4e2d <code>unused<\/code> \u8fd9\u4e2a <code>event<\/code> \u6307\u9488\u5fc5\u987b\u58f0\u660e\uff0c\u4e0d\u7136\u7528\u6237\u6001\u7684 go \u5c31\u62ff\u4e0d\u5230\u8fd9\u4e2a\u6570\u636e\u7ed3\u6784\u3002<\/li>\n<li>c \u4ee3\u7801\u4e2d\u5f00\u59cb\u7684 <code>ignore<\/code> \u662f\u5fc5\u987b\u7684\uff0c\u907f\u514d go build \u62a5\u9519: <code>C source files not allowed when not using cgo or SWIG<\/code><\/li>\n<li><code>go generate<\/code> \u547d\u4ee4\u4f1a\u6839\u636e go \u4ee3\u7801\u4e2d\u7684 <code>go:generate<\/code> \u8bed\u53e5\u751f\u6210\u811a\u624b\u67b6\u4ee3\u7801\uff0c\u5c31\u50cf BPF Skeleton<sup id=\"fnref-3\"><a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fn-3\" rel=\"noopener noreferrer\">3<\/a><\/sup>\uff0c\u7136\u540e\u6211\u4eec\u5c31\u53ef\u4ee5\u5728 go \u4ee3\u7801\u4e2d\u4fbf\u6377\u5730\u8bbf\u95ee c \u4e2d\u5b9a\u4e49\u7684 map\uff0cprog \u4ee5\u53ca\u4e00\u4e9b\u6570\u636e\u7ed3\u6784\u3002<code>-type event counter<\/code> \u4f7f\u5f97 c \u4e2d\u5b9a\u4e49\u7684 <code>event<\/code> \u7ed3\u6784\u4f53\u5728 go \u4e2d\u5c31\u662f <code>counterEvent<\/code> \u7ed3\u6784\u4f53\u3002<\/li>\n<li>\u5185\u6838\u7a7a\u95f4\u5411\u7528\u6237\u7a7a\u95f4\u53d1\u9001\u6570\u636e\/\u4e8b\u4ef6\u53ef\u4ee5\u901a\u8fc7 perfbuf \u548c ringbuf \u5b9e\u73b0\uff0c\u4ece\u800c\u907f\u514d\u7528\u6237\u7a7a\u95f4\u8f6e\u8be2\u6570\u636e\u3002\u8fd9\u4e24\u8005\u867d\u7136\u529f\u80fd\u6709\u4e0d\u5c11\u5dee\u522b\uff0c\u4f46\u662fapi\u90fd\u5dee\u4e0d\u591a<sup id=\"fnref-4\"><a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fn-4\" rel=\"noopener noreferrer\">4<\/a><\/sup>\u3002\u5f53\u6211\u4eec\u6536\u5230\u5185\u6838\u7684\u901a\u77e5\u540e\uff0c\u901a\u8fc7 Iterate \u6765\u904d\u5386\u7edf\u8ba1\u6570\u636e\u7684 map\uff0c\u5b9e\u73b0\u4e00\u79cd\u7c7b\u4f3c\u4e8e\u63a8\u62c9\u7ed3\u5408\u7684\u67b6\u6784\u3002<\/li>\n<\/ol>\n<h3>\u5c0f\u63d2\u66f2<\/h3>\n<p>\u5982\u679c\u6211\u4eec\u7684 <code>pkt_count_map<\/code> \u8fd9\u6837\u5199\u7684\u8bdd\uff1a<\/p>\n<pre><code>struct tuple key = {ip,bpf_ntohs(sport)};\n__u32 *pkt_count = bpf_map_lookup_elem(&amp;pkt_count_map, &amp;key);\nif (!pkt_count) {\n    ...\n}else{\n    ...\n}<\/code><\/pre>\n<p>\u5c31\u53ef\u80fd\u4f1a\u5f97\u51fa\u4e00\u4e2a\u770b\u8d77\u6765\u5f88\u5947\u602a\u7684\u7ed3\u679c\uff1a<\/p>\n<pre><code>Waiting for events..\ntuple num: 5\n16777343\/127.0.0.1:60162 =&gt; 3\n16777343\/127.0.0.1:45076 =&gt; 3\n16777343\/127.0.0.1:45082 =&gt; 3\n16777343\/127.0.0.1:60162 =&gt; 4\n16777343\/127.0.0.1:45076 =&gt; 4<\/code><\/pre>\n<p>\u4ee5\u53ca<\/p>\n<pre><code>bpftool map dump name pkt_count_map\n[{\n        &quot;key&quot;: {\n            &quot;addr&quot;: 16777343,\n            &quot;port&quot;: 60162\n        },\n        &quot;value&quot;: 3\n    },{\n        &quot;key&quot;: {\n            &quot;addr&quot;: 16777343,\n            &quot;port&quot;: 45082\n        },\n        &quot;value&quot;: 3\n    },{\n        &quot;key&quot;: {\n            &quot;addr&quot;: 16777343,\n            &quot;port&quot;: 45076\n        },\n        &quot;value&quot;: 3\n    },{\n        &quot;key&quot;: {\n            &quot;addr&quot;: 16777343,\n            &quot;port&quot;: 45082\n        },\n        &quot;value&quot;: 4\n    },{\n        &quot;key&quot;: {\n            &quot;addr&quot;: 16777343,\n            &quot;port&quot;: 60162\n        },\n        &quot;value&quot;: 4\n    },{\n        &quot;key&quot;: {\n            &quot;addr&quot;: 16777343,\n            &quot;port&quot;: 45076\n        },\n        &quot;value&quot;: 4\n    }\n]<\/code><\/pre>\n<p>\u4e4d\u4e00\u770b\u4f60\u4f1a\u53d1\u73b0 map \u7684 key \u600e\u4e48\u6709\u4e9b\u91cd\u590d\u4e86\uff1f\u8fd9\u91cc\u5148\u5356\u4e2a\u5173\u5b50\uff0c\u540e\u9762\u6709\u673a\u4f1a\u518d\u6765\u5206\u6790\u3002<\/p>\n<h2>\u603b\u7ed3<\/h2>\n<p>\u672c\u6587\u6211\u4eec\u4e86\u89e3 ebpf-go \u7684\u4e00\u4e9b\u5e38\u89c1\u7528\u6cd5\uff0c\u8ba9\u5927\u5bb6\u5bf9 ebpf-go \u6709\u4e86\u4e00\u4e2a\u6a21\u7cca\u4f46\u6574\u4f53\u7684\u8ba4\u8bc6\uff0c\u66f4\u591a\u7684\u7ec6\u8282\uff0c\u53ef\u4ee5\u901a\u8fc7\u5b98\u7f51\u7684\u6587\u6863<sup id=\"fnref-5\"><a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fn-5\" rel=\"noopener noreferrer\">5<\/a><\/sup>\u4ee5\u53ca examples<sup id=\"fnref-6\"><a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fn-6\" rel=\"noopener noreferrer\">6<\/a><\/sup> \u8fdb\u884c\u4e86\u89e3\u3002<\/p>\n<p>\u4e0b\u4e00\u7bc7\u6587\u7ae0\uff0c\u6211\u4eec\u5c31\u4ece\u5b9e\u6218\u7684\u89d2\u5ea6\uff0c\u770b\u770b cilium<sup id=\"fnref-7\"><a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fn-7\" rel=\"noopener noreferrer\">7<\/a><\/sup> \u662f\u600e\u4e48\u901a\u8fc7 ebpf-go \u6765\u53d1\u6325 ebpf \u5a01\u529b\u7684\u3002<\/p>\n<h2>\u53c2\u8003<\/h2>\n<div class=\"footnotes\">\n<hr>\n<ol>\n<li id=\"fn-1\"> <a target=\"_blank\" href=\"https:\/\/link.segmentfault.com\/?enc=PGkUrn8nbb4Pgzv5%2BVg8QA%3D%3D.GKbGtpQZHY7wD%2F1b0OQFW0Udb68gqtfUDa2utqcSAkk%3D\" rel=\"noopener noreferrer\">https:\/\/libbpf.readthedocs.io\/<\/a>  <a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fnref-1\" rel=\"noopener noreferrer\">&#8617;<\/a><\/li>\n<li id=\"fn-2\"> <a target=\"_blank\" href=\"https:\/\/link.segmentfault.com\/?enc=adCIp5%2FC26%2BFaSiTgoJW9g%3D%3D.q1x2j4X6J%2BJT%2FhIH64DP3jwkkGHhnZ3GZUm8jyPq55g%3D\" rel=\"noopener noreferrer\">https:\/\/ebpf-go.dev\/about\/<\/a> <a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fnref-2\" rel=\"noopener noreferrer\">&#8617;<\/a><\/li>\n<li id=\"fn-3\"> <a target=\"_blank\" href=\"https:\/\/link.segmentfault.com\/?enc=yWaChTvsV9Tk2YbvDklJ4g%3D%3D.Qzq5%2Fplsfo8ATP%2F76rok%2F8S7Qdr1jelE2Utpcnfw0svJVZMLYrC3L6BNHLfkkkB5XdDqzgLA8sWYjwAliUzHb9JIKNO2893SSsHGPApJjE9Df93f4xIUQSEAdWgcu56Z\" rel=\"noopener noreferrer\">https:\/\/www.kernel.org\/doc\/html\/next\/bpf\/libbpf\/libbpf_overvi&#8230;<\/a> <a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fnref-3\" rel=\"noopener noreferrer\">&#8617;<\/a><\/li>\n<li id=\"fn-4\"> <a target=\"_blank\" href=\"https:\/\/link.segmentfault.com\/?enc=SuPdrbSHwuN7%2FaYsbEqGTg%3D%3D.K%2BR0yE6wgO1rg4ARzYndrq%2FgrIuA02XRMb%2Bk3pJs%2BlcjauHRnEyfQNm54wonGB7IhcmSIAcmeppDXjuGTJ8pKqkLt39EDb%2FxwsrPUBqbzqc%3D\" rel=\"noopener noreferrer\">https:\/\/nakryiko.com\/posts\/bpf-ringbuf\/#bpf-ringbuf-vs-bpf-pe&#8230;<\/a> <a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fnref-4\" rel=\"noopener noreferrer\">&#8617;<\/a><\/li>\n<li id=\"fn-5\"> <a target=\"_blank\" href=\"https:\/\/link.segmentfault.com\/?enc=sCGfWGug3bY%2BFbObDl2OxA%3D%3D.rr36twJaSW%2FpRPsk3d12Zop90jOYU6k3M%2BXGnOoa5lXBFh7GygulX1Cy3g%2BQFAXp\" rel=\"noopener noreferrer\">https:\/\/ebpf-go.dev\/guides\/getting-started\/<\/a> <a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fnref-5\" rel=\"noopener noreferrer\">&#8617;<\/a><\/li>\n<li id=\"fn-6\"> <a target=\"_blank\" href=\"https:\/\/link.segmentfault.com\/?enc=L0CKFBszc76yDR4P%2BaMoPA%3D%3D.W7U3i9nKThafnH5GHP%2Bj42n32idaIVxZ3W2yncYI4BzCBMpn%2BnI%2FU07dSye9Ue2vM4SeAzxqdbp20VBYFfeYQA%3D%3D\" rel=\"noopener noreferrer\">https:\/\/github.com\/cilium\/ebpf\/tree\/main\/examples<\/a> <a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fnref-6\" rel=\"noopener noreferrer\">&#8617;<\/a><\/li>\n<li id=\"fn-7\"> <a target=\"_blank\" href=\"https:\/\/link.segmentfault.com\/?enc=DcomjoYwlEuIjr%2BkeDFdPQ%3D%3D.SWpOpWfxoBobEWmvv76V%2Bx7CFPrcu1QcmZlH7ItzB3cVB4DzNxuHSsK9d3Q7jrHgij3fzYVEtzB5oGzdqD7g5g%3D%3D\" rel=\"noopener noreferrer\">https:\/\/docs.cilium.io\/en\/stable\/overview\/intro\/<\/a> <a target=\"_blank\" href=\"https:\/\/segmentfault.com\/a\/#fnref-7\" rel=\"noopener noreferrer\">&#8617;<\/a><\/li>\n<\/ol>\n<\/div>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000044635034\">https:\/\/segmentfault.com\/a\/1190000044635034<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u524d\u8a00 \u6211\u4eec\u5728\u300a\u7528eBPF\/XDP\u6765\u66ff\u4ee3LVS\u300b\u7cfb\u5217\u3001\u300a\u4e00\u5f20\u56fe\u611f\u53d7\u771f\u5b9e\u7684 TCP \u72b6\u6001\u8f6c\u79fb\u300b\u7cfb\u5217\uff0c\u4ee5\u53ca\u300a\u5982\u4f55\u7ec8\u7ed3 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-10008359","post","type-post","status-publish","format-standard","hentry","category-share"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10008359","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10008359"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10008359\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10008359"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10008359"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10008359"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}