tcp 发包时 路由调用

主动发出tcp连接时路由stack

 

 

 如果srcip没有设置;则通过路由查找源ip然后赋值初始化fl4

 最后调用ip_route_output_flow----->__ip_route_output_key  查找路由

查找路由时,由于有sip;所以直接进入一下逻辑

 然后查找rth;

然后初始化flp出口

 如果根据路由查找后的端口有变化;则需要重新路由

static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable *rt,
                           __be16 orig_sport, __be16 orig_dport,
                           __be16 sport, __be16 dport,
                           struct sock *sk)
{
    if (sport != orig_sport || dport != orig_dport) {
        fl4->fl4_dport = dport;
        fl4->fl4_sport = sport;
        ip_rt_put(rt);
        flowi4_update_output(fl4, sk->sk_bound_dev_if,
                     RT_CONN_FLAGS(sk), fl4->daddr,
                     fl4->saddr);
        security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
        return ip_route_output_flow(sock_net(sk), fl4, sk);
    }
    return rt;
}

 

 

 最后封包发送syn

 对于 路由查找:fib_lookup

路由查找

如下内核的路由查询入口函数fib_lookup,可见其查询顺序为:路由策略->main路由表->default路由表。对local路由表的查询包含在main路由表查询中。

 

static inline int fib_lookup(struct net *net, struct flowi4 *flp,
                 struct fib_result *res, unsigned int flags)
{
    struct fib_table *tb;
    int err = -ENETUNREACH;

    flags |= FIB_LOOKUP_NOREF;
    if (net->ipv4.fib_has_custom_rules)
        return __fib_lookup(net, flp, res, flags);

    rcu_read_lock();

    res->tclassid = 0;

    tb = rcu_dereference_rtnl(net->ipv4.fib_main);
    if (tb)
        err = fib_table_lookup(tb, flp, res, flags);

    if (!err)
        goto out;

    tb = rcu_dereference_rtnl(net->ipv4.fib_default);
    if (tb)
        err = fib_table_lookup(tb, flp, res, flags);

out:
    if (err == -EAGAIN)
        err = -ENETUNREACH;

    rcu_read_unlock();

    return err;
}

 

 

Thread 2 hit Breakpoint 6, tcp_v4_connect (sk=0xffff8880041b9a40, uaddr=0xffffc90000273e88, addr_len=16) at net/ipv4/tcp_ipv4.c:199
199    {
(gdb) c
Continuing.

Thread 2 hit Breakpoint 1, ip_route_connect (protocol=<optimized out>, sk=<optimized out>, dport=<optimized out>, sport=<optimized out>, oif=<optimized out>, tos=<optimized out>, src=<optimized out>, dst=<optimized out>, fl4=<optimized out>) at ./include/net/route.h:315
315        ip_route_connect_init(fl4, dst, src, tos, oif, protocol,
(gdb) c
Continuing.

Thread 2 hit Breakpoint 2, 0xffffffff81967c87 in __ip_route_output_key (flp=<optimized out>, net=<optimized out>) at ./include/net/route.h:126
126        return ip_route_output_key_hash(net, flp, NULL);
(gdb) c
Continuing.

Thread 2 hit Breakpoint 7, ip_route_output_key_hash_rcu (net=net@entry=0xffffffff825f5380 <init_net>, fl4=fl4@entry=0xffff8880041b9d98, res=res@entry=0xffffc90000273d38, skb=skb@entry=0x0 <fixed_percpu_data>) at net/ipv4/route.c:2519
2519        int orig_oif = fl4->flowi4_oif;
(gdb) n
2524        if (fl4->saddr) {
(gdb) 
2577        if (fl4->flowi4_oif) {
(gdb) 
2606        if (!fl4->daddr) {
(gdb) 
2617        err = fib_lookup(net, fl4, res, 0);
(gdb) s
fib_lookup (flags=1, res=0xffffc90000273d38, flp=0xffff8880041b9d98, net=0xffffffff825f5380 <init_net>) at ./include/net/ip_fib.h:370
370        if (net->ipv4.fib_has_custom_rules)
(gdb) n
375        res->tclassid = 0;
(gdb) 
377        tb = rcu_dereference_rtnl(net->ipv4.fib_main);
(gdb) 
378        if (tb)
(gdb) 
379            err = fib_table_lookup(tb, flp, res, flags);
(gdb) s
fib_table_lookup (tb=0xffff888004083280, flp=flp@entry=0xffff8880041b9d98, res=res@entry=0xffffc90000273d38, fib_flags=fib_flags@entry=1) at net/ipv4/fib_trie.c:1402
1402        const t_key key = ntohl(flp->daddr);
(gdb) n
1411        n = get_child_rcu(pn, cindex);
(gdb) p /x key
$33 = 0xc0a80280
(gdb) n
1412        if (!n) {
(gdb) 
1423            index = get_cindex(key, n);
(gdb) 
1439            if (index >= (1ul << n->bits))
(gdb) 
1443            if (IS_LEAF(n))
(gdb) 
1449            if (n->slen > n->pos) {
(gdb) 
1455            if (unlikely(!n))
(gdb) 
1491                while (!cindex) {
(gdb) 
1512                cindex &= cindex - 1;
(gdb) 
1515                cptr = &pn->tnode[cindex];
(gdb) 
1480            while ((n = rcu_dereference(*cptr)) == NULL) {
(gdb) n
1468            if (unlikely(prefix_mismatch(key, n)) || (n->slen == n->pos))
(gdb) 
1472            if (unlikely(IS_LEAF(n)))
(gdb) 
1524        hlist_for_each_entry_rcu(fa, &n->leaf, fa_list) {
(gdb) 
1525            struct fib_info *fi = fa->fa_info;
(gdb) 
1530                if (index >= (1ul << fa->fa_slen))
(gdb) 
1524        hlist_for_each_entry_rcu(fa, &n->leaf, fa_list) {
(gdb) 
1525            struct fib_info *fi = fa->fa_info;
(gdb) 
1530                if (index >= (1ul << fa->fa_slen))
(gdb) 
1533            if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
(gdb) 
1535            if (fi->fib_dead)
(gdb) 
1537            if (fa->fa_info->fib_scope < flp->flowi4_scope)
(gdb) 
1539            fib_alias_accessed(fa);
(gdb) 
1540            err = fib_props[fa->fa_type].error;
(gdb) 
1541            if (unlikely(err < 0)) {
(gdb) 
1549            if (fi->fib_flags & RTNH_F_DEAD)
(gdb) 
1552            if (unlikely(fi->nh)) {
(gdb) 
1565            for (nhsel = 0; nhsel < fib_info_num_path(fi); nhsel++) {
(gdb) 
1566                nhc = fib_info_nhc(fi, nhsel);
(gdb) 
1568                if (!fib_lookup_good_nhc(nhc, fib_flags, flp))
(gdb) 
1571                if (!(fib_flags & FIB_LOOKUP_NOREF))
(gdb) 
1574                res->prefix = htonl(n->key);
(gdb) 
1575                res->prefixlen = KEYLENGTH - fa->fa_slen;
(gdb) 
1576                res->nh_sel = nhsel;
(gdb) 
1578                res->type = fa->fa_type;
(gdb) 
1579                res->scope = fi->fib_scope;
(gdb) 
1581                res->table = tb;
(gdb) 
1582                res->fa_head = &n->leaf;
(gdb) 
1586                trace_fib_table_lookup(tb->tb_id, flp, nhc, err);
(gdb) p /x res
$34 = 0xffffc90000273d38
(gdb) p /x *res
$35 = {
  prefix = 0x2a8c0,
  prefixlen = 0x18,
  nh_sel = 0x0,
  type = 0x1,
  scope = 0xfd,
  tclassid = 0x0,
  nhc = 0xffff8880040a5380,
  fi = 0xffff8880040a5300,
  table = 0xffff888004083280,
  fa_head = 0xffff888003cd0508
}

由于没有设置pbr,所以直接到fib_main 查询

tb = rcu_dereference_rtnl(net->ipv4.fib_main);
    if (tb)
        err = fib_table_lookup(tb, flp, res, flags);

如果设置pbr;则会遍历所有rulelist;在初始化的时候会将main local等table挂在在rule-list上

 

由函数fib_insert_alias可知,在trie树叶子节点中,路由表项时按照表ID由大到小排列的,如果local和main表中存在相同的路由,优先选择的是local表中的路由,宏RT_TABLE_LOCAL(255)大于RT_TABLE_MAIN(254)。

static int fib_insert_alias(struct trie *t, struct key_vector *tp,
                struct key_vector *l, struct fib_alias *new, struct fib_alias *fa, t_key key)
{
    if (!l)
        return fib_insert_node(t, tp, new, key);

    if (fa) {
        hlist_add_before_rcu(&new->fa_list, &fa->fa_list);
    } else {
        struct fib_alias *last;

        hlist_for_each_entry(last, &l->leaf, fa_list) {
            if (new->fa_slen < last->fa_slen)
                break;
            if ((new->fa_slen == last->fa_slen) &&
                (new->tb_id > last->tb_id))
                break;
            fa = last;
        }

        if (fa)
            hlist_add_behind_rcu(&new->fa_list, &fa->fa_list);
        else
            hlist_add_head_rcu(&new->fa_list, &l->leaf);
    }

 

posted @ 2024-10-13 15:42  codestacklinuxer  阅读(27)  评论(0)    收藏  举报