【Linux4.1.12源码分析】IP层报文发送之ip_local_out

时间:2022-07-20 11:04:42

http://blog.csdn.net/one_clouder/article/details/52665276


IP层本地报文发送有两个函数ip_local_out和ip_local_out_sk,实际实现两者是等同的,因为本地发送的报文,skb必然关联着一个sock对象。

1、ip_local_out函数

[cpp] view plain copy
  1. static inline int ip_local_out(struct sk_buff *skb)  
  2. {  
  3.     return ip_local_out_sk(skb->sk, skb);    //本地报文发送,本地发送的报文都关联着一个sock对象  
  4. }  
2、ip_local_out_sk函数 [cpp] view plain copy
  1. int ip_local_out_sk(struct sock *sk, struct sk_buff *skb)   //本地报文发送,本地发送的报文都关联着一个sock对象  
  2. {  
  3.     int err;  
  4.   
  5.     err = __ip_local_out(skb);      //报文安全检测(netfilter)  
  6.     if (likely(err == 1))           //返回值为1,说明netfilter允许报文通过  
  7.         err = dst_output_sk(sk, skb);   //最终会调用ip_output函数  
  8.   
  9.     return err;  
  10. }  
3、__ip_local_out函数 [cpp] view plain copy
  1. int __ip_local_out(struct sk_buff *skb)  
  2. {  
  3.     return __ip_local_out_sk(skb->sk, skb);  
  4. }  
4、__ip_local_out_sk函数 [cpp] view plain copy
  1. int __ip_local_out_sk(struct sock *sk, struct sk_buff *skb)  
  2. {  
  3.     struct iphdr *iph = ip_hdr(skb);  
  4.   
  5.     iph->tot_len = htons(skb->len);  
  6.     ip_send_check(iph);     //计算IP层csum值  
  7.     return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, sk, skb, NULL,  //调用netfilter,返回值为1说明允许报文通过,由调用者负责下一步的处理  
  8.                skb_dst(skb)->dev, dst_output_sk);  
  9. }  
5、dst_output_sk函数 [cpp] view plain copy
  1. /* Output packet to network from transport.  */  
  2. static inline int dst_output_sk(struct sock *sk, struct sk_buff *skb)  
  3. {  
  4.     return skb_dst(skb)->output(sk, skb);    //实际调用ip_output函数  
  5. }  
ip_local_out函数,主要实现了如下功能:设置IP头中报文长度信息和csum值; netfilter NF_INET_LOCAL_OUT点的处理。 最后调用ip_outputt函数,进入报文发送的下一个阶段。