OK, after some further investigation (and reading the tcpdump man page again) it appears that the packet is being corrupted somehow - like the VLAN tag is not being identified properly, the packet is not interpreted as a DHCP reply, and the requests continue going out.
Here is what the server sends out:
tcpdump -Xevnni eth1 vlan 20
19:12:07.567831 02:42:ac:12:00:02 > 9c:eb:e8:32:58:ca, ethertype 802.1Q (0x8100), length 346: vlan 20, p 0, ethertype IPv4, (tos 0xc0, ttl 64, id 9401, offset 0, flags [none], proto UDP (17), length 328)
192.168.20.2.67 > 192.168.20.155.68: BOOTP/DHCP, Reply, length 300, xid 0x8aeecb24, secs 581, Flags [none]
Your-IP 192.168.20.155
Server-IP 192.168.20.2
Client-Ethernet-Address 9c:eb:e8:32:58:ca
Vendor-rfc1048 Extensions
Magic Cookie 0x63825363
DHCP-Message Option 53, length 1: Offer
Server-ID Option 54, length 4: 192.168.20.2
Lease-Time Option 51, length 4: 3600
RN Option 58, length 4: 1800
RB Option 59, length 4: 3150
Subnet-Mask Option 1, length 4: 255.255.255.0
BR Option 28, length 4: 192.168.20.255
Default-Gateway Option 3, length 4: 192.168.20.2
Domain-Name-Server Option 6, length 4: 192.168.20.2
Domain-Name Option 15, length 2: "pi"
0x0000: 45c0 0148 24b9 0000 4011 aa3e c0a8 1402 E..H$...@..>....
0x0010: c0a8 149b 0043 0044 0134 ab33 0201 0600 .....C.D.4.3....
0x0020: 8aee cb24 0245 0000 0000 0000 c0a8 149b ...$.E..........
0x0030: c0a8 1402 0000 0000 9ceb e832 58ca 0000 ...........2X...
0x0040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0100: 0000 0000 0000 0000 6382 5363 3501 0236 ........c.Sc5..6
0x0110: 04c0 a814 0233 0400 000e 103a 0400 0007 .....3.....:....
0x0120: 083b 0400 000c 4e01 04ff ffff 001c 04c0 .;....N.........
0x0130: a814 ff03 04c0 a814 0206 04c0 a814 020f ................
0x0140: 0270 69ff 0000 0000 .pi.....
But here is what the client receives:
tcpdump -Xevnni ethusb vlan 20
22:12:07.565406 02:42:ac:12:00:02 > 9c:eb:e8:32:58:ca, ethertype 802.1Q (0x8100), length 346: vlan 20, p 0, LLC, dsap Unknown (0x44) Group, ssap Unknown (0xc0) Command, ctrl 0x4801: Supervisory, Receiver Ready, rcv seq 36, Flags [Command], length 328
0x0000: 24b9 6980 4011 aa3e c0a8 1402 c0a8 149b $.i.@..>........
0x0010: 0043 0044 0134 ab33 0201 0600 8aee cb24 .C.D.4.3.......$
0x0020: 0245 0000 0000 0000 c0a8 149b c0a8 1402 .E..............
0x0030: 0000 0000 9ceb e832 58ca 0000 0000 0000 .......2X.......
0x0040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00f0: 0000 0000 0000 0000 0000 0000 0000 b4ca ................
0x0100: 0000 0000 6382 5363 3501 0236 04c0 a814 ....c.Sc5..6....
0x0110: 0233 0400 000e 103a 0400 0007 083b 0400 .3.....:.....;..
0x0120: 000c 4e01 04ff ffff 001c 04c0 a814 ff03 ..N.............
0x0130: 04c0 a814 0206 04c0 a814 020f 0270 69ff .............pi.
0x0140: 0000 0000 ....
I haven't tried any other type of traffic to see what happens, but as stated before assigning static IPs and sending ICMP packets in either direction works fine.
It doesn't appear to be an MTU issue as the packets are on the order of 300 bytes long.
Any help would be much appreciated!