- 浏览: 1403610 次
- 性别:
- 来自: 火星
文章分类
最新评论
-
aidd:
内核处理time_wait状态详解 -
ahtest:
赞一下~~
一个简单的ruby Metaprogram的例子 -
itiProCareer:
简直胡说八道,误人子弟啊。。。。谁告诉你 Ruby 1.9 ...
ruby中的类变量与类实例变量 -
dear531:
还得补充一句,惊群了之后,数据打印显示,只有一个子线程继续接受 ...
linux已经不存在惊群现象 -
dear531:
我用select试验了,用的ubuntu12.10,内核3.5 ...
linux已经不存在惊群现象
首先来看一下基于3层的ipv4以及ipv6实现的一些4层的协议:
这里要注意并没有IGMPV6,这是因为在ipv6中,它是作为iCMPv6的一部分实现的.
首先我们要知道输入数据包的ip头中的protocol域标识了,将要传递的4层协议.
我们这里主要介绍的是ip数据包从3层传递到4层的接口(也就是输入帧接口).而输出帧的处理,我前面的blog都已经有介绍,想了解的话,可以去看前面的blog.
先来看主要的数据结构,然后我们会分析ip_local_deliver_finish函数(也就是3层处理的出口函数).
在内核中,每一个4层协议都是一个net_protocol结构体,而内核会在启动的时候将所有的4层协议都注册到一个数组inet_protos中,然后根据数据包的ip头来得到相应的handle函数:
L4的协议都是在linux/in.h这个文件中,都是以IPPROTO开头的一些宏.由于ip头中的4层协议域是8位,因此4层协议的最大数值也就是255.而在内核中,255是raw ip, IPPPROTO_RAW:
这里要上面列出的协议,并不是所有的都在内核态handle的,其中一些经常在用户态handle的例如(IPPROTO_RSVP).
内核是通过inet_add_protocol来添加协议到inet_protos数组中的,相应的还有一个删除方法,我们先来看inet_protos的结构:
这里要注意的就是读写inet_protos时,使用的是自旋锁,而只读时,使用的是RCU(Read-Copy Update).
然后来看inet_add_protocol的源码:
然后这些协议的注册都是在内核boot的时候在inet_init中初始化的,下面就是inet_init的代码片段.:
知道协议如何注册之后,我们来分析ip_local_deliver_finish函数,来看3层是如何将数据包发送到4层的.
1 我们知道linux支持raw数据包的发送,因此在这里会对raw socket进行了特殊处理,它会clone一份数据包然后传递给相应的raw处理函数,然后再继续后面的处理.
2 ipsec.这时还需要加上相应的ipsec头,然后再传给4层处理.看下面的图:
最后来看一下raw socket的处理,通过上面我们知道,会调用raw_local_deliver来进行raw socket的相关处理(如果没有raw socket,则会直接返回):
当应用程序使用raw ip socket,他只需要攒递给内核协议id(4层的协议),以及目的地址.因此这里存取sock的hash表使用的key就是4层协议id.
这里要注意并没有IGMPV6,这是因为在ipv6中,它是作为iCMPv6的一部分实现的.
首先我们要知道输入数据包的ip头中的protocol域标识了,将要传递的4层协议.
我们这里主要介绍的是ip数据包从3层传递到4层的接口(也就是输入帧接口).而输出帧的处理,我前面的blog都已经有介绍,想了解的话,可以去看前面的blog.
先来看主要的数据结构,然后我们会分析ip_local_deliver_finish函数(也就是3层处理的出口函数).
在内核中,每一个4层协议都是一个net_protocol结构体,而内核会在启动的时候将所有的4层协议都注册到一个数组inet_protos中,然后根据数据包的ip头来得到相应的handle函数:
struct net_protocol { ///协议的处理函数,也就是将要处理输入数据报的4层协议的处理函数. int (*handler)(struct sk_buff *skb); ///协议的错误处理函数. void (*err_handler)(struct sk_buff *skb, u32 info); ///gso相关的两个函数. int (*gso_send_check)(struct sk_buff *skb); struct sk_buff *(*gso_segment)(struct sk_buff *skb, int features); ///主要是被ipsec所使用的两个域 unsigned int no_policy:1, netns_ok:1; };
L4的协议都是在linux/in.h这个文件中,都是以IPPROTO开头的一些宏.由于ip头中的4层协议域是8位,因此4层协议的最大数值也就是255.而在内核中,255是raw ip, IPPPROTO_RAW:
enum { IPPROTO_IP = 0, /* Dummy protocol for TCP */ IPPROTO_ICMP = 1, /* Internet Control Message Protocol */ IPPROTO_IGMP = 2, /* Internet Group Management Protocol */ IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */ IPPROTO_TCP = 6, /* Transmission Control Protocol */ IPPROTO_EGP = 8, /* Exterior Gateway Protocol */ IPPROTO_PUP = 12, /* PUP protocol */ IPPROTO_UDP = 17, /* User Datagram Protocol */ IPPROTO_IDP = 22, /* XNS IDP protocol */ IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol */ IPPROTO_RSVP = 46, /* RSVP protocol */ IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */ IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */ IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */ IPPROTO_AH = 51, /* Authentication Header protocol */ IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET */ IPPROTO_PIM = 103, /* Protocol Independent Multicast */ IPPROTO_COMP = 108, /* Compression Header protocol */ IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */ IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */ IPPROTO_RAW = 255, /* Raw IP packets */ IPPROTO_MAX };
这里要上面列出的协议,并不是所有的都在内核态handle的,其中一些经常在用户态handle的例如(IPPROTO_RSVP).
内核是通过inet_add_protocol来添加协议到inet_protos数组中的,相应的还有一个删除方法,我们先来看inet_protos的结构:
这里要注意的就是读写inet_protos时,使用的是自旋锁,而只读时,使用的是RCU(Read-Copy Update).
然后来看inet_add_protocol的源码:
struct net_protocol *inet_protos[MAX_INET_PROTOS] ____cacheline_aligned_in_smp; ///这里只是举两个例子,tcp和udp的协议注册函数.我们这次暂时就不分析tcp和udp的处理函数了(我会在3层结束后,分析4层源码) static struct net_protocol tcp_protocol = { .handler = tcp_v4_rcv, .err_handler = tcp_v4_err, .gso_send_check = tcp_v4_gso_send_check, .gso_segment = tcp_tso_segment, .no_policy = 1, .netns_ok = 1, }; static struct net_protocol udp_protocol = { .handler = udp_rcv, .err_handler = udp_err, .no_policy = 1, .netns_ok = 1, }; int inet_add_protocol(struct net_protocol *prot, unsigned char protocol) { int hash, ret; ///计算当前协议在数组中的slot. hash = protocol & (MAX_INET_PROTOS - 1); ///使用自旋锁. spin_lock_bh(&inet_proto_lock); if (inet_protos[hash]) { ret = -1; } else { ///将相应的prot添加到数组 inet_protos[hash] = prot; ret = 0; } spin_unlock_bh(&inet_proto_lock); return ret; }
然后这些协议的注册都是在内核boot的时候在inet_init中初始化的,下面就是inet_init的代码片段.:
static int __init inet_init(void) { ........................................... /* * Add all the base protocols. */ if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0) printk(KERN_CRIT "inet_init: Cannot add ICMP protocol\n"); if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0) printk(KERN_CRIT "inet_init: Cannot add UDP protocol\n"); if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0) printk(KERN_CRIT "inet_init: Cannot add TCP protocol\n"); #ifdef CONFIG_IP_MULTICAST if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0) printk(KERN_CRIT "inet_init: Cannot add IGMP protocol\n"); #endif .................................. }
知道协议如何注册之后,我们来分析ip_local_deliver_finish函数,来看3层是如何将数据包发送到4层的.
1 我们知道linux支持raw数据包的发送,因此在这里会对raw socket进行了特殊处理,它会clone一份数据包然后传递给相应的raw处理函数,然后再继续后面的处理.
2 ipsec.这时还需要加上相应的ipsec头,然后再传给4层处理.看下面的图:
static int ip_local_deliver_finish(struct sk_buff *skb) { ///取出相应的net信息. struct net *net = dev_net(skb->dev); ///下面两个主要是调整data指针,使data指针指向4层的数据开始处. __skb_pull(skb, ip_hdrlen(skb)); skb_reset_transport_header(skb); ///加rcu锁. rcu_read_lock(); { ///取出ip头中的协议. int protocol = ip_hdr(skb)->protocol; int hash, raw; struct net_protocol *ipprot; resubmit: ///得到raw socket, 如果不是raw socket,则返回0. raw = raw_local_deliver(skb, protocol); ///计算4层协议的slot. hash = protocol & (MAX_INET_PROTOS - 1); ///rcu读取相应的协议处理结构. ipprot = rcu_dereference(inet_protos[hash]); ///主要是ipprot是否有被当前主机注册. if (ipprot != NULL && (net == &init_net || ipprot->netns_ok)) { int ret; ///判断ipsec,并进行相关处理. if (!ipprot->no_policy) { if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { kfree_skb(skb); goto out; } nf_reset(skb); } ///调用handler,进入相应的4层协议的处理. ret = ipprot->handler(skb); if (ret < 0) { protocol = -ret; goto resubmit; } IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS); } ................................................ out: rcu_read_unlock(); return 0; }
最后来看一下raw socket的处理,通过上面我们知道,会调用raw_local_deliver来进行raw socket的相关处理(如果没有raw socket,则会直接返回):
当应用程序使用raw ip socket,他只需要攒递给内核协议id(4层的协议),以及目的地址.因此这里存取sock的hash表使用的key就是4层协议id.
///相应的hash表,保存raw socket. struct raw_hashinfo { rwlock_t lock; struct hlist_head ht[RAW_HTABLE_SIZE]; }; static struct raw_hashinfo raw_v4_hashinfo = { .lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock), }; int raw_local_deliver(struct sk_buff *skb, int protocol) { int hash; struct sock *raw_sk; ///通过协议计算hash值(使用4层协议id). hash = protocol & (RAW_HTABLE_SIZE - 1); ///得到相应的raw_sk. raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); /* If there maybe a raw socket we must check - if not we * don't care less */ ///交给raw socket的处理函数,raw_v4_input中会clone一个skb,然后交给最后的raw_rev函数去处理最终的数据包. if (raw_sk && !raw_v4_input(skb, ip_hdr(skb), hash)) raw_sk = NULL; return raw_sk != NULL; }
发表评论
-
Receive packet steering patch详解
2010-07-25 16:46 12156Receive packet steering简称rp ... -
内核中拥塞窗口初始值对http性能的影响分析
2010-07-11 00:20 9708这个是google的人提出的 ... -
linux 内核tcp拥塞处理(一)
2010-03-12 16:17 9579这次我们来分析tcp的拥塞控制,我们要知道协议栈都是很保守的, ... -
内核tcp协议栈SACK的处理
2010-01-24 21:13 12185上一篇处理ack的blog中我 ... -
内核tcp的ack的处理
2010-01-17 03:06 11163我们来看tcp输入对于ack,段的处理。 先是ack的处理, ... -
内核处理time_wait状态详解
2010-01-10 17:39 6822这次来详细看内核的time_wait状态的实现,在前面介绍定时 ... -
tcp协议栈处理各种事件的分析
2009-12-30 01:29 13638首先我们来看socket如何将一些状态的变化通知给对应的进程, ... -
linux内核sk_buff的结构分析
2009-12-25 00:42 47921我看的内核版本是2.6.32. 在内核中sk_buff表示一 ... -
tcp的输入段的处理
2009-12-18 00:56 8362tcp是全双工的协议,因此每一端都会有流控。一个tcp段有可能 ... -
内核协议栈tcp层的内存管理
2009-11-28 17:13 12089我们先来看tcp内存管理相关的几个内核参数,这些都能通过pro ... -
linux内核定时器的实现
2009-10-31 01:44 10197由于linux还不是一个实时的操作系统,因此如果需要更高精度, ... -
linux内核中tcp连接的断开处理
2009-10-25 21:47 10342我们这次主要来分析相关的两个断开函数close和shotdow ... -
linux内核tcp的定时器管理(二)
2009-10-05 20:52 5432这次我们来看后面的3个定时器; 首先是keep alive定 ... -
linux内核tcp的定时器管理(一)
2009-10-04 23:29 9837在内核中tcp协议栈有6种 ... -
linux 内核tcp接收数据的实现
2009-09-26 20:24 14529相比于发送数据,接收数据更复杂一些。接收数据这里和3层的接口是 ... -
linux 内核tcp数据发送的实现
2009-09-10 01:41 19795在分析之前先来看下SO_RCVTIMEO和SO_SNDTIME ... -
tcp connection setup的实现(三)
2009-09-03 00:34 5206先来看下accept的实现. 其实accept的作用很简单, ... -
tcp connection setup的实现(二)
2009-09-01 00:46 8439首先来看下内核如何处理3次握手的半连接队列和accept队列( ... -
tcp connection setup的实现(一)
2009-08-23 04:10 5827bind的实现: 先来介绍几个地址结构. struct ... -
linux内核中socket的实现
2009-08-15 04:38 21110首先来看整个与socket相关的操作提供了一个统一的接口sys ...
相关推荐
标题中的“IP包流量分析WINPCAP实现”指的是利用WINPCAP库进行网络数据包捕获和流量分析的技术。WINPCAP(Windows Packet Capture)是一个开源的、系统级的网络数据包过滤和分析库,主要在Windows操作系统上使用。它...
Java 实现 IP 数据包分析是一项涉及网络编程与协议解析的技术工作。在 Java 中,我们可以使用 `java.net` 包中的 Socket 和 Datagram 类来处理网络通信,但这些类并不直接支持 IP 层的数据包操作。因此,要进行 IP ...
2. 配置SVI接口的IP地址和子网掩码: ```plaintext Cisco3550(config-if)#ip address 192.168.1.1 255.255.255.0 ``` 3. 启用该接口: ```plaintext Cisco3550(config-if)#no shutdown ``` 4. 返回到全局...
【IP包流量分析程序的设计与实现】 ...总的来说,设计和实现一个IP包流量分析程序是理解和优化网络性能的关键步骤。通过Java这样的高级编程语言,我们可以构建出强大且灵活的工具,以应对不断变化的网络环境和需求。
这需要理解IP地址和网络接口层的工作原理。本地地址通常指的是本机的IP地址,分析这些包有助于我们了解本地计算机与其他设备之间的通信情况。开发者可能使用了IP头信息来判断数据包的源或目标地址。 然后,“解析其...
本文将深入探讨“网路岗7-IP报文分析工具”这一专业工具,它主要用于分析TCP/IP协议,帮助用户实现协议解析与监听。 首先,我们要了解TCP/IP协议族。TCP/IP(Transmission Control Protocol/Internet Protocol)是...
本文将深入探讨如何利用Java编程语言实现对IP和TCP协议数据包的拦截与分析,以便获取IP地址的详细信息。 首先,我们需要理解IP(Internet Protocol)和TCP(Transmission Control Protocol)的基本概念。IP协议负责...
CUBIC作为Linux默认的拥塞控制算法,它的接口实现和状态处理对于理解Linux的TCP性能至关重要。 释放TCP连接的过程同样复杂。无论是主动关闭还是被动关闭,TCP连接的关闭都需要经过一系列的握手过程,以确保数据的...
4. **网络接口层**: 网络接口层处理硬件层面的通信,如以太网、无线网络等。这部分源码在`net/core/dev.c`和`drivers/net`目录下,实现了驱动程序与协议栈之间的接口。 5. **数据包的收发**: 数据包的接收和...
通过实际操作和观察,我们可以深入理解网络层的工作原理,这对网络管理员、安全分析师和IT专业人士来说都是非常有价值的技能。同时,掌握这些知识也有助于解决网络性能问题和防止潜在的安全威胁。
流量分析则是对这些IP包进行解析和统计的过程,以便获取网络活动的详细信息。 首先,我们需要了解流量分析的基本步骤。这通常包括数据捕获、数据过滤、数据解析和数据分析。数据捕获是使用嗅探器(如Wireshark)等...
4. **网络接口层**:对应OSI模型中的数据链路层和物理层,处理数据的实际发送和接收。 #### 四、OSI与TCP/IP模型之间的关系 1. **概念借鉴**:TCP/IP模型在一定程度上借鉴了OSI模型的概念,如分层思想和服务、接口...
通过研究和分析MPEG4IP源码,开发者不仅可以学习到多媒体编码和解码的基本原理,还能深入了解MPEG-4标准的实现细节。此外,源码中还包含了构建工程文件,这意味着可以直接编译和运行,这对于测试和调试是极其宝贵的...
### 三层交换机实现VLAN之间通信的知识点...通过以上对实训项目的详细介绍和分析,我们可以深入理解三层交换机如何实现VLAN之间的通信,并且掌握具体的配置方法和技术要点。这对于网络工程师来说是一项非常实用的技能。
在IP流量包分析程序中,RAW SOCKET模式至关重要,因为它使得程序可以直接读取和处理IP层的数据,而不是依赖于上层协议的封装。这为深入的流量分析提供了可能,但同时也需要开发者具备更深入的网络协议知识。 在开发...
本主题将深入探讨如何使用C语言来抓取和分析IP数据报的格式。首先,我们来理解IP数据包的基本结构。 IP数据包由两部分组成:头部和数据部分。头部通常包含20到60字节的信息,而数据部分则承载上层协议(如TCP、UDP...
它通过捕获网络接口层的数据包,为开发者、网络安全专家和系统管理员提供深入的网络诊断信息。WinCap(通常指的是Wireshark的前身)是一种强大的网络封包分析软件,它允许我们查看网络上流通的数据包,解析其内容,...
"应用结构和编程接口.rar_TCP/IP协议编程_ip"这个压缩包文件,显然聚焦于TCP/IP协议编程和IP层的理解与应用,特别是从应用层的角度出发。这里我们将深入探讨相关知识点。 首先,TCP/IP协议族是由四层模型构成:应用...