ip_rcv_finish() --> ip_route_input()
ip_route_input()给进来的包skb查找路由,现在缓冲区的路由hash表中查找,如果没找到,在调用ip_route_input_slow()到路由表中查找。
The function ip_route_input() is invoked for each IP packet arriving over a network interface. The parameters are a pointer to the socket-buffer structure, the destination and source addresses, the TOS value, and a pointer to the net_device structure of the receiving network interface.
First, rt_hash() is used on the addresses and the TOS value to compute an index in the hash table of the routing cache. If necessary, the list anchored in the chain element is walked through to find a cache entry matching addresses, input interface, TOS value, and fwmark, if present. If this search is successful, then a pointer to the entry is placed as dst in the sk_buff structure, and the task is complete.
If no matching cache entry is found, then either of the two following functions is responsible for further handling:
ip_route_input_mc() is invoked if the destination address is a multicast address. Another prerequisite is that the input interface either belongs to that multicast group or has been configured for multicast routing. The packet can be discarded if this is not the case. What is done there is similar to the procedure for local-destination addresses described below, the only difference being that the packet is always delivered to the local machine rather than causing an FIB query.
ip_route_input_slow() serves to handle "normal" destination addresses.
/usr/src/linux-2.6.19/net/ipv4/route.c
int
ip_route_input(struct
sk_buff *skb, __be32 daddr, __be32 saddr,
u8 tos, struct
net_device *dev)
{
struct
rtable * rth;
unsigned hash;
int iif = dev->ifindex;
tos &= IPTOS_RT_MASK;
hash =
rt_hash(daddr, saddr, iif);
rcu_read_lock();
for (rth = rcu_dereference(
rt_hash_table[hash].chain); rth;
rth = rcu_dereference(rth->u.rt_next)) {
if (rth->fl.fl4_dst == daddr &&
rth->fl.fl4_src == saddr &&
rth->fl.iif == iif &&
rth->fl.oif == 0 &&
#ifdef CONFIG_IP_ROUTE_FWMARK
rth->fl.fl4_fwmark == skb->nfmark &&
#endif
rth->fl.fl4_tos == tos) {
rth->u.dst.lastuse = jiffies;
dst_hold(&rth->u.dst);
rth->u.dst.__use++;
RT_CACHE_STAT_INC(in_hit);
rcu_read_unlock();
skb->dst = (struct dst_entry*)rth;
return 0;
}
RT_CACHE_STAT_INC(in_hlist_search);
}
rcu_read_unlock();
if (MULTICAST(daddr)) {
struct
in_device *in_dev;
rcu_read_lock();
if ((in_dev = __in_dev_get_rcu(dev)) != NULL) {
int our = ip_check_mc(in_dev, daddr, saddr,
skb->nh.iph->protocol);
if (our
#ifdef CONFIG_IP_MROUTE
|| (!LOCAL_MCAST(daddr) && IN_DEV_MFORWARD(in_dev))
#endif
) {
rcu_read_unlock();
return
ip_route_input_mc(skb, daddr, saddr,
tos, dev, our);
}
}
rcu_read_unlock();
return -EINVAL;
}
return
ip_route_input_slow(skb, daddr, saddr, tos, dev);
}
ip_route_input() -- IP路由(输入路由)
最新推荐文章于 2024-08-24 14:00:00 发布