ip_rcv_finish()函数的主要工作:
- 决定报文是否必须本地传递或者转发。就第二种而言,则必须找到出口设备和下个跳点
- 分析处理一些IP选项。并不是所有选项都在此处处理。
int con_ip_rcv_finish(struct sk_buff *skb)
{struct iphdr *iph = skb->nh.iph;u16 status_ext = 0;u32 sessfw = 0;u32 tunnel_tcpmss = 0;/** Initialise the virtual path cache for the packet. It describes* how the packet travels inside Linux networking.*/if (skb->dst == NULL) {int err = 1;struct hsf_rt_entry rt = {0};if(g_session_forward_enable){
#ifdef CONFIG_NETSESSIONif (NSINFO2DIR(skb->nsinfo) == NS_DIR_ORIGINAL){status_ext = NS_SESSION_FORWARD_ORIGINAL;}else{status_ext = NS_SESSION_FORWARD_REPLY;}if (ns &&(ns_test_bit_u16(status_ext, ns->status_ext)) &&!ns_is_vpn_ipsec(skb) && !ns_master_is_vpn_ipsec(skb) &&!test_bit(NS_LOCAL_BIT, &(ns->status)) &&(!(ns->status & NS_SLB_RS_COUNT_MASK) || adx_ns_session_forward_proc(ns->vs_index))&&((!(ns->status & NS_CONFIRMED)) || ns_if_magic_equal(&(ns->ff_info[NS_DIR_ORIGINAL])))&& (!(skb->service_flags & SKB_SERVICE_FLAG_VXLAN_LOCAL_DELIVER))){err = 0;sessfw = 1;goto route_label;}
#endif}if (0 != err){err = con_ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, skb->dev, &rt);}if(KERN_HSF_ROUTE_FORWARD == err){
#ifdef CONFIG_NETSESSIONif (skb->ns && SESSFW_OK(skb->dev) && (NSINFO2DIR(skb->nsinfo) == NS_DIR_ORIGINAL) &&!ns_is_vpn_ipsec(skb) && !ns_master_is_vpn_ipsec(skb) &&!(skb->service_flags & SKB_SERVICE_FLAG_IPSEC_DECRYPT)&& (!(skb->service_flags & SKB_SERVICE_FLAG_VXLAN_LOCAL_DELIVER))){ns_session_forward_fix_data(skb, ns);}
#endiferr = kern_hsf_ip_forward(skb,&rt);if(err){//printk("forward faild\n");}return err;}route_label:if (unlikely(err)) {if (err == -EHOSTUNREACH)IP_INC_STATS_BH(dev_net(skb->dev), IPSTATS_MIB_INADDRERRORS);krl_counter_inc(krl_ipt_route_hook);packet_monitor_drop(skb, "Route failed");SNIFFER_PACKET(SNIFFER_MODULE_DROP, skb, SNIFFER_DROP_ROUTE_FAILED);goto drop;}}if (iph->ihl > 5 && ip_rcv_options(skb)){goto drop;}#ifdef CONFIG_NETSESSIONif(skb->service_flags & SKB_SERVICE_FLAG_IPSEC_DECRYPT && skb->ns){ns->ifindex = skb->dev->ifindex;}
#endifif (g_session_forward_enable && unlikely(sessfw)){s32 ret;ret = session_forward_fix[ns_mode](skb);if (ret != 2)return ret;else if (skb->dst != NULL)return dst_input(skb);/* 没匹配上会话转发 */elsegoto drop;}else{if (skb->dst)return dst_input(skb);elsereturn ip_local_inject_deliver(skb);}drop:kfree_skb(skb);return NET_RX_DROP;
}