// sk->sk_dst_cache存储路由信息 -- 抵达目的地的路径
static inline void
__sk_dst_set(struct sock *sk, struct dst_entry *dst)
{
struct dst_entry *old_dst;
old_dst = sk->sk_dst_cache;
sk->sk_dst_cache = dst;
dst_release(old_dst);
}
static inline void
sk_dst_set(struct sock *sk, struct dst_entry *dst)
{
write_lock(&sk->sk_dst_lock);
__sk_dst_set(sk, dst);
write_unlock(&sk->sk_dst_lock);
}
// return sock->sk_dst_cache, 有效则返回,无效则返回null
static inline struct dst_entry *
__sk_dst_check(struct sock *sk, u32 cookie)
{
struct dst_entry *dst = sk->sk_dst_cache;
if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
sk->sk_dst_cache = NULL;
dst_release(dst);
return NULL;
}
return dst;
}
转发包,没有socket字段相关联
socket的选项信息,存放在inet_sock->opt字段中,因为选项通常是相同的,所以无需在skbuff中,特意创建字段
替每个封包重建选项信息,太浪费性能了
在sock和skb_buff中,都有路由信息 即sock->sk_dst_cache 和 skb->dst
ip_queue_xmit中路由相关的处理逻辑:
如果skb中已经包含路由信息,直接跳出;
如果skb中没有路由信息,而sock中的路由信息是有效的,则将sock中的信息,复制到skb中;
即:
rt = sk_dst_check(sk, 0);
skb->dst = dst_clone(&rt->u.dst);
如果sock中的路径也是无效的,则使用路由子系统,查找新的路径,给skb使用,调用的函数为 ip_route_output_flow.
最简单的情况下,直接将inet->daddr设置为DIP即可,在有source route选项是,会有特殊处理,代码没有细看 。