《TCP/IP详解 卷2:实现》 —2.6.3 m_pullup函数和连续的协议首部
2.6.3 m_pullup函数和连续的协议首部
函数m_pullup有两个用途。第一个是当一个协议(IP、ICMP、IGMP、UDP或TCP)发现在第一个mbuf的数据量(m_len)小于协议首部的最小长度(例如:IP是20,UDP是8,TCP是20)时,调用m_pullup是基于假定协议首部的剩余部分存放在链表的下一个mbuf,m_pullup重新安排mbuf链表,使得前N字节的数据被连续地存放在链表的第一个mbuf中。N是这个函数的一个参数,它必须小于或等于100(MHLEN)。如果前N字节连续存放在第一个mbuf中,则可以使用宏mtod和dtom。
例如,我们在IP输入例程中会遇到下面这样的代码:
如果第一个mbuf中的数据量小于20(标准IP首部的大小),m_pullup被调用。函数m_pullup失败的原因有两个:(1)如果它需要其他mbuf并且调用MGET失败;(2)如果整个mbuf链表中的数据量总数少于要求的连续字节数(即我们所说的N,在本例中是20)。通常,第二个原因是主要的。在此例中,如果m_pullup失败,一个IP计数器加1,并且此IP数据报被丢弃。注意,这段代码假设失败的原因是mbuf 链表中数据量少于20字节。
实际上,在这种情况下,m_pullup很少能被调用(注意,C语言的&&操作符仅当mbuf长度小于期待值时才调用它),并且当它被调用时,通常会失败。通过查看图2-14~图2-16,我们可以找到原因:在第一个mbuf中,或在簇中,从IP首部开始至少有100字节的连续字节。这允许60字节的最大IP首部,并且后面跟着40字节的TCP首部(其他协议如ICMP、IGMP和UDP的协议首部不到40字节)。如果mbuf链表中的数据可用(分组不小于协议要求的最小值),则所要求的字节数总能连续地存放在第一个mbuf中。但是,如果接收的分组太小(m_len小于期待的最小值),则m_pullup被调用,并且它返回一个差错,因为在mbuf链表中没有所要求数目的可用数据量。
源于伯克利的内核维护一个叫MPFail的变量,每次m_pullup失败时,它都加1。在一个Net/3系统中曾经接收了超过2700万的IP数据报,而MPFail只有9。计数器ipstat.ips_toosmall也是9,并且所有其他协议计数器(ICMP、IGMP、UDP和TCP等)所计的m_pullup失败次数为0。这证实了我们的断言:大多数m_pullup的失败是因为接收的IP数据报太小。
- 点赞
- 收藏
- 关注作者
评论(0)