part B
exercise 9:
阅读手册3.2节
exercise 10:
在kern/e1000.c中添加函数
void e1000_receive_init() { for(int i=0; i<RX_MAX; i++){ memset(&rx_list[i], 0, sizeof(struct rx_desc)); memset(&rx_buf[i], 0, sizeof(struct packets)); rx_list[i].addr = PADDR(rx_buf[i].buffer); //rx_list[i].status &= ~E1000_TXD_STAT_DD; } pci_e1000[E1000_MTA>>2] = 0; pci_e1000[E1000_RDBAL>>2] = PADDR(rx_list); pci_e1000[E1000_RDBAH>>2] = 0; pci_e1000[E1000_RDLEN>>2] = RX_MAX*sizeof(struct rx_desc); pci_e1000[E1000_RDH>>2] = 0; pci_e1000[E1000_RDT>>2] = RX_MAX -1; pci_e1000[E1000_RCTL>>2] = (E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO | E1000_RCTL_SZ_2048 | E1000_RCTL_SECRC); pci_e1000[E1000_RA>>2] = 0x52 | (0x54<<8) | (0x00<<16) | (0x12<<24); pci_e1000[(E1000_RA>>2) + 1] = (0x34) | (0x56<<8) | E1000_RAH_AV; }
并且不要忘记把这个函数加入kern/e1000.c中e1000_init()函数中:
int e1000_init(struct pci_func* pcif) { pci_func_enable(pcif); //pci_e1000 是1个指针,指向映射地址, uint32_t* pci_e1000; //他创建了一个虚拟内存映射 pci_e1000 = mmio_map_region(pcif->reg_base[0], pcif->reg_size[0]); e1000_print_status(E1000_STATUS); e1000_transmit_init(); e1000_receive_init(); return 1; }
在kern/e1000.h中加入函数声明:
void e1000_receive_init();
现在可以对receive功能进行基本测试:
运行
make E1000_DEBUG=TX,TXERR,RX,RXERR,RXFILTER Run -net_testinput
testinput将传输一个ARP(Address Resolution Protocol
地址解析协议)通知包(使用您的包传输系统调用),QEMU将自动应答
该通知包。即使您的驱动程序还不能接收到此回复,应该看到一条“e1000: unicast match[0]: 52:54:00:12:34:56”消息,指示e1000接收了一个数据包,并且匹配了配置的receive filter。
如果看到"e1000: unicast mismatch: 52:54:00:12:34:56" 消息,则e1000过滤掉了数据包,这意味着可能没有正确配置RAL和RAH。确保字节顺序正确,不要忘记在RAH中设置“Address Valid
”位。
如果没有收到任何“e1000”消息,可能没有正确地启用receive。
exercise 11:
int e1000_receive(void* addr) { //int head = pci_e1000[E1000_RDH >> 2]; int tail = (pci_e1000[E1000_RDT >> 2]+1)%RX_MAX; // 有效描述符指的是可供E1000存放接收到数据的描述符或者是说数据已经被读取过了 struct rx_desc* rx_valid = &rx_list[tail]; if ((rx_valid->status & E1000_TXD_STAT_DD) == E1000_TXD_STAT_DD) { int len = rx_valid->length; memcpy(addr, rx_buf[tail].buffer, len); rx_valid->status &= ~E1000_TXD_STAT_DD; pci_e1000[E1000_RDT >> 2] = tail; return len; } return -1; }
系统调用部分类似与transmit,这里就不写了
exercise 12:
void input(envid_t ns_envid) { binaryname = "ns_input"; // LAB 6: Your code here: // - read a packet from the device driver // - send it to the network server // Hint: When you IPC a page to the network server, it will be // reading from it for a while, so don't immediately receive // another packet in to the same physical page. char buf[2048]; int length; while(1){ while((length = sys_packet_try_receive(buf))<0)//尝试接收网卡输入 sys_yield(); nsipcbuf.pkt.jp_len=length; memcpy(nsipcbuf.pkt.jp_data, buf, length); ipc_send(ns_envid, NSREQ_INPUT, &nsipcbuf, PTE_U | PTE_P); for(int i=0; i<50000; i++) if(i%1000==0) sys_yield(); } }
运行
make E1000_DEBUG=TX,TXERR,RX,RXERR,RXFILTER run-net_testinput
出现:
input: 0000 5254 0012 3456 5255 0a00 0202 0806 0001 input: 0010 0800 0604 0002 5255 0a00 0202 0a00 0202 input: 0020 5254 0012 3456 0a00 020f 0000 0000 0000 input: 0030 0000 0000 0000 0000 0000 0000 0000 0000
make grade:
testoutput [5 packets]: OK (2.0s) testoutput [100 packets]: OK (2.1s) Part A score: 35/35 testinput [5 packets]: OK (1.9s) testinput [100 packets]: OK (1.4s) tcp echo server [echosrv]: OK (1.5s)
exercise 13:
static int send_data(struct http_request* req, int fd) { // LAB 6: Your code here. //panic("send_data not implemented"); char buf[128]; int r; while (1) { r = read(fd, buf, 128); if (r <= 0) return r; if (write(req->sock, buf, r) != r) return -1; } }
// LAB 6: Your code here. //panic("send_file not implemented"); struct Stat st; if ((fd = open(req->url, O_RDONLY)) < 0) return send_error(req, 404); if ((r = fstat(fd, &st)) < 0) return send_error(req, 404); if (st.st_isdir) return send_error(req, 404);
make grade