From 60967c601f7a7d12d1d71b6772806fe98e6bd95f Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Fri, 29 Jan 2016 12:12:47 +0100 Subject: [PATCH 01/13] Implement l2fwd-like app --- src/program/l2fwd/README | 12 ++++++ src/program/l2fwd/README.inc | 1 + src/program/l2fwd/l2fwd.lua | 84 ++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 src/program/l2fwd/README create mode 120000 src/program/l2fwd/README.inc create mode 100644 src/program/l2fwd/l2fwd.lua diff --git a/src/program/l2fwd/README b/src/program/l2fwd/README new file mode 100644 index 0000000000..4b46c6ae0a --- /dev/null +++ b/src/program/l2fwd/README @@ -0,0 +1,12 @@ +Usage: l2fwd + +PCI1: [tap:iface|virtio:pciaddr|pciaddr] +PCI2: [tap:iface|virtio:pciaddr|pciaddr] + +Forwards all traffic from PCI1 to PCI2. + +Examples: + + l2fwd 0000:02:00.0 0000:01:00.1 + l2fwd 0000:02:00.0 tap:eth0 + l2fwd virtio:0000:02:00.0 tap:eth0 diff --git a/src/program/l2fwd/README.inc b/src/program/l2fwd/README.inc new file mode 120000 index 0000000000..100b93820a --- /dev/null +++ b/src/program/l2fwd/README.inc @@ -0,0 +1 @@ +README \ No newline at end of file diff --git a/src/program/l2fwd/l2fwd.lua b/src/program/l2fwd/l2fwd.lua new file mode 100644 index 0000000000..d81c002b5b --- /dev/null +++ b/src/program/l2fwd/l2fwd.lua @@ -0,0 +1,84 @@ +module(...,package.seeall) + +local lib = require("core.lib") +local main = require("core.main") + +L2Fwd = {} + +function L2Fwd.new(conf) + local o = {} + return setmetatable(o, { __index = L2Fwd }) +end + +function L2Fwd:push() + local input, output = assert(self.input.input), assert(self.output.output) + + while not link.empty(input) do + link.transmit(output, link.receive(input)) + end +end + +local function show_usage(code) + print(require("program.l2fwd.README_inc")) + main.exit(code) +end + +local function parse_args(args) + local handlers = {} + local opts = { duration = 3 } + function handlers.h() show_usage(0) end + function handlers.v() + opts.verbose = true + end + function handlers.D(arg) + opts.duration = assert(tonumber(arg), "duration must be a number") + end + args = lib.dogetopt(args, handlers, "hvD:", { help="h", verbose="v", duration="D"}) + if #args ~= 2 then show_usage(1) end + return opts, unpack(args) +end + +local function select_nic_driver(arg) + local driver, pciaddr = arg:match("(%a+):([%w:.]+)") + if driver == "tap" then + return require("apps.socket.raw").RawSocket, pciaddr + elseif driver == "virtio" then + return require("apps.virtio_net.virtio_net").VirtioNet, pciaddr + else + return require("apps.intel.intel_app").Intel82599, arg + end +end + +function run(args) + local opts, pciaddr1, pciaddr2 = parse_args(args) + local c = config.new() + + local driver1 = select_nic_driver(pciaddr1) + local driver2 = select_nic_driver(pciaddr2) + + config.app(c, "nic1", driver1, {pciaddr = pciaddr1}) + config.app(c, "nic2", driver2, {pciaddr = pciaddr2}) + + config.link(c, "nic1.tx -> nic2.rx") + + engine.configure(c) + if opts.verbose then + while true do + engine.main({duration = opts.duration, report = {showlinks=true, showload=true}}) + end + else + engine.main({duration = opts.duration, noreport = true}) + end +end + +function selftest() + print("selftest: l2fwd") + local driver, pciaddr + driver, pciaddr = select_nic_driver("virtio:0000:00:01.0") + assert(type(driver) == "table" and pciaddr == "0000:00:01.0") + driver, pciaddr = select_nic_driver("tap:eth0") + assert(type(driver) == "table" and pciaddr == "eth0") + driver, pciaddr = select_nic_driver("0000:00:01.0") + assert(type(driver) == "table" and pciaddr == "0000:00:01.0") + print("OK") +end From 8682fdfe446167ee0fc8cf1df2b104838892d3b8 Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Fri, 19 Feb 2016 18:18:22 +0100 Subject: [PATCH 02/13] Fix parsing and initialization of network cards --- src/program/l2fwd/l2fwd.lua | 49 ++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/src/program/l2fwd/l2fwd.lua b/src/program/l2fwd/l2fwd.lua index d81c002b5b..3ca852c0a9 100644 --- a/src/program/l2fwd/l2fwd.lua +++ b/src/program/l2fwd/l2fwd.lua @@ -38,26 +38,33 @@ local function parse_args(args) return opts, unpack(args) end -local function select_nic_driver(arg) - local driver, pciaddr = arg:match("(%a+):([%w:.]+)") - if driver == "tap" then - return require("apps.socket.raw").RawSocket, pciaddr - elseif driver == "virtio" then - return require("apps.virtio_net.virtio_net").VirtioNet, pciaddr +local function parse_nic_driver(arg) + local driver_class, pciaddr_or_iface = arg:match("(%a+):([%w:.]+)") + if not driver_class then return "pci", arg end + return driver_class, pciaddr_or_iface +end + +local function config_nic(c, app_name, dev_addr) + local driver + local driver_class, pciaddr_or_iface = parse_nic_driver(dev_addr) + if driver_class == "tap" then + driver = require("apps.socket.raw").RawSocket + config.app(c, app_name, driver, pciaddr_or_iface) + elseif driver_class == "virtio" then + driver = require("apps.virtio_net.virtio_net").VirtioNet + config.app(c, app_name, driver, {pciaddr = pciaddr_or_iface}) else - return require("apps.intel.intel_app").Intel82599, arg + driver = require("apps.intel.intel_app").Intel82599 + config.app(c, app_name, driver, {pciaddr = pciaddr_or_iface}) end end function run(args) - local opts, pciaddr1, pciaddr2 = parse_args(args) + local opts, arg1, arg2 = parse_args(args) local c = config.new() - local driver1 = select_nic_driver(pciaddr1) - local driver2 = select_nic_driver(pciaddr2) - - config.app(c, "nic1", driver1, {pciaddr = pciaddr1}) - config.app(c, "nic2", driver2, {pciaddr = pciaddr2}) + config_nic(c, "nic1", arg1) + config_nic(c, "nic2", arg2) config.link(c, "nic1.tx -> nic2.rx") @@ -73,12 +80,14 @@ end function selftest() print("selftest: l2fwd") - local driver, pciaddr - driver, pciaddr = select_nic_driver("virtio:0000:00:01.0") - assert(type(driver) == "table" and pciaddr == "0000:00:01.0") - driver, pciaddr = select_nic_driver("tap:eth0") - assert(type(driver) == "table" and pciaddr == "eth0") - driver, pciaddr = select_nic_driver("0000:00:01.0") - assert(type(driver) == "table" and pciaddr == "0000:00:01.0") + local driver_class, pciaddr_or_iface + driver_class, pciaddr_or_iface = parse_nic_driver("virtio:0000:00:01.0") + assert(driver_class == "virtio" and pciaddr_or_iface == "0000:00:01.0") + driver_class, pciaddr_or_iface = parse_nic_driver("tap:eth0") + assert(driver_class == "tap" and pciaddr_or_iface == "eth0") + driver_class, pciaddr_or_iface = parse_nic_driver("pci:0000:00:01.0") + assert(driver_class == "pci" and pciaddr_or_iface == "0000:00:01.0") + driver_class, pciaddr_or_iface = parse_nic_driver("0000:00:01.0") + assert(driver_class == "pci" and pciaddr_or_iface == "0000:00:01.0") print("OK") end From 42819b93837e9774b25663c64db89c2b80797dae Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Wed, 24 Feb 2016 13:37:14 +0100 Subject: [PATCH 03/13] Make actual use of L2Fwd --- src/program/l2fwd/l2fwd.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/program/l2fwd/l2fwd.lua b/src/program/l2fwd/l2fwd.lua index 3ca852c0a9..a1cc4a00c8 100644 --- a/src/program/l2fwd/l2fwd.lua +++ b/src/program/l2fwd/l2fwd.lua @@ -63,10 +63,12 @@ function run(args) local opts, arg1, arg2 = parse_args(args) local c = config.new() + config.app(c, "l2fwd", L2Fwd) config_nic(c, "nic1", arg1) config_nic(c, "nic2", arg2) - config.link(c, "nic1.tx -> nic2.rx") + config.link(c, "nic1.tx -> l2fwd.input") + config.link(c, "l2fwd.output -> nic2.rx") engine.configure(c) if opts.verbose then From c5637949263ebf4acec7a0683ab557f7a51f632e Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Wed, 24 Feb 2016 13:44:16 +0100 Subject: [PATCH 04/13] Two-way forward --- src/program/l2fwd/l2fwd.lua | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/program/l2fwd/l2fwd.lua b/src/program/l2fwd/l2fwd.lua index a1cc4a00c8..04fb4b3cba 100644 --- a/src/program/l2fwd/l2fwd.lua +++ b/src/program/l2fwd/l2fwd.lua @@ -63,12 +63,15 @@ function run(args) local opts, arg1, arg2 = parse_args(args) local c = config.new() - config.app(c, "l2fwd", L2Fwd) + config.app(c, "l2fwd1", L2Fwd) + config.app(c, "l2fwd2", L2Fwd) config_nic(c, "nic1", arg1) config_nic(c, "nic2", arg2) - config.link(c, "nic1.tx -> l2fwd.input") - config.link(c, "l2fwd.output -> nic2.rx") + config.link(c, "nic1.tx -> l2fwd1.input") + config.link(c, "l2fwd1.output -> nic2.rx") + config.link(c, "nic2.tx -> l2fwd2.input") + config.link(c, "l2fwd2.output -> nic2.rx") engine.configure(c) if opts.verbose then From 3f271e6cbf6179a0b02660b191c3d1ed9db72a51 Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Wed, 24 Feb 2016 17:20:46 +0100 Subject: [PATCH 05/13] Implementing a two-way forwarder involves one NIC more --- src/program/l2fwd/l2fwd.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/program/l2fwd/l2fwd.lua b/src/program/l2fwd/l2fwd.lua index 04fb4b3cba..d96694445e 100644 --- a/src/program/l2fwd/l2fwd.lua +++ b/src/program/l2fwd/l2fwd.lua @@ -34,7 +34,7 @@ local function parse_args(args) opts.duration = assert(tonumber(arg), "duration must be a number") end args = lib.dogetopt(args, handlers, "hvD:", { help="h", verbose="v", duration="D"}) - if #args ~= 2 then show_usage(1) end + if #args ~= 3 then show_usage(1) end return opts, unpack(args) end @@ -60,18 +60,19 @@ local function config_nic(c, app_name, dev_addr) end function run(args) - local opts, arg1, arg2 = parse_args(args) + local opts, arg1, arg2, arg3 = parse_args(args) local c = config.new() config.app(c, "l2fwd1", L2Fwd) config.app(c, "l2fwd2", L2Fwd) config_nic(c, "nic1", arg1) config_nic(c, "nic2", arg2) + config_nic(c, "nic3", arg3) config.link(c, "nic1.tx -> l2fwd1.input") config.link(c, "l2fwd1.output -> nic2.rx") - config.link(c, "nic2.tx -> l2fwd2.input") - config.link(c, "l2fwd2.output -> nic2.rx") + config.link(c, "nic3.tx -> l2fwd2.input") + config.link(c, "l2fwd2.output -> nic1.rx") engine.configure(c) if opts.verbose then From 79fb2e068e1cb8980cb2a00a462e5a1377a23950 Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Wed, 24 Feb 2016 18:28:38 +0100 Subject: [PATCH 06/13] Create timer to show report every one second --- src/program/l2fwd/l2fwd.lua | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/program/l2fwd/l2fwd.lua b/src/program/l2fwd/l2fwd.lua index d96694445e..082d99c81e 100644 --- a/src/program/l2fwd/l2fwd.lua +++ b/src/program/l2fwd/l2fwd.lua @@ -25,7 +25,7 @@ end local function parse_args(args) local handlers = {} - local opts = { duration = 3 } + local opts = {} function handlers.h() show_usage(0) end function handlers.v() opts.verbose = true @@ -76,11 +76,18 @@ function run(args) engine.configure(c) if opts.verbose then - while true do - engine.main({duration = opts.duration, report = {showlinks=true, showload=true}}) + local fn = function() + print("Report (last 1 sec):") + engine.report_links() + engine.report_load() end + local t = timer.new("report", fn, 1e9, 'repeating') + timer.activate(t) + end + if opts.duration then + engine.main({duration=opts.duration}) else - engine.main({duration = opts.duration, noreport = true}) + engine.main() end end From 245b20712801e06b540cd8b933d512c92d896a93 Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Thu, 25 Feb 2016 19:13:37 +0100 Subject: [PATCH 07/13] Refactor packetblaster --- src/program/packetblaster/packetblaster.lua | 114 +++++++++++--------- 1 file changed, 62 insertions(+), 52 deletions(-) diff --git a/src/program/packetblaster/packetblaster.lua b/src/program/packetblaster/packetblaster.lua index e1e4124b37..f4cb79d398 100644 --- a/src/program/packetblaster/packetblaster.lua +++ b/src/program/packetblaster/packetblaster.lua @@ -15,83 +15,93 @@ local lib = require("core.lib") local ffi = require("ffi") local C = ffi.C -local usage = require("program.packetblaster.README_inc") -local usage_replay = require("program.packetblaster.replay.README_inc") -local usage_synth = require("program.packetblaster.synth.README_inc") +local mode -local long_opts = { - duration = "D", - help = "h", - src = "s", - dst = "d", - sizes = "S" -} +local function show_usage (code) + if mode == 'replay' then + print(require("program.packetblaster.replay.README_inc")) + elseif mode == 'synth' then + print(require("program.packetblaster.synth.README_inc")) + else + print(require("program.packetblaster.README_inc")) + end + main.exit(code) +end -function run (args) - local opt = {} - local mode = table.remove(args, 1) - local duration - local c = config.new() - function opt.D (arg) - duration = assert(tonumber(arg), "duration is not a number!") +local function parse_args (args, short_opts, long_opts) + local handlers = {} + local opts = {} + function handlers.D (arg) + opts.duration = assert(tonumber(arg), "duration is not a number!") end - function opt.h (arg) - if mode == 'replay' then print(usage_replay) - elseif mode == 'synth' then print(usage_synth) - else print(usage) end - main.exit(1) + function handlers.h (arg) + show_usage(0) end - if mode == 'replay' and #args > 1 then - args = lib.dogetopt(args, opt, "hD:", long_opts) + function handlers.s (arg) opts.source = arg end + function handlers.d (arg) opts.destination = arg end + function handlers.S (arg) + opts.sizes = {} + for size in string.gmatch(arg, "%d+") do + sizes[#sizes+1] = tonumber(size) + end + end + args = lib.dogetopt(args, handlers, short_opts, long_opts) + if #args <= 1 then show_usage(1) end + return opts, args +end + +function run (args) + local opts, c + mode = table.remove(args, 1) + if mode == 'replay' then + c = config.new() + opts, args = parse_args(args, "hD:r", {help="h", duration="D"}) local filename = table.remove(args, 1) config.app(c, "pcap", PcapReader, filename) config.app(c, "loop", basic_apps.Repeater) config.app(c, "source", basic_apps.Tee) config.link(c, "pcap.output -> loop.input") config.link(c, "loop.output -> source.input") - elseif mode == 'synth' and #args >= 1 then - local source - local destination - local sizes - function opt.s (arg) source = arg end - function opt.d (arg) destination = arg end - function opt.S (arg) - sizes = {} - for size in string.gmatch(arg, "%d+") do - sizes[#sizes+1] = tonumber(size) - end - end - - args = lib.dogetopt(args, opt, "hD:s:d:S:", long_opts) + config_sources(c, args) + elseif mode == 'synth' then + c = config.new() + opts, args = parse_args(args, "hD:rs:d:S:", {help="h", duration="D", + src="s", dst="d", sizes="S"}) config.app(c, "source", Synth, { sizes = sizes, src = source, dst = destination }) + config_sources(c, args) else - opt.h() + show_usage(1) end - local patterns = args + + engine.busywait = true + intel10g.num_descriptors = 32*1024 + engine.configure(c) + local fn = function () + print("Transmissions (last 1 sec):") + engine.report_apps() + end + local t = timer.new("report", fn, 1e9, 'repeating') + timer.activate(t) + if opts.duration then engine.main({duration=opts.duration}) + else engine.main() end +end + +function config_sources (c, patterns) local nics = 0 pci.scan_devices() for _,device in ipairs(pci.devices) do if is_device_suitable(device, patterns) then nics = nics + 1 local name = "nic"..nics - config.app(c, name, LoadGen, device.pciaddress) + config.app(c, name, LoadGen, { + pciaddr = device.pciaddress, + }) config.link(c, "source."..tostring(nics).."->"..name..".input") end end assert(nics > 0, " matches no suitable devices.") - engine.busywait = true - intel10g.num_descriptors = 32*1024 - engine.configure(c) - local fn = function () - print("Transmissions (last 1 sec):") - engine.report_apps() - end - local t = timer.new("report", fn, 1e9, 'repeating') - timer.activate(t) - if duration then engine.main({duration=duration}) - else engine.main() end end function is_device_suitable (pcidev, patterns) From 63e2f46116e7af1e55d1da15ea0e8d1088e800e9 Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Thu, 25 Feb 2016 19:14:32 +0100 Subject: [PATCH 08/13] Add 'bounce' mode for packetblaster --- src/apps/intel/loadgen.lua | 33 ++++++++++--- src/program/packetblaster/README | 1 + src/program/packetblaster/bounce/README | 14 ++++++ src/program/packetblaster/bounce/README.inc | 1 + src/program/packetblaster/packetblaster.lua | 54 ++++++++++++++++++--- 5 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 src/program/packetblaster/bounce/README create mode 120000 src/program/packetblaster/bounce/README.inc diff --git a/src/apps/intel/loadgen.lua b/src/apps/intel/loadgen.lua index 969cafc352..85b88ad3a3 100644 --- a/src/apps/intel/loadgen.lua +++ b/src/apps/intel/loadgen.lua @@ -14,9 +14,10 @@ local can_transmit, transmit LoadGen = {} -function LoadGen:new (pciaddress) - local o = { pciaddress = pciaddress, - dev = intel10g.new_sf({pciaddr=pciaddress}) } +function LoadGen:new (conf) + local o = { pciaddr= conf.pciaddr, + dev = intel10g.new_sf({pciaddr=conf.pciaddr}), + report_rx = conf.report_rx, } o.dev:open() o.dev:wait_linkup() disable_tx_descriptor_writeback(o.dev) @@ -69,10 +70,26 @@ function LoadGen:pull () end function LoadGen:report () - print(self.pciaddress, - "TXDGPC (TX packets)", lib.comma_value(tonumber(self.dev.s.TXDGPC())), - "GOTCL (TX octets)", lib.comma_value(tonumber(self.dev.s.GOTCL()))) - self.dev.s.TXDGPC:reset() - self.dev.s.GOTCL:reset() + local s = self.dev.s + local function format(reg) + return lib.comma_value(tonumber(reg())) + end + local function reset(...) + for _, reg in ipairs{...} do + reg:reset() + end + end + + print(self.pciaddr, + "TXDGPC (TX packets)", format(s.TXDGPC), + "GOTCL (TX octets)", format(s.GOTCL)) + reset(s.TXDGPC, s.GOTCL) + if self.report_rx then + print(self.pciaddr, + -- TODO: RXDGPC reported 0 packets received, but non-filtered got packets. + "RXNFGPC (RX packets)", format(s.RXNFGPC), + "GORCL (RX octets)", format(s.GORCL)) + reset(s.RXNFGPC, s.GORCL) + end end diff --git a/src/program/packetblaster/README b/src/program/packetblaster/README index 034c9303d0..5aa6f70246 100644 --- a/src/program/packetblaster/README +++ b/src/program/packetblaster/README @@ -1,4 +1,5 @@ Usage: + packetblaster bounce packetblaster replay packetblaster synth diff --git a/src/program/packetblaster/bounce/README b/src/program/packetblaster/bounce/README new file mode 100644 index 0000000000..51c716542c --- /dev/null +++ b/src/program/packetblaster/bounce/README @@ -0,0 +1,14 @@ +Usage: packetblaster bounce [OPTIONS] + + -D DURATION, --duration DURATION + Run for DURATION seconds. + Default: unlimited + -h, --help + Print usage information. + +packetblaster transmits packets continuously to network adapter. +Packets will eventually reach , if both network adapters are wired together. +Packets bounce on and get back to . + +Examples: + packetblaster bounce myfile.cap 0000:01:00.0 0000:01:00.1 diff --git a/src/program/packetblaster/bounce/README.inc b/src/program/packetblaster/bounce/README.inc new file mode 120000 index 0000000000..100b93820a --- /dev/null +++ b/src/program/packetblaster/bounce/README.inc @@ -0,0 +1 @@ +README \ No newline at end of file diff --git a/src/program/packetblaster/packetblaster.lua b/src/program/packetblaster/packetblaster.lua index f4cb79d398..2a2f61e751 100644 --- a/src/program/packetblaster/packetblaster.lua +++ b/src/program/packetblaster/packetblaster.lua @@ -11,6 +11,7 @@ local main = require("core.main") local PcapReader= require("apps.pcap.pcap").PcapReader local Synth = require("apps.test.synth").Synth local LoadGen = require("apps.intel.loadgen").LoadGen +local Intel82599 = require("apps.intel.intel_app").Intel82599 local lib = require("core.lib") local ffi = require("ffi") local C = ffi.C @@ -22,6 +23,8 @@ local function show_usage (code) print(require("program.packetblaster.replay.README_inc")) elseif mode == 'synth' then print(require("program.packetblaster.synth.README_inc")) + elseif mode == 'bounce' then + print(require("program.packetblaster.bounce.README_inc")) else print(require("program.packetblaster.README_inc")) end @@ -50,6 +53,11 @@ local function parse_args (args, short_opts, long_opts) return opts, args end +local function report_fn () + print("Transmissions (last 1 sec):") + engine.report_apps() +end + function run (args) local opts, c mode = table.remove(args, 1) @@ -71,6 +79,27 @@ function run (args) src = source, dst = destination }) config_sources(c, args) + elseif mode == 'bounce' then + c = config.new() + opts, args = parse_args(args, "hD:r", {help="h", duration="D"}) + if #args > 3 then show_usage(1) end + local filename, nic, bouncer = unpack(args) + config.app(c, "pcap", PcapReader, filename) + config.app(c, "loop", basic_apps.Repeater) + config.app(c, "source", basic_apps.Tee) + config.link(c, "pcap.output -> loop.input") + config.link(c, "loop.output -> source.input") + local nics = config_sources(c, {nic}, {report_rx = true}) + assert(#nics == 1, "Too many nics") + config.app(c, "bouncer", Intel82599, { + pciaddr = bouncer + }) + config.link(c, "bouncer.tx -> bouncer.rx") + local nic_name = nics[1] + report_fn = function() + print("Transmissions and receptions (last 1 sec):") + engine.app_table[nic_name]:report() + end else show_usage(1) end @@ -80,28 +109,37 @@ function run (args) engine.configure(c) local fn = function () print("Transmissions (last 1 sec):") - engine.report_apps() + engine.app_table.nic1:report() end - local t = timer.new("report", fn, 1e9, 'repeating') + local t = timer.new("report", report_fn, 1e9, 'repeating') timer.activate(t) if opts.duration then engine.main({duration=opts.duration}) else engine.main() end end -function config_sources (c, patterns) - local nics = 0 +function config_sources (c, patterns, opts) + local nic_name = (function() + local id = 0 + return function() + id = id + 1 + return id, "nic"..id + end + end)() + local nics = {} pci.scan_devices() for _,device in ipairs(pci.devices) do if is_device_suitable(device, patterns) then - nics = nics + 1 - local name = "nic"..nics + local id, name = nic_name() config.app(c, name, LoadGen, { pciaddr = device.pciaddress, + report_rx = opts and opts.report_rx or false, }) - config.link(c, "source."..tostring(nics).."->"..name..".input") + config.link(c, ("source.%d -> %s.input"):format(id, name)) + table.insert(nics, name) end end - assert(nics > 0, " matches no suitable devices.") + assert(#nics > 0, " matches no suitable devices.") + return nics end function is_device_suitable (pcidev, patterns) From fb2ccbbdbd30b1596492136ea3265b874640b0cc Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Fri, 26 Feb 2016 08:04:59 +0100 Subject: [PATCH 09/13] L2Fwd clean up * L2Fwd app is not necessary. * Drop support of tap interfaces (packetblaster can only blast packets to a PCI device). --- src/program/l2fwd/l2fwd.lua | 64 ++++++++++++------------------------- 1 file changed, 20 insertions(+), 44 deletions(-) diff --git a/src/program/l2fwd/l2fwd.lua b/src/program/l2fwd/l2fwd.lua index 082d99c81e..1a849c55e4 100644 --- a/src/program/l2fwd/l2fwd.lua +++ b/src/program/l2fwd/l2fwd.lua @@ -3,21 +3,6 @@ module(...,package.seeall) local lib = require("core.lib") local main = require("core.main") -L2Fwd = {} - -function L2Fwd.new(conf) - local o = {} - return setmetatable(o, { __index = L2Fwd }) -end - -function L2Fwd:push() - local input, output = assert(self.input.input), assert(self.output.output) - - while not link.empty(input) do - link.transmit(output, link.receive(input)) - end -end - local function show_usage(code) print(require("program.l2fwd.README_inc")) main.exit(code) @@ -34,47 +19,38 @@ local function parse_args(args) opts.duration = assert(tonumber(arg), "duration must be a number") end args = lib.dogetopt(args, handlers, "hvD:", { help="h", verbose="v", duration="D"}) - if #args ~= 3 then show_usage(1) end + if #args ~= 2 then show_usage(1) end return opts, unpack(args) end local function parse_nic_driver(arg) - local driver_class, pciaddr_or_iface = arg:match("(%a+):([%w:.]+)") + local driver_class, pciaddr = arg:match("(%a+):([%w:.]+)") if not driver_class then return "pci", arg end - return driver_class, pciaddr_or_iface + return driver_class, pciaddr end -local function config_nic(c, app_name, dev_addr) +local function config_nic(c, app_name, pciaddr) local driver - local driver_class, pciaddr_or_iface = parse_nic_driver(dev_addr) - if driver_class == "tap" then - driver = require("apps.socket.raw").RawSocket - config.app(c, app_name, driver, pciaddr_or_iface) - elseif driver_class == "virtio" then + local driver_class, pciaddr = parse_nic_driver(pciaddr) + if driver_class == "virtio" then driver = require("apps.virtio_net.virtio_net").VirtioNet - config.app(c, app_name, driver, {pciaddr = pciaddr_or_iface}) + config.app(c, app_name, driver, {pciaddr = pciaddr}) else driver = require("apps.intel.intel_app").Intel82599 - config.app(c, app_name, driver, {pciaddr = pciaddr_or_iface}) + config.app(c, app_name, driver, {pciaddr = pciaddr}) end end function run(args) - local opts, arg1, arg2, arg3 = parse_args(args) + local opts, arg1, arg2 = parse_args(args) local c = config.new() - config.app(c, "l2fwd1", L2Fwd) - config.app(c, "l2fwd2", L2Fwd) config_nic(c, "nic1", arg1) config_nic(c, "nic2", arg2) - config_nic(c, "nic3", arg3) - config.link(c, "nic1.tx -> l2fwd1.input") - config.link(c, "l2fwd1.output -> nic2.rx") - config.link(c, "nic3.tx -> l2fwd2.input") - config.link(c, "l2fwd2.output -> nic1.rx") + config.link(c, "nic1.tx -> nic2.rx") + config.link(c, "nic2.tx -> nic1.rx") - engine.configure(c) if opts.verbose then local fn = function() print("Report (last 1 sec):") @@ -84,6 +60,8 @@ function run(args) local t = timer.new("report", fn, 1e9, 'repeating') timer.activate(t) end + + engine.configure(c) if opts.duration then engine.main({duration=opts.duration}) else @@ -93,14 +71,12 @@ end function selftest() print("selftest: l2fwd") - local driver_class, pciaddr_or_iface - driver_class, pciaddr_or_iface = parse_nic_driver("virtio:0000:00:01.0") - assert(driver_class == "virtio" and pciaddr_or_iface == "0000:00:01.0") - driver_class, pciaddr_or_iface = parse_nic_driver("tap:eth0") - assert(driver_class == "tap" and pciaddr_or_iface == "eth0") - driver_class, pciaddr_or_iface = parse_nic_driver("pci:0000:00:01.0") - assert(driver_class == "pci" and pciaddr_or_iface == "0000:00:01.0") - driver_class, pciaddr_or_iface = parse_nic_driver("0000:00:01.0") - assert(driver_class == "pci" and pciaddr_or_iface == "0000:00:01.0") + local driver_class, pciaddr + driver_class, pciaddr = parse_nic_driver("virtio:0000:00:01.0") + assert(driver_class == "virtio" and pciaddr == "0000:00:01.0") + driver_class, pciaddr = parse_nic_driver("pci:0000:00:01.0") + assert(driver_class == "pci" and pciaddr == "0000:00:01.0") + driver_class, pciaddr = parse_nic_driver("0000:00:01.0") + assert(driver_class == "pci" and pciaddr == "0000:00:01.0") print("OK") end From 41ebfb0c7bd7e4c192bb75ddca51d5f8ecaceb60 Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Fri, 26 Feb 2016 08:24:23 +0100 Subject: [PATCH 10/13] Update L2Fwd README --- src/program/l2fwd/README | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/program/l2fwd/README b/src/program/l2fwd/README index 4b46c6ae0a..2eae790ef5 100644 --- a/src/program/l2fwd/README +++ b/src/program/l2fwd/README @@ -1,12 +1,11 @@ Usage: l2fwd -PCI1: [tap:iface|virtio:pciaddr|pciaddr] -PCI2: [tap:iface|virtio:pciaddr|pciaddr] +PCI1: [pciaddr|pci:pciaddr|virtio:pciaddr] +PCI2: [pciaddr|pci:pciaddr|virtio:pciaddr] -Forwards all traffic from PCI1 to PCI2. +Creates a full-duplex softwire between PCI1 and PCI2. Examples: - l2fwd 0000:02:00.0 0000:01:00.1 - l2fwd 0000:02:00.0 tap:eth0 - l2fwd virtio:0000:02:00.0 tap:eth0 + l2fwd 0000:01:00.0 0000:02:00.0 + l2fwd virtio:0000:01:00.0 virtio:0000:02:00.0 From c366435b9488c7ff3a0d25727f46c6406c2ab133 Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Fri, 26 Feb 2016 09:17:48 +0100 Subject: [PATCH 11/13] Fix packetblaster mode 'synth' --- src/program/packetblaster/packetblaster.lua | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/program/packetblaster/packetblaster.lua b/src/program/packetblaster/packetblaster.lua index 2a2f61e751..ac54fb06eb 100644 --- a/src/program/packetblaster/packetblaster.lua +++ b/src/program/packetblaster/packetblaster.lua @@ -43,13 +43,18 @@ local function parse_args (args, short_opts, long_opts) function handlers.s (arg) opts.source = arg end function handlers.d (arg) opts.destination = arg end function handlers.S (arg) - opts.sizes = {} + local sizes = {} for size in string.gmatch(arg, "%d+") do sizes[#sizes+1] = tonumber(size) end + opts.sizes = sizes end args = lib.dogetopt(args, handlers, short_opts, long_opts) - if #args <= 1 then show_usage(1) end + if (mode == 'replay' and #args <= 1) or + (mode == 'synth' and #args < 1) or + (mode == 'bounce' and not #args == 3) then + show_usage(1) + end return opts, args end @@ -75,14 +80,13 @@ function run (args) c = config.new() opts, args = parse_args(args, "hD:rs:d:S:", {help="h", duration="D", src="s", dst="d", sizes="S"}) - config.app(c, "source", Synth, { sizes = sizes, - src = source, - dst = destination }) + config.app(c, "source", Synth, { sizes = opts.sizes, + src = opts.source, + dst = opts.destination }) config_sources(c, args) elseif mode == 'bounce' then c = config.new() opts, args = parse_args(args, "hD:r", {help="h", duration="D"}) - if #args > 3 then show_usage(1) end local filename, nic, bouncer = unpack(args) config.app(c, "pcap", PcapReader, filename) config.app(c, "loop", basic_apps.Repeater) From 2012bd6606ade368e6e8f05335e15389a23b6005 Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Fri, 26 Feb 2016 09:28:38 +0100 Subject: [PATCH 12/13] Remove unused packetblaster short option 'r' --- src/program/packetblaster/packetblaster.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/program/packetblaster/packetblaster.lua b/src/program/packetblaster/packetblaster.lua index ac54fb06eb..85e3b50027 100644 --- a/src/program/packetblaster/packetblaster.lua +++ b/src/program/packetblaster/packetblaster.lua @@ -68,7 +68,7 @@ function run (args) mode = table.remove(args, 1) if mode == 'replay' then c = config.new() - opts, args = parse_args(args, "hD:r", {help="h", duration="D"}) + opts, args = parse_args(args, "hD:", {help="h", duration="D"}) local filename = table.remove(args, 1) config.app(c, "pcap", PcapReader, filename) config.app(c, "loop", basic_apps.Repeater) @@ -78,7 +78,7 @@ function run (args) config_sources(c, args) elseif mode == 'synth' then c = config.new() - opts, args = parse_args(args, "hD:rs:d:S:", {help="h", duration="D", + opts, args = parse_args(args, "hD:s:d:S:", {help="h", duration="D", src="s", dst="d", sizes="S"}) config.app(c, "source", Synth, { sizes = opts.sizes, src = opts.source, @@ -86,7 +86,7 @@ function run (args) config_sources(c, args) elseif mode == 'bounce' then c = config.new() - opts, args = parse_args(args, "hD:r", {help="h", duration="D"}) + opts, args = parse_args(args, "hD:", {help="h", duration="D"}) local filename, nic, bouncer = unpack(args) config.app(c, "pcap", PcapReader, filename) config.app(c, "loop", basic_apps.Repeater) From 982b5a14ede75e5764f7d3f56292b75f0e1b1a3e Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Mon, 29 Feb 2016 12:22:31 +0100 Subject: [PATCH 13/13] More clean up on l2fwd - Remove reset() method in LoadGen. - Remove unnecessary prefix 'pci'. --- src/apps/intel/loadgen.lua | 12 ++++-------- src/program/l2fwd/README | 4 ++-- src/program/l2fwd/l2fwd.lua | 2 ++ 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/apps/intel/loadgen.lua b/src/apps/intel/loadgen.lua index 85b88ad3a3..c6ed0b2385 100644 --- a/src/apps/intel/loadgen.lua +++ b/src/apps/intel/loadgen.lua @@ -74,22 +74,18 @@ function LoadGen:report () local function format(reg) return lib.comma_value(tonumber(reg())) end - local function reset(...) - for _, reg in ipairs{...} do - reg:reset() - end - end print(self.pciaddr, "TXDGPC (TX packets)", format(s.TXDGPC), "GOTCL (TX octets)", format(s.GOTCL)) - reset(s.TXDGPC, s.GOTCL) + s.TXDGPC:reset() + s.GOTCL:reset() if self.report_rx then print(self.pciaddr, -- TODO: RXDGPC reported 0 packets received, but non-filtered got packets. "RXNFGPC (RX packets)", format(s.RXNFGPC), "GORCL (RX octets)", format(s.GORCL)) - reset(s.RXNFGPC, s.GORCL) + s.RXNFGPC:reset() + s.GORCL:reset() end end - diff --git a/src/program/l2fwd/README b/src/program/l2fwd/README index 2eae790ef5..4ad0b269cf 100644 --- a/src/program/l2fwd/README +++ b/src/program/l2fwd/README @@ -1,7 +1,7 @@ Usage: l2fwd -PCI1: [pciaddr|pci:pciaddr|virtio:pciaddr] -PCI2: [pciaddr|pci:pciaddr|virtio:pciaddr] +PCI1: [pciaddr|virtio:pciaddr] +PCI2: [pciaddr|virtio:pciaddr] Creates a full-duplex softwire between PCI1 and PCI2. diff --git a/src/program/l2fwd/l2fwd.lua b/src/program/l2fwd/l2fwd.lua index 1a849c55e4..872fddc755 100644 --- a/src/program/l2fwd/l2fwd.lua +++ b/src/program/l2fwd/l2fwd.lua @@ -36,6 +36,8 @@ local function config_nic(c, app_name, pciaddr) driver = require("apps.virtio_net.virtio_net").VirtioNet config.app(c, app_name, driver, {pciaddr = pciaddr}) else + assert(driver_class == "pci", + ("Not supported driver class '%s'"):format(driver_class)) driver = require("apps.intel.intel_app").Intel82599 config.app(c, app_name, driver, {pciaddr = pciaddr}) end