diff options
Diffstat (limited to 'vpp-api/lua/examples/lute')
-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 |
7 files changed, 2145 insertions, 0 deletions
diff --git a/vpp-api/lua/examples/lute/README.md b/vpp-api/lua/examples/lute/README.md new file mode 100644 index 00000000000..8d37250ad83 --- /dev/null +++ b/vpp-api/lua/examples/lute/README.md @@ -0,0 +1,66 @@ +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 new file mode 100644 index 00000000000..89b9924b901 --- /dev/null +++ b/vpp-api/lua/examples/lute/lute.lua @@ -0,0 +1,777 @@ +--[[ +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 new file mode 100644 index 00000000000..a24d04bfb36 --- /dev/null +++ b/vpp-api/lua/examples/lute/script-inout-acl-noacl.lute @@ -0,0 +1,329 @@ +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 new file mode 100644 index 00000000000..9edebf02f97 --- /dev/null +++ b/vpp-api/lua/examples/lute/script-inout-acl-old.lute @@ -0,0 +1,329 @@ +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 new file mode 100644 index 00000000000..d7e7423c7cf --- /dev/null +++ b/vpp-api/lua/examples/lute/script-inout-acl.lute @@ -0,0 +1,329 @@ +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 new file mode 100644 index 00000000000..c3dd90f2dbe --- /dev/null +++ b/vpp-api/lua/examples/lute/script.lute @@ -0,0 +1,7 @@ +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 new file mode 100644 index 00000000000..ac237ef9d90 --- /dev/null +++ b/vpp-api/lua/examples/lute/sessions-acl.lute @@ -0,0 +1,308 @@ +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!") + |