ip_rcv_finish

ip_rcv() --> ip_rcv_finish() 

    ip_rcv_finish()在完成包接收后进行路由处理
    The function ip_route_input() is invoked within ip_rcv_finish(skb) to determine the route of a packet. The skb->dst pointer of the socket buffer is set to an entry in the routing cache, which stores not only the destination on the IP level, but also a pointer to an entry in the hard header cache (cache for layer-2 frame packet headers), if present. If ip_route_input() cannot find a route, then the packet is discarded. 

    In the next step, ip_rcv_finish() checks for whether the IP packet header includes options. If this is the case, then the options are analyzed, and an ip_options structure is created. All options set are stored in this structure in an efficient form.

    dst_input()
    Finally in ip_rcv_finish(), the procedure of the IP protocol reaches the junction between packets addressed to the local computer and packets to be forwarded. The information about the further path of an IP packet is stored in the routing entry skb->dst. Notice that a trick often used in the Linux kernel is used here. If a switch (variable value) is used to select different functions, then we simply insert a pointer to each of these functions. This saves us an if or switch instruction for each decision of how the program should continue. In the example used here, the pointer skb->dst->input() points to the function that should be used to handle a packet further:
    (1)  ip_local_deliver() is entered in the case of unicast and multicast packets that should be delivered to the local computer.
    (2)  ip_forward()       handles all unicast packets that should be forwarded.
    (3) ip_mr_input()      is used for multicast packets that should be forwarded.

    We can see from the above discussion that a packet can take different paths. The following section describes how packets to be forwarded are handled (skb->dst->input = ip_forward). Subsequently, we will see how skb->dst->input = ip_local_deliver handles packets to be delivery locally.

/usr/src/linux-2.6.19/net/ipv4/ip_input.c

static inline int ip_rcv_finish(struct sk_buff *skb)
{
    struct iphdr *iph = skb->nh.iph;
    if (skb->dst == NULL) {
        int err =  ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
                     skb->dev);
        if (unlikely(err)) {
            if (err == -EHOSTUNREACH)
                IP_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
            goto drop;
        }
    }

#ifdef CONFIG_NET_CLS_ROUTE
    if (unlikely(skb->dst->tclassid)) {
        struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
        u32 idx = skb->dst->tclassid;
        st[idx&0xFF].o_packets++;
        st[idx&0xFF].o_bytes+=skb->len;
        st[(idx>>16)&0xFF].i_packets++;
        st[(idx>>16)&0xFF].i_bytes+=skb->len;
    }
#endif

    if (iph->ihl > 5 && ip_rcv_options(skb))
        goto drop;
    return  dst_input(skb);

drop:
    kfree_skb(skb);
    return NET_RX_DROP;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值