tcp/ip协议栈知识
来源:互联网 发布:linux查询用户密码命令 编辑:程序博客网 时间:2024/05/22 12:46
http://www.eefocus.com/article/09-06/75257s.html:
http://blog.tianya.cn/blogger/post_show.asp?BlogID=643342&PostID=13157890: 两个都是, linux内核网络协议栈的介绍分析,后面这一个写得挺好的。
struct dst_entry:最终生成的IP数据报的路由称为目的入口(dst_entry),目的入口反映了相邻的外部主机在主机内部的一种“映象。
http://www.makefile.net/2013/03/detail-of-dst_entry-struct.html:介绍struct dst_entry 和struct rtable结构体的成员以及一些意义
通过在一张路由表(struct fib_table)中,根据查询路由的目的IP地址(key)在其路由哈希表(struct fn_hash)中找到一个路由域(struct fn_zone),并在路由域中匹配到一个key相等的路由节点(struct fib_node),取其路由别名(struct fib_alias)和路由信息(struct fib_info),生成一个路由查询结果(struct fib_result)。
由查询结果生成struct dst_entry目的入口,再由目的入口生成struct rtable
路由缓存表rt_hash_table是一个很大的数组(依据系统的内存大小而定),每一项都是一个struct rtable
路由可以分为两部分:路由缓存(rt_hash_table)和路由表()。路由表又分为两项RT_TABLE_LOCAL和RT_TABLE_MAIN
RT_TABLE_LOCAL存储目的地址是本机的路由表项,这些目的地址就是为各个网卡配置的IP地址;
RT_TABLE_MAIN存储到其它主机的路由表项;
ip_route_input_slow() -> fib_lookup()是在路由表里查询,ip_route_input里包含一个判断,看是到缓存里查找还是到路由表里查询。如果支持转发,则无论在路由表中找到与否,都会生成这次查询的一个缓存,包括源IP、目的IP、接收的网卡,插入路由缓存中
neighbour_table{ }是一个包含和本机所连接的所有邻元素的信息的数据结构,该结构中有个元素是neighbour结构的数组,数组的每一个元素都是一个对应于邻机的neighbour结构。在neighbour结构中,包含有与该邻居相连的网络接口设备net_device的指针,网络接口的硬件地址,邻居的硬件地址,包含有neigh_ops{}指针,这些函数指针是直接用来连接传输数据的,包含有queue_xmit(struct * sk_buff)函数入口地址,这个函数可能会调用硬件驱动程序的发送函数。
接收不是发给自己的数据包的处理如下:
netif_receive_skb->ip_rcv(如果不是发给自己的,(skb->pkt_type == PACKET_OTHERHOST))-->ip_rcv_finish()在完成包接收后进行路由处理。
ip_rcv_finish包含两个重要的函数:
1、 ip_route_input:determine the route of a packet. The skb->dst pointer of the socket buffer is set to an entry in the routing cache
2、dst_input():the procedure of the IP protocol reaches the junction between packets addressed to the local computer (局域网中的电脑)and packets to be forwarded.是发给局域网中的主机还是转发给外网中的主机。如果是发给局域网内的主机则调用ip_local_deliver,如果发给外面的电脑则调用ip_forward() ,具体调用哪一个是根据放在skb->dst->input里面的。下面是这个函数的具体实现,可以看出,只是调用了skb->dst->input里面保存的函数
static inline int dst_input(struct sk_buff *skb)
{
int err;
for (;;) {
err = skb->dst->input(skb);
if (likely(err == 0))
return err;
if (unlikely(err != NET_XMIT_BYPASS))
return err;
}
}
下面再看看ip_route_input的实现,到路由表里查询:
ip_route_input()==>ip_route_input_slow()
在ip_route_input_slow()中:
if ((err = fib_lookup(&fl, &res)) != 0) {
if (!IN_DEV_FORWARD(in_dev))
goto e_hostunreach;
goto no_route;
}
调用fib_lookup()函数用来在fib中查询路由信息,将路由查询结果保存在fib_result结构的res中。
接下来:
if (res.type == RTN_LOCAL) {
int result;
result = fib_validate_source(saddr, daddr, tos,
loopback_dev.ifindex,
dev, &spec_dst, &itag);
if (result dst->input=ip_local_deliver*/
goto local_input;
}
如果查询的结果显示,路由类型RTN_LOCAL的话,跳转到local_input段,设置skb->dst->input = ip_local_deliver
接下来,路由类型是RTN_LOCAL的已经跳转到下面去了,剩下的就是非LCOAL的,也就是Forward的:
if (!IN_DEV_FORWARD(in_dev))
goto e_hostunreach;
if (res.type != RTN_UNICAST)
goto martian_destination;
/*设置skb->dst->input=ip_forward*/
err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);
调用IN_DEV_FORWARD宏来判断网络设备是否处于FORWARD状态;调用ip_mkroute_input()函数来设置skb->dst->input=ip_forward
http://hi.baidu.com/zengzhaonong/item/e01607b9aafe16eb4ec7fd71:介绍ip_rcv_finish的函数
http://hi.baidu.com/zengzhaonong/item/dff0fc9971c880da7a7f0172:介绍ip_forward的函数
下面看ip_forward的处理
下面一部分转载于http://blog.csdn.net/yming0221/article/details/7979838
struct sock是传输层的套接字,里面包含了一个传输层协议相关的操作集合,如tcp、udp、icmp协议,各协议对应一个不同的协议操作集合,这些操作函数是传输层和网络层交互的接口如下。
struct proto udp_prot:UDP协议操作集
struct proto tcp_prot:tcp协议操作集
struct proto是一个协议操作函数集合,包含了很多的操作函数
BSD层的socket结构体如下:
- struct socket {
- socket_state state;
- kmemcheck_bitfield_begin(type);
- short type;
- kmemcheck_bitfield_end(type);
- unsigned long flags;
- struct socket_wq __rcu *wq;
- struct file *file;
- struct sock *sk;
- const struct proto_ops *ops;
- };
struct proto_ops是inet层的协议操作集。到传输层的入口
UDP协议在INET层操作集是const struct proto_ops inet_dgram_ops
TCP协议z在INET层操作集const struct proto_ops inet_stream_ops
上面结构体里的type包含几个值如下:
- enum sock_type {
- SOCK_DGRAM = 1,
- SOCK_STREAM = 2,
- SOCK_RAW = 3,
- SOCK_RDM = 4,
- SOCK_SEQPACKET = 5,
- SOCK_DCCP = 6,
- SOCK_PACKET = 10,
- };
下面的结构体就是在系统初始化时用来管理协议族初始化的结构体:
- struct net_proto_family {
- int family;
- int (*create)(struct net *net, struct socket *sock,
- int protocol, int kern);
- struct module *owner;
- };
第二个属性就是协议族对应的初始化函数指针;
INET协议族对应该结构的定义如下:
- static const struct net_proto_family inet_family_ops = {
- .family = PF_INET, //协议族
- .create = inet_create, //用来创建套接字的函数指针
- .owner = THIS_MODULE,
- };
创建套接字时,根据不同的协议族来调用不同的创建函数,内核里保存了一个struct net_proto_family结构的数组net_families包含了不同的协议族创建函数.这个数组是用下面的函数一个个初始化的。每个协议都要调用这个函数来注册到系统中。
int sock_register(const struct net_proto_family *ops) { int err; spin_lock(&net_family_lock); ///代码非常简单,就是根据类型,然后放到相应的位置. if (net_families[ops->family]) err = -EEXIST; else { net_families[ops->family] = ops; err = 0; } }
- tcp/ip协议栈知识
- TCP/IP协议相关知识
- 浅谈TCP/IP协议栈(一)入门知识
- TCP/IP协议技术应用知识汇总
- TCP/IP协议模型的相关知识
- TCP/IP协议 I - 初始知识
- TCP/IP协议栈
- TCP/IP协议栈
- TCP/IP 协议栈
- TCP/IP 协议栈
- TCP/IP协议栈
- TCP/IP协议栈
- TCP/IP协议栈
- TCP-IP协议栈
- TCP/IP协议栈
- TCP/IP协议栈
- TCP/IP 协议 ----- 协议栈
- TCP/IP协议栈 之 TCP协议
- mysql中避免重复插入相同数据(insert if not exists)
- php 一个表单有多个按钮,如何判断是哪个按钮提交过来的
- JBPM4---简易的请假实例
- gdb-7.6编译
- vmware 和windows共享文件夹设置
- tcp/ip协议栈知识
- C语言逗号运算符和逗号表达式
- animation实现activity 开启 退出动画.
- 多服务器共享session及session散列存储时的创建目录代码
- 设计模式-05-原型模式
- 仿3D特效查看图片
- Qt学习:QPainter之反走样
- linux下打开windows txt文件中文乱码问题
- Linear Regression 线性回归