MIT 6.1810: Networking

警告
本文最后更新于 2023-04-22,文中内容可能已过时。

MIT 6.1810 中第七个 lab 的 solution

Networking

Your job is to complete e1000_transmit() and e1000_recv(), both in kernel/e1000.c, so that the driver can transmit and receive packets. You are done when make grade says your solution passes all the tests.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
int
e1000_transmit(struct mbuf *m)
{
  uint32 index = regs[E1000_TDT];

  acquire(&e1000_lock);
  if((tx_ring[index].status & E1000_TXD_STAT_DD) != E1000_TXD_STAT_DD){
    release(&e1000_lock);
    return -1;
  }

  if(tx_mbufs[index]) mbuffree(tx_mbufs[index]);

  tx_ring[index].addr = (uint64)m->head;
  tx_ring[index].length = m->len;
  tx_ring[index].cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS;
  tx_mbufs[index] = m;

  regs[E1000_TDT] = (index + 1) % TX_RING_SIZE;

  release(&e1000_lock);
  return 0;
}

static void
e1000_recv(void)
{
  while(1){
    uint32 index = (regs[E1000_RDT] + 1) % RX_RING_SIZE;

    if((rx_ring[index].status & E1000_RXD_STAT_DD) != E1000_RXD_STAT_DD)
      break;

    rx_mbufs[index]->len = rx_ring[index].length;
    net_rx(rx_mbufs[index]);

    rx_mbufs[index] = mbufalloc(0);
    rx_ring[index].addr = (uint64)rx_mbufs[index]->head;
    rx_ring[index].status = 0;

    regs[E1000_RDT] = index;
  }
}