我正在 Linux 中编写一个网络模块,我看到只有从 skb 缓冲区跳过 20 个字节后才能提取 tcp header ,即使 API 是“skb_transport_header”。 其背后的原因是什么?有人可以详细解释一下吗?传出数据包不需要同样的。我知道在接收数据包时,当数据包从 L1 流向 L5 时, header 会被删除。但是,当数据包传出时,会添加 header 。这在这里有何不同?
/**对于输入包**/
struct tcphdr *tcp;
tcp = (struct tcphdr *)(skb_transport_header(skb)+20);
/** 对于传出数据包 **/
struct tcphdr *tcp;
tcp = (struct tcphdr *)(skb_transport_header(skb));
最佳答案
这取决于您在堆栈中处理数据包的位置。就在收到数据包之后,传输 header 偏移量尚未设置。一旦你确定这个数据包实际上是发往本地盒子的,就不再需要了。这发生在 ip_local_deliver_finish() 中的 IPv4 中。 (请注意,例如,tcp_hdr() 假定 transport_header 位置已经设置。)
这是完全有道理的(尽管很难确定在正常流程中发生这种事情的位置):随着每一层被识别和处理,下一层的起始偏移量被记录在 sk_buff 中。 header 实际上并没有被删除,skb“数据”位置只是被调整为指向它们之外。层特定的位置也进行了类似的调整。
在输出时,它更直接一些,并且以相反的顺序完成:首先创建传输 header 。然后,网络 header 被添加到它前面,等等。
关于sockets - 为什么 skb_buffer 需要跳过 20 个字节才能在数据包输入时读取传输缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23693335/