从TCP拥塞控制Linux内核模块中访问TCP头部

4

我正在为Linux内核开发TCP拥塞控制算法,这将作为内核模块实现。 在代码中,我想要访问TCP头,并使用以下函数来完成。

void get_hdr(struct sock *sk){ 
  struct sk_buff *skb;
  skb = skb_peek_tail(&sk->sk_receive_queue);
  if (skb != NULL)
     printk(KERN_INFO "skb address: %p", skb);
  struct tcphdr *tcp_header = tcp_hdr(skb);
  if(tcp_header != 0)
     printk(KERN_INFO "tcp_header address: %p", tcp_header);
  else
     printk(KERN_INFO "tcp_header is NULL");
}

我认为这基本上应该可以工作,因为它在内核中这里也是这样做的。

然而,查看我的kern.log,我发现:

skb address: dbd94501
tcp_header address is NULL

显然调用tcp_hdr(skb)失败了。

我不知道为什么会这样。有没有人能够给我一些启发,告诉我应该在哪里寻找或者需要做哪些更改才能够得到tcp头呢?

谢谢,

Stefan


你在 skb->transport_header 中看到了什么?你是如何连接内核的?使用 Netfilter 吗? - eater
你好 @eater,感谢您的评论。我不得不在实验室里对其进行测试。我发现我一开始提供给sk的指针是错误的。然而,使用正确的指针后,我的skb_peek_tail调用返回null。我想我需要更深入地研究一下。无论如何,顺便说一句,我不是钩入内核。这是一个直接作为内核代码运行的内核模块。 - Phi
2
通过钩入内核,我的问题是你的内核模块是如何被网络堆栈调用的。例如,如果你的模块在ip_input之前被调用,那么skb->transport_header可能还没有被设置。但这听起来好像有其他问题。顺便说一下,请阅读注释并确保你理解使用skb_peek_tail()的危险。 - eater
2个回答

1

在代码行

struct tcphdr *tcp_header = tcp_hdr(skb);

你仍然可能有skb == NULL。

为什么不把整个if部分放在大括号中?

void get_hdr(struct sock *sk){ 
 struct sk_buff *skb;
 skb = skb_peek_tail(&sk->sk_receive_queue);
 if (skb != NULL) {
    printk(KERN_INFO "skb address: %p", skb);
    struct tcphdr *tcp_header = tcp_hdr(skb);
    if(tcp_header != 0)
       printk(KERN_INFO "tcp_header address: %p", tcp_header);
    else
       printk(KERN_INFO "tcp_header is NULL");
 }
}

1

这可能是一个没有任何传输头的数据包。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接