- 浏览: 1407254 次
- 性别:
- 来自: 火星
-
最新评论
-
aidd:
内核处理time_wait状态详解 -
ahtest:
赞一下~~
一个简单的ruby Metaprogram的例子 -
itiProCareer:
简直胡说八道,误人子弟啊。。。。谁告诉你 Ruby 1.9 ...
ruby中的类变量与类实例变量 -
dear531:
还得补充一句,惊群了之后,数据打印显示,只有一个子线程继续接受 ...
linux已经不存在惊群现象 -
dear531:
我用select试验了,用的ubuntu12.10,内核3.5 ...
linux已经不存在惊群现象
文章列表
这次主要介绍的是ip层的切片与组包的实现。
首先来看一下分片好的帧的一些概念:
1 第一个帧的offset位非0并且MF位为1
2 所有的在第一个帧和最后一个帧之间的帧都拥有长度大于0的域
3 最后一个帧MF位为0 并且offset位非0。(这样就能判断是否是最后一个帧了).
这里要注意在linux中,ip头的frag_off域包含了 rfcip头的定义中的nf,df,以及offset域,因此我们每次需要按位与来取得相应的域的值,看下面
ip_local_deliver的代码片段就清楚了:
///取出mf位和offset域,从而决定是否要组包。
if (ip_hdr(skb) ...
- 2009-07-26 13:08
- 浏览 8851
- 评论(0)
这次我们来看数据包如何从4层传递到3层。
先看下面的图,这张图表示了4层和3层之间(也就是4层传输给3层)的传输所需要调用的主要的函数:
我们注意到3层最终会把帧用dst_output函数进行输出,而这个函数,我们上一次已经讲过了,他会调用skb->dst->output这个虚函数(他会对包进行3层的处理),而最终会调用一个XX_finish_output的函数,从而将数据传递到neighboring子系统。
这张我们主要聚焦于ip_push_pending_frames,ip_append_data,ip_append_page,ip_queue_xmit这几个函数。
...
- 2009-07-12 18:22
- 浏览 9667
- 评论(1)
这次主要介绍下forward和local delivery。
上次我们提到当ip_rcv_finish完成后后调用相关的发送函数ip_forward或者ip_local_deliver.这次就主要介绍这两个函数。
先来看forward。
forward一般由下面几部组成:
1 执行ip option
2 确定这个包能被forward
3 减小ttl,当ttl为0时,丢掉这个包
4 如果需要,则将这个包切片
5 发送包到输出网络设备
这里要注意,如果包由于一些原因,不能被forward,则必须发送ICMP消息到发送主机。
int ip_forward(struct sk_buff *s ...
- 2009-07-05 11:28
- 浏览 5067
- 评论(0)
首先来看校验相关的一些结构:
1 net_device结构:
包含一个features的域,这个表示设备的一些特性(比如控制校验),下面的几个flag就是用来控制校验:
#define NETIF_F_IP_CSUM 2 /* Can checksum TCP/UDP over IPv4. */
#define NETIF_F_NO_CSUM 4 /* Does no ...
- 2009-06-28 16:55
- 浏览 8618
- 评论(0)
首先来看这个ip层的结构:
这里看到非常多的netfilter hook,这是因为netfilter主要是针对ip层的。
ip层的主要任务有下面5个方面:
1 ip数据包的校验
2 防火墙的处理(也就是netfilter子系统)
3 处理options(这里的options包含了一些可选的信息。比如时间戳或者源路由option).
4 切包和组包(由于mtu的存在,因此我们需要切包和组包).
5 接收,输出和转发操作。
接下来我们来看ip头的结构:
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
_ ...
- 2009-06-21 22:57
- 浏览 4032
- 评论(2)
我们知道netdevice有一个priv域,这个域用来保存设备的私有数据,当这个设备是一个网桥的时候,priv域也就指向一个struct net_bridge.
接下来看net_bridge以及相关的数据结构:
struct net_bridge
{
///自旋锁
spinlock_t lock;
///网桥所有端口的链表,其中每个元素都是一个net_bridge_port结构。
struct list_head port_list;
///加到这个网桥的物理设备
struct net_device *dev;
///这个锁是用来保护下面的那个hash链表。
...
- 2009-06-14 18:18
- 浏览 5480
- 评论(1)
Spanning Tree Protocol(STP)主要是用在网桥上,用来避免网络回路,并制造冗余连接(也就是保证网络的可靠性).
这里只是一个大概的介绍,具体的还是要去看IEEE 的 802.1D STP的文档。
先看下面的图:
我们可以看到在stp中,只有一个根节点,然后root port指的是将此网桥和root连接起来的那个端口,而designated port指的是在连接这个lan的端口中,距离root最近的那个port。
这里虚线部分就是没有激活的link,而对应的端口也是关闭的,这些连接其实就是冗余连接,当实线的某些连接不可用时,这些虚线部分的一些就会根据stp的算法 ...
- 2009-06-07 19:48
- 浏览 5489
- 评论(0)
网桥用来连接不同的网段。使不同的网段能够相互通信,看起来很像三层的路由。它能够有多个port,从而能够将数据帧从一个port复制到另一个port。
这里要注意一点,linux下的网桥只能用于以太网。
来看下示意图:
其中一个是bridge,一个是route。
网桥的主要工作是从输入帧学习主机的位置,建立一个地址的表(也就是表明这个主机(mac地址)属于那个网络),然后基于这个表来复制输入帧到正确的位置。
这里虽然bridge只是起一个引导的作用,可是在下面两个情况下,网桥也有可能处理输入帧:
1 将输入帧up到上层协议栈。
比如说这个网桥刚好还是一个router。
2 将帧传 ...
- 2009-05-29 04:07
- 浏览 4020
- 评论(0)
我们知道在tcp/ip模型中,基本每一层都可以处理多重协议类型,那么当一个输入帧到达后,内核的每一层是如何来取得相应的处理函数呢?也就是说当我要把包传递给上层的时候,如何取得相应协议的处理函数。
我们这里先来 ...
- 2009-05-23 02:17
- 浏览 5880
- 评论(0)
首先来看如何打开和关闭一个输出队列。
帧的输出状态是通过device->state设为__LINK_STATE_XOFF来表示的。而打开和关闭队列也就是通过这个状态位来处理。
static inline void netif_start_queue(struct net_device *dev)
{
netif_tx_start_queue(netdev_get_tx_queue(dev, 0));
}
static inline void netif_tx_start_queue(struct netdev_queue *dev_queue)
{
clear_bi ...
- 2009-05-16 03:20
- 浏览 5378
- 评论(0)
最近刚刚一个项目自己用libevent,因此这几天又把libevent的代码拿出来翻了下,当初看的时候有些似是而非的东西,这次是基本没有了。这篇也算是前面几篇libevent的blog的补充了。
struct event_base {
const struct eventop *evsel;
void *evbase;
int event_count; /* counts number of total events */
int event_count_active; /* counts number of active events */
int event_g ...
我这里描述的只是2层的处理。
首先,我们来看softnet_data这个结构,每个cpu都有这样的一个队列,它主要是用来存储incoming frame。由于他是每个cpu都有一个队列,因此在不同的cpu之间我们就不要任何锁来控制并发的处理这个帧队 ...
- 2009-05-11 01:57
- 浏览 6313
- 评论(0)
首先来看当网络接收帧到达时,设备如何唤醒驱动。
1 轮询
也就是内核不断的监测相应的寄存器,从而得到是否有网络帧到来。
2中断
当有数据时,设备执行一个硬件中断,然后内核调用相应的处理函数。这种处理当网络在高负载的情况时,效率会很低(中断太频繁)。并且会引起receive-livelock.这是因为内核处理输入帧分为了两部分,一部分是驱动复制帧到输入队列,一部分是内核执行相关代码。第一部分的优先级比第二部分高。这时在高负载的情况下会出现输入队列由于队列已满而阻塞,而已复制的帧由于中断太频繁而无法占用cpu。。
3在一个中断执行多个帧
老的处理方法,也就是上面的处理方法,就是每个帧都会产 ...
- 2009-05-03 22:14
- 浏览 3935
- 评论(0)
首先来看如何分配内存给一个网络设备。
内核通过alloc_netdev来分配内存给一个指定的网络设备:
#define alloc_netdev(sizeof_priv, name, setup) \
alloc_netdev_mq(sizeof_priv, name, setup, 1)
struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
void (*setup)(struct net_device *), unsigned int queue_count)
其中alloc_netd ...
- 2009-05-01 02:49
- 浏览 7591
- 评论(0)
先来看下内核初始化时调用的一些函数:
这里主要的初始化有三类:
1 boot比如grub,u-boot传递给内核的参数,内核的处理。这里是调用parse_args.
2 中断和时钟的初始化。
3 初始化的函数,这里主要是通过do_initcalls标记的驱动初 ...
- 2009-04-19 02:42
- 浏览 4476
- 评论(0)