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); }
http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!!
但行好事 莫问前程
--身高体重180的胖子

浙公网安备 33010602011771号