cursor_advance 在 BPF 中的具体用法是什么?
What exactly is usage of cursor_advance in BPF?
我正在浏览 IOvisor 项目的幻灯片,https://events.static.linuxfound.org/sites/events/files/slides/iovisor-lc-bof-2016.pdf
#include <bcc/proto.h>
struct IPKey { u32 dip; u32 sip; };
BPF_TABLE("hash", struct IPKey, int, mytable, 1024);
int recv_packet(struct __sk_buff *skb) {
struct IPKey key;
u8 *cursor = 0;
struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
struct ip_t *ip = cursor_advance(cursor, sizeof(*ip));
key.dip = ip->dst;
key.sip = ip->src;
int *leaf = mytable.lookup(&key);
if (leaf)
*(leaf)++;
return 0;
}
此代码在示例中。
我经常使用 cursor_advance()
,现在我想弄清楚它到底做了什么。
我怀疑 cursor
是一个指针,我们在其中保存我们正在解析的数据包的地址。
然后,使用 cursor_advance()
我们将光标移动以太网的大小 header,因为 ethernet_t
包含所有以太网 header 信息。
然后,光标现在位于数据包以太网末尾的地址 header 如果我们使用 ethernet_t
header 中声明的变量,例如 type
,就像: ethernet->type
,我们可以访问保存在 type
的信息,因为结构 ethernet
会读取保存在该地址中的值?
对不起,我的解释不是很好。
我只是在寻找一般性解释,或者我的理论是否正确。
谢谢!
你的理解对我来说是正确的。只需将其视为用于连续解析数据包的不同 header 的“游标”。 cursor_advance()
宏是 defined 为:
#define cursor_advance(_cursor, _len) \
({ void *_tmp = _cursor; _cursor += _len; _tmp; })
它将 _len
添加到 _cursor
,并且 returns 是 _cursor
在我们添加 _len
之前的值。
所以第一次调用cursor_advance()
returns初始值:ethernet
指向数据包的开头,我们可以利用它的属性来访问数据包的不同字段以太网 header。但同样的调用也将 cursor
向前移动了以太网的长度 header,所以现在它指向下一个 header(L3,例如 IP)的开头。第二次调用cursor_advance()
returns指向L3层的指针,我们将其存储在ip
中。 cursor
也向前移动,假设数据包是 IPv4,现在将指向 L4 header。
注意:除了 BCC 中可用的几个网络示例之外,我不认为这种机制在 BPF 程序中被广泛使用。相反,程序通常使用 skb->data
和 skb->data_end
.
浏览数据包 headers
我正在浏览 IOvisor 项目的幻灯片,https://events.static.linuxfound.org/sites/events/files/slides/iovisor-lc-bof-2016.pdf
#include <bcc/proto.h>
struct IPKey { u32 dip; u32 sip; };
BPF_TABLE("hash", struct IPKey, int, mytable, 1024);
int recv_packet(struct __sk_buff *skb) {
struct IPKey key;
u8 *cursor = 0;
struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
struct ip_t *ip = cursor_advance(cursor, sizeof(*ip));
key.dip = ip->dst;
key.sip = ip->src;
int *leaf = mytable.lookup(&key);
if (leaf)
*(leaf)++;
return 0;
}
此代码在示例中。
我经常使用 cursor_advance()
,现在我想弄清楚它到底做了什么。
我怀疑 cursor
是一个指针,我们在其中保存我们正在解析的数据包的地址。
然后,使用 cursor_advance()
我们将光标移动以太网的大小 header,因为 ethernet_t
包含所有以太网 header 信息。
然后,光标现在位于数据包以太网末尾的地址 header 如果我们使用 ethernet_t
header 中声明的变量,例如 type
,就像: ethernet->type
,我们可以访问保存在 type
的信息,因为结构 ethernet
会读取保存在该地址中的值?
对不起,我的解释不是很好。
我只是在寻找一般性解释,或者我的理论是否正确。
谢谢!
你的理解对我来说是正确的。只需将其视为用于连续解析数据包的不同 header 的“游标”。 cursor_advance()
宏是 defined 为:
#define cursor_advance(_cursor, _len) \
({ void *_tmp = _cursor; _cursor += _len; _tmp; })
它将 _len
添加到 _cursor
,并且 returns 是 _cursor
在我们添加 _len
之前的值。
所以第一次调用cursor_advance()
returns初始值:ethernet
指向数据包的开头,我们可以利用它的属性来访问数据包的不同字段以太网 header。但同样的调用也将 cursor
向前移动了以太网的长度 header,所以现在它指向下一个 header(L3,例如 IP)的开头。第二次调用cursor_advance()
returns指向L3层的指针,我们将其存储在ip
中。 cursor
也向前移动,假设数据包是 IPv4,现在将指向 L4 header。
注意:除了 BCC 中可用的几个网络示例之外,我不认为这种机制在 BPF 程序中被广泛使用。相反,程序通常使用 skb->data
和 skb->data_end
.