I am working on the xv6 lab of network. My job is to finish e1000_transmit() and e1000_recv() in driver code for E1000 so that the driver can transmit and receive packets.
Here is the basic introduction to this lab: https://pdos.csail.mit.edu/6.S081/2023/labs/net.html
The code will be executed on qemu-system-riscv64. I found when I swap net_rx() and regs[E1000_RDT] = cur; in e1000_recv(), xv6 doesn't receive UDP packet from the host.
Here is my correct version of e1000_recv()(I did't follow the introduction hints completely).
void
e1000_recv(void)
{
//
// Your code here.
//
// Check for packets that have arrived from the e1000
// Create and deliver an mbuf for each packet (using net_rx()).
//
//printf("RX\n");
struct mbuf *tmp = 0;
uint32 rdh = 0;
uint32 rdt = 0;
uint32 cur = 0;
do
{
rdh = regs[E1000_RDH];
rdt = regs[E1000_RDT];
cur = (rdt + 1) % RX_RING_SIZE;
//printf("rx rdh:%d rdt:%d cur:%d\n", rdh, rdt, cur);
if (cur == rdh)
{
break;
}
if ((rx_ring[cur].status & E1000_RXD_STAT_DD) == 0)
{
return;
}
tmp = mbufalloc(0);
if (tmp == 0)
{
printf("rx error\n");
}
tmp->head = tmp->buf;
tmp->len = rx_ring[cur].length;
tmp->next = rx_mbufs[cur]->next;
memmove(tmp->head, (void *)rx_ring[cur].addr, rx_ring[cur].length);
rx_ring[cur].status = 0;
rx_ring[cur].length = 0;
rx_ring[cur].csum = 0;
rx_ring[cur].errors = 0;
rx_ring[cur].special = 0;
net_rx(tmp);
regs[E1000_RDT] = cur;
} while (cur != rdh);
}
regs[E1000_RDT] = cur; is after net_rx(), it's okay when we use make grade (CPU core number is three). make grade will run nettests that includes trasmitting and receiving packets tests. But here we focus on the first test that is only a process in xv6 system is transmitting and listening.
Here is the tcpdump result.
reading from file packets.pcap, link-type EN10MB (Ethernet), snapshot length 65536
01:09:30.363741 IP 10.0.2.15.2000 > 10.0.2.2.26099: UDP, length 19
0x0000: ffff ffff ffff 5254 0012 3456 0800 4500 ......RT..4V..E.
0x0010: 002f 0000 0000 6411 3eae 0a00 020f 0a00 ./....d.>.......
0x0020: 0202 07d0 65f3 001b 0000 6120 6d65 7373 ....e.....a.mess
0x0030: 6167 6520 6672 6f6d 2078 7636 21 age.from.xv6!
01:09:30.363915 ARP, Request who-has 10.0.2.15 tell 10.0.2.2, length 46
0x0000: ffff ffff ffff 5255 0a00 0202 0806 0001 ......RU........
0x0010: 0800 0604 0001 5255 0a00 0202 0a00 0202 ......RU........
0x0020: 0000 0000 0000 0a00 020f 0000 0000 0000 ................
0x0030: 0000 0000 0000 0000 0000 0000 ............
01:09:31.316558 ARP, Reply 10.0.2.15 is-at 52:54:00:12:34:56, length 28
0x0000: ffff ffff ffff 5254 0012 3456 0806 0001 ......RT..4V....
0x0010: 0800 0604 0002 5254 0012 3456 0a00 020f ......RT..4V....
0x0020: 5255 0a00 0202 0a00 0202 RU........
01:09:31.316716 IP 10.0.2.2.26099 > 10.0.2.15.2000: UDP, length 17
0x0000: 5254 0012 3456 5255 0a00 0202 0800 4500 RT..4VRU......E.
0x0010: 002d 0000 0000 4011 62b0 0a00 0202 0a00 [email protected].......
0x0020: 020f 65f3 07d0 0019 3216 7468 6973 2069 ..e.....2.this.i
0x0030: 7320 7468 6520 686f 7374 2100 s.the.host!.
01:09:31.321030 IP 10.0.2.15.2000 > 10.0.2.2.26099: UDP, length 19
0x0000: ffff ffff ffff 5254 0012 3456 0800 4500 ......RT..4V..E.
0x0010: 002f 0000 0000 6411 3eae 0a00 020f 0a00 ./....d.>.......
0x0020: 0202 07d0 65f3 001b 0000 6120 6d65 7373 ....e.....a.mess
0x0030: 6167 6520 6672 6f6d 2078 7636 21 age.from.xv6!
...
...
And after swapping the above two lines. xv6 can't receive the UDP packet(the swapping won't cause problems in logic). Below is the result of tcpdump.
reading from file packets.pcap, link-type EN10MB (Ethernet), snapshot length 65536
01:22:28.362597 IP 10.0.2.15.2000 > 10.0.2.2.26099: UDP, length 19
0x0000: ffff ffff ffff 5254 0012 3456 0800 4500 ......RT..4V..E.
0x0010: 002f 0000 0000 6411 3eae 0a00 020f 0a00 ./....d.>.......
0x0020: 0202 07d0 65f3 001b 0000 6120 6d65 7373 ....e.....a.mess
0x0030: 6167 6520 6672 6f6d 2078 7636 21 age.from.xv6!
01:22:28.362785 ARP, Request who-has 10.0.2.15 tell 10.0.2.2, length 46
0x0000: ffff ffff ffff 5255 0a00 0202 0806 0001 ......RU........
0x0010: 0800 0604 0001 5255 0a00 0202 0a00 0202 ......RU........
0x0020: 0000 0000 0000 0a00 020f 0000 0000 0000 ................
0x0030: 0000 0000 0000 0000 0000 0000 ............
01:22:29.316720 ARP, Reply 10.0.2.15 is-at 52:54:00:12:34:56, length 28
0x0000: ffff ffff ffff 5254 0012 3456 0806 0001 ......RT..4V....
0x0010: 0800 0604 0002 5254 0012 3456 0a00 020f ......RT..4V....
0x0020: 5255 0a00 0202 0a00 0202 RU........
Also, when I use make qemu, make server and nettests instead of make grade(It uses python script to execute make qemu, make server and nettests) the tests can pass. And when I change CPUS from 3 to 1, make grade can also pass. It's weird.
The net lab introduction gives some hints that we should put regs[E1000_RDT] = cur; at the end.But I want to know the reason why my change have above problems. I have read the E1000 hareware manul, and I can't find any explanation.