Part B: Receiving packets and the web server Receiving Packets
正如你构建发包功能的过程一样,你还得配置E1000来接受数据包,并且提供一个接收描述符队列和接收描述符,3.2节描述了数据包接收的过程,包括接收队列的结构和接收描述符,初始化过程的细节在14.4章节。
练习9.阅读3.2节,你可以无视关于中断和checksum offloading的所有部分(你在后面决定要用这些功能时可以回顾这些部分),你无需关注临界值和内部缓冲如何工作的细节。
接收队列和发送队列非常相似,除了它由等待输入数据包填充的空数据包缓冲区构成,因此,当网络空闲时,发送队列是空的(因为所有包都已经被发送),但接收队列是满的(带着空数据包缓冲区)
当E1000接收到一个packet时,它会首先检查这个packet是否满足该网卡的configured filters(比如,这个包的目的地址是不是该E1000的MAC地址)并且忽略那些不符合这些filter的数据包。否则,E1000尝试获取从接收队列获取下一个空闲的描述符。如果Head指针(RDH)已经追赶上了Tail指针(RDT),那么说明接收队列已经用完了空闲的描述符,因此网卡就会丢弃这个数据包。如果还有空闲的接收描述符,它会将数据包拷贝到描述符包含的缓冲区中,并且设置描述符的DD(descriptor done)和EOP(End of Packet)状态位,然后增加RDH。
如果E1000网卡收到一个包,它的数据大于一个接收描述符的数据包缓存区空间,它会继续从接收队列中获取尽可能多的描述符,用来存放数据包的所有内容。为了表明这样的情况,它会在每个描述符中都设置DD状态位,但只在最后一个描述符中设置EOP状态位。我们可以让驱动对这种情况进行处理,或者只是简单地对对网卡进行配置,让它不接收这样的“长数据包”,但是我们要确保我们的接收缓冲区能够接收最大的以太网数据包(1518字节)。
接收描述符的布局:
接收缓冲区大小和RCTL寄存器BSIZE和BSEX控制位的关系:
练习 10: 根据14.4章节建立接收队列并配置E1000网卡,无需支持”长数据包的接收”和multicast。暂时不要配置使用中断,同时忽略CRC。
默认情况下,网卡会过滤所有的数据包,我们必须配置接收地址寄存器(RAL和RAH)为网卡的MAC地址以使得能接受发送给该网卡的包。目前可以简单地硬编码MAC地址为52:54:00:12:34:56。注意字节顺序MAC地址从左到右是从低地址到高地址的,所以52:54:00:12为低32位,34:56为高16位
E1000网卡只支持一系列特殊的接收缓冲区大小(可查看13.4.22章节关于RCTL.BSIZE的描述)。假如我们配置的接收缓冲区足够大并关闭对长包的接收,那么我们就无需担心跨越多个接收缓冲区的包。同时记住接