1. 程式人生 > 實用技巧 >mit 6.828學習筆記不知道幾--lab6PartB

mit 6.828學習筆記不知道幾--lab6PartB

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