GNS3/dynamips

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.