fbpx

System-Engineering | 7 min read

TRex meets SRX

ngworx Team
June 2020
written by Remi Locherer
Senior Network & Security Engineer

You may have read my recent article on TRex the open-source traffic generator. I was keen to test it with a real device and not only with looped back cables. Lucky me, ngworx had one of the new Juniper SRX380 firewalls available and I could use it for my purpose. It promised to be more fund than the small SRX300 I already have access to since it has 4 10Gig Ethernet interfaces.

Thanks to the Corona crisis, I’m currently working from home which makes the logistics for the project slightly more involving than it would have been otherwise. Thanks to my SRX380-express-bicycle I could get the device from ngworx’s office safely and integrate it into my home lab.

SRX380-express-bicycle

SRX meets TRex

Testing methods

I could think of many interesting configurations and scenarios to test. But since time is limited and I’m still new to TRex I decided to start simple. The datasheet for the SRX 300 series lists some performance numbers and I picked the first few entries in the list:

  • forwarding of 64 byte packets
  • forwarding of 1518 byte packets
  • forwarding of IMIX packets

Since these SRX firewalls have two basic modes to operate in (flow mode and packet mode), I have six tests.

The datasheet mentions that these numbers were evaluated using UDP traffic and following RFC 2544.  To test this type of traffic the stateful features of TRex are not needed. So I looked in the folder with the stateless example test profiles in the TRex installation. I started with udp_1pkt_simple_bdir.py. It generates UDP packets for both TRex network interfaces and uses different source and destination IP addresses, depending on the interface the packets are transmitted. Unfortunately, the packet size was not exactly what I wanted (64 byte). So I copied that file and changed it slightly.

64byte Test
--- udp_1pkt_simple_bdir.py     2020-04-23 15:48:17.000000000 +0200
+++ udp_1pkt_64_simple_bdir.py  2020-05-07 14:14:30.115299144 +0200
@@ -14,7 +14,7 @@
 
         pkt   = STLPktBuilder(
                               pkt = Ether()/IP(src=src_ip,dst=dst_ip)/
-                              UDP(dport=12,sport=1025)/(10*'x') )
+                              UDP(dport=12,sport=1025)/(18*'x') )


 
         return [ STLStream( packet = pkt,mode = STLTXCont()) ]

For the 1518 byte profile I applied the same logic:

1518byte Test
--- udp_1pkt_simple_bdir.py     2020-04-23 15:48:17.000000000 +0200
+++ udp_1pkt_1518_simple_bdir.py        2020-05-07 14:01:43.732334756 +0200
@@ -14,7 +14,7 @@
 
         pkt   = STLPktBuilder(
                               pkt = Ether()/IP(src=src_ip,dst=dst_ip)/
-                              UDP(dport=12,sport=1025)/(10*'x') )
+                              UDP(dport=12,sport=1025)/(1472*'x') )
 
         return [ STLStream( packet = pkt,mode = STLTXCont()) ]

For the IMIX test I just started with the profile I found in the same folder as the previous test: stl/imix.py. I started testing in packet mode and the tests delivered performance numbers in the expected range. After I changed to flow mode the situation changed drastically. While the 64 byte and 1518 byte test looked still good, the numbers for the IMIX tests were extremely low. Initially, I could not make sense out of it and started asking my colleagues for ideas on how to debug this on the SRX side. After much reading and testing with different packet sizes and different numbers of concurrent flows, I found the important difference between the IMIX test and the other two: UDP port numbers! The IMIX profile from TRex does not fill in the port numbers in the  UDP header. Once I figured this out I quickly adapted the test and then got the throughput in the expected range. Of course with proper firewall rules (security policy) such UDP packets would have been filtered.

IMIX test with UDP port numbers
--- imix.py     2020-05-07 22:26:41.596174753 +0200
+++ imix_ports.py       2020-05-07 22:28:25.349425029 +0200
@@ -19,7 +19,7 @@
 
     def create_stream (self, size, pps, isg, vm ):
         # Create base packet and pad it to size
-        base_pkt = Ether()/IP()/UDP()
+        base_pkt = Ether()/IP()/UDP(dport=12,sport=1025)
         pad = max(0, size - len(base_pkt)) * 'x'
 
         pkt = STLPktBuilder(pkt = base_pkt/pad,

SRX Configuration

Before starting with the tests I checked what Junos version JTAC recommends for the two devices and installed the suggested versions. At the time of my testing, this was  18.4R3-S2 for SRX300 and 20.1R1-S1.1 for SRX380.

Below are the configurations I used for SRX380 (packet and flow mode). For SRX300 I used the exact same minimal configs except I used ge-0/0/6 and ge-0/0/7 instead of the xe interfaces.

The two static routes are important since the TRex tests I’m using generate traffic with source or destination IP addresses form these subnets.

When changing the configuration from packet mode to flow mode it is very important to reboot the device in order to activate the new mode.

Packet Mode Configuration

View code
system {
    host-name srx380;
    root-authentication {
        encrypted-password "$5$/fPLUxa0$hr8SnLNFbYvmTci2IbTI1nCW63lVZbSlohanKKVkop6"; ## SECRET-DATA
    }
    services {
        ssh;
        xnm-clear-text;
        netconf {
            ssh;
        }
    }
    domain-name lab.home;
    syslog {
        archive size 100k files 3;
        user * {
            any emergency;
        }
        file messages {
            any notice;
            authorization info;
        }
        file interactive-commands {
            interactive-commands any;
        }
    }
}
security {
    forwarding-options {
        family {
            mpls {
                mode packet-based;
            }
        }
    }
}
interfaces {
    xe-0/0/16 {
        unit 0 {
            family inet {
                address 11.11.11.1/24;
            }
        }
    }
    xe-0/0/17 {
        unit 0 {
            family inet {
                address 12.12.12.1/24;
            }
        }
    }
    lo0 {
        unit 0 {
            family inet {
                address 127.0.0.1/32;
            }
        }
    }
}
protocols {
    l2-learning {
        global-mode switching;
    }
}
routing-options {
    static {
        route 16.0.0.0/8 next-hop 11.11.11.11;
        route 48.0.0.0/8 next-hop 12.12.12.12;
    }
    router-id 1.1.1.1;
}
Related Service See how we help businesses with our network engineering services:
Network Engineering We provide engineering services for over the whole lifecycle process. See more

Flow Mode Configuration

View code
system {
    root-authentication {
        encrypted-password "$5$/fPLUxa0$hr8SnLNFbYvmTci2IbTI1nCW63lVZbSlohanKKVkop6"; ## SECRET-DATA
    }
    host-name srx380;
    domain-name lab.home;
    services {
        ssh;
        xnm-clear-text;
        netconf {
            ssh;
        }
    }
    syslog {
        archive size 100k files 3;
        user * {
            any emergency;
        }
        file messages {
            any notice;
            authorization info;
        }
        file interactive-commands {
            interactive-commands any;
        }
    }
}
security {
    policies {
        from-zone zone-six to-zone zone-seven {
            policy six-to-seven {
                match {
                    source-address any;
                    destination-address any;
                    application any;
                }
                then {
                    permit;
                }
            }
        }
        from-zone zone-seven to-zone zone-six {
            policy seven-to-six {
                match {
                    source-address any;
                    destination-address any;
                    application any;
                }
                then {
                    permit;
                }
            }
        }
    }
    zones {
        security-zone zone-six {
            interfaces {
                xe-0/0/16.0;
            }
        }
        security-zone zone-seven {
            interfaces {
                xe-0/0/17.0;
            }
        }
    }
}
interfaces {
    xe-0/0/16 {
        unit 0 {
            family inet {
                address 11.11.11.1/24;
            }
        }
    }
    xe-0/0/17 {
        unit 0 {
            family inet {
                address 12.12.12.1/24;
            }
        }
    }
    lo0 {
        unit 0 {
            family inet {
                address 127.0.0.1/32;
            }
        }
    }
}
routing-options {
    static {
        route 16.0.0.0/8 next-hop 11.11.11.11;
        route 48.0.0.0/8 next-hop 12.12.12.12;
    }
    router-id 1.1.1.1;
}
protocols {
    l2-learning {
        global-mode switching;
    }
}

Results

While running the tests I was connected to the serial console of the SRX device and compared the stats from TRex with the output from “monitor interface traffic”.  The numbers displayed were the same as the TRex numbers. I also noticed that there was no impact on the responsiveness of the console during the tests. Maybe this is taken for granted but I think it is noteworthy.

Packet Mode

SRX meets TRex

The measurement that stands out here is the 1518 bytes test on SRX300: 1.5 Gbps from the datasheet vs. 1 Gbps measured. Since the numbers are almost the same as in flow mode I suspected that the configured state on the SRX300 was wrong. This was not the case. I checked and repeated this test several times but could not figure out what the cause for this could be.  Maybe the limitation is how the interfaces are connected internally and more throughput can be reached by involving more than two interfaces.

Flow Mode

SRX meets TRex

There are two surprises with the tests in flow mode. First the bad results with the first IMIX test run (UDP ports not set). And second the IMIX result for SRX380 that is 2 Gbps better than specified by Juniper (with UDP ports set).

Conclusion

For most test cases I could push more packets through the SRX compared to the datasheet. This shows that Juniper is conservative while creating the datasheets. This makes them a reliable source when searching a device that fits when we plan and build networks.

The IMIX test case with empty UDP headers showed several things:

  • The importance of understanding how the test exactly works.
  • Checking if the results look reasonable.
  • How easy it is to adapt TRex tests or write new tests.

I enjoyed it very much to learn how to work TRex while testing these Juniper firewalls. In case you are interested in getting a head start with your TRex setup or you need a specific performance characteristic of your network tested, feel free to contact ngworx (https://ngworx.ag/en/contact/).

ngworx Team
June 2020
written by Remi Locherer
Senior Network & Security Engineer

Most Popular

Network-Engineering | 8 min read

Junos upgrade – filesystem is full

Not enough storage during Junos upgrade (EX2300 and EX3400). An extension of Juniper's article…

Read more

Juniper Networks

Want to learn more about Juniper Networks? Discover their solutions, products, awards, team leaders, partners, training programs, and the latest events by clicking the button below.