Skip to content

Commit

Permalink
Merge pull request snabbco#1013 from Igalia/fix-packetblaster-lwaftr
Browse files Browse the repository at this point in the history
Fix packetblaster lwaftr
  • Loading branch information
wingo authored Feb 13, 2018
2 parents 6321d36 + 87c4263 commit f4411a6
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 67 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
57 changes: 35 additions & 22 deletions src/program/packetblaster/lwaftr/lib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ local ether_header_ptr_type = ffi.typeof("$*", ether_header_t)
local ethernet_header_size = ffi.sizeof(ether_header_t)
local OFFSET_ETHERTYPE = 12

-- The ethernet CRC field is not included in the packet as seen by
-- Snabb, but it is part of the frame and therefore a contributor to the
-- frame size.
local ethernet_crc_size = 4

local ether_vlan_header_type = ffi.typeof([[
struct {
uint16_t tag;
Expand All @@ -56,6 +61,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 +373,44 @@ 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_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
24 changes: 12 additions & 12 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,10 @@ 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")
end
sizes[#sizes+1] = s
sizes_ipv6[#sizes_ipv6+1] = s + 40
sizes[#sizes + 1] = assert(tonumber(size), "size not a number: "..size)
end
end

Expand Down Expand Up @@ -161,6 +153,12 @@ function run (args)

args = lib.dogetopt(args, opt, "VD:hS:s:a:d:b:iI:c:r:46p:v:o:t:i:k:", long_opts)

for _,s in ipairs(sizes) do
if s < 18 + (vlan and 4 or 0) + 20 + 8 then
error("Minimum frame size is 46 bytes (18 ethernet+CRC, 20 IPv4, and 8 UDP)")
end
end

if not target then
print("either --pci, --tap, --sock, --int or --pcap are required parameters")
main.exit(1)
Expand All @@ -172,14 +170,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
Binary file modified src/program/packetblaster/lwaftr/test_lwaftr_1.pcap
Binary file not shown.
Binary file modified src/program/packetblaster/lwaftr/test_lwaftr_2.pcap
Binary file not shown.
3 changes: 2 additions & 1 deletion src/program/packetblaster/selftest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ function test_lwaftr_pcap {
exit 1
fi
cmp $TEMP_PCAP $PCAP
status=$?
rm $TEMP_PCAP
if [ $status != 0 ]; then
echo "Error: lwaftr generated pcap differs from ${PCAP}"
Expand All @@ -25,7 +26,7 @@ function test_lwaftr_pcap {
}

test_lwaftr_pcap program/packetblaster/lwaftr/test_lwaftr_1.pcap --count 1
test_lwaftr_pcap program/packetblaster/lwaftr/test_lwaftr_2.pcap --count 2 --vlan 100 --size 0
test_lwaftr_pcap program/packetblaster/lwaftr/test_lwaftr_2.pcap --count 2 --vlan 100 --size 50

# lwaftr tap test
sudo ip netns add snabbtest || exit $TEST_SKIPPED
Expand Down

0 comments on commit f4411a6

Please sign in to comment.