SKB路由缓存与SOCK路由缓存1
发送tcp报文时:
nc 10.10.10.2 80
tcp_v4_connect
1.1--->ip_route_connect
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) {//发包的时候, 制定dst ip;但是src ip没有指定。 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);// 使用路由的daddr saddr } security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); return ip_route_output_flow(net, fl4, sk); 然后重新查找路由 }
static inline struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp)--->return ip_route_output_key_hash(net, flp, NULL);
struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *fl4, const struct sk_buff *skb) { __u8 tos = RT_FL_TOS(fl4); struct fib_result res = { .type = RTN_UNSPEC, .fi = NULL, .table = NULL, .tclassid = 0, }; struct rtable *rth; fl4->flowi4_iif = LOOPBACK_IFINDEX; fl4->flowi4_tos = tos & IPTOS_RT_MASK; fl4->flowi4_scope = ((tos & RTO_ONLINK) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); rcu_read_lock(); rth = ip_route_output_key_hash_rcu(net, fl4, &res, skb); rcu_read_unlock(); return rth; }
可以看出:ip_route_connect 一开始只指定了dst ip;但是src ip为空,所以会去查找路由。获取源ip;
在获取到src ip后;会重新路由;重新路由的时候,明显会调用如下逻辑创建route
1.2 ---->sk_setup_caps(sk, &rt->dst);--->sk_dst_set(sk, dst);也就是:设置SOCK路由缓存
1.3 设置路由缓存
int __ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, __u8 tos) { struct inet_sock *inet = inet_sk(sk); struct net *net = sock_net(sk); rt = skb_rtable(skb); if (rt) goto packet_routed; /* Make sure we can route this packet. * 如果输出该数据包的传输控制块中 * 缓存了输出路由缓存项,则需检测 * 该路由缓存项是否过期。 * 如果过期,重新通过输出网络设备、 * 目的地址、源地址等信息查找输出 * 路由缓存项。如果查找到对应的路 * 由缓存项,则将其缓存到传输控制 * 块中,否则丢弃该数据包。 * 如果未过期,则直接使用缓存在 * 传输控制块中的路由缓存项*/ rt = (struct rtable *)__sk_dst_check(sk, 0); if (!rt) { __be32 daddr; /* Use correct destination address if we have options. */ daddr = inet->inet_daddr; if (inet_opt && inet_opt->opt.srr) daddr = inet_opt->opt.faddr; sk_setup_caps(sk, &rt->dst); } skb_dst_set_noref(skb, &rt->dst);/* 将路由设置到skb中 */
packet_routed:
首先查找SKB路由缓,没有在查找sk 缓存,通设置到skb路由缓存中;
如果sk 缓存 skb缓存都为null;则重新路由;然后设置到sk 以及skb 路由缓存中
http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!!
但行好事 莫问前程
--身高体重180的胖子