diff options
author | Damjan Marion <damarion@cisco.com> | 2016-12-28 18:38:59 +0100 |
---|---|---|
committer | Damjan Marion <damarion@cisco.com> | 2017-01-01 18:11:43 +0100 |
commit | cb034b9b374927c7552e36dcbc306d8456b2a0cb (patch) | |
tree | 9ff64f9792560630c8cf8faa2f74fc20671c30f1 /vpp-api/lua | |
parent | fdc62abdc113ea63dc867375bd49ef3043dcd290 (diff) |
Move java,lua api and remaining plugins to src/
Change-Id: I1c3b87e886603678368428ae56a6bd3327cbc90d
Signed-off-by: Damjan Marion <damarion@cisco.com>
Diffstat (limited to 'vpp-api/lua')
-rw-r--r-- | vpp-api/lua/README.md | 50 | ||||
-rw-r--r-- | vpp-api/lua/bench.lua | 70 | ||||
-rw-r--r-- | vpp-api/lua/examples/cli/README.md | 5 | ||||
-rw-r--r-- | vpp-api/lua/examples/cli/lua-cli.lua | 747 | ||||
-rw-r--r-- | vpp-api/lua/examples/example-acl-plugin.lua | 110 | ||||
-rw-r--r-- | vpp-api/lua/examples/example-classifier.lua | 51 | ||||
-rw-r--r-- | vpp-api/lua/examples/example-cli.lua | 44 | ||||
-rw-r--r-- | vpp-api/lua/examples/lute/README.md | 66 | ||||
-rw-r--r-- | vpp-api/lua/examples/lute/lute.lua | 777 | ||||
-rw-r--r-- | vpp-api/lua/examples/lute/script-inout-acl-noacl.lute | 329 | ||||
-rw-r--r-- | vpp-api/lua/examples/lute/script-inout-acl-old.lute | 329 | ||||
-rw-r--r-- | vpp-api/lua/examples/lute/script-inout-acl.lute | 329 | ||||
-rw-r--r-- | vpp-api/lua/examples/lute/script.lute | 7 | ||||
-rw-r--r-- | vpp-api/lua/examples/lute/sessions-acl.lute | 308 | ||||
-rw-r--r-- | vpp-api/lua/vpp-lapi.lua | 989 |
15 files changed, 0 insertions, 4211 deletions
diff --git a/vpp-api/lua/README.md b/vpp-api/lua/README.md deleted file mode 100644 index 4ecdb34d2f3..00000000000 --- a/vpp-api/lua/README.md +++ /dev/null @@ -1,50 +0,0 @@ -This is the experimental version of Lua API, aimed for the luajit use. - -Please take a look and send the feedback to ayourtch@gmail.com. - -To run the examples here: - -1) install luajit - "sudo apt-get install luajit" on ubuntu - -2) "make build-vpp-api" in the top VPP directory - -3) "make run" in a separate terminal window - This ensures you have an instance of VPP running - -4) sudo luajit examples/example-cli.lua - -This will result in something like this: - -Version: -00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ -00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - -{ [1] = { ["luaapi_message_name"] = show_version_reply,["program"] = vpe,["version"] = ,["build_date"] = Fri Nov 25 10:58:48 UTC 2016,["retval"] = 0,["build_directory"] = /home/ubuntu/vpp,["_vl_msg_id"] = 170,["context"] = 0,} ,} ---- -{ [1] = { ["luaapi_message_name"] = cli_inband_reply,["_vl_msg_id"] = 94,["length"] = 66,["reply"] = vpp v built by ubuntu on vpp-toys at Fri Nov 25 10:58:48 UTC 2016 -,["retval"] = 0,["context"] = 0,} ,} ---- - -5) You can also run the performance test bench: - -$ sudo luajit bench.lua -10001 iterations, average speed 5624LL per second -10001 iterations, average speed 6650LL per second -10001 iterations, average speed 6053LL per second -10001 iterations, average speed 7056LL per second -10001 iterations, average speed 6388LL per second -10001 iterations, average speed 5849LL per second -10001 iterations, average speed 6321LL per second -10001 iterations, average speed 6368LL per second -10001 iterations, average speed 5958LL per second -10001 iterations, average speed 6482LL per second -Average tps across the tests: 6274LL - -Note: the above is run in an lxd container running inside 2-core -xhyve VM on a Macbook Pro, so I would not take the performance numbers for granted :) - -The "examples" directory contains a few naive examples, as well as a couple of more -advanced ones - a tab-completing CLI for VPP that can call both the APIs and CLI, -and also a small test utility which I use for automating some small tests using -VPP. - diff --git a/vpp-api/lua/bench.lua b/vpp-api/lua/bench.lua deleted file mode 100644 index 8e5a0b4b101..00000000000 --- a/vpp-api/lua/bench.lua +++ /dev/null @@ -1,70 +0,0 @@ ---[[ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -]] - -local vpp = require "vpp-lapi" - -local ffi = require "ffi" - -ffi.cdef([[ - struct timespec { - long tv_sec; /* seconds */ - long tv_nsec; /* nanoseconds */ - }; - - int clock_gettime(int clk_id, struct timespec *tp); -]]) - - -local time_cache = ffi.new("struct timespec[1]") -local time_cache_1 = time_cache[0] -function get_ns() - ffi.C.clock_gettime(0, time_cache) - return time_cache_1.tv_nsec + 1000000000 * time_cache_1.tv_sec -end - -function do_bench() - local cycle_start = get_ns() - local n_iterations = 10000 - local count = 1 - for i = 1,n_iterations do - -- print(i) - vpp:api_call("show_version") - count = count + 1 - -- print(i, "done") - end - cycle_end = get_ns() - local tps = n_iterations*1000000000LL/(cycle_end - cycle_start) - print (tostring(count) .. " iterations, average speed " .. tostring(tps) .. " per second") - return tps -end - -root_dir = "/home/ubuntu/vpp" -pneum_path = root_dir .. "/build-root/install-vpp_lite_debug-native/vpp-api/lib64/libpneum.so" -vpp:init({ pneum_path = pneum_path }) -vpp:json_api(root_dir .. "/build-root/install-vpp_lite_debug-native/vpp/vpp-api/vpe.api.json") - -vpp:connect("lua-bench") -local n_tests = 10 -local tps_acc = 0LL -for i=1,n_tests do - tps_acc = tps_acc + do_bench() -end -print("Average tps across the tests: " .. tostring(tps_acc/n_tests)) - -vpp:disconnect() - - diff --git a/vpp-api/lua/examples/cli/README.md b/vpp-api/lua/examples/cli/README.md deleted file mode 100644 index 3a5f8ee9986..00000000000 --- a/vpp-api/lua/examples/cli/README.md +++ /dev/null @@ -1,5 +0,0 @@ -This is a small experiment to have a wrapper CLI which can call both API functions as well as debug CLI. - -To facilitate tab completion and help, the API call names are broken up with spaces replacing the underscores. - - diff --git a/vpp-api/lua/examples/cli/lua-cli.lua b/vpp-api/lua/examples/cli/lua-cli.lua deleted file mode 100644 index b3a24d7d0ef..00000000000 --- a/vpp-api/lua/examples/cli/lua-cli.lua +++ /dev/null @@ -1,747 +0,0 @@ ---[[ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -]] - --- Experimental prototype CLI using API to VPP, with tab completion --- --- Written by Andrew Yourtchenko (ayourtch@cisco.com) 2010,2016 --- - -vpp = require "vpp-lapi" - - -local dotdotdot = "..." - --- First the "readline" routine - -readln = { -split = function(str, pat) - local t = {} -- NOTE: use {n = 0} in Lua-5.0 - local fpat = "(.-)" .. pat - local last_end = 1 - if str then - local s, e, cap = str:find(fpat, 1) - while s do - if s ~= 1 or cap ~= "" then - table.insert(t,cap) - end - last_end = e+1 - s, e, cap = str:find(fpat, last_end) - end - if last_end <= #str then - cap = str:sub(last_end) - table.insert(t, cap) - end - end - return t -end, - -reader = function() - local rl = {} - - rl.init = function() - os.execute("stty -icanon min 1 -echo") - rl.rawmode = true - end - - rl.done = function() - os.execute("stty icanon echo") - rl.rawmode = false - end - - rl.prompt = ">" - rl.history = { "" } - rl.history_index = 1 - rl.history_length = 1 - - rl.hide_cmd = function() - local bs = string.char(8) .. " " .. string.char(8) - for i = 1, #rl.command do - io.stdout:write(bs) - end - end - - rl.show_cmd = function() - if rl.command then - io.stdout:write(rl.command) - end - end - - rl.store_history = function(cmd) - if cmd == "" then - return - end - rl.history[rl.history_length] = cmd - rl.history_length = rl.history_length + 1 - rl.history_index = rl.history_length - rl.history[rl.history_length] = "" - end - - rl.readln = function() - local done = false - local need_prompt = true - rl.command = "" - - if not rl.rawmode then - rl.init() - end - - while not done do - if need_prompt then - io.stdout:write(rl.prompt) - io.stdout:write(rl.command) - need_prompt = false - end - - local ch = io.stdin:read(1) - if ch:byte(1) == 27 then - -- CONTROL - local ch2 = io.stdin:read(1) - -- arrows - if ch2:byte(1) == 91 then - local ch3 = io.stdin:read(1) - local b = ch3:byte(1) - if b == 65 then - ch = "UP" - elseif b == 66 then - ch = "DOWN" - elseif b == 67 then - ch = "RIGHT" - elseif b == 68 then - ch = "LEFT" - end - -- print("Byte: " .. ch3:byte(1)) - -- if ch3:byte(1) - end - end - - if ch == "?" then - io.stdout:write(ch) - io.stdout:write("\n") - if rl.help then - rl.help(rl) - end - need_prompt = true - elseif ch == "\t" then - if rl.tab_complete then - rl.tab_complete(rl) - end - io.stdout:write("\n") - need_prompt = true - elseif ch == "\n" then - io.stdout:write(ch) - done = true - elseif ch == "\004" then - io.stdout:write("\n") - rl.command = nil - done = true - elseif ch == string.char(127) then - if rl.command ~= "" then - io.stdout:write(string.char(8) .. " " .. string.char(8)) - rl.command = string.sub(rl.command, 1, -2) - end - elseif #ch > 1 then - -- control char - if ch == "UP" then - rl.hide_cmd() - if rl.history_index == #rl.history then - rl.history[rl.history_index] = rl.command - end - if rl.history_index > 1 then - rl.history_index = rl.history_index - 1 - rl.command = rl.history[rl.history_index] - end - rl.show_cmd() - elseif ch == "DOWN" then - rl.hide_cmd() - if rl.history_index < rl.history_length then - rl.history_index = rl.history_index + 1 - rl.command = rl.history[rl.history_index] - end - rl.show_cmd() - end - else - io.stdout:write(ch) - rl.command = rl.command .. ch - end - end - if rl.command then - rl.store_history(rl.command) - end - return rl.command - end - return rl -end - -} - ---[[ - -r = reader() - -local done = false - -while not done do - local cmd = r.readln() - print("Command: " .. tostring(cmd)) - if not cmd or cmd == "quit" then - done = true - end -end - -r.done() - -]] - ---------- MDS show tech parser - -local print_section = nil -local list_sections = false - -local curr_section = "---" -local curr_parser = nil - --- by default operate in batch mode -local batch_mode = true - -local db = {} -local device = {} -device.output = {} -local seen_section = {} - -function start_collection(name) - device = {} - seen_section = {} -end - -function print_error(errmsg) - print("@#$:" .. errmsg) -end - -function keys(tbl) - local t = {} - for k, v in pairs(tbl) do - table.insert(t, k) - end - return t -end - -function tset (parent, ...) - - -- print ('set', ...) - - local len = select ('#', ...) - local key, value = select (len-1, ...) - local cutpoint, cutkey - - for i=1,len-2 do - - local key = select (i, ...) - local child = parent[key] - - if value == nil then - if child == nil then return - elseif next (child, next (child)) then cutpoint = nil cutkey = nil - elseif cutpoint == nil then cutpoint = parent cutkey = key end - - elseif child == nil then child = {} parent[key] = child end - - parent = child - end - - if value == nil and cutpoint then cutpoint[cutkey] = nil - else parent[key] = value return value end - end - - -function tget (parent, ...) - local len = select ('#', ...) - for i=1,len do - parent = parent[select (i, ...)] - if parent == nil then break end - end - return parent - end - - -local pager_lines = 23 -local pager_printed = 0 -local pager_skipping = false -local pager_filter_pipe = nil - -function pager_reset() - pager_printed = 0 - pager_skipping = false - if pager_filter_pipe then - pager_filter_pipe:close() - pager_filter_pipe = nil - end -end - - -function print_more() - io.stdout:write(" --More-- ") -end - -function print_nomore() - local bs = string.char(8) - local bs10 = bs .. bs .. bs .. bs .. bs .. bs .. bs .. bs .. bs .. bs - io.stdout:write(bs10 .. " " .. bs10) -end - -function print_line(txt) - if pager_filter_pipe then - pager_filter_pipe:write(txt .. "\n") - return - end - if pager_printed >= pager_lines then - print_more() - local ch = io.stdin:read(1) - if ch == " " then - pager_printed = 0 - elseif ch == "\n" then - pager_printed = pager_printed - 1 - elseif ch == "q" then - pager_printed = 0 - pager_skipping = true - end - print_nomore() - end - if not pager_skipping then - print(txt) - pager_printed = pager_printed + 1 - else - -- skip printing - end -end - -function paged_write(text) - local t = readln.split(text, "[\n]") - if string.sub(text, -1) == "\n" then - table.insert(t, "") - end - for i, v in ipairs(t) do - if i < #t then - print_line(v) - else - if pager_filter_pipe then - pager_filter_pipe:write(v) - else - io.stdout:write(v) - end - end - end -end - - - - - -function get_choices(tbl, key) - local res = {} - for k, v in pairs(tbl) do - if string.sub(k, 1, #key) == key then - table.insert(res, k) - elseif 0 < #key and dotdotdot == k then - table.insert(res, k) - end - end - return res -end - -function get_exact_choice(choices, val) - local exact_idx = nil - local substr_idx = nil - local substr_seen = false - - if #choices == 1 then - if choices[1] == dotdotdot then - return 1 - elseif string.sub(choices[1], 1, #val) == val then - return 1 - else - return nil - end - else - for i, v in ipairs(choices) do - if v == val then - exact_idx = i - substr_seen = true - elseif choices[i] ~= dotdotdot and string.sub(choices[i], 1, #val) == val then - if substr_seen then - substr_idx = nil - else - substr_idx = i - substr_seen = true - end - elseif choices[i] == dotdotdot then - if substr_seen then - substr_idx = nil - else - substr_idx = i - substr_seen = true - end - end - end - end - return exact_idx or substr_idx -end - -function device_cli_help(rl) - local key = readln.split(rl.command, "[ ]+") - local tree = rl.tree - local keylen = #key - local fullcmd = "" - local error = false - local terse = true - - if ((#rl.command >= 1) and (string.sub(rl.command, -1) == " ")) or (#rl.command == 0) then - table.insert(key, "") - terse = false - end - - for i, v in ipairs(key) do - local choices = get_choices(tree, v) - local idx = get_exact_choice(choices, v) - if idx then - local choice = choices[idx] - tree = tree[choice] - fullcmd = fullcmd .. choice .. " " - else - if i < #key then - error = true - end - end - - if i == #key and not error then - for j, w in ipairs(choices) do - if terse then - paged_write(w .. "\t") - else - paged_write(" " .. w .. "\n") - end - end - paged_write("\n") - if terse then - paged_write(" \n") - end - end - end - pager_reset() -end - -function device_cli_tab_complete(rl) - local key = readln.split(rl.command, "[ ]+") - local tree = rl.tree - local keylen = #key - local fullcmd = "" - local error = false - - for i, v in ipairs(key) do - local choices = get_choices(tree, v) - local idx = get_exact_choice(choices, v) - if idx and choices[idx] ~= dotdotdot then - local choice = choices[idx] - tree = tree[choice] - -- print("level " .. i .. " '" .. choice .. "'") - fullcmd = fullcmd .. choice .. " " - else - -- print("level " .. i .. " : " .. table.concat(choices, " ") .. " ") - error = true - end - end - if not error then - rl.command = fullcmd - else - -- print("\n\nerror\n") - end - pager_reset() -end - -function device_cli_exec(rl) - - local cmd_nopipe = rl.command - local cmd_pipe = nil - - local pipe1, pipe2 = string.find(rl.command, "[|]") - if pipe1 then - cmd_nopipe = string.sub(rl.command, 1, pipe1-1) - cmd_pipe = string.sub(rl.command, pipe2+1, -1) - end - - local key = readln.split(cmd_nopipe .. " <cr>", "[ ]+") - local tree = rl.tree - local keylen = #key - local fullcmd = "" - local error = false - local func = nil - - if cmd_pipe then - pager_filter_pipe = io.popen(cmd_pipe, "w") - end - - - rl.choices = {} - - for i, v in ipairs(key) do - local choices = get_choices(tree, v) - local idx = get_exact_choice(choices, v) - if idx then - local choice = choices[idx] - if i == #key then - func = tree[choice] - else - if choice == dotdotdot then - -- keep the tree the same, update the choice value to match the input string - choices[idx] = v - choice = v - else - tree = tree[choice] - end - end - -- print("level " .. i .. " '" .. choice .. "'") - table.insert(rl.choices, choice) - else - -- print("level " .. i .. " : " .. table.concat(choices, " ") .. " ") - error = true - return nil - end - end - return func -end - -function populate_tree(commands) - local tree = {} - - for k, v in pairs(commands) do - local key = readln.split(k .. " <cr>", "[ ]+") - local xtree = tree - for i, kk in ipairs(key) do - if i == 1 and kk == "sh" then - kk = "show" - end - if i == #key then - if type(v) == "function" then - xtree[kk] = v - else - xtree[kk] = function(rl) paged_write(table.concat(v, "\n") .. "\n") end - end - else - if not xtree[kk] then - xtree[kk] = {} - end - xtree = xtree[kk] - end - end - end - return tree -end - -function trim (s) - return (string.gsub(s, "^%s*(.-)%s*$", "%1")) -end - - -function init_vpp(vpp) - local root_dir = "/home/ubuntu/vpp" - local pneum_path = root_dir .. "/build-root/install-vpp_lite_debug-native/vpp-api/lib64/libpneum.so" - - vpp:init({ pneum_path = pneum_path }) - - vpp:init({ pneum_path = pneum_path }) - vpp:json_api(root_dir .. "/build-root/install-vpp_lite_debug-native/vpp/vpp-api/vpe.api.json") - - - - vpp:connect("lua_cli") -end - -function run_cli(vpp, cli) - local reply = vpp:api_call("cli_inband", { cmd = cli }) - if reply and #reply == 1 then - local rep = reply[1] - if 0 == rep.retval then - return rep.reply - else - return "XXXXXLUACLI: API RETVAL ERROR : " .. tostring(rep.retval) - end - else - return "XXXXXLUACLI ERROR, RAW REPLY: " .. vpp.dump(reply) - end -end - - -function toprintablestring(s) - if type(s) == "string" then - return "\n"..vpp.hex_dump(s) - else - return tostring(s) - end -end - -function interactive_cli(r) - while not done do - pager_reset() - local cmd = r.readln() - if not cmd then - done = true - elseif cmd == "quit" or cmd == "exit" then - done = true - else - local func = device_cli_exec(r) - if func then - func(r) - else - if trim(cmd) == "" then - else - for i = 1, #r.prompt do - paged_write(" ") - end - paged_write("^\n% Invalid input detected at '^' marker.\n\n") - end - end - end - end -end - -device = {} -device.output = {} - -init_vpp(vpp) -cmds_str = run_cli(vpp, "?") -vpp_cmds = readln.split(cmds_str, "\n") -vpp_clis = {} - -for linenum, line in ipairs(vpp_cmds) do - local m,h = string.match(line, "^ (.-) (.*)$") - if m and #m > 0 then - table.insert(vpp_clis, m) - device.output["vpp debug cli " .. m] = function(rl) - -- print("ARBITRARY CLI" .. vpp.dump(rl.choices)) - print("LUACLI command: " .. table.concat(rl.choices, " ")) - local sub = {} - -- - for i=4, #rl.choices -1 do - table.insert(sub, rl.choices[i]) - end - local cli = table.concat(sub, " ") - print("Running CLI: " .. tostring(cli)) - paged_write(run_cli(vpp, cli)) - end - device.output["vpp debug cli " .. m .. " " .. dotdotdot] = function(rl) - print("ARGH") - end - - local ret = run_cli(vpp, "help " .. m) - device.output["help vpp debug cli " .. m] = { ret } - end -end - -for linenum, line in ipairs(vpp_clis) do - -- print(line, ret) -end - -for msgnum, msgname in pairs(vpp.msg_number_to_name) do - local cli, numspaces = string.gsub(msgname, "_", " ") - device.output["call " .. cli .. " " .. dotdotdot] = function(rl) - print("ARGH") - end - device.output["call " .. cli] = function(rl) - print("LUACLI command: " .. table.concat(rl.choices, " ")) - print("Running API: " .. msgname) -- vpp.dump(rl.choices)) - local out = {} - local args = {} - local ntaken = 0 - local argname = "" - for i=(1+1+numspaces+1), #rl.choices-1 do - -- print(i, rl.choices[i]) - if ntaken > 0 then - ntaken = ntaken -1 - else - local fieldname = rl.choices[i] - local field = vpp.msg_name_to_fields[msgname][fieldname] - if field then - local s = rl.choices[i+1] - s=s:gsub("\\x(%x%x)",function (x) return string.char(tonumber(x,16)) end) - args[fieldname] = s - ntaken = 1 - end - end - end - -- print("ARGS: ", vpp.dump(args)) - local ret = vpp:api_call(msgname, args) - for i, reply in ipairs(ret) do - table.insert(out, "=================== Entry #" .. tostring(i)) - for k, v in pairs(reply) do - table.insert(out, " " .. tostring(k) .. " : " .. toprintablestring(v)) - end - end - -- paged_write(vpp.dump(ret) .. "\n\n") - paged_write(table.concat(out, "\n").."\n\n") - end - device.output["call " .. cli .. " help"] = function(rl) - local out = {} - for k, v in pairs(vpp.msg_name_to_fields[msgname]) do - table.insert(out, tostring(k) .. " : " .. v["ctype"] .. " ; " .. tostring(vpp.dump(v)) ) - end - -- paged_write(vpp.dump(vpp.msg_name_to_fields[msgname]) .. "\n\n") - paged_write(table.concat(out, "\n").."\n\n") - end --- vpp.msg_name_to_number = {} -end - - - -local r = readln.reader() -local done = false - -r.prompt = "VPP(luaCLI)#" - -r.help = device_cli_help -r.tab_complete = device_cli_tab_complete -print("===== CLI view, use ^D to end =====") - -r.tree = populate_tree(device.output) --- readln.pretty("xxxx", r.tree) - - -for idx, an_arg in ipairs(arg) do - local fname = an_arg - if fname == "-i" then - pager_lines = 23 - interactive_cli(r) - else - pager_lines = 100000000 - for line in io.lines(fname) do - r.command = line - local func = device_cli_exec(r) - if func then - func(r) - end - end - end -end - -if #arg == 0 then - print("You should specify '-i' as an argument for the interactive session,") - print("but with no other sources of commands, we start interactive session now anyway") - interactive_cli(r) -end - -vpp:disconnect() -r.done() - - diff --git a/vpp-api/lua/examples/example-acl-plugin.lua b/vpp-api/lua/examples/example-acl-plugin.lua deleted file mode 100644 index ca01f18d71d..00000000000 --- a/vpp-api/lua/examples/example-acl-plugin.lua +++ /dev/null @@ -1,110 +0,0 @@ ---[[ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -]] - - -vpp = require "vpp-lapi" - -root_dir = "/home/ubuntu/vpp" -pneum_path = root_dir .. "/build-root/install-vpp_debug-native/vpp-api/lib64/libpneum.so" - -vpp:init({ pneum_path = pneum_path }) - -vpp:consume_api(root_dir .. "/build-root/install-vpp_debug-native/vlib-api/vlibmemory/memclnt.api") -vpp:consume_api(root_dir .. "/build-root/install-vpp_debug-native/vpp/vpp-api/vpe.api") -vpp:connect("aytest") -vpp:consume_api(root_dir .. "/plugins/acl-plugin/acl/acl.api", "acl") - --- api calls -reply = vpp:api_call("show_version") -print("Version: ", reply[1].version) -print(vpp.hex_dump(reply[1].version)) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 230 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 8 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 15 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_add", { context = 42, count = 2, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_in = reply[1].acl_index - -reply = vpp:api_call("acl_add", { context = 42, count = 3, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 }, { is_permit = 1, is_ipv6 = 0 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_out = reply[1].acl_index - - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_add", { context = 42, count = 0 }) -print(vpp.dump(reply)) -print("---") - -acl_index_to_delete = reply[1].acl_index -print("Deleting " .. tostring(acl_index_to_delete)) -reply = vpp:api_call("acl_del", { context = 42, acl_index = acl_index_to_delete }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 0}) -for ri, rv in ipairs(reply) do - print("Reply message #" .. tostring(ri)) - print(vpp.dump(rv)) - for ai, av in ipairs(rv.r) do - print("ACL rule #" .. tostring(ai) .. " : " .. vpp.dump(av)) - end - -end -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") -reply = vpp:api_call("acl_del", { context = 42, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 0}) -print(vpp.dump(reply)) -print("---") - - -vpp:disconnect() - - diff --git a/vpp-api/lua/examples/example-classifier.lua b/vpp-api/lua/examples/example-classifier.lua deleted file mode 100644 index ec9c3d3e020..00000000000 --- a/vpp-api/lua/examples/example-classifier.lua +++ /dev/null @@ -1,51 +0,0 @@ ---[[ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -]] - - -local vpp = require "vpp-lapi" -local bit = require("bit") - -root_dir = "/home/ubuntu/vpp" -pneum_path = root_dir .. "/build-root/install-vpp_lite_debug-native/vpp-api/lib64/libpneum.so" - - -vpp:init({ pneum_path = pneum_path }) - -vpp:json_api(root_dir .. "/build-root/install-vpp_lite_debug-native/vpp/vpp-api/vpe.api.json") - -vpp:connect("aytest") - --- api calls - -print("Calling API to add a new classifier table") -reply = vpp:api_call("classify_add_del_table", { - context = 43, - memory_size = bit.lshift(2, 20), - client_index = 42, - is_add = 1, - nbuckets = 32, - skip_n_vectors = 0, - match_n_vectors = 1, - mask = "\255\255\255\255\255\255\255\255" .. "\255\255\255\255\255\255\255\255" -}) -print(vpp.dump(reply)) -print("---") - - -vpp:disconnect() - - diff --git a/vpp-api/lua/examples/example-cli.lua b/vpp-api/lua/examples/example-cli.lua deleted file mode 100644 index 8b84989f1f6..00000000000 --- a/vpp-api/lua/examples/example-cli.lua +++ /dev/null @@ -1,44 +0,0 @@ ---[[ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -]] - -vpp = require "vpp-lapi" - -root_dir = "/home/ubuntu/vpp" -pneum_path = root_dir .. "/build-root/install-vpp_lite_debug-native/vpp-api/lib64/libpneum.so" - -vpp:init({ pneum_path = pneum_path }) - -vpp:json_api(root_dir .. "/build-root/install-vpp_lite_debug-native/vpp/vpp-api/vpe.api.json") - -vpp:connect("aytest") - --- api calls -reply = vpp:api_call("show_version") -print("Version: ", reply[1].version) -print(vpp.hex_dump(reply[1].version)) -print(vpp.dump(reply)) -print("---") - - -reply = vpp:api_call("cli_inband", { cmd = "show vers" }) -print(vpp.dump(reply)) -print("---") - - -vpp:disconnect() - - diff --git a/vpp-api/lua/examples/lute/README.md b/vpp-api/lua/examples/lute/README.md deleted file mode 100644 index 8d37250ad83..00000000000 --- a/vpp-api/lua/examples/lute/README.md +++ /dev/null @@ -1,66 +0,0 @@ -LUTE: Lua Unit Test Environment - -This is a small helper utility to automate some simple tests -that one might need to do. - -Think of it as a hybrid of a screen and expect who -also took some habits from HTML inline code. - -It is quite probably useless for building anything serious, -but practice shows it is quite efficient at allowing -convenient temporary quick tests, and for something -that was written over a course of a couple of evenings it -is quite a nice little helper tool. - -It allows do launch and drive multiple shell sessions, -and by virtue of having been written in Lua, it of course -also allows to add the business logic using the Lua code. - -If you launch the lute without parameters, it gives you -the interactive shell to execute the commands in. - -If you launch it with an argument, it will attempt to -read and execute the commands from the file. - -Commands: - -shell FOO - - spawn a shell in a new PTY under the label FOO. - -run FOO bar - - Send "bar" keystrokes followed by "ENTER" to the session FOO - - Special case: "break" word on its own gets translated into ^C being sent. - -cd FOO - - "change domain" into session FOO. All subsequent inputs will go, - line-buffered, into the session FOO. To jump back up, use ^D (Control-D), - or within the file, use ^D^D^D (caret D caret D caret D on its own line) - -expect FOO blablabla - - Pause further interpretation of the batch mode until you see "blablabla" - in the output of session FOO, or until timeout happens. - -sleep N - - Sleep an integer N seconds, if you are in batch mode. - -echo blabla - - Echo the remainder of the line to standard output. - -For Lua code, there is a pre-existing pseudo-session called "lua", -which accepts "run lua" command which does what you would expect -(evaluate the rest of the string in Lua context - being the same -as lute itself). Also you can do "cd lua" and get into a -multiline-enabled interpreter shell. - -This way for the VPP case you can automate some of the things in your routine -that you would have to have done manually, and test drive API as well -as use the realistic native OS components to create the environment around it. - - diff --git a/vpp-api/lua/examples/lute/lute.lua b/vpp-api/lua/examples/lute/lute.lua deleted file mode 100644 index 89b9924b901..00000000000 --- a/vpp-api/lua/examples/lute/lute.lua +++ /dev/null @@ -1,777 +0,0 @@ ---[[ -version = 1 -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -]] - --- LUTE: Lua Unit Test Environment --- AKA what happens when screen tries to marry with lua and expect, --- but escapes mid-ceremony. --- --- comments: @ayourtch - -ffi = require("ffi") - -vpp = {} -function vpp.dump(o) - if type(o) == 'table' then - local s = '{ ' - for k,v in pairs(o) do - if type(k) ~= 'number' then k = '"'..k..'"' end - s = s .. '['..k..'] = ' .. vpp.dump(v) .. ',' - end - return s .. '} ' - else - return tostring(o) - end -end - - -ffi.cdef([[ - -int posix_openpt(int flags); -int grantpt(int fd); -int unlockpt(int fd); -char *ptsname(int fd); - -typedef long pid_t; -typedef long ssize_t; -typedef long size_t; -typedef int nfds_t; -typedef long time_t; -typedef long suseconds_t; - -pid_t fork(void); -pid_t setsid(void); - -int close(int fd); -int open(char *pathname, int flags); - -int dup2(int oldfd, int newfd); - -ssize_t read(int fd, void *buf, size_t count); -ssize_t write(int fd, const void *buf, size_t count); - -struct pollfd { - int fd; /* file descriptor */ - short events; /* requested events */ - short revents; /* returned events */ - }; - -int poll(struct pollfd *fds, nfds_t nfds, int timeout); - -struct timeval { - time_t tv_sec; /* seconds */ - suseconds_t tv_usec; /* microseconds */ - }; - -int gettimeofday(struct timeval *tv, struct timezone *tz); - -int inet_pton(int af, const char *src, void *dst); - -]]) - -ffi.cdef([[ -void *memset(void *s, int c, size_t n); -void *memcpy(void *dest, void *src, size_t n); -void *memmove(void *dest, const void *src, size_t n); -void *memmem(const void *haystack, size_t haystacklen, - const void *needle, size_t needlelen); -]]) - - - -local O_RDWR = 2 - - -function os_time() - local tv = ffi.new("struct timeval[1]") - local ret = ffi.C.gettimeofday(tv, nil) - return tonumber(tv[0].tv_sec) + (tonumber(tv[0].tv_usec)/1000000.0) -end - -function sleep(n) - local when_wakeup = os_time() + n - while os_time() <= when_wakeup do - ffi.C.poll(nil, 0, 10) - end -end - - -function c_str(text_in) - local text = text_in - local c_str = ffi.new("char[?]", #text+1) - ffi.copy(c_str, text) - return c_str -end - -function ip46(addr_text) - local out = ffi.new("char [200]") - local AF_INET6 = 10 - local AF_INET = 2 - local is_ip6 = ffi.C.inet_pton(AF_INET6, c_str(addr_text), out) - if is_ip6 == 1 then - return ffi.string(out, 16), true - end - local is_ip4 = ffi.C.inet_pton(AF_INET, c_str(addr_text), out) - if is_ip4 then - return (string.rep("4", 12).. ffi.string(out, 4)), false - end -end - -function pty_master_open() - local fd = ffi.C.posix_openpt(O_RDWR) - ffi.C.grantpt(fd) - ffi.C.unlockpt(fd) - local p = ffi.C.ptsname(fd) - print("PTS:" .. ffi.string(p)) - return fd, ffi.string(p) -end - -function pty_run(cmd) - local master_fd, pts_name = pty_master_open() - local child_pid = ffi.C.fork() - if (child_pid == -1) then - print("Error fork()ing") - return -1 - end - - if child_pid ~= 0 then - -- print("Parent") - return master_fd, child_pid - end - - -- print("Child") - if (ffi.C.setsid() == -1) then - print("Child error setsid") - os.exit(-1) - end - - ffi.C.close(master_fd) - - local slave_fd = ffi.C.open(c_str(pts_name), O_RDWR) - if slave_fd == -1 then - print("Child can not open slave fd") - os.exit(-2) - end - - ffi.C.dup2(slave_fd, 0) - ffi.C.dup2(slave_fd, 1) - ffi.C.dup2(slave_fd, 2) - os.execute(cmd) -end - -function readch() - local buf = ffi.new("char[1]") - local nread= ffi.C.read(0, buf, 1) - -- print("\nREADCH : " .. string.char(buf[0])) - return string.char(buf[0]) -end - -function stdout_write(str) - ffi.C.write(1, c_str(str), #str) -end - - -readln = { -split = function(str, pat) - local t = {} -- NOTE: use {n = 0} in Lua-5.0 - local fpat = "(.-)" .. pat - local last_end = 1 - if str then - local s, e, cap = str:find(fpat, 1) - while s do - if s ~= 1 or cap ~= "" then - table.insert(t,cap) - end - last_end = e+1 - s, e, cap = str:find(fpat, last_end) - end - if last_end <= #str then - cap = str:sub(last_end) - table.insert(t, cap) - end - end - return t -end, - -reader = function() - local rl = {} - - rl.init = function() - os.execute("stty -icanon min 1 -echo") - rl.rawmode = true - end - - rl.done = function() - os.execute("stty icanon echo") - rl.rawmode = false - end - - rl.prompt = ">" - rl.history = { "" } - rl.history_index = 1 - rl.history_length = 1 - - rl.hide_cmd = function() - local bs = string.char(8) .. " " .. string.char(8) - for i = 1, #rl.command do - stdout_write(bs) - end - end - - rl.show_cmd = function() - if rl.command then - stdout_write(rl.command) - end - end - - rl.store_history = function(cmd) - if cmd == "" then - return - end - rl.history[rl.history_length] = cmd - rl.history_length = rl.history_length + 1 - rl.history_index = rl.history_length - rl.history[rl.history_length] = "" - end - - rl.readln = function(stdin_select_fn, batch_cmd, batch_when, batch_expect) - local done = false - local need_prompt = true - rl.command = "" - - if not rl.rawmode then - rl.init() - end - - while not done do - local indent_value = #rl.prompt + #rl.command - if need_prompt then - stdout_write(rl.prompt) - stdout_write(rl.command) - need_prompt = false - end - if type(stdin_select_fn) == "function" then - while not stdin_select_fn(indent_value, batch_cmd, batch_when, batch_expect) do - stdout_write(rl.prompt) - stdout_write(rl.command) - indent_value = #rl.prompt + #rl.command - end - if batch_cmd and ((os_time() > batch_when) or (batch_expect and expect_success(batch_expect, buf, 0))) then - stdout_write("\n" .. rl.prompt .. batch_cmd .. "\n") - if batch_expect then - expect_done(batch_expect) - end - return batch_cmd, batch_expect - end - end - local ch = readch() - if ch:byte(1) == 27 then - -- CONTROL - local ch2 = readch() - -- arrows - if ch2:byte(1) == 91 then - local ch3 = readch() - local b = ch3:byte(1) - if b == 65 then - ch = "UP" - elseif b == 66 then - ch = "DOWN" - elseif b == 67 then - ch = "RIGHT" - elseif b == 68 then - ch = "LEFT" - end - -- print("Byte: " .. ch3:byte(1)) - -- if ch3:byte(1) - end - end - - if ch == "?" then - stdout_write(ch) - stdout_write("\n") - if rl.help then - rl.help(rl) - end - need_prompt = true - elseif ch == "\t" then - if rl.tab_complete then - rl.tab_complete(rl) - end - stdout_write("\n") - need_prompt = true - elseif ch == "\n" then - stdout_write(ch) - done = true - elseif ch == "\004" then - stdout_write("\n") - rl.command = nil - done = true - elseif ch == string.char(127) then - if rl.command ~= "" then - stdout_write(string.char(8) .. " " .. string.char(8)) - rl.command = string.sub(rl.command, 1, -2) - end - elseif #ch > 1 then - -- control char - if ch == "UP" then - rl.hide_cmd() - if rl.history_index == #rl.history then - rl.history[rl.history_index] = rl.command - end - if rl.history_index > 1 then - rl.history_index = rl.history_index - 1 - rl.command = rl.history[rl.history_index] - end - rl.show_cmd() - elseif ch == "DOWN" then - rl.hide_cmd() - if rl.history_index < rl.history_length then - rl.history_index = rl.history_index + 1 - rl.command = rl.history[rl.history_index] - end - rl.show_cmd() - end - else - stdout_write(ch) - rl.command = rl.command .. ch - end - end - if rl.command then - rl.store_history(rl.command) - end - return rl.command - end - return rl -end - -} - -local select_fds = {} -local sessions = {} - -local line_erased = false - -function erase_line(indent) - if not line_erased then - line_erased = true - stdout_write(string.rep(string.char(8), indent)..string.rep(" ", indent)..string.rep(string.char(8), indent)) - end -end - -function do_select_stdin(indent, batch_cmd, batch_when, batch_expect) - while true do - local nfds = 1+#select_fds - local pfds = ffi.new("struct pollfd[?]", nfds) - pfds[0].fd = 0; - pfds[0].events = 1; - pfds[0].revents = 0; - for i = 1,#select_fds do - pfds[i].fd = select_fds[i].fd - pfds[i].events = 1 - pfds[i].revents = 0 - end - if batch_cmd and ((os_time() > batch_when) or (batch_expect and expect_success(batch_expect, buf, 0))) then - return true - end - while ffi.C.poll(pfds, nfds, 10) == 0 do - if batch_cmd and ((os_time() > batch_when) or (batch_expect and expect_success(batch_expect, buf, 0))) then - return true - end - if line_erased then - line_erased = false - return false - end - end - if pfds[0].revents == 1 then - return true - end - for i = 1,#select_fds do - if(pfds[i].revents > 0) then - if pfds[i].fd ~= select_fds[i].fd then - print("File descriptors unequal", pfds[i].fd, select_fds[i].fd) - end - select_fds[i].cb(select_fds[i], pfds[i].revents, indent) - end - end - end -end - -local buf = ffi.new("char [32768]") - -function session_stdout_write(prefix, data) - data = prefix .. data:gsub("\n", "\n"..prefix):gsub("\n"..prefix.."$", "\n") - - stdout_write(data) -end - -function expect_success(sok, buf, nread) - local expect_buf_sz = ffi.sizeof(sok.expect_buf) - 128 - local expect_buf_avail = expect_buf_sz - sok.expect_buf_idx - -- print("EXPECT_SUCCESS: nread ".. tostring(nread).. " expect_buf_idx: " .. tostring(sok.expect_buf_idx) .. " expect_buf_avail: " .. tostring(expect_buf_avail) ) - if expect_buf_avail < 0 then - print "EXPECT BUFFER OVERRUN ALREADY" - os.exit(1) - end - if expect_buf_avail < nread then - if (nread >= ffi.sizeof(sok.expect_buf)) then - print("Read too large of a chunk to fit into expect buffer") - return nil - end - local delta = nread - expect_buf_avail - - ffi.C.memmove(sok.expect_buf, sok.expect_buf + delta, expect_buf_sz - delta) - sok.expect_buf_idx = sok.expect_buf_idx - delta - expect_buf_avail = nread - end - if sok.expect_buf_idx + nread > expect_buf_sz then - print("ERROR, I have just overrun the buffer !") - os.exit(1) - end - ffi.C.memcpy(sok.expect_buf + sok.expect_buf_idx, buf, nread) - sok.expect_buf_idx = sok.expect_buf_idx + nread - if sok.expect_str == nil then - return true - end - local match_p = ffi.C.memmem(sok.expect_buf, sok.expect_buf_idx, sok.expect_str, sok.expect_str_len) - if match_p ~= nil then - return true - end - return false -end - -function expect_done(sok) - local expect_buf_sz = ffi.sizeof(sok.expect_buf) - 128 - if not sok.expect_str then - return false - end - local match_p = ffi.C.memmem(sok.expect_buf, sok.expect_buf_idx, sok.expect_str, sok.expect_str_len) - if match_p ~= nil then - if sok.expect_cb then - sok.expect_cb(sok) - end - local match_idx = ffi.cast("char *", match_p) - ffi.cast("char *", sok.expect_buf) - ffi.C.memmove(sok.expect_buf, ffi.cast("char *", match_p) + sok.expect_str_len, expect_buf_sz - match_idx - sok.expect_str_len) - sok.expect_buf_idx = match_idx + sok.expect_str_len - sok.expect_success = true - - sok.expect_str = nil - sok.expect_str_len = 0 - return true - end -end - -function slave_events(sok, revents, indent) - local fd = sok.fd - local nread = ffi.C.read(fd, buf, ffi.sizeof(buf)-128) - local idx = nread - 1 - while idx >= 0 and buf[idx] ~= 10 do - idx = idx - 1 - end - if idx >= 0 then - erase_line(indent) - session_stdout_write(sok.prefix, sok.buf .. ffi.string(buf, idx+1)) - sok.buf = "" - end - sok.buf = sok.buf .. ffi.string(buf+idx+1, nread-idx-1) - -- print("\nRead: " .. tostring(nread)) - -- stdout_write(ffi.string(buf, nread)) - if expect_success(sok, buf, nread) then - return true - end - return false -end - - -function start_session(name) - local mfd, cpid = pty_run("/bin/bash") - local sok = { ["fd"] = mfd, ["cb"] = slave_events, ["buf"] = "", ["prefix"] = name .. ":", ["expect_buf"] = ffi.new("char [165536]"), ["expect_buf_idx"] = 0, ["expect_str"] = nil } - table.insert(select_fds, sok) - sessions[name] = sok -end - -function command_transform(exe) - if exe == "break" then - exe = string.char(3) - end - return exe -end - -function session_write(a_session, a_str) - if has_session(a_session) then - return tonumber(ffi.C.write(sessions[a_session].fd, c_str(a_str), #a_str)) - else - return 0 - end -end - -function session_exec(a_session, a_cmd) - local exe = command_transform(a_cmd) .. "\n" - session_write(a_session, exe) -end - -function session_cmd(ui, a_session, a_cmd) - if not has_session(a_session) then - stdout_write("ERR: No such session '" .. tostring(a_session) .. "'\n") - return nil - end - if a_session == "lua" then - local func, msg = loadstring(ui.lua_acc .. a_cmd) - -- stdout_write("LOADSTR: " .. vpp.dump({ ret, msg }) .. "\n") - if not func and string.match(msg, "<eof>") then - if a_session ~= ui.in_session then - stdout_write("ERR LOADSTR: " .. tostring(msg) .. "\n") - return nil - end - ui.lua_acc = ui.lua_acc .. a_cmd .. "\n" - return true - end - ui.lua_acc = "" - local ret, msg = pcall(func) - if ret then - return true - else - stdout_write("ERR: " .. msg .. "\n") - return nil - end - else - session_exec(a_session, a_cmd) - if ui.session_cmd_delay then - return { "delay", ui.session_cmd_delay } - end - return true - end -end - -function has_session(a_session) - if a_session == "lua" then - return true - end - return (sessions[a_session] ~= nil) -end - -function command_match(list, input, output) - for i, v in ipairs(list) do - local m = {} - m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9] = string.match(input, v[1]) - -- print("MATCH: ", vpp.dump(m)) - if m[1] then - output["result"] = m - output["result_index"] = i - return m - end - end - return nil -end - -function cmd_spawn_shell(ui, a_arg) - start_session(a_arg[1]) - return true -end - -function cmd_run_cmd(ui, a_arg) - local a_sess = a_arg[1] - local a_cmd = a_arg[2] - return session_cmd(ui, a_sess, a_cmd) -end - -function cmd_cd(ui, a_arg) - local a_sess = a_arg[1] - if has_session(a_sess) then - ui.in_session = a_sess - return true - else - stdout_write("ERR: Unknown session '".. tostring(a_sess) .. "'\n") - return nil - end -end - -function cmd_sleep(ui, a_arg) - return { "delay", tonumber(a_arg[1]) } -end - -function cmd_expect(ui, a_arg) - local a_sess = a_arg[1] - local a_expect = a_arg[2] - local sok = sessions[a_sess] - if not sok then - stdout_write("ERR: unknown session '" .. tostring(a_sess) .. "'\n") - return nil - end - sok.expect_str = c_str(a_expect) - sok.expect_str_len = #a_expect - return { "expect", a_sess } -end - -function cmd_info(ui, a_arg) - local a_sess = a_arg[1] - local sok = sessions[a_sess] - if not sok then - stdout_write("ERR: unknown session '" .. tostring(a_sess) .. "'\n") - return nil - end - print("Info for session " .. tostring(a_sess) .. "\n") - print("Expect buffer index: " .. tostring(sok.expect_buf_idx)) - print("Expect buffer: '" .. tostring(ffi.string(sok.expect_buf, sok.expect_buf_idx)) .. "'\n") - if sok.expect_str then - print("Expect string: '" .. tostring(ffi.string(sok.expect_str, sok.expect_str_len)) .. "'\n") - else - print("Expect string not set\n") - end -end - -function cmd_echo(ui, a_arg) - local a_data = a_arg[1] - print("ECHO: " .. tostring(a_data)) -end - -main_command_table = { - { "^shell ([a-zA-Z0-9_]+)$", cmd_spawn_shell }, - { "^run ([a-zA-Z0-9_]+) (.+)$", cmd_run_cmd }, - { "^cd ([a-zA-Z0-9_]+)$", cmd_cd }, - { "^sleep ([0-9]+)$", cmd_sleep }, - { "^expect ([a-zA-Z0-9_]+) (.-)$", cmd_expect }, - { "^info ([a-zA-Z0-9_]+)$", cmd_info }, - { "^echo (.-)$", cmd_echo } -} - - - -function ui_set_prompt(ui) - if ui.in_session then - if ui.in_session == "lua" then - if #ui.lua_acc > 0 then - ui.r.prompt = ui.in_session .. ">>" - else - ui.r.prompt = ui.in_session .. ">" - end - else - ui.r.prompt = ui.in_session .. "> " - end - else - ui.r.prompt = "> " - end - return ui.r.prompt -end - -function ui_run_command(ui, cmd) - -- stdout_write("Command: " .. tostring(cmd) .. "\n") - local ret = false - if ui.in_session then - if cmd then - if cmd == "^D^D^D" then - ui.in_session = nil - ret = true - else - ret = session_cmd(ui, ui.in_session, cmd) - end - else - ui.in_session = nil - ret = true - end - else - if cmd then - local out = {} - if cmd == "" then - ret = true - end - if command_match(main_command_table, cmd, out) then - local i = out.result_index - local m = out.result - if main_command_table[i][2] then - ret = main_command_table[i][2](ui, m) - end - end - end - if not cmd or cmd == "quit" then - return "quit" - end - end - return ret -end - -local ui = {} -ui.in_session = nil -ui.r = readln.reader() -ui.lua_acc = "" -ui.session_cmd_delay = 0.3 - -local lines = "" - -local done = false --- a helper function which always returns nil -local no_next_line = function() return nil end - --- a function which returns the next batch line -local next_line = no_next_line - -local batchfile = arg[1] - -if batchfile then - local f = io.lines(batchfile) - next_line = function() - local line = f() - if line then - return line - else - next_line = no_next_line - session_stdout_write(batchfile .. ":", "End of batch\n") - return nil - end - end -end - - -local batch_when = 0 -local batch_expect = nil -while not done do - local prompt = ui_set_prompt(ui) - local batch_cmd = next_line() - local cmd, expect_sok = ui.r.readln(do_select_stdin, batch_cmd, batch_when, batch_expect) - if expect_sok and not expect_success(expect_sok, buf, 0) then - if not cmd_ret and next_line ~= no_next_line then - print("ERR: expect timeout\n") - next_line = no_next_line - end - else - local cmd_ret = ui_run_command(ui, cmd) - if not cmd_ret and next_line ~= no_next_line then - print("ERR: Error during batch execution\n") - next_line = no_next_line - end - - if cmd_ret == "quit" then - done = true - end - batch_expect = nil - batch_when = 0 - if type(cmd_ret) == "table" then - if cmd_ret[1] == "delay" then - batch_when = os_time() + tonumber(cmd_ret[2]) - end - if cmd_ret[1] == "expect" then - batch_expect = sessions[cmd_ret[2]] - batch_when = os_time() + 15 - end - end - end -end -ui.r.done() - -os.exit(1) - - - diff --git a/vpp-api/lua/examples/lute/script-inout-acl-noacl.lute b/vpp-api/lua/examples/lute/script-inout-acl-noacl.lute deleted file mode 100644 index a24d04bfb36..00000000000 --- a/vpp-api/lua/examples/lute/script-inout-acl-noacl.lute +++ /dev/null @@ -1,329 +0,0 @@ -shell vppbuild -run vppbuild stty -echo -run vppbuild sudo -u ubuntu -i bash -c "(cd vpp && make plugins && echo ALLGOOD)" -expect vppbuild ALLGOOD - -shell s0 -shell s1 -shell s2 - - -cd s1 -unshare -n /bin/bash -/sbin/ifconfig -a -^D^D^D - -cd s2 -unshare -n /bin/bash -/sbin/ifconfig -a -^D^D^D - - -cd lua - -function session_get_bash_pid(s) - if not has_session(s) then - return nil - end - local fname = "/tmp/lute-"..s.."-pid.txt" - - session_exec(s, "echo $$ >" .. fname) - -- it's a dirty hack but it's quick - sleep(0.5) - local pid = io.lines(fname)() - print("Got pid for " .. s .. " : " .. tostring(pid)) - return(tonumber(pid)) -end - -function session_connect_with(s0, s1) - -- local pid0 = tostring(session_get_bash_pid(s0)) - local pid1 = tostring(session_get_bash_pid(s1)) - local eth_options = { "rx", "tx", "sg", "tso", "ufo", "gso", "gro", "lro", "rxvlan", "txvlan", "rxhash" } - local this_end = s0 .. "_" .. s1 - local other_end = s1 .. "_" .. s0 - session_exec(s0, "ip link add name " .. this_end .. " type veth peer name " .. other_end) - session_exec(s0, "ip link set dev " .. this_end .. " up promisc on") - for i, option in ipairs(eth_options) do - session_exec(s0, "/sbin/ethtool --offload " .. this_end .. " " .. option .. " off") - session_exec(s0, "/sbin/ethtool --offload " .. other_end .. " " .. option .. " off") - end - session_exec(s0, "ip link set dev " .. other_end .. " up promisc on netns /proc/" .. pid1 .. "/ns/net") - sleep(0.5) -end - -^D^D^D -run lua session_connect_with("s0", "s1") -run lua session_connect_with("s0", "s2") - -cd s1 -ip -6 addr add dev s1_s0 2001:db8:1::1/64 -ip -4 addr add dev s1_s0 192.0.2.1/24 -ip link set dev s1_s0 up promisc on -^D^D^D - -cd s2 -ip -6 addr add dev s2_s0 2001:db8:1::2/64 -ip -6 addr add dev s2_s0 2001:db8:1::3/64 -ip -6 addr add dev s2_s0 2001:db8:1::4/64 -ip -4 addr add dev s2_s0 192.0.2.2/24 -ip -4 addr add dev s2_s0:1 192.0.2.3/24 -ip -4 addr add dev s2_s0:2 192.0.2.4/24 -ip link set dev s2_s0 up promisc on -^D^D^D - -run s1 ip addr -run s2 ip addr -shell VPP -cd VPP -cd /home/ubuntu/vpp -make debug -r -^D^D^D -expect VPP DBGvpp# - -cd lua --- Initialization of the Lua environment for talking to VPP -vpp = require("vpp-lapi") -root_dir = "/home/ubuntu/vpp" -pneum_path = root_dir .. "/build-root/install-vpp_debug-native/vpp-api/lib64/libpneum.so" -vpp:init({ pneum_path = pneum_path }) -vpp:consume_api(root_dir .. "/build-root/install-vpp_debug-native/vlib-api/vlibmemory/memclnt.api") -vpp:consume_api(root_dir .. "/build-root/install-vpp_debug-native/vpp/vpp-api/vpe.api") -vpp:connect("aytest") -vpp:consume_api(root_dir .. "/plugins/acl-plugin/acl/acl.api", "acl") - -^D^D^D - -cd lua - -reply = vpp:api_call("af_packet_create", { host_if_name = "s0_s1", hw_addr = "AAAAAA" }) -vpp_if_to_s1 = reply[1].sw_if_index - -reply = vpp:api_call("af_packet_create", { host_if_name = "s0_s2", hw_addr = "AAAAAA" }) -vpp_if_to_s2 = reply[1].sw_if_index - -ifaces = { vpp_if_to_s1, vpp_if_to_s2 } - -reply = vpp:api_call("sw_interface_set_flags", { sw_if_index = vpp_if_to_s1, admin_up_down = 1, link_up_down = 1 }) -print(vpp.dump(reply)) -reply = vpp:api_call("sw_interface_set_flags", { sw_if_index = vpp_if_to_s2, admin_up_down = 1, link_up_down = 1 }) -print(vpp.dump(reply)) - -bd_id = 42 - -reply = vpp:api_call("bridge_domain_add_del", { bd_id = bd_id, flood = 1, uu_flood = 1, forward = 1, learn = 1, arp_term = 0, is_add = 1 }) -print(vpp.dump(reply)) - -for i, v in ipairs(ifaces) do - reply = vpp:api_call("sw_interface_set_l2_bridge", { rx_sw_if_index = v, bd_id = bd_id, shg = 0, bvi = 0, enable = 1 } ) - print(vpp.dump(reply)) -end - -^D^D^D - -run s1 ping -c 3 192.0.2.2 -expect s1 packet loss -run s1 ping -c 3 192.0.2.3 -expect s1 packet loss -run s1 ping -c 3 192.0.2.4 -expect s1 packet loss -run s1 ping6 -c 3 2001:db8:1::2 -expect s1 packet loss -run s1 ping6 -c 3 2001:db8:1::3 -expect s1 packet loss -run s1 ping6 -c 3 2001:db8:1::4 -expect s1 packet loss - - -cd lua ---- ACL testing - ---[[ temporary comment out - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 230 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 8 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 15 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_add_replace", { context = 42, count = 2, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_in = reply[1].acl_index - -reply = vpp:api_call("acl_add_replace", { context = 42, count = 3, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 }, { is_permit = 1, is_ipv6 = 0 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_out = reply[1].acl_index - - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_add_replace", { context = 42, count = 0 }) -print(vpp.dump(reply)) -print("---") - -acl_index_to_delete = reply[1].acl_index -print("Deleting " .. tostring(acl_index_to_delete)) -reply = vpp:api_call("acl_del", { context = 42, acl_index = acl_index_to_delete }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 0}) -for ri, rv in ipairs(reply) do - print("Reply message #" .. tostring(ri)) - print(vpp.dump(rv)) - for ai, av in ipairs(rv.r) do - print("ACL rule #" .. tostring(ai) .. " : " .. vpp.dump(av)) - end - -end -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") -reply = vpp:api_call("acl_del", { context = 42, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 0}) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 4294967295 }) -print(vpp.dump(reply)) -print("---") - - -]] -- end of comment out - ----- Should be nothing ^^ -r = { - { is_permit = 1, is_ipv6 = 1, dst_ip_addr = ip46("2001:db8:1::2"), dst_ip_prefix_len = 128 }, - { is_permit = 0, is_ipv6 = 1, dst_ip_addr = ip46("2001:db8:1::3"), dst_ip_prefix_len = 128 }, - { is_permit = 1, is_ipv6 = 1, dst_ip_addr = ip46("2001:db8::"), dst_ip_prefix_len = 32 }, - { is_permit = 1, is_ipv6 = 0, dst_ip_addr = ip46("192.0.2.2"), dst_ip_prefix_len = 32}, - { is_permit = 0, is_ipv6 = 0, dst_ip_addr = ip46("192.0.2.3"), dst_ip_prefix_len = 32 }, -} - -reply = vpp:api_call("acl_add_replace", { context = 42, count = 5, r = r }) -print(vpp.dump(reply)) -print("---") -interface_acl_in = reply[1].acl_index - -reply = vpp:api_call("acl_add_replace", { context = 42, count = 3, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 }, { is_permit = 1, is_ipv6 = 0 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_out = reply[1].acl_in - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = vpp_if_to_s1, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - ---reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = vpp_if_to_s2, is_add = 1, is_input = 0, acl_index = interface_acl_out }) --- print(vpp.dump(reply)) ---print("---") - -^D^D^D - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::2 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 0 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::3 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 1 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::4 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 2 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping -c 3 192.0.2.2 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 3 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping -c 3 192.0.2.3 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 4 - - -cd lua - ---- TEST OUTBOUND ACL - -r1 = { - { is_permit = 1, is_ipv6 = 1, src_ip_addr = ip46("2001:db8:1::1"), src_ip_prefix_len = 128, dst_ip_addr = ip46("2001:db8:1::2"), dst_ip_prefix_len = 128 }, - { is_permit = 0, is_ipv6 = 1, src_ip_addr = ip46("2001:db8:1::1"), src_ip_prefix_len = 128, dst_ip_addr = ip46("2001:db8:1::4"), dst_ip_prefix_len = 128 } -} - -reply = vpp:api_call("acl_add_replace", { context = 42, count = 3, r = r1 }) -print(vpp.dump(reply)) -print("---") -interface_acl_out = reply[1].acl_index - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = vpp_if_to_s2, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") - - -^D^D^D - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::2 -expect s1 packet loss -run VPP show trace -expect VPP match: outacl 2 rule 0 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::3 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 1 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::4 -expect s1 packet loss -run VPP show trace -expect VPP match: outacl 2 rule 1 - -run lua print("ALL GOOD!") - diff --git a/vpp-api/lua/examples/lute/script-inout-acl-old.lute b/vpp-api/lua/examples/lute/script-inout-acl-old.lute deleted file mode 100644 index 9edebf02f97..00000000000 --- a/vpp-api/lua/examples/lute/script-inout-acl-old.lute +++ /dev/null @@ -1,329 +0,0 @@ -shell vppbuild -run vppbuild stty -echo -run vppbuild sudo -u ubuntu -i bash -c "(cd vpp && make plugins && echo ALLGOOD)" -expect vppbuild ALLGOOD - -shell s0 -shell s1 -shell s2 - - -cd s1 -unshare -n /bin/bash -/sbin/ifconfig -a -^D^D^D - -cd s2 -unshare -n /bin/bash -/sbin/ifconfig -a -^D^D^D - - -cd lua - -function session_get_bash_pid(s) - if not has_session(s) then - return nil - end - local fname = "/tmp/lute-"..s.."-pid.txt" - - session_exec(s, "echo $$ >" .. fname) - -- it's a dirty hack but it's quick - sleep(0.5) - local pid = io.lines(fname)() - print("Got pid for " .. s .. " : " .. tostring(pid)) - return(tonumber(pid)) -end - -function session_connect_with(s0, s1) - -- local pid0 = tostring(session_get_bash_pid(s0)) - local pid1 = tostring(session_get_bash_pid(s1)) - local eth_options = { "rx", "tx", "sg", "tso", "ufo", "gso", "gro", "lro", "rxvlan", "txvlan", "rxhash" } - local this_end = s0 .. "_" .. s1 - local other_end = s1 .. "_" .. s0 - session_exec(s0, "ip link add name " .. this_end .. " type veth peer name " .. other_end) - session_exec(s0, "ip link set dev " .. this_end .. " up promisc on") - for i, option in ipairs(eth_options) do - session_exec(s0, "/sbin/ethtool --offload " .. this_end .. " " .. option .. " off") - session_exec(s0, "/sbin/ethtool --offload " .. other_end .. " " .. option .. " off") - end - session_exec(s0, "ip link set dev " .. other_end .. " up promisc on netns /proc/" .. pid1 .. "/ns/net") - sleep(0.5) -end - -^D^D^D -run lua session_connect_with("s0", "s1") -run lua session_connect_with("s0", "s2") - -cd s1 -ip -6 addr add dev s1_s0 2001:db8:1::1/64 -ip -4 addr add dev s1_s0 192.0.2.1/24 -ip link set dev s1_s0 up promisc on -^D^D^D - -cd s2 -ip -6 addr add dev s2_s0 2001:db8:1::2/64 -ip -6 addr add dev s2_s0 2001:db8:1::3/64 -ip -6 addr add dev s2_s0 2001:db8:1::4/64 -ip -4 addr add dev s2_s0 192.0.2.2/24 -ip -4 addr add dev s2_s0:1 192.0.2.3/24 -ip -4 addr add dev s2_s0:2 192.0.2.4/24 -ip link set dev s2_s0 up promisc on -^D^D^D - -run s1 ip addr -run s2 ip addr -shell VPP -cd VPP -cd /home/ubuntu/vpp -make debug -r -^D^D^D -expect VPP DBGvpp# - -cd lua --- Initialization of the Lua environment for talking to VPP -vpp = require("vpp-lapi") -root_dir = "/home/ubuntu/vpp" -pneum_path = root_dir .. "/build-root/install-vpp_debug-native/vpp-api/lib64/libpneum.so" -vpp:init({ pneum_path = pneum_path }) -vpp:consume_api(root_dir .. "/build-root/install-vpp_debug-native/vlib-api/vlibmemory/memclnt.api") -vpp:consume_api(root_dir .. "/build-root/install-vpp_debug-native/vpp/vpp-api/vpe.api") -vpp:connect("aytest") -vpp:consume_api(root_dir .. "/plugins/acl-plugin/acl/acl.api", "acl") - -^D^D^D - -cd lua - -reply = vpp:api_call("af_packet_create", { host_if_name = "s0_s1", hw_addr = "AAAAAA" }) -vpp_if_to_s1 = reply[1].sw_if_index - -reply = vpp:api_call("af_packet_create", { host_if_name = "s0_s2", hw_addr = "AAAAAA" }) -vpp_if_to_s2 = reply[1].sw_if_index - -ifaces = { vpp_if_to_s1, vpp_if_to_s2 } - -reply = vpp:api_call("sw_interface_set_flags", { sw_if_index = vpp_if_to_s1, admin_up_down = 1, link_up_down = 1 }) -print(vpp.dump(reply)) -reply = vpp:api_call("sw_interface_set_flags", { sw_if_index = vpp_if_to_s2, admin_up_down = 1, link_up_down = 1 }) -print(vpp.dump(reply)) - -bd_id = 42 - -reply = vpp:api_call("bridge_domain_add_del", { bd_id = bd_id, flood = 1, uu_flood = 1, forward = 1, learn = 1, arp_term = 0, is_add = 1 }) -print(vpp.dump(reply)) - -for i, v in ipairs(ifaces) do - reply = vpp:api_call("sw_interface_set_l2_bridge", { rx_sw_if_index = v, bd_id = bd_id, shg = 0, bvi = 0, enable = 1 } ) - print(vpp.dump(reply)) -end - -^D^D^D - -run s1 ping -c 3 192.0.2.2 -expect s1 packet loss -run s1 ping -c 3 192.0.2.3 -expect s1 packet loss -run s1 ping -c 3 192.0.2.4 -expect s1 packet loss -run s1 ping6 -c 3 2001:db8:1::2 -expect s1 packet loss -run s1 ping6 -c 3 2001:db8:1::3 -expect s1 packet loss -run s1 ping6 -c 3 2001:db8:1::4 -expect s1 packet loss - - -cd lua ---- ACL testing - ---[[ temporary comment out - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 230 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 8 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 15 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_add", { context = 42, count = 2, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_in = reply[1].acl_index - -reply = vpp:api_call("acl_add", { context = 42, count = 3, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 }, { is_permit = 1, is_ipv6 = 0 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_out = reply[1].acl_index - - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_add", { context = 42, count = 0 }) -print(vpp.dump(reply)) -print("---") - -acl_index_to_delete = reply[1].acl_index -print("Deleting " .. tostring(acl_index_to_delete)) -reply = vpp:api_call("acl_del", { context = 42, acl_index = acl_index_to_delete }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 0}) -for ri, rv in ipairs(reply) do - print("Reply message #" .. tostring(ri)) - print(vpp.dump(rv)) - for ai, av in ipairs(rv.r) do - print("ACL rule #" .. tostring(ai) .. " : " .. vpp.dump(av)) - end - -end -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") -reply = vpp:api_call("acl_del", { context = 42, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 0}) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 4294967295 }) -print(vpp.dump(reply)) -print("---") - - -]] -- end of comment out - ----- Should be nothing ^^ -r = { - { is_permit = 1, is_ipv6 = 1, dst_ip_addr = ip46("2001:db8:1::2"), dst_ip_prefix_len = 128 }, - { is_permit = 0, is_ipv6 = 1, dst_ip_addr = ip46("2001:db8:1::3"), dst_ip_prefix_len = 128 }, - { is_permit = 1, is_ipv6 = 1, dst_ip_addr = ip46("2001:db8::"), dst_ip_prefix_len = 32 }, - { is_permit = 1, is_ipv6 = 0, dst_ip_addr = ip46("192.0.2.2"), dst_ip_prefix_len = 32}, - { is_permit = 0, is_ipv6 = 0, dst_ip_addr = ip46("192.0.2.3"), dst_ip_prefix_len = 32 }, -} - -reply = vpp:api_call("acl_add", { context = 42, count = 5, r = r }) -print(vpp.dump(reply)) -print("---") -interface_acl_in = reply[1].acl_index - -reply = vpp:api_call("acl_add", { context = 42, count = 3, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 }, { is_permit = 1, is_ipv6 = 0 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_out = reply[1].acl_in - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = vpp_if_to_s1, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - ---reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = vpp_if_to_s2, is_add = 1, is_input = 0, acl_index = interface_acl_out }) --- print(vpp.dump(reply)) ---print("---") - -^D^D^D - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::2 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 0 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::3 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 1 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::4 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 2 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping -c 3 192.0.2.2 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 3 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping -c 3 192.0.2.3 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 4 - - -cd lua - ---- TEST OUTBOUND ACL - -r1 = { - { is_permit = 1, is_ipv6 = 1, src_ip_addr = ip46("2001:db8:1::1"), src_ip_prefix_len = 128, dst_ip_addr = ip46("2001:db8:1::2"), dst_ip_prefix_len = 128 }, - { is_permit = 0, is_ipv6 = 1, src_ip_addr = ip46("2001:db8:1::1"), src_ip_prefix_len = 128, dst_ip_addr = ip46("2001:db8:1::4"), dst_ip_prefix_len = 128 } -} - -reply = vpp:api_call("acl_add", { context = 42, count = 3, r = r1 }) -print(vpp.dump(reply)) -print("---") -interface_acl_out = reply[1].acl_index - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = vpp_if_to_s2, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") - - -^D^D^D - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::2 -expect s1 packet loss -run VPP show trace -expect VPP match: outacl 2 rule 0 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::3 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 1 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::4 -expect s1 packet loss -run VPP show trace -expect VPP match: outacl 2 rule 1 - -run lua print("ALL GOOD!") - diff --git a/vpp-api/lua/examples/lute/script-inout-acl.lute b/vpp-api/lua/examples/lute/script-inout-acl.lute deleted file mode 100644 index d7e7423c7cf..00000000000 --- a/vpp-api/lua/examples/lute/script-inout-acl.lute +++ /dev/null @@ -1,329 +0,0 @@ -shell vppbuild -run vppbuild stty -echo -run vppbuild sudo -u ubuntu -i bash -c "(cd vpp && make plugins && echo ALLGOOD)" -expect vppbuild ALLGOOD - -shell s0 -shell s1 -shell s2 - - -cd s1 -unshare -n /bin/bash -/sbin/ifconfig -a -^D^D^D - -cd s2 -unshare -n /bin/bash -/sbin/ifconfig -a -^D^D^D - - -cd lua - -function session_get_bash_pid(s) - if not has_session(s) then - return nil - end - local fname = "/tmp/lute-"..s.."-pid.txt" - - session_exec(s, "echo $$ >" .. fname) - -- it's a dirty hack but it's quick - sleep(0.5) - local pid = io.lines(fname)() - print("Got pid for " .. s .. " : " .. tostring(pid)) - return(tonumber(pid)) -end - -function session_connect_with(s0, s1) - -- local pid0 = tostring(session_get_bash_pid(s0)) - local pid1 = tostring(session_get_bash_pid(s1)) - local eth_options = { "rx", "tx", "sg", "tso", "ufo", "gso", "gro", "lro", "rxvlan", "txvlan", "rxhash" } - local this_end = s0 .. "_" .. s1 - local other_end = s1 .. "_" .. s0 - session_exec(s0, "ip link add name " .. this_end .. " type veth peer name " .. other_end) - session_exec(s0, "ip link set dev " .. this_end .. " up promisc on") - for i, option in ipairs(eth_options) do - session_exec(s0, "/sbin/ethtool --offload " .. this_end .. " " .. option .. " off") - session_exec(s0, "/sbin/ethtool --offload " .. other_end .. " " .. option .. " off") - end - session_exec(s0, "ip link set dev " .. other_end .. " up promisc on netns /proc/" .. pid1 .. "/ns/net") - sleep(0.5) -end - -^D^D^D -run lua session_connect_with("s0", "s1") -run lua session_connect_with("s0", "s2") - -cd s1 -ip -6 addr add dev s1_s0 2001:db8:1::1/64 -ip -4 addr add dev s1_s0 192.0.2.1/24 -ip link set dev s1_s0 up promisc on -^D^D^D - -cd s2 -ip -6 addr add dev s2_s0 2001:db8:1::2/64 -ip -6 addr add dev s2_s0 2001:db8:1::3/64 -ip -6 addr add dev s2_s0 2001:db8:1::4/64 -ip -4 addr add dev s2_s0 192.0.2.2/24 -ip -4 addr add dev s2_s0:1 192.0.2.3/24 -ip -4 addr add dev s2_s0:2 192.0.2.4/24 -ip link set dev s2_s0 up promisc on -^D^D^D - -run s1 ip addr -run s2 ip addr -shell VPP -cd VPP -cd /home/ubuntu/vpp -make debug -r -^D^D^D -expect VPP DBGvpp# - -cd lua --- Initialization of the Lua environment for talking to VPP -vpp = require("vpp-lapi") -root_dir = "/home/ubuntu/vpp" -pneum_path = root_dir .. "/build-root/install-vpp_debug-native/vpp-api/lib64/libpneum.so" -vpp:init({ pneum_path = pneum_path }) -vpp:consume_api(root_dir .. "/build-root/install-vpp_debug-native/vlib-api/vlibmemory/memclnt.api") -vpp:consume_api(root_dir .. "/build-root/install-vpp_debug-native/vpp/vpp-api/vpe.api") -vpp:connect("aytest") -vpp:consume_api(root_dir .. "/plugins/acl-plugin/acl/acl.api", "acl") - -^D^D^D - -cd lua - -reply = vpp:api_call("af_packet_create", { host_if_name = "s0_s1", hw_addr = "AAAAAA" }) -vpp_if_to_s1 = reply[1].sw_if_index - -reply = vpp:api_call("af_packet_create", { host_if_name = "s0_s2", hw_addr = "AAAAAA" }) -vpp_if_to_s2 = reply[1].sw_if_index - -ifaces = { vpp_if_to_s1, vpp_if_to_s2 } - -reply = vpp:api_call("sw_interface_set_flags", { sw_if_index = vpp_if_to_s1, admin_up_down = 1, link_up_down = 1 }) -print(vpp.dump(reply)) -reply = vpp:api_call("sw_interface_set_flags", { sw_if_index = vpp_if_to_s2, admin_up_down = 1, link_up_down = 1 }) -print(vpp.dump(reply)) - -bd_id = 42 - -reply = vpp:api_call("bridge_domain_add_del", { bd_id = bd_id, flood = 1, uu_flood = 1, forward = 1, learn = 1, arp_term = 0, is_add = 1 }) -print(vpp.dump(reply)) - -for i, v in ipairs(ifaces) do - reply = vpp:api_call("sw_interface_set_l2_bridge", { rx_sw_if_index = v, bd_id = bd_id, shg = 0, bvi = 0, enable = 1 } ) - print(vpp.dump(reply)) -end - -^D^D^D - -run s1 ping -c 3 192.0.2.2 -expect s1 packet loss -run s1 ping -c 3 192.0.2.3 -expect s1 packet loss -run s1 ping -c 3 192.0.2.4 -expect s1 packet loss -run s1 ping6 -c 3 2001:db8:1::2 -expect s1 packet loss -run s1 ping6 -c 3 2001:db8:1::3 -expect s1 packet loss -run s1 ping6 -c 3 2001:db8:1::4 -expect s1 packet loss - - -cd lua ---- ACL testing - ---[[ temporary comment out - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 230 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 8 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 15 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_add_replace", { context = 42, acl_index = -1, count = 2, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_in = reply[1].acl_index - -reply = vpp:api_call("acl_add_replace", { context = 42, acl_index = -1, count = 3, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 }, { is_permit = 1, is_ipv6 = 0 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_out = reply[1].acl_index - - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_add_replace", { context = 42, acl_index = -1, count = 0 }) -print(vpp.dump(reply)) -print("---") - -acl_index_to_delete = reply[1].acl_index -print("Deleting " .. tostring(acl_index_to_delete)) -reply = vpp:api_call("acl_del", { context = 42, acl_index = acl_index_to_delete }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 0}) -for ri, rv in ipairs(reply) do - print("Reply message #" .. tostring(ri)) - print(vpp.dump(rv)) - for ai, av in ipairs(rv.r) do - print("ACL rule #" .. tostring(ai) .. " : " .. vpp.dump(av)) - end - -end -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") -reply = vpp:api_call("acl_del", { context = 42, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 0}) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 4294967295 }) -print(vpp.dump(reply)) -print("---") - - -]] -- end of comment out - ----- Should be nothing ^^ -r = { - { is_permit = 1, is_ipv6 = 1, dst_ip_addr = ip46("2001:db8:1::2"), dst_ip_prefix_len = 128 }, - { is_permit = 0, is_ipv6 = 1, dst_ip_addr = ip46("2001:db8:1::3"), dst_ip_prefix_len = 128 }, - { is_permit = 1, is_ipv6 = 1, dst_ip_addr = ip46("2001:db8::"), dst_ip_prefix_len = 32 }, - { is_permit = 1, is_ipv6 = 0, dst_ip_addr = ip46("192.0.2.2"), dst_ip_prefix_len = 32}, - { is_permit = 0, is_ipv6 = 0, dst_ip_addr = ip46("192.0.2.3"), dst_ip_prefix_len = 32 }, -} - -reply = vpp:api_call("acl_add_replace", { context = 42, acl_index = -1, count = 5, r = r }) -print(vpp.dump(reply)) -print("---") -interface_acl_in = reply[1].acl_index - -reply = vpp:api_call("acl_add_replace", { context = 42, acl_index = -1, count = 3, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 }, { is_permit = 1, is_ipv6 = 0 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_out = reply[1].acl_in - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = vpp_if_to_s1, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - ---reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = vpp_if_to_s2, is_add = 1, is_input = 0, acl_index = interface_acl_out }) --- print(vpp.dump(reply)) ---print("---") - -^D^D^D - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::2 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 0 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::3 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 1 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::4 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 2 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping -c 3 192.0.2.2 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 3 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping -c 3 192.0.2.3 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 4 - - -cd lua - ---- TEST OUTBOUND ACL - -r1 = { - { is_permit = 1, is_ipv6 = 1, src_ip_addr = ip46("2001:db8:1::1"), src_ip_prefix_len = 128, dst_ip_addr = ip46("2001:db8:1::2"), dst_ip_prefix_len = 128 }, - { is_permit = 0, is_ipv6 = 1, src_ip_addr = ip46("2001:db8:1::1"), src_ip_prefix_len = 128, dst_ip_addr = ip46("2001:db8:1::4"), dst_ip_prefix_len = 128 } -} - -reply = vpp:api_call("acl_add_replace", { context = 42, acl_index = -1, count = 3, r = r1 }) -print(vpp.dump(reply)) -print("---") -interface_acl_out = reply[1].acl_index - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = vpp_if_to_s2, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") - - -^D^D^D - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::2 -expect s1 packet loss -run VPP show trace -expect VPP match: outacl 2 rule 0 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::3 -expect s1 packet loss -run VPP show trace -expect VPP match: inacl 0 rule 1 - -run VPP clear trace -run VPP trace add af-packet-input 100 -run s1 ping6 -c 3 2001:db8:1::4 -expect s1 packet loss -run VPP show trace -expect VPP match: outacl 2 rule 1 - -run lua print("ALL GOOD!") - diff --git a/vpp-api/lua/examples/lute/script.lute b/vpp-api/lua/examples/lute/script.lute deleted file mode 100644 index c3dd90f2dbe..00000000000 --- a/vpp-api/lua/examples/lute/script.lute +++ /dev/null @@ -1,7 +0,0 @@ -shell s1 -expect s1 $ -run s1 echo testing123 -expect s1 $ -run s1 echo done -quit - diff --git a/vpp-api/lua/examples/lute/sessions-acl.lute b/vpp-api/lua/examples/lute/sessions-acl.lute deleted file mode 100644 index ac237ef9d90..00000000000 --- a/vpp-api/lua/examples/lute/sessions-acl.lute +++ /dev/null @@ -1,308 +0,0 @@ -run lua -- collectgarbage("stop") - -shell vppbuild -run vppbuild stty -echo -run vppbuild sudo -u ubuntu -i bash -c "(cd vpp && make plugins && echo ALLGOOD)" -expect vppbuild ALLGOOD - -shell s0 -shell s1 -shell s2 - - -cd s1 -unshare -n /bin/bash -/sbin/ifconfig -a -^D^D^D - -cd s2 -unshare -n /bin/bash -/sbin/ifconfig -a -^D^D^D - - -cd lua - -function session_get_bash_pid(s) - if not has_session(s) then - return nil - end - local fname = "/tmp/lute-"..s.."-pid.txt" - - session_exec(s, "echo $$ >" .. fname) - -- it's a dirty hack but it's quick - sleep(0.5) - local pid = io.lines(fname)() - print("Got pid for " .. s .. " : " .. tostring(pid)) - return(tonumber(pid)) -end - -function session_connect_with(s0, s1) - -- local pid0 = tostring(session_get_bash_pid(s0)) - local pid1 = tostring(session_get_bash_pid(s1)) - local eth_options = { "rx", "tx", "sg", "tso", "ufo", "gso", "gro", "lro", "rxvlan", "txvlan", "rxhash" } - local this_end = s0 .. "_" .. s1 - local other_end = s1 .. "_" .. s0 - session_exec(s0, "ip link add name " .. this_end .. " type veth peer name " .. other_end) - session_exec(s0, "ip link set dev " .. this_end .. " up promisc on") - for i, option in ipairs(eth_options) do - session_exec(s0, "/sbin/ethtool --offload " .. this_end .. " " .. option .. " off") - session_exec(s0, "/sbin/ethtool --offload " .. other_end .. " " .. option .. " off") - end - session_exec(s0, "ip link set dev " .. other_end .. " up promisc on netns /proc/" .. pid1 .. "/ns/net") - sleep(0.5) -end - -^D^D^D -run lua session_connect_with("s0", "s1") -run lua session_connect_with("s0", "s2") - -cd s1 -ip -6 addr add dev s1_s0 2001:db8:1::1/64 -ip -4 addr add dev s1_s0 192.0.2.1/24 -ip link set dev s1_s0 up promisc on -^D^D^D - -cd s2 -ip -6 addr add dev s2_s0 2001:db8:1::2/64 -ip -6 addr add dev s2_s0 2001:db8:1::3/64 -ip -6 addr add dev s2_s0 2001:db8:1::4/64 -ip -4 addr add dev s2_s0 192.0.2.2/24 -ip -4 addr add dev s2_s0:1 192.0.2.3/24 -ip -4 addr add dev s2_s0:2 192.0.2.4/24 -ip link set dev s2_s0 up promisc on -^D^D^D - -run s1 ip addr -run s2 ip addr -shell VPP -cd VPP -cd /home/ubuntu/vpp -make debug -r -^D^D^D -expect VPP DBGvpp# - -cd lua --- Initialization of the Lua environment for talking to VPP -vpp = require("vpp-lapi") -root_dir = "/home/ubuntu/vpp" -pneum_path = root_dir .. "/build-root/install-vpp_debug-native/vpp-api/lib64/libpneum.so" -vpp:init({ pneum_path = pneum_path }) -vpp:consume_api(root_dir .. "/build-root/install-vpp_debug-native/vlib-api/vlibmemory/memclnt.api") -vpp:consume_api(root_dir .. "/build-root/install-vpp_debug-native/vpp/vpp-api/vpe.api") -vpp:connect("aytest") -vpp:consume_api(root_dir .. "/plugins/acl-plugin/acl/acl.api", "acl") - -^D^D^D - -cd lua - -reply = vpp:api_call("af_packet_create", { host_if_name = "s0_s1", hw_addr = "AAAAAA" }) -vpp_if_to_s1 = reply[1].sw_if_index - -reply = vpp:api_call("af_packet_create", { host_if_name = "s0_s2", hw_addr = "AAAAAA" }) -vpp_if_to_s2 = reply[1].sw_if_index - -ifaces = { vpp_if_to_s1, vpp_if_to_s2 } - -reply = vpp:api_call("sw_interface_set_flags", { sw_if_index = vpp_if_to_s1, admin_up_down = 1, link_up_down = 1 }) -print(vpp.dump(reply)) -reply = vpp:api_call("sw_interface_set_flags", { sw_if_index = vpp_if_to_s2, admin_up_down = 1, link_up_down = 1 }) -print(vpp.dump(reply)) - -bd_id = 42 - -reply = vpp:api_call("bridge_domain_add_del", { bd_id = bd_id, flood = 1, uu_flood = 1, forward = 1, learn = 1, arp_term = 0, is_add = 1 }) -print(vpp.dump(reply)) - -for i, v in ipairs(ifaces) do - reply = vpp:api_call("sw_interface_set_l2_bridge", { rx_sw_if_index = v, bd_id = bd_id, shg = 0, bvi = 0, enable = 1 } ) - print(vpp.dump(reply)) -end - -^D^D^D - -run s1 ping -c 3 192.0.2.2 -expect s1 packet loss -run s1 ping -c 3 192.0.2.3 -expect s1 packet loss -run s1 ping -c 3 192.0.2.4 -expect s1 packet loss -run s1 ping6 -c 3 2001:db8:1::2 -expect s1 packet loss -run s1 ping6 -c 3 2001:db8:1::3 -expect s1 packet loss -run s1 ping6 -c 3 2001:db8:1::4 -expect s1 packet loss - - -cd lua ---- ACL testing - ---[[ temporary comment out - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 230 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 8 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = 15 }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_add", { context = 42, count = 2, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_in = reply[1].acl_index - -reply = vpp:api_call("acl_add", { context = 42, count = 3, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 }, { is_permit = 1, is_ipv6 = 0 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_out = reply[1].acl_index - - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = 0, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_add", { context = 42, count = 0 }) -print(vpp.dump(reply)) -print("---") - -acl_index_to_delete = reply[1].acl_index -print("Deleting " .. tostring(acl_index_to_delete)) -reply = vpp:api_call("acl_del", { context = 42, acl_index = acl_index_to_delete }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 0}) -for ri, rv in ipairs(reply) do - print("Reply message #" .. tostring(ri)) - print(vpp.dump(rv)) - for ai, av in ipairs(rv.r) do - print("ACL rule #" .. tostring(ai) .. " : " .. vpp.dump(av)) - end - -end -print("---") - -reply = vpp:api_call("acl_del", { context = 42, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") -reply = vpp:api_call("acl_del", { context = 42, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 0}) -print(vpp.dump(reply)) -print("---") - -reply = vpp:api_call("acl_dump", { context = 42, sw_if_index = 4294967295 }) -print(vpp.dump(reply)) -print("---") - - -]] -- end of comment out - ----- Should be nothing ^^ -r = { - { is_permit = 1, is_ipv6 = 1, dst_ip_addr = ip46("2001:db8:1::2"), dst_ip_prefix_len = 128 }, - { is_permit = 0, is_ipv6 = 1, dst_ip_addr = ip46("2001:db8:1::3"), dst_ip_prefix_len = 128 }, - { is_permit = 1, is_ipv6 = 1, dst_ip_addr = ip46("2001:db8::"), dst_ip_prefix_len = 32 }, - { is_permit = 1, is_ipv6 = 0, dst_ip_addr = ip46("192.0.2.2"), dst_ip_prefix_len = 32}, - { is_permit = 0, is_ipv6 = 0, dst_ip_addr = ip46("192.0.2.3"), dst_ip_prefix_len = 32 }, -} - -reply = vpp:api_call("acl_add", { context = 42, count = 5, r = r }) -print(vpp.dump(reply)) -print("---") -interface_acl_in = reply[1].acl_index - -reply = vpp:api_call("acl_add", { context = 42, count = 3, r = { { is_permit = 1, is_ipv6 = 1 }, { is_permit = 0, is_ipv6 = 1 }, { is_permit = 1, is_ipv6 = 0 } } }) -print(vpp.dump(reply)) -print("---") -interface_acl_out = reply[1].acl_in - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = vpp_if_to_s1, is_add = 1, is_input = 1, acl_index = interface_acl_in }) -print(vpp.dump(reply)) -print("---") - ---- TEST OUTBOUND ACL - -r1 = { - { is_permit = 1, is_ipv6 = 1, src_ip_addr = ip46("2001:db8:1::1"), src_ip_prefix_len = 128, dst_ip_addr = ip46("2001:db8:1::2"), dst_ip_prefix_len = 128 }, - { is_permit = 0, is_ipv6 = 1, src_ip_addr = ip46("2001:db8:1::1"), src_ip_prefix_len = 128, dst_ip_addr = ip46("2001:db8:1::4"), dst_ip_prefix_len = 128 }, - { is_permit = 2, is_ipv6 = 0 } -} - -reply = vpp:api_call("acl_add", { context = 42, count = 3, r = r1 }) -print(vpp.dump(reply)) -print("---") -interface_acl_out = reply[1].acl_index - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = vpp_if_to_s2, is_add = 1, is_input = 0, acl_index = interface_acl_out }) -print(vpp.dump(reply)) -print("---") - -r2 = { - { is_permit = 1, is_ipv6 = 1 }, - { is_permit = 0, is_ipv6 = 0 } -} - -reply = vpp:api_call("acl_add", { context = 42, count = 2, r = r2 }) -print(vpp.dump(reply)) -print("---") -second_interface_acl_in = reply[1].acl_index - -reply = vpp:api_call("acl_interface_add_del", { context = 42, sw_if_index = vpp_if_to_s2, is_add = 1, is_input = 1, acl_index = second_interface_acl_in }) -print(vpp.dump(reply)) -print("---") - -^D^D^D - -run VPP show classify tables -run VPP clear trace -run VPP trace add af-packet-input 100 -run s2 nc -v -l -p 22 -run s1 nc 192.0.2.2 22 -run s1 echo -sleep 1 -run s1 break -sleep 1 -run VPP show trace -expect VPP match: outacl 2 rule 2 -run VPP show classify tables - - -run VPP show classify tables -run VPP clear trace -run VPP trace add af-packet-input 100 -run s2 nc -v -l -p 22 -run s1 nc 192.0.2.2 22 -run s1 echo -sleep 1 -run s1 break -sleep 1 -run VPP show trace -expect VPP match: outacl 2 rule 2 -run VPP show classify tables - - -run lua print("ALL GOOD!") - diff --git a/vpp-api/lua/vpp-lapi.lua b/vpp-api/lua/vpp-lapi.lua deleted file mode 100644 index ebfd032b096..00000000000 --- a/vpp-api/lua/vpp-lapi.lua +++ /dev/null @@ -1,989 +0,0 @@ ---[[ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -]] - --- json decode/encode from https://gist.github.com/tylerneylon/59f4bcf316be525b30ab --- licensed by the author tylerneylon into public domain. Thanks! - -local json = {} - --- Internal functions. - -local function kind_of(obj) - if type(obj) ~= 'table' then return type(obj) end - local i = 1 - for _ in pairs(obj) do - if obj[i] ~= nil then i = i + 1 else return 'table' end - end - if i == 1 then return 'table' else return 'array' end -end - -local function escape_str(s) - local in_char = {'\\', '"', '/', '\b', '\f', '\n', '\r', '\t'} - local out_char = {'\\', '"', '/', 'b', 'f', 'n', 'r', 't'} - for i, c in ipairs(in_char) do - s = s:gsub(c, '\\' .. out_char[i]) - end - return s -end - --- Returns pos, did_find; there are two cases: --- 1. Delimiter found: pos = pos after leading space + delim; did_find = true. --- 2. Delimiter not found: pos = pos after leading space; did_find = false. --- This throws an error if err_if_missing is true and the delim is not found. -local function skip_delim(str, pos, delim, err_if_missing) - pos = pos + #str:match('^%s*', pos) - if str:sub(pos, pos) ~= delim then - if err_if_missing then - error('Expected ' .. delim .. ' near position ' .. pos) - end - return pos, false - end - return pos + 1, true -end - --- Expects the given pos to be the first character after the opening quote. --- Returns val, pos; the returned pos is after the closing quote character. -local function parse_str_val(str, pos, val) - val = val or '' - local early_end_error = 'End of input found while parsing string.' - if pos > #str then error(early_end_error) end - local c = str:sub(pos, pos) - if c == '"' then return val, pos + 1 end - if c ~= '\\' then return parse_str_val(str, pos + 1, val .. c) end - -- We must have a \ character. - local esc_map = {b = '\b', f = '\f', n = '\n', r = '\r', t = '\t'} - local nextc = str:sub(pos + 1, pos + 1) - if not nextc then error(early_end_error) end - return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc)) -end - --- Returns val, pos; the returned pos is after the number's final character. -local function parse_num_val(str, pos) - local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos) - local val = tonumber(num_str) - if not val then error('Error parsing number at position ' .. pos .. '.') end - return val, pos + #num_str -end - - --- Public values and functions. - -function json.stringify(obj, as_key) - local s = {} -- We'll build the string as an array of strings to be concatenated. - local kind = kind_of(obj) -- This is 'array' if it's an array or type(obj) otherwise. - if kind == 'array' then - if as_key then error('Can\'t encode array as key.') end - s[#s + 1] = '[' - for i, val in ipairs(obj) do - if i > 1 then s[#s + 1] = ', ' end - s[#s + 1] = json.stringify(val) - end - s[#s + 1] = ']' - elseif kind == 'table' then - if as_key then error('Can\'t encode table as key.') end - s[#s + 1] = '{' - for k, v in pairs(obj) do - if #s > 1 then s[#s + 1] = ', ' end - s[#s + 1] = json.stringify(k, true) - s[#s + 1] = ':' - s[#s + 1] = json.stringify(v) - end - s[#s + 1] = '}' - elseif kind == 'string' then - return '"' .. escape_str(obj) .. '"' - elseif kind == 'number' then - if as_key then return '"' .. tostring(obj) .. '"' end - return tostring(obj) - elseif kind == 'boolean' then - return tostring(obj) - elseif kind == 'nil' then - return 'null' - else - error('Unjsonifiable type: ' .. kind .. '.') - end - return table.concat(s) -end - -json.null = {} -- This is a one-off table to represent the null value. - -function json.parse(str, pos, end_delim) - pos = pos or 1 - if pos > #str then error('Reached unexpected end of input.') end - local pos = pos + #str:match('^%s*', pos) -- Skip whitespace. - local first = str:sub(pos, pos) - if first == '{' then -- Parse an object. - local obj, key, delim_found = {}, true, true - pos = pos + 1 - while true do - key, pos = json.parse(str, pos, '}') - if key == nil then return obj, pos end - if not delim_found then error('Comma missing between object items.') end - pos = skip_delim(str, pos, ':', true) -- true -> error if missing. - obj[key], pos = json.parse(str, pos) - pos, delim_found = skip_delim(str, pos, ',') - end - elseif first == '[' then -- Parse an array. - local arr, val, delim_found = {}, true, true - pos = pos + 1 - while true do - val, pos = json.parse(str, pos, ']') - if val == nil then return arr, pos end - if not delim_found then error('Comma missing between array items.') end - arr[#arr + 1] = val - pos, delim_found = skip_delim(str, pos, ',') - end - elseif first == '"' then -- Parse a string. - return parse_str_val(str, pos + 1) - elseif first == '-' or first:match('%d') then -- Parse a number. - return parse_num_val(str, pos) - elseif first == end_delim then -- End of an object or array. - return nil, pos + 1 - else -- Parse true, false, or null. - local literals = {['true'] = true, ['false'] = false, ['null'] = json.null} - for lit_str, lit_val in pairs(literals) do - local lit_end = pos + #lit_str - 1 - if str:sub(pos, lit_end) == lit_str then return lit_val, lit_end + 1 end - end - local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10) - error('Invalid json syntax starting at ' .. pos_info_str) - end -end - - -local vpp = {} - -local ffi = require("ffi") - ---[[ - -The basic type definitions. A bit of weird gymnastic with -unionization of the hton* and ntoh* functions results -is to make handling of signed and unsigned types a bit cleaner, -essentially building typecasting into a C union. - -The vl_api_opaque_message_t is a synthetic type assumed to have -enough storage to hold the entire API message regardless of the type. -During the operation it is casted to the specific message struct types. - -]] - - -ffi.cdef([[ - -typedef uint8_t u8; -typedef int8_t i8; -typedef uint16_t u16; -typedef int16_t i16; -typedef uint32_t u32; -typedef int32_t i32; -typedef uint64_t u64; -typedef int64_t i64; -typedef double f64; -typedef float f32; - -#pragma pack(1) -typedef union { - u16 u16; - i16 i16; -} lua_ui16t; - -#pragma pack(1) -typedef union { - u32 u32; - i32 i32; -} lua_ui32t; - -u16 ntohs(uint16_t hostshort); -u16 htons(uint16_t hostshort); -u32 htonl(uint32_t along); -u32 ntohl(uint32_t along); -void *memset(void *s, int c, size_t n); -void *memcpy(void *dest, void *src, size_t n); - -#pragma pack(1) -typedef struct _vl_api_opaque_message { - u16 _vl_msg_id; - u8 data[65536]; -} vl_api_opaque_message_t; -]]) - - --- CRC-based version stuff - -local crc32c_table = ffi.new('const uint32_t[256]', - { 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, - 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, - 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, - 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, - 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, - 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, - 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, - 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, - 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, - 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, - 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, - 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, - 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, - 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, - 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, - 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, - 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, - 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, - 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, - 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, - 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, - 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, - 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, - 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, - 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, - 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, - 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, - 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, - 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, - 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, - 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, - 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, - 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, - 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, - 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, - 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, - 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, - 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, - 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, - 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, - 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, - 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, - 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, - 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, - 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, - 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, - 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, - 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, - 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, - 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, - 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, - 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, - 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, - 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, - 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, - 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, - 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, - 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, - 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, - 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, - 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, - 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, - 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, - 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 } -); - -local function CRC8(crc, d) - return bit.bxor(bit.rshift(crc, 8), crc32c_table[bit.band(0xff, bit.bxor(crc, d))]) -end - -local function CRC16(crc, d) - crc = CRC8(crc, bit.band(d, 0xFF)) - d = bit.rshift(d, 8) - crc = CRC8(crc, bit.band(d, 0xFF)) - return crc -end - -local function string_crc(str, crc) - for i=1,#str do - -- print("S", i, string.byte(str, i), string.char(string.byte(str, i))) - crc = CRC8(crc, string.byte(str, i)) - end - return crc -end - -local tokens = { - { ["match"] =' ', ["act"] = { } }, - { ["match"] ='\n', ["act"] = { } }, - { ["match"] ="manual_endian", ["act"] = { "NODE_MANUAL_ENDIAN", "MANUAL_ENDIAN", 276 } }, - { ["match"] ="define", ["act"] = { "NODE_DEFINE", "DEFINE", 267 } }, - { ["match"] ="dont_trace", ["act"] = { "NODE_DONT_TRACE", "DONT_TRACE", 279 } }, - { ["match"] ="f64", ["act"] = { "NODE_F64", "PRIMTYPE", string_crc } }, - { ["match"] ="i16", ["act"] = { "NODE_I16", "PRIMTYPE", string_crc } }, - { ["match"] ="i32", ["act"] = { "NODE_I32", "PRIMTYPE", string_crc } }, - { ["match"] ="i64", ["act"] = { "NODE_I64", "PRIMTYPE", string_crc } }, - { ["match"] ="i8", ["act"] = { "NODE_I8", "PRIMTYPE", string_crc } }, - { ["match"] ="manual_print", ["act"] = { "NODE_MANUAL_PRINT", "MANUAL_PRINT", 275 } }, - { ["match"] ="noversion", ["act"] = { "NODE_NOVERSION", "NOVERSION", 274 } }, - { ["match"] ="packed", ["act"] = { "NODE_PACKED", "TPACKED", 266 } }, - { ["match"] ="typeonly", ["act"] = { "NODE_TYPEONLY", "TYPEONLY", 278 } }, - { ["match"] ="u16", ["act"] = { "NODE_U16", "PRIMTYPE", string_crc } }, - { ["match"] ="u32", ["act"] = { "NODE_U32", "PRIMTYPE", string_crc } }, - { ["match"] ="u64", ["act"] = { "NODE_U64", "PRIMTYPE", string_crc } }, - { ["match"] ="u8", ["act"] = { "NODE_U8", "PRIMTYPE", string_crc } }, - { ["match"] ="union", ["act"] = { "NODE_UNION", "UNION", 271 } }, - { ["match"] ="uword", ["act"] = { "NODE_UWORD", "PRIMTYPE", string_crc } }, - { ["match"] ="%(", ["act"] = { "NODE_LPAR", "LPAR", 259 } }, - { ["match"] ="%)", ["act"] = { "NODE_RPAR", "RPAR", 258 } }, - { ["match"] =";", ["act"] = { "NODE_SEMI", "SEMI", 260 } }, - { ["match"] ="%[", ["act"] = { "NODE_LBRACK", "LBRACK", 261 } }, - { ["match"] ="%]", ["act"] = { "NODE_RBRACK", "RBRACK", 262 } }, - { ["match"] ="%{", ["act"] = { "NODE_LCURLY", "LCURLY", 268 } }, - { ["match"] ="%}", ["act"] = { "NODE_RCURLY", "RCURLY", 269 } }, - { ["match"] ='%b""', ["act"] = { "NODE_STRING", "STRING", string_crc } }, - { ["match"] ='%b@@', ["act"] = { "NODE_HELPER", "HELPER_STRING", string_crc } }, - -- TODO: \ must be consumed - { ["match"] ='[_a-zA-Z][_a-zA-Z0-9]*', - ["act"] = { "NODE_NAME", "NAME", string_crc } }, - { ["match"] ='[0-9]+', ["act"] = { "NODE_NUMBER", "NUMBER", string_crc } }, - { ["match"] ='#[^\n]+', ["act"] = { "NODE_PRAGMA", "PRAGMA", nil } }, -} - - -function vpp.crc_version_string(data) - local input_crc = 0 - -- Get rid of comments - data = data:gsub("/%*.-%*/", "") - data = data:gsub("//[^\n]+", "") - -- print(data) - idx = 1 - while (true) do - local matched = nil - for k, v in ipairs(tokens) do - if not matched then - local x, y, cap = string.find(data, v["match"], idx) - if x == idx then - matched = { ["node"] = v["act"], ["x"] = x, ["y"] = y, ["cap"] = cap, ["chars"] = string.sub(data, x, y) } - -- print(k, v, x, y, cap, matched.chars, matched.node[0] ) - end - end - end - if matched then - idx = idx + (matched.y - matched.x + 1) - if matched.node[1] then - local act = matched.node[3] - if type(act) == "function" then - input_crc = act(matched.chars, input_crc) - elseif type(act) == "number" then - input_crc = CRC16(input_crc, act) - end - -- print(vpp.dump(matched)) - end - else - -- print("NOT MATCHED!") - local crc = CRC16(input_crc, 0xFFFFFFFF) - return string.sub(string.format("%x", crc), -8) - end - end -end - - -function vpp.dump(o) - if type(o) == 'table' then - local s = '{ ' - for k,v in pairs(o) do - if type(k) ~= 'number' then k = '"'..k..'"' end - s = s .. '['..k..'] = ' .. vpp.dump(v) .. ',' - end - return s .. '} ' - else - return tostring(o) - end -end - -function vpp.hex_dump(buf) - local ret = {} - for i=1,math.ceil(#buf/16) * 16 do - if (i-1) % 16 == 0 then table.insert(ret, string.format('%08X ', i-1)) end - table.insert(ret, ( i > #buf and ' ' or string.format('%02X ', buf:byte(i)) )) - if i % 8 == 0 then table.insert(ret, ' ') end - if i % 16 == 0 then table.insert(ret, buf:sub(i-16+1, i):gsub('%c','.')..'\n' ) end - end - return table.concat(ret) -end - - -function vpp.c_str(text_in) - local text = text_in -- \000 will be helpfully added by ffi.copy - local c_str = ffi.new("char[?]", #text+1) - ffi.copy(c_str, text) - return c_str -end - - -function vpp.init(vpp, args) - local pneum_api = args.pneum_api or [[ - int cough_pneum_attach(char *pneum_path, char *cough_path); - int pneum_connect(char *name, char *chroot_prefix, void *cb); - int pneum_disconnect(void); - int pneum_read(char **data, int *l); - int pneum_write(char *data, int len); - void pneum_free(char *data); - uint32_t pneum_get_msg_index(unsigned char * name); -]] - - vpp.pneum_path = args.pneum_path - ffi.cdef(pneum_api) - local init_res = 0 - vpp.pneum = ffi.load(vpp.pneum_path) - if (init_res < 0) then - return nil - end - - vpp.next_msg_num = 1 - vpp.msg_name_to_number = {} - vpp.msg_name_to_fields = {} - vpp.msg_number_to_name = {} - vpp.msg_number_to_type = {} - vpp.msg_number_to_pointer_type = {} - vpp.msg_name_to_crc = {} - vpp.c_type_to_fields = {} - vpp.events = {} - vpp.plugin_version = {} - vpp.is_connected = false - - - vpp.t_lua2c = {} - vpp.t_c2lua = {} - vpp.t_lua2c["u8"] = function(c_type, src, dst_c_ptr) - if type(src) == "string" then - -- ffi.copy adds a zero byte at the end. Grrr. - -- ffi.copy(dst_c_ptr, src) - ffi.C.memcpy(dst_c_ptr, vpp.c_str(src), #src) - return(#src) - elseif type(src) == "table" then - for i,v in ipairs(src) do - ffi.cast("u8 *", dst_c_ptr)[i-1] = v - end - return(#src) - else - return 1, src -- ffi.cast("u8", src) - end - end - vpp.t_c2lua["u8"] = function(c_type, src_ptr, src_len) - if src_len then - return ffi.string(src_ptr, src_len) - else - return (tonumber(src_ptr)) - end - end - - vpp.t_lua2c["u16"] = function(c_type, src, dst_c_ptr) - if type(src) == "table" then - for i,v in ipairs(src) do - ffi.cast("u16 *", dst_c_ptr)[i-1] = ffi.C.htons(v) - end - return(2 * #src) - else - return 2, (ffi.C.htons(src)) - end - end - vpp.t_c2lua["u16"] = function(c_type, src_ptr, src_len) - if src_len then - local out = {} - for i = 0,src_len-1 do - out[i+1] = tonumber(ffi.C.ntohs(src_ptr[i])) - end - return out - else - return (tonumber(ffi.C.ntohs(src_ptr))) - end - end - - vpp.t_lua2c["u32"] = function(c_type, src, dst_c_ptr) - if type(src) == "table" then - for i,v in ipairs(src) do - ffi.cast("u32 *", dst_c_ptr)[i-1] = ffi.C.htonl(v) - end - return(4 * #src) - else - return 4, (ffi.C.htonl(src)) - end - end - vpp.t_c2lua["u32"] = function(c_type, src_ptr, src_len) - if src_len then - local out = {} - for i = 0,src_len-1 do - out[i+1] = tonumber(ffi.C.ntohl(src_ptr[i])) - end - return out - else - return (tonumber(ffi.C.ntohl(src_ptr))) - end - end - vpp.t_lua2c["i32"] = function(c_type, src, dst_c_ptr) - if type(src) == "table" then - for i,v in ipairs(src) do - ffi.cast("i32 *", dst_c_ptr)[i-1] = ffi.C.htonl(v) - end - return(4 * #src) - else - return 4, (ffi.C.htonl(src)) - end - end - vpp.t_c2lua["i32"] = function(c_type, src_ptr, src_len) - local ntohl = function(src) - local u32val = ffi.cast("u32", src) - local ntohlval = (ffi.C.ntohl(u32val)) - local out = tonumber(ffi.cast("i32", ntohlval + 0LL)) - return out - end - if src_len then - local out = {} - for i = 0,src_len-1 do - out[i+1] = tonumber(ntohl(src_ptr[i])) - end - else - return (tonumber(ntohl(src_ptr))) - end - end - - vpp.t_lua2c["u64"] = function(c_type, src, dst_c_ptr) - if type(src) == "table" then - for i,v in ipairs(src) do - ffi.cast("u64 *", dst_c_ptr)[i-1] = v --- FIXME ENDIAN - end - return(8 * #src) - else - return 8, ffi.cast("u64", src) --- FIXME ENDIAN - end - end - vpp.t_c2lua["u64"] = function(c_type, src_ptr, src_len) - if src_len then - local out = {} - for i = 0,src_len-1 do - out[i+1] = tonumber(src_ptr[i]) -- FIXME ENDIAN - end - return out - else - return (tonumber(src_ptr)) --FIXME ENDIAN - end - end - - - - - vpp.t_lua2c["__MSG__"] = function(c_type, src, dst_c_ptr) - local dst = ffi.cast(c_type .. " *", dst_c_ptr) - local additional_len = 0 - local fields_info = vpp.c_type_to_fields[c_type] - -- print("__MSG__ type: " .. tostring(c_type)) - ffi.C.memset(dst_c_ptr, 0, ffi.sizeof(dst[0])) - -- print(vpp.dump(fields_info)) - -- print(vpp.dump(src)) - for k,v in pairs(src) do - local field = fields_info[k] - if not field then - print("ERROR: field " .. tostring(k) .. " in message " .. tostring(c_type) .. " is unknown") - end - local lua2c = vpp.t_lua2c[field.c_type] - -- print("__MSG__ field " .. tostring(k) .. " : " .. vpp.dump(field)) - -- if the field is not an array type, try to coerce the argument to a number - if not field.array and type(v) == "string" then - v = tonumber(v) - end - if not lua2c then - print("__MSG__ " .. tostring(c_type) .. " t_lua2c: can not store field " .. field.name .. - " type " .. field.c_type .. " dst " .. tostring(dst[k])) - return 0 - end - local len = 0 - local val = nil - if field.array and (type(v) == "table") then - -- print("NTFY: field " .. tostring(k) .. " in message " .. tostring(c_type) .. " is an array") - for field_i, field_v in ipairs(v) do - -- print("NTFY: setting member#" .. tostring(field_i) .. " to value " .. vpp.dump(field_v)) - local field_len, field_val = lua2c(field.c_type, field_v, dst[k][field_i-1]) - len = len + field_len - end - else - len, val = lua2c(field.c_type, v, dst[k]) - end - if not field.array then - dst[k] = val - else - if 0 == field.array then - additional_len = additional_len + len - -- print("Adding " .. tostring(len) .. " bytes due to field " .. tostring(field.name)) - -- If there is a variable storing the length - -- and the input table does not set it, do magic - if field.array_size and not src[field.array_size] then - local size_field = fields_info[field.array_size] - if size_field then - dst[field.array_size] = vpp.t_c2lua[size_field.c_type](size_field.c_type, len) - end - end - end - end - -- print("Full message:\n" .. vpp.hex_dump(ffi.string(ffi.cast('void *', req_store_cache), 64))) - end - return (ffi.sizeof(dst[0])+additional_len) - end - - vpp.t_c2lua["__MSG__"] = function(c_type, src_ptr, src_len) - local out = {} - local reply_typed_ptr = ffi.cast(c_type .. " *", src_ptr) - local field_desc = vpp.c_type_to_fields[c_type] - if src_len then - for i = 0,src_len-1 do - out[i+1] = vpp.t_c2lua[c_type](c_type, src_ptr[i]) - end - return out - end - - for k, v in pairs(field_desc) do - local v_c2lua = vpp.t_c2lua[v.c_type] - if v_c2lua then - local len = v.array - -- print(dump(v)) - if len then - local len_field_name = k .. "_length" - local len_field = field_desc[len_field_name] - if (len_field) then - local real_len = vpp.t_c2lua[len_field.c_type](len_field.c_type, reply_typed_ptr[len_field_name]) - out[k] = v_c2lua(v.c_type, reply_typed_ptr[k], real_len) - elseif len == 0 then - -- check if len = 0, then must be a field which contains the size - len_field = field_desc[v.array_size] - local real_len = vpp.t_c2lua[len_field.c_type](len_field.c_type, reply_typed_ptr[v.array_size]) - -- print("REAL length: " .. vpp.dump(v) .. " : " .. tostring(real_len)) - out[k] = v_c2lua(v.c_type, reply_typed_ptr[k], real_len) - else - -- alas, just stuff the entire array - out[k] = v_c2lua(v.c_type, reply_typed_ptr[k], len) - end - else - out[k] = v_c2lua(v.c_type, reply_typed_ptr[k]) - end - else - out[k] = "<no accessor function for type " .. tostring(v.c_type) .. ">" - end - -- print(k, out[k]) - end - return out - end - - return vpp -end - -function vpp.resolve_message_number(msgname) - local name = msgname .. "_" .. vpp.msg_name_to_crc[msgname] - local idx = vpp.pneum.pneum_get_msg_index(vpp.c_str(name)) - if vpp.debug_dump then - print("Index for " .. tostring(name) .. " is " .. tostring(idx)) - end - vpp.msg_name_to_number[msgname] = idx - vpp.msg_number_to_name[idx] = msgname - vpp.msg_number_to_type[idx] = "vl_api_" .. msgname .. "_t" - vpp.msg_number_to_pointer_type[idx] = vpp.msg_number_to_type[idx] .. " *" - ffi.cdef("\n\n enum { vl_msg_" .. msgname .. " = " .. idx .. " };\n\n") -end - -function vpp.connect(vpp, client_name) - local name = "lua_client" - if client_name then - name = client_name - end - local ret = vpp.pneum.pneum_connect(vpp.c_str(client_name), nil, nil) - if tonumber(ret) == 0 then - vpp.is_connected = true - end - for k, v in pairs(vpp.msg_name_to_number) do - vpp.resolve_message_number(k) - end - end - -function vpp.disconnect(vpp) - vpp.pneum.pneum_disconnect() - end - -function vpp.json_api(vpp, path, plugin_name) - -- print("Consuming the VPP api from "..path) - local ffii = {} - local f = io.open(path, "r") - if not f then - print("Could not open " .. path) - return nil - end - local data = f:read("*all") - local json = json.parse(data) - if not (json.types or json.messages) then - print("Can not parse " .. path) - return nil - end - - local all_types = {} - - for i, v in ipairs(json.types) do - table.insert(all_types, { typeonly = 1, desc = v }) - end - for i, v in ipairs(json.messages) do - table.insert(all_types, { typeonly = 0, desc = v }) - end - for i, v in ipairs(all_types) do - local typeonly = v.typeonly - local name = v.desc[1] - local c_type = "vl_api_" .. name .. "_t" - - local fields = {} - -- vpp.msg_name_to_fields[name] = fields - -- print("CTYPE " .. c_type) - vpp.c_type_to_fields[c_type] = fields - vpp.t_lua2c[c_type] = vpp.t_lua2c["__MSG__"] - vpp.t_c2lua[c_type] = vpp.t_c2lua["__MSG__"] - - local cdef = { "\n\n#pragma pack(1)\ntypedef struct _vl_api_", name, " {\n" } - for ii, vv in ipairs(v.desc) do - if type(vv) == "table" then - if vv.crc then - vpp.msg_name_to_crc[name] = string.sub(vv.crc, 3) -- strip the leading 0x - else - local fieldtype = vv[1] - local fieldname = vv[2] - local fieldcount = vv[3] - local fieldcountvar = vv[4] - local fieldrec = { name = fieldname, c_type = fieldtype, array = fieldcount, array_size = fieldcountvar } - if fieldcount then - table.insert(cdef, " " .. fieldtype .. " " .. fieldname .. "[" .. fieldcount .. "];\n") - if fieldtype == "u8" then - -- any array of bytes is treated as a string - elseif vpp.t_lua2c[fieldtype] then - -- print("Array of " .. fieldtype .. " is ok!") - else - print("Unknown array type: ", name, " : " , fieldname, " : ", fieldtype, ":", fieldcount, ":", fieldcountvar) - end - else - table.insert(cdef, " " .. fieldtype .. " " .. fieldname .. ";\n") - end - fields[fieldname] = fieldrec - end - end - end - - table.insert(cdef, "} vl_api_" .. name .. "_t;") - table.insert(ffii, table.concat(cdef)) - - if typeonly == 0 then - -- we will want to resolve this later - if vpp.debug_dump then - print("Remember to resolve " .. name) - end - vpp.msg_name_to_number[name] = -1 - if vpp.is_connected then - vpp.resolve_message_number(name) - end - end - - end - local cdef_full = table.concat(ffii) - ffi.cdef(cdef_full) -end - -function vpp.consume_api(vpp, path, plugin_name) - -- print("Consuming the VPP api from "..path) - local ffii = {} - local f = io.open(path, "r") - if not f then - print("Could not open " .. path) - return nil - end - local data = f:read("*all") - -- Remove all C comments - data = data:gsub("/%*.-%*/", "") - if vpp.is_connected and not plugin_name then - print(path .. ": must specify plugin name!") - return - end - if plugin_name then - vpp.plugin_version[plugin_name] = vpp.crc_version_string(data) - local full_plugin_name = plugin_name .. "_" .. vpp.plugin_version[plugin_name] - local reply = vpp:api_call("get_first_msg_id", { name = full_plugin_name } ) - vpp.next_msg_num = tonumber(reply[1].first_msg_id) - print("Plugin " .. full_plugin_name .. " first message is " .. tostring(vpp.next_msg_num)) - end - -- print ("data len: ", #data) - data = data:gsub("\n(.-)(%S+)%s*{([^}]*)}", function (preamble, name, members) - local _, typeonly = preamble:gsub("typeonly", "") - local maybe_msg_id_field = { [0] = "u16 _vl_msg_id;", "" } - local onedef = "\n\n#pragma pack(1)\ntypedef struct _vl_api_"..name.. " {\n" .. - -- " u16 _vl_msg_id;" .. - maybe_msg_id_field[typeonly] .. - members:gsub("%[[a-zA-Z_]+]", "[0]") .. - "} vl_api_" .. name .. "_t;" - - local c_type = "vl_api_" .. name .. "_t" - - local fields = {} - -- vpp.msg_name_to_fields[name] = fields - -- print("CTYPE " .. c_type) - vpp.c_type_to_fields[c_type] = fields - vpp.t_lua2c[c_type] = vpp.t_lua2c["__MSG__"] - vpp.t_c2lua[c_type] = vpp.t_c2lua["__MSG__"] - local mirec = { name = "_vl_msg_id", c_type = "u16", array = nil, array_size = nil } - if typeonly == 0 then - fields[mirec.name] = mirec - end - - -- populate the field reflection table for the message - -- sets the various type information as well as the accessors for lua<->C conversion - members:gsub("(%S+)%s+(%S+);", function (fieldtype, fieldname) - local fieldcount = nil - local fieldcountvar = nil - -- data = data:gsub("%[[a-zA-Z_]+]", "[0]") - fieldname = fieldname:gsub("(%b[])", function(cnt) - fieldcount = tonumber(cnt:sub(2, -2)); - if not fieldcount then - fieldcount = 0 - fieldcountvar = cnt:sub(2, -2) - end - return "" - end) - local fieldrec = { name = fieldname, c_type = fieldtype, array = fieldcount, array_size = fieldcountvar } - if fieldcount then - if fieldtype == "u8" then - -- any array of bytes is treated as a string - elseif vpp.t_lua2c[fieldtype] then - -- print("Array of " .. fieldtype .. " is ok!") - else - print("Unknown array type: ", name, " : " , fieldname, " : ", fieldtype, ":", fieldcount, ":", fieldcountvar) - end - end - fields[fieldname] = fieldrec - end) - - -- print(dump(fields)) - - if typeonly == 0 then - local this_message_number = vpp.next_msg_num - vpp.next_msg_num = vpp.next_msg_num + 1 - vpp.msg_name_to_number[name] = this_message_number - vpp.msg_number_to_name[this_message_number] = name - vpp.msg_number_to_type[this_message_number] = "vl_api_" .. name .. "_t" - vpp.msg_number_to_pointer_type[this_message_number] = vpp.msg_number_to_type[this_message_number] .. " *" - onedef = onedef .. "\n\n enum { vl_msg_" .. name .. " = " .. this_message_number .. " };\n\n" - end - table.insert(ffii, onedef); - return ""; - end) - local cdef = table.concat(ffii) - -- print(cdef) - ffi.cdef(cdef) - end - - -function vpp.lua2c(vpp, c_type, src, dst_c_ptr) - -- returns the number of bytes written to memory pointed by dst - local lua2c = vpp.t_lua2c[c_type] - if lua2c then - return(lua2c(c_type, src, dst_c_ptr)) - else - print("vpp.lua2c: do not know how to store type " .. tostring(c_type)) - local x = "a" .. nil - return 0 - end -end - -function vpp.c2lua(vpp, c_type, src_ptr, src_len) - -- returns the lua data structure - local c2lua = vpp.t_c2lua[c_type] - if c2lua then - return(c2lua(c_type, src_ptr, src_len)) - else - print("vpp.c2lua: do not know how to load type " .. c_type) - return nil - end -end - -local req_store_cache = ffi.new("vl_api_opaque_message_t[1]") - -function vpp.api_write(vpp, api_name, req_table) - local msg_num = vpp.msg_name_to_number[api_name] - if not msg_num then - print ("API call "..api_name.." is not known") - return nil - end - - if not req_table then - req_table = {} - end - req_table._vl_msg_id = msg_num - - local packed_len = vpp:lua2c(vpp.msg_number_to_type[msg_num], req_table, req_store_cache) - if vpp.debug_dump then - print("Write Message length: " .. tostring(packed_len) .. "\n" .. vpp.hex_dump(ffi.string(ffi.cast('void *', req_store_cache), packed_len))) - end - - res = vpp.pneum.pneum_write(ffi.cast('void *', req_store_cache), packed_len) - return res - end - -local rep_store_cache = ffi.new("vl_api_opaque_message_t *[1]") -local rep_len_cache = ffi.new("int[1]") - -function vpp.api_read(vpp) - local rep_type = "vl_api_opaque_message_t" - local rep = rep_store_cache - local replen = rep_len_cache - res = vpp.pneum.pneum_read(ffi.cast("void *", rep), replen) - if vpp.debug_dump then - print("Read Message length: " .. tostring(replen[0]) .. "\n" .. vpp.hex_dump(ffi.string(ffi.cast('void *', rep[0]), replen[0]))) - end - - local reply_msg_num = ffi.C.ntohs(rep[0]._vl_msg_id) - local reply_msg_name = vpp.msg_number_to_name[reply_msg_num] - - local reply_typed_ptr = ffi.cast(vpp.msg_number_to_pointer_type[reply_msg_num], rep[0]) - local out = vpp:c2lua(vpp.msg_number_to_type[reply_msg_num], rep[0], nil, replen[0]) - if type(out) == "table" then - out["luaapi_message_name"] = reply_msg_name - end - - vpp.pneum.pneum_free(ffi.cast('void *',rep[0])) - - return reply_msg_name, out - end - -function vpp.api_call(vpp, api_name, req_table, options_in) - local msg_num = vpp.msg_name_to_number[api_name] - local end_message_name = api_name .."_reply" - local replies = {} - local cstruct = "" - local options = options_in or {} - if msg_num then - if vpp.debug_dump then - print("Message #" .. tostring(msg_num) .. " for name " .. tostring(api_name)) - end - vpp:api_write(api_name, req_table) - if not vpp.msg_name_to_number[end_message_name] or options.force_ping then - end_message_name = "control_ping_reply" - vpp:api_write("control_ping") - end - repeat - reply_message_name, reply = vpp:api_read() - if reply and not reply.context then - -- there may be async events inbetween - table.insert(vpp.events, reply) - else - if reply_message_name ~= "control_ping_reply" then - -- do not insert the control ping encapsulation - table.insert(replies, reply) - end - end - -- print(reply) - until reply_message_name == end_message_name - else - print(api_name .. " is an unknown API call") - return nil - end - return replies - end - -return vpp |