mit 6.828學習筆記不知道幾--lab6PartB
阿新 • • 發佈:2020-12-03
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