Project

General

Profile

Feature #9111 » suri_microburst_udp.py

Lukas Sismis, 09/22/2026 03:41 PM

 
from trex_stl_lib.api import *


#
# Physical / outer Ethernet
#
DST_MAC = "b8:3f:d2:1c:61:09"
SRC_MAC = "00:11:17:40:AD:4F"
OUTER_VLAN = 21

#
# Burst parameters
#
#PKTS_PER_BURST = 100000
#IBG_US = 100000.0 # 100 ms
#RATE_PERCENT = 100
#BURST_COUNT = 100000

PKTS_PER_BURST = 25000
IBG_US = 2000000.0 # 1 second
RATE_PERCENT = 100
BURST_COUNT = 100000

def chain(records):
"""Chain Scapy DNSRR objects together."""
if not records:
return None

result = records[0]

for rr in records[1:]:
result = result / rr

return result


class STLSuriMicroburst(object):

def build_dns(self):

answers = []

#
# Many A records
#
for i in range(10):
answers.append(
DNSRR(
rrname="bulk.suri.test.",
type="A",
ttl=300,
rdata="10.20.0.{}".format(i + 1)
)
)

#
# Several AAAA records
#
for i in range(4):
answers.append(
DNSRR(
rrname="bulk.suri.test.",
type="AAAA",
ttl=300,
rdata="2001:db8::{:x}".format(i + 1)
)
)

#
# CNAME chain
#
answers += [
DNSRR(
rrname="alias1.suri.test.",
type="CNAME",
ttl=300,
rdata="alias2.suri.test."
),

DNSRR(
rrname="alias2.suri.test.",
type="CNAME",
ttl=300,
rdata="bulk.suri.test."
),
]

#
# TXT records with substantial payload.
#
for i in range(3):
txt = (
"suricata-microburst-record-{:02d}-".format(i)
+ ("X" * 128)
)

answers.append(
DNSRR(
rrname="txt{}.suri.test.".format(i),
type="TXT",
ttl=300,
rdata=txt.encode("ascii")
)
)

#
# Authority section
#
authority = [
DNSRR(
rrname="suri.test.",
type="NS",
ttl=600,
rdata="ns1.suri.test."
),

DNSRR(
rrname="suri.test.",
type="NS",
ttl=600,
rdata="ns2.suri.test."
),
]

#
# Additional/glue records
#
additional = [
DNSRR(
rrname="ns1.suri.test.",
type="A",
ttl=600,
rdata="10.30.0.1"
),

DNSRR(
rrname="ns2.suri.test.",
type="A",
ttl=600,
rdata="10.30.0.2"
),

DNSRR(
rrname="ns1.suri.test.",
type="AAAA",
ttl=600,
rdata="2001:db8:30::1"
),

DNSRR(
rrname="ns2.suri.test.",
type="AAAA",
ttl=600,
rdata="2001:db8:30::2"
),
]

dns = DNS(
id=0x4242,

qr=1, # response
aa=1, # authoritative
rd=1,
ra=1,

qdcount=1,
ancount=len(answers),
nscount=len(authority),
arcount=len(additional),

qd=DNSQR(
qname="bulk.suri.test.",
qtype="ANY"
),

an=chain(answers),
ns=chain(authority),
ar=chain(additional),
)

return dns


def get_streams(self, tunables, **kwargs):

dns = self.build_dns()

#
# Inner tenant packet.
#
# Another VLAN is deliberately included INSIDE VXLAN.
#
inner = (
Ether(
src="02:00:00:00:00:53",
dst="02:00:00:00:00:10"
)
/ Dot1Q(
vlan=301
)
/ IP(
src="10.10.0.53",
dst="10.10.0.10",
ttl=63
)
/ UDP(
sport=53,
dport=53000
)
/ dns
)

#
# Physical packet:
#
# Ethernet
# -> VLAN 21
# -> IPv4
# -> UDP/4789
# -> VXLAN
# -> Ethernet
# -> VLAN 301
# -> IPv4
# -> UDP
# -> DNS
#
pkt = (
Ether(
src=SRC_MAC,
dst=DST_MAC
)
/ Dot1Q(
vlan=OUTER_VLAN
)
/ IP(
src="198.18.0.1",
dst="198.18.0.2",
ttl=64
)
/ UDP(
sport=55000,
dport=4789
)
/ VXLAN(
vni=4242
)
/ inner
)

#
# Standard Ethernet MTU sanity check.
#
# Scapy/TRex packet length excludes Ethernet FCS.
#
packet_len = len(pkt)

print(
"Heavy Suricata packet: {} bytes without FCS, "
"{} bytes including FCS".format(
packet_len,
packet_len + 4
)
)

if packet_len > 1514:
raise Exception(
"Packet is {} bytes without FCS; exceeds normal "
"1518-byte Ethernet frame size".format(packet_len)
)

return [
STLStream(
name="suricata_heavy_dns_microburst",

packet=STLPktBuilder(
pkt=pkt
),

mode=STLTXMultiBurst(
percentage=RATE_PERCENT,
pkts_per_burst=PKTS_PER_BURST,
ibg=IBG_US,
count=BURST_COUNT,
)
)
]


def register():
return STLSuriMicroburst()
(4-4/5)