1

我现在正在研究 XDP 代码,我对程序如何处理数据包标头的某些部分感到有些困惑。所以!当我查看获取数据包 IP 地址的代码时,它是这样的:

static inline int parse_ipv4(void *data, u64 nh_off, void *data_end) {
struct iphdr *iph = data + nh_off;

if ((void*)&iph[1] > data_end)
    return 0;
    return iph->protocol;
}

现在这里有一些让我感到困惑的事情:

struct iphdr *iph = data + nh_off;
  1. 我认为nh_off是下一个标头的偏移值,所以如果您添加data + nh_off,那不应该带您进入下一个数据包吗?因为据我了解,如果你在数据中添加下一个标头偏移量,则应该有下一个数据包等待处理!

  2. 做什么

    (void*)&iph[1]

    究竟是做什么的?我试图猜测这行代码做了几天,但我仍然没有任何线索。

如果我的问题太专心或含糊,我很抱歉。这件事困扰了我一段时间,如果有人能与我分享他们的知识,我将不胜感激。非常感谢你。

4

1 回答 1

3

这完全取决于您的代码,因为我看不到nh_off您的情况是如何定义的。但大多数时候,它确实指向下一个标题,所以我们会:

  1. nh_off是以太网头解析后下一个头nh_off的偏移量,即IP头在数据包中的偏移量(通常在这个阶段设置为14,如果没有VLAN/encap,以太网头中的字节数是用过的)。

    Settingstruct iphdr *iph = data + nh_off;声明并初始化iph为一个struct iphdr指针,因此我们可以在之后重用它以轻松地从 IPv4 标头中访问每个字段。它指向data + nh_off,即数据包的开头加上 IPv4 标头在数据包中开始的偏移量。

    在您的 eBPF 程序中无法访问下一个要处理的数据包;当通过对 BPF 程序的新调用处理新数据包时您将获得一个ctx带有data指向它的指针的新数据包,但您一次只能看到一个数据包。

  2. 所以iph指向您的 IPv4 标头的开头。我们可以使用该指针轻松访问各个字段(例如iph->protocol,获取 L4 协议)。但在我们这样做之前,我们必须确保数据包足够长并且实际上包含这些字段。否则,我们可以进行越界访问(因此验证者首先会拒绝该程序)。这是我们在这里做的检查:if ((void*)&iph[1] > data_end) return 0;

    在该验证中,(void*)&iph[1]意味着: i) 考虑一个struct iphdr *数组 ( &iph,一个指向 a 的指针的指针struct iphdr)。ii) 获取该数组的第二个单元格,例如 second 指向的结构的地址,例如数据包中struct iphdr *第一个之后开始的字节的地址。struct iphdr并且 iii) 将其转换为 avoid *以便我们可以将其与 进行比较data_end。换句话说,这是一种比较data_end(数据包最后一个字节之后的内存地址)和 IPv4 标头之后的字节地址(因此 L4 的第一个字节可能是数据包足够长)的方法。如果(void*)&iph[1]大于data_end,那么我们考虑的 IPv4 标头比我们得到的实际数据包长,我们不能取消引用iph来尝试到达例如protocol场地。

用一张图,也许:

Packet data

| Ethernet     | IPv4               | IPv4 data (e.g. L4, data)       |
+--------------+--------------------+------ ... ----------------------+
^              ^                    ^                                 ^
data           data + nh_off        |                                 data_end
               iph                  |
               &iph[0]              &iph[1]

如果我们有以下内容,我们将有一个访问问题iph->protocol(这就是我们return 0如果比较成功的原因):

Packet data

| Ethernet     | <something>   | End of packet
+--------------+----------------    +
^              ^               ^    ^
data           data + nh_off   |    |
               iph             |    |
               &iph[0]         |    &iph[1]
                               data_end
于 2019-10-06T11:33:30.310 回答