tcp v4 connect 三次路由查找 route

 https://www.cnblogs.com/codestack/p/12629487.html

tcp_v4_connect调用栈如下

rt = ip_route_connect(fl4, nexthop, inet->inet_saddr,
                  RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
                  IPPROTO_TCP,
                  orig_sport, orig_dport, sk);
rt = ip_route_newports(fl4, rt, orig_sport, orig_dport,
                   inet->inet_sport, inet->inet_dport, sk);
static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
                          __be32 dst, __be32 src, u32 tos,
                          int oif, u8 protocol,
                          __be16 sport, __be16 dport,
                          struct sock *sk)
{
    struct net *net = sock_net(sk);
    struct rtable *rt;

    ip_route_connect_init(fl4, dst, src, tos, oif, protocol,
                  sport, dport, sk);

    if (!dst || !src) {
        rt = __ip_route_output_key(net, fl4); 
        if (IS_ERR(rt))
            return rt;
        ip_rt_put(rt);
        flowi4_update_output(fl4, oif, tos, fl4->daddr, fl4->saddr);
    }
    security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
    return ip_route_output_flow(net, fl4, sk);
}

 可知:如果源srcip为0

则会调用三次路由查找

1、第一次saddr 0---- >ip_route_connect---->__ip_route_output_key(net, fl4); 

2、第二次saddr 和 daddr 都知道 ---->ip_route_connect--->ip_route_output_flow(net, fl4, sk);

3、由于src port不知道再次查找路由 ---->ip_route_newports

 

但是里有个很坑的逻辑:在fib_select_path 选择下一条的时候,可能会出现第一次路由选择A,第二次路由选择B

void fib_select_path(struct net *net, struct fib_result *res,
             struct flowi4 *fl4, const struct sk_buff *skb)
{
    if (fl4->flowi4_oif)
        goto check_saddr;

#ifdef CONFIG_IP_ROUTE_MULTIPATH
    if (fib_info_num_path(res->fi) > 1) {
        int h = fib_multipath_hash(net, fl4, skb, NULL);

        fib_select_multipath(res, h);
    }
    else
#endif
    if (!res->prefixlen &&
        res->table->tb_num_default > 1 &&
        res->type == RTN_UNICAST)
        fib_select_default(fl4, res);

check_saddr:
    if (!fl4->saddr)
        fl4->saddr = fib_result_prefsrc(net, res);
}

也就是hash的时候int h = fib_multipath_hash(net, fl4, skb, NULL);可能选择不同的nexthop

 

posted @ 2020-01-06 22:17  codestacklinuxer  阅读(360)  评论(0)    收藏  举报