Ethernet switch crashes on JumboFrames+dot1q
adam-kulagowski opened this issue · 3 comments
While sending Jumbo Frames trough Ethernet switch, the dynamips process crashes.
How to reproduce:
- create two endpoints (dockers, VMs etc). Each with mtu set to 9000B
- create two switches between them
- each switch should have one access port towards the endpoint and one trunk port towards the second switch
- send ping with size 8000B from one endpoint to the other
Straced dynamips process shows the following error:
select(8, [6 7], NULL, NULL, {tv_sec=0, tv_usec=20000}) = 0 (Timeout)
select(8, [6 7], NULL, NULL, {tv_sec=0, tv_usec=20000}) = 0 (Timeout)
select(8, [6 7], NULL, NULL, {tv_sec=0, tv_usec=20000}) = 1 (in [6], left {tv_sec=0, tv_usec=18687})
recvfrom(6, "\f\272\346xy\0\f\272\346\234@\0\10\0E\0#$\321\207 \0@\1RO\n\0\0\1\n\0"..., 32768, 0, NULL, NULL) = 9010
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_ACCERR, si_addr=0x7f1a4225b870} ---
+++ killed by SIGSEGV (core dumped) +++
My topology looks like this (this is simplified version, originally I encountered this issue in GNS3 while sending big OSPF packets)
LEFT NS (10.0.0.1) [vl1] --- [vl0] GRT -- sw1 E0 access -- sw1 E1 trunk -- sw2 E1 trunk -- sw2 E0 access -- [vr0] GRT -- [vr1] RIGHT NS (10.0.0.2)
Detailed steps to reproduce:
Configure environment
Configure Veth interfaces between switch and namespace
ip link add vl0 type veth peer name vl1
ip link add vr0 type veth peer name vr1
ip l set up vl0 mtu 9000
ip l set up vr0 mtu 9000
Create two namespaces (they will act as endpoints) and move veth interfaces there
ip netns add left
ip netns add right
ip link set dev vl1 netns left
ip link set dev vr1 netns right
ip netns exec left ip link set vl1 up mtu 9000
ip netns exec right ip link set vr1 up mtu 9000
Assign IP addresses to those endpoints
ip netns exec left ip addr add 10.0.0.1/24 dev vl1
ip netns exec right ip addr add 10.0.0.2/24 dev vr1
Configure dynamips switch
Start the switch in Hypervisor mode
/usr/bin/dynamips -H 10000
Configure that switch using telnet
ethsw create sw1
nio create_gen_eth E10 vl0
nio create_udp E11 10001 127.0.0.1 20001
ethsw add_nio sw1 E10
ethsw add_nio sw1 E11
ethsw set_access_port sw1 E10 10
ethsw set_dot1q_port sw1 E11 1
ethsw create sw2
nio create_gen_eth E20 vr0
nio create_udp E21 20001 127.0.0.1 10001
ethsw add_nio sw2 E20
ethsw add_nio sw2 E21
ethsw set_access_port sw2 E20 10
ethsw set_dot1q_port sw2 E21 1
Crash the switch issuing ping commmand:
ip netns exec left ping 10.0.0.2 -s 8000
I'm using dynamips version:
Cisco Router Simulation Platform (version 0.2.21-amd64/Linux stable)
Copyright (c) 2005-2011 Christophe Fillot.
Build date: Jul 12 2019 11:00:00
Please let me know if anything more is needed to reproduce this issue on Your side.
Best regards,
Adam
This issue allowed me to make a test script, nice. :)
The problem is that ETHSW_MAX_PKT_SIZE
is set to 2048 and packet lengths are not checked at all.
There is a buffer overflow when dot1q code adds a tag using a buffer based on that size.
I'm not a network guy, so... what should ethsw do when it encounters a big packet?
Since this is software the only real limit for a packet is available memory.
Is it supposed to enforce a fixed/configurable packet limit and drop bigger packets?
I don't see any harm to increase the buffer size to accommodate jumbo Ethernet frames (https://en.wikipedia.org/wiki/Jumbo_frame)
Maybe we could add this as an option by adding an hypervisor command in the ethsw module?
https://github.com/GNS3/dynamips/blob/master/README.hypervisor#L615L647
ethsw set_jumbo <switch_name> <0|1>
for instance or even let the option to configure a MTU ethsw set_mtu <switch_name> <1500-9000>
The switch should drop frames bigger than the port MTU.
Adding a config option is a feature request and should be placed in a a different issue.
For now I'll just ignore the packet limit like the rest of the code does, which fixes this issue.