Skip to content

Commit

Permalink
Sizes for "packetblaster lwaftr" are frame sizes
Browse files Browse the repository at this point in the history
This change makes it so that the sizes passed to "packetblaster lwaftr"
are frame sizes instead of packet sizes without the ethernet headers.

This seems to better correspond to the intent of including 64 as a
default size.  Often you want to generate test traffic of the minimum
frame size, and this makes that goal more attainable.

Additionally this commit fixes a bug whereby the frame size was longer
than the actual packet data, because the length in the UDP headers was
wrong.
  • Loading branch information
wingo committed Feb 13, 2018
1 parent c6d0e22 commit 3cf4cda
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 63 deletions.
79 changes: 47 additions & 32 deletions src/program/packetblaster/lwaftr/README
Original file line number Diff line number Diff line change
Expand Up @@ -16,54 +16,69 @@ Usage: packetblaster lwaftr [OPTIONS]

--vlan VLANID VLAN tag traffic with VLANID if set

--src_mac SOURCE
Source MAC-Address
--src_mac SOURCE Source MAC-Address
Default: 00:00:00:00:00:00
--dst_mac DESTINATION
Destination MAC-Address

--dst_mac DESTINATION Destination MAC-Address
Default: 00:00:00:00:00:00
--size SIZES
A comma separated list of numbers. Send packets of
SIZES bytes. The size specifies the lenght of the IPv4
packet. The actual packet size on the wire is 14 Bytes
longer (Ethernet header). Smallest allowed IPv4 packet
size is 28 (20 Bytes for IPv4 header, 8 Bytes payload
for packet loss detection)
Default: 64,64,64,64,64,64,64,594,594,594,1500 (IMIX)
--b4 IPV6,IPV4,PORT
First B4 Client IPv6 mapped to IPv4 and UDP Port.

--size SIZES A comma separated list of numbers. Send packets whose
frames are SIZES bytes long. The frame size includes
the size of the packet, including its ethernet
headers, and additionally a 4-byte CRC that is written
and read by the NIC.

Note that the minimum ethernet frame size is 64 bytes.
While it's technically possible to make smaller frames
and we do allow it, the NIC will pad it up to the
minimum before sending, so it's a bit pointless.
Since Snabb does not see the CRC in the packet, that
means that from Snabb's perspective the minimum useful
packet size is 60 bytes.

The smallest allowed frame size is 46 bytes,
comprising 14 bytes for the ethernet header, 20 for
the IPv4 header, 8 for the UDP header, and 4
additional bytes for the ethernet checksum. If the
packet has at least 8 bytes of payload, the generated
packets will include a unique identifier in the
payload as well.

Default: 64,64,64,64,64,64,64,594,594,594,1500

--b4 IPV6,IPV4,PORT First B4 Client IPv6 mapped to IPv4 and UDP Port.
B4 IPv6,IPv4 and Port are incremented for every count,
then rolled over. Port is incremented by the port number:
e.g. 1024 -> 1024, 2048, 3096 .. 64512 (63 in total)
Default: 2001:db8::,10.0.0.0,1024
--aftr IPV6
IPv6 address of lwaftr server (softwire tunnel endpoint)

--aftr IPV6 IPv6 address of lwaftr server (softwire tunnel endpoint)
Default: 2001:db8:ffff::100
--ipv4 IPV4
Public IPv4. Used as source for IPv4 traffic and

--ipv4 IPV4 Public IPv4. Used as source for IPv4 traffic and
as destination in IPv6 packets from B4
Default: 8.8.8.8
--count COUNT
Number of B4 clients to simulate.

--count COUNT Number of B4 clients to simulate.
Default: 1
--rate RATE
Rate in MPPS for the generated traffic. Fractions are

--rate RATE Rate in MPPS for the generated traffic. Fractions are
allowed (e.g. 3.148 for IMIX line rate). If set too high,
the actual transmitted rate depends on the interfaces capacity.
Setting rate to 0 turns it to listening only mode while
reporting on incoming packets
Default: 1 MPPS
--v4only, -4
Generate only IPv4 packets from the Internet towards lwaftr
--v6only, -6
Generate only IPv6 packets from B4 to lwaftr
--duration DURATION
Run for DURATION seconds.

--v4only, -4 Generate only IPv4 packets from the Internet towards lwaftr

--v6only, -6 Generate only IPv6 packets from B4 to lwaftr

--duration DURATION Run for DURATION seconds.
Default: unlimited
-V, --verbose
Display verbose link information every second
-h, --help
Print usage information.

-V, --verbose Display verbose link information every second

-h, --help Print usage information.


This tool generates two types of traffic according to RFC7596:
Expand Down
53 changes: 31 additions & 22 deletions src/program/packetblaster/lwaftr/lib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ struct {
uint8_t dst_ip[4];
} __attribute__((packed))
]]
local ipv4_header_size = ffi.sizeof(ipv4hdr_t)
local ipv4_header_ptr_type = ffi.typeof("$*", ipv4hdr_t)

local ipv6_ptr_type = ffi.typeof([[
Expand Down Expand Up @@ -367,37 +368,45 @@ function Lwaftrgen:pull ()
ipv4_udp_hdr.dst_port = C.htons(self.current_port)
ipv6_ipv4_udp_hdr.src_port = C.htons(self.current_port)

for _,size in ipairs(self.sizes) do
-- The sizes are frame sizes, including the 4-byte ethernet CRC
-- that we don't see in Snabb.

local vlan_size = self.vlan and ether_vlan_header_size or 0
local ethernet_crc_size = 4
local ethernet_total_size = ethernet_header_size + vlan_size
local minimum_size = ethernet_total_size + ipv4_header_size +
udp_header_size + ethernet_crc_size

for _,size in ipairs(self.sizes) do
assert(size >= minimum_size)
local packet_len = size - ethernet_crc_size
local ipv4_len = packet_len - ethernet_total_size
local udp_len = ipv4_len - ipv4_header_size
if not self.ipv6_only then
ipv4_hdr.total_length = C.htons(size)
if self.vlan then
ipv4_udp_hdr.len = C.htons(size - 28 + 4)
self.ipv4_pkt.length = size + ethernet_header_size + 4
else
ipv4_udp_hdr.len = C.htons(size - 28)
self.ipv4_pkt.length = size + ethernet_header_size
end
ipv4_hdr.total_length = C.htons(ipv4_len)
ipv4_udp_hdr.len = C.htons(udp_len)
self.ipv4_pkt.length = packet_len
ipv4_hdr.checksum = 0
ipv4_hdr.checksum = C.htons(ipsum(self.ipv4_pkt.data + ethernet_header_size, 20, 0))
self.ipv4_payload.number = self.ipv4_packet_number;
self.ipv4_packet_number = self.ipv4_packet_number + 1
ipv4_hdr.checksum = C.htons(ipsum(self.ipv4_pkt.data + ethernet_total_size, 20, 0))
if size >= minimum_size + payload_size then
self.ipv4_payload.number = self.ipv4_packet_number;
self.ipv4_packet_number = self.ipv4_packet_number + 1
end
local ipv4_pkt = packet.clone(self.ipv4_pkt)
transmit(output, ipv4_pkt)
end

if not self.ipv4_only then
ipv6_hdr.payload_length = C.htons(size)
ipv6_ipv4_hdr.total_length = C.htons(size)
if self.vlan then
ipv6_ipv4_udp_hdr.len = C.htons(size - 28 + 4)
self.ipv6_pkt.length = size + 54 + 4
else
ipv6_ipv4_udp_hdr.len = C.htons(size - 28)
self.ipv6_pkt.length = size + 54
-- Expectation from callers is to make packets that are SIZE
-- bytes big, *plus* the IPv6 header.
ipv6_hdr.payload_length = C.htons(ipv4_len)
ipv6_ipv4_hdr.total_length = C.htons(ipv4_len)
ipv6_ipv4_udp_hdr.len = C.htons(udp_len)
self.ipv6_pkt.length = packet_len + ipv6_header_size
if size >= minimum_size + payload_size then
self.ipv6_payload.number = self.ipv6_packet_number;
self.ipv6_packet_number = self.ipv6_packet_number + 1
end
self.ipv6_payload.number = self.ipv6_packet_number;
self.ipv6_packet_number = self.ipv6_packet_number + 1
local ipv6_pkt = packet.clone(self.ipv6_pkt)
transmit(output, ipv6_pkt)
end
Expand Down
16 changes: 7 additions & 9 deletions src/program/packetblaster/lwaftr/lwaftr.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ local long_opts = {
duration = "D", -- terminate after n seconds
verbose = "V", -- verbose, display stats
help = "h", -- display help text
size = "S", -- packet size list (defaults to IMIX)
size = "S", -- frame size list (defaults to IMIX)
src_mac = "s", -- source ethernet address
dst_mac = "d", -- destination ethernet address
vlan = "v", -- VLAN id
Expand Down Expand Up @@ -64,18 +64,14 @@ function run (args)
end

local sizes = { 64, 64, 64, 64, 64, 64, 64, 594, 594, 594, 1500 }
local sizes_ipv6 = { 104, 104, 104, 104, 104, 104, 104, 634, 634, 634, 1540 }
function opt.S (arg)
sizes = {}
sizes_ipv6 = {}
for size in string.gmatch(arg, "%d+") do
local s = tonumber(size)
if s < 28 then
s = 28
print("Warning: Increasing IPv4 packet size to 28")
if s < 18 + 20 + 8 then
error("Minimum frame size is 46 bytes (18 ethernet+CRC, 20 IPv4, and 8 UDP)")
end
sizes[#sizes+1] = s
sizes_ipv6[#sizes_ipv6+1] = s + 40
end
end

Expand Down Expand Up @@ -172,14 +168,16 @@ function run (args)
if not ipv4_only then
print(string.format("IPv6: %s > %s: %s:%d > %s:12345", b4_ipv6, aftr_ipv6, b4_ipv4, b4_port, public_ipv4))
print(" source IPv6 and source IPv4/Port adjusted per client")
print("IPv6 packet sizes: " .. table.concat(sizes_ipv6,","))
local sizes_ipv6 = {}
for i,size in ipairs(sizes) do sizes_ipv6[i] = size + 40 end
print("IPv6 frame sizes: " .. table.concat(sizes_ipv6,","))
end

if not ipv6_only then
print()
print(string.format("IPv4: %s:12345 > %s:%d", public_ipv4, b4_ipv4, b4_port))
print(" destination IPv4 and Port adjusted per client")
print("IPv4 packet sizes: " .. table.concat(sizes,","))
print("IPv4 frame sizes: " .. table.concat(sizes,","))
end

if ipv4_only and ipv6_only then
Expand Down

0 comments on commit 3cf4cda

Please sign in to comment.