int ip_output(struct sk_buff *skb)
{
struct net_device *dev = skb_dst(skb)->dev;
IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len); /*统计发送出去的数据包*/
skb->dev = dev; /*具体选择从哪个网卡设备上发送出去IP报文*/
skb->protocol = htons(ETH_P_IP); /* 指定报文类型为IP packet. */
return NF_HOOK_COND(PF_INET, NF_INET_POST_ROUTING, skb, NULL, dev,
ip_finish_output,
!(IPCB(skb)->flags & IPSKB_REROUTED)); //HOOK点 POST_ROUTING.
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/*
发送一个IP层的数据包.
*/
static int ip_finish_output(struct sk_buff *skb)
{
#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
/* Policy lookup after SNAT yielded a new policy */
if (skb_dst(skb)->xfrm != NULL) {
IPCB(skb)->flags |= IPSKB_REROUTED;
return dst_output(skb);
}
#endif
if (skb->len > ip_skb_dst_mtu(skb) && !skb_is_gso(skb)) /* 判定需要分段,具体过程:http://blog.csdn.net/opens_tym/article/details/17658569 */
return ip_fragment(skb, ip_finish_output2);
else
return ip_finish_output2(skb);
}
阅读(3213) | 评论(0) | 转发(0) |