Clean up the Lua API, make it luajit-only, no C
This removes the libcough which was a temporary layer atop the libpneum to make it synchronous. Now Lua API only requres luajit, and has no dependencies on compiling any C. Also comment out a couple of debug print functions. Change-Id: I35fd1c8088c6fd1b10b9e4d903ad241ab32fd91a Signed-off-by: Andrew Yourtchenko <ayourtch@gmail.com>
This commit is contained in:

committed by
Damjan Marion

parent
085f5c0066
commit
985f3d11fa
2
vpp-api/lua/.gitignore
vendored
2
vpp-api/lua/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
# A .gitignore to avoid ignoring the Makefile
|
||||
!Makefile
|
@ -1,6 +0,0 @@
|
||||
all: libcough.so
|
||||
|
||||
libcough.so: cough.c
|
||||
gcc -o libcough.so -shared -fPIC cough.c
|
||||
clean:
|
||||
rm -f libcough.so
|
@ -6,44 +6,39 @@ To run the examples here:
|
||||
|
||||
1) install luajit - "sudo apt-get install luajit" on ubuntu
|
||||
|
||||
2) make build-vpp-api in the top directory
|
||||
2) "make build-vpp-api" in the top VPP directory
|
||||
|
||||
3) "make" in this directory to build libcough.so
|
||||
3) "make run" in a separate terminal window
|
||||
This ensures you have an instance of VPP running
|
||||
|
||||
4) "make run" in a separate terminal window
|
||||
|
||||
5) sudo luajit examples/example-cli.lua
|
||||
4) sudo luajit examples/example-cli.lua
|
||||
|
||||
This will result in something like this:
|
||||
|
||||
libcough detected
|
||||
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 ................
|
||||
|
||||
Version: 17.01-rc0~37-g8b3191e
|
||||
00000000 31 37 2E 30 31 2D 72 63 30 7E 33 37 2D 67 38 62 17.01-rc0~37-g8b
|
||||
00000010 33 31 39 31 65 00 00 00 00 00 00 00 00 00 00 00 3191e...........
|
||||
|
||||
{ [1] = { ["luaapi_message_name"] = show_version_reply,["program"] = vpe,["version"] = 17.01-rc0~37-g8b3191e,["build_date"] = Fri Nov 11 15:30:21 UTC 2016,["retval"] = 0,["build_directory"] = /home/ubuntu/vpp,["_vl_msg_id"] = 166,["context"] = 0,} ,}
|
||||
{ [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"] = 90,["length"] = 94,["reply"] = vpp v17.01-rc0~37-g8b3191e built by ubuntu on vpp-lapi-commit at Fri Nov 11 15:30:21 UTC 2016
|
||||
{ [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,} ,}
|
||||
---
|
||||
|
||||
6) You can also run the performance test bench:
|
||||
5) You can also run the performance test bench:
|
||||
|
||||
$ sudo luajit bench.lua
|
||||
libcough detected
|
||||
|
||||
10001 iterations, average speed 4108LL per second
|
||||
10001 iterations, average speed 4660LL per second
|
||||
10001 iterations, average speed 4095LL per second
|
||||
10001 iterations, average speed 4542LL per second
|
||||
10001 iterations, average speed 8048LL per second
|
||||
10001 iterations, average speed 6805LL per second
|
||||
10001 iterations, average speed 5170LL per second
|
||||
10001 iterations, average speed 6585LL per second
|
||||
10001 iterations, average speed 6714LL per second
|
||||
10001 iterations, average speed 6942LL per second
|
||||
Average tps across the tests: 5766LL
|
||||
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 :)
|
||||
|
@ -1,183 +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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a temporary helper library to seamlessly run against
|
||||
* the current API as exposed by libpneum.
|
||||
* In the future once the sync API is exposed as well as
|
||||
* a way to free the received data, this can go away.
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
pthread_mutex_t mut;
|
||||
pthread_mutex_t *cb_lock = &mut;
|
||||
|
||||
void *pneum_handle = NULL;
|
||||
|
||||
typedef void* (*arbitrary)();
|
||||
|
||||
int (*orig_pneum_connect)(char *name, char *chroot_prefix) = NULL;
|
||||
int (*orig_pneum_connect_sync)(char *name, char *chroot_prefix) = NULL;
|
||||
int (*orig_pneum_disconnect)(void) = NULL;
|
||||
int (*orig_pneum_read)(char **data, int *l) = NULL;
|
||||
int (*orig_pneum_write)(char *data, int len) = NULL;
|
||||
int (*orig_pneum_has_data)(void) = NULL;
|
||||
int (*orig_pneum_data_free)(char *data) = NULL;
|
||||
|
||||
arbitrary my_function = NULL;
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint32_t u32;
|
||||
|
||||
u8 *cough_read_buffer;
|
||||
u32 cough_read_buffer_size = 1000000;
|
||||
u32 cough_read_head = 0;
|
||||
u32 cough_read_lock_start = 0; /* lock_start till head is busy memory */
|
||||
u32 cough_read_tail = 0;
|
||||
|
||||
|
||||
int wrap_pneum_callback(char *data, int len) {
|
||||
// printf("Cough callback! with %d bytes\n", len);
|
||||
pthread_mutex_lock(cb_lock);
|
||||
if(cough_read_lock_start == cough_read_head) {
|
||||
// printf("Reset read head!\n");
|
||||
cough_read_head = 0;
|
||||
cough_read_tail = 0;
|
||||
cough_read_lock_start = 0;
|
||||
}
|
||||
u32 store_len = len;
|
||||
memcpy(cough_read_buffer + cough_read_head, &store_len, sizeof(u32));
|
||||
cough_read_head += sizeof(u32);
|
||||
memcpy(cough_read_buffer + cough_read_head, data, len);
|
||||
cough_read_head += len;
|
||||
pthread_mutex_unlock(cb_lock);
|
||||
return len;
|
||||
}
|
||||
|
||||
int cough_pneum_attach(char *pneum_fname, char *cough_fname) {
|
||||
/* this is needed to make the pneum aware of the wrap_pneum_callback */
|
||||
pneum_handle = dlopen(cough_fname, RTLD_NOW|RTLD_GLOBAL);
|
||||
/* now let's try to load pneum itself */
|
||||
pneum_handle = dlopen(pneum_fname, RTLD_NOW|RTLD_GLOBAL);
|
||||
if (pneum_handle) {
|
||||
*(void**)(&orig_pneum_connect) = dlsym(pneum_handle,"pneum_connect");
|
||||
*(void**)(&orig_pneum_connect_sync) = dlsym(pneum_handle,"pneum_connect_sync");
|
||||
*(void**)(&orig_pneum_disconnect) = dlsym(pneum_handle,"pneum_disconnect");
|
||||
*(void**)(&orig_pneum_read) = dlsym(pneum_handle,"pneum_read");
|
||||
*(void**)(&orig_pneum_write) = dlsym(pneum_handle,"pneum_write");
|
||||
*(void**)(&orig_pneum_has_data) = dlsym(pneum_handle,"pneum_has_data");
|
||||
*(void**)(&orig_pneum_data_free) = dlsym(pneum_handle,"pneum_data_free");
|
||||
// If you uncomment the below line we pretend we have an async-only libpneum
|
||||
orig_pneum_connect_sync = NULL;
|
||||
cough_read_buffer = malloc(cough_read_buffer_size);
|
||||
} else {
|
||||
printf("Could not get cough handle\n");
|
||||
printf("Error: %s", dlerror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
*(void**)(&my_function) = dlsym(pneum_handle,"something");
|
||||
}
|
||||
|
||||
|
||||
int pneum_connect(char *name, char *chroot_prefix) {
|
||||
if(orig_pneum_connect) {
|
||||
return(orig_pneum_connect(name, chroot_prefix));
|
||||
} else {
|
||||
printf("COUGH: pneum_connect\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int pneum_connect_sync(char *name, char *chroot_prefix) {
|
||||
if(orig_pneum_connect_sync) {
|
||||
int ret = (orig_pneum_connect_sync(name, chroot_prefix));
|
||||
return ret;
|
||||
} else {
|
||||
return(orig_pneum_connect(name, chroot_prefix));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int pneum_disconnect(void) {
|
||||
if(orig_pneum_disconnect) {
|
||||
return orig_pneum_disconnect();
|
||||
} else {
|
||||
printf("COUGH: pneum_disconnect\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int pneum_has_data(void) {
|
||||
if (orig_pneum_connect_sync) {
|
||||
/* always return 1 in a pass-through case */
|
||||
return 1;
|
||||
} else {
|
||||
// printf("COUGH: pneum_has_data\n");
|
||||
return (cough_read_head != cough_read_tail);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int pneum_read(char **data, int *l) {
|
||||
if(orig_pneum_connect_sync) {
|
||||
return orig_pneum_read(data, l);
|
||||
} else {
|
||||
while(!pneum_has_data());
|
||||
u32 n_bytes;
|
||||
pthread_mutex_lock(cb_lock);
|
||||
memcpy(&n_bytes, cough_read_buffer + cough_read_tail, sizeof(u32));
|
||||
cough_read_tail += sizeof(u32);
|
||||
void * dataptr = (void *) (cough_read_buffer + cough_read_tail);
|
||||
*data = dataptr;
|
||||
cough_read_tail += n_bytes;
|
||||
*l = n_bytes;
|
||||
pthread_mutex_unlock(cb_lock);
|
||||
return n_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
int pneum_write(char *data, int len) {
|
||||
if(orig_pneum_write) {
|
||||
return(orig_pneum_write(data, len));
|
||||
} else {
|
||||
printf("COUGH: pneum_write\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void pneum_data_free(char *data) {
|
||||
if (orig_pneum_connect_sync) {
|
||||
if(orig_pneum_data_free) {
|
||||
orig_pneum_data_free(data);
|
||||
} else {
|
||||
printf("COUGH: pneum_data_free\n");
|
||||
}
|
||||
} else {
|
||||
u32 *len;
|
||||
uint32_t index = ((u8*)data) - cough_read_buffer;
|
||||
pthread_mutex_lock(cb_lock);
|
||||
if ((index < cough_read_head) && (index > cough_read_lock_start)) {
|
||||
len = (void *)(data - sizeof(u32));
|
||||
cough_read_lock_start = index + *len;
|
||||
}
|
||||
pthread_mutex_unlock(cb_lock);
|
||||
}
|
||||
}
|
@ -273,33 +273,17 @@ 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);
|
||||
int pneum_connect_sync(char *name, char *chroot_prefix);
|
||||
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_data_free(char *data);
|
||||
void pneum_free(char *data);
|
||||
]]
|
||||
|
||||
vpp.pneum_path = args.pneum_path
|
||||
ffi.cdef(pneum_api)
|
||||
local init_res = 0
|
||||
if pcall(function()
|
||||
vpp.cough_path = args.cough_path or "./libcough.so"
|
||||
vpp.cough = ffi.load(vpp.cough_path)
|
||||
end) then
|
||||
pcall(function()
|
||||
if(vpp.cough.cough_pneum_attach) then
|
||||
vpp.pneum_is_cough = true
|
||||
print("libcough detected\n")
|
||||
init_res = vpp.cough.cough_pneum_attach(vpp.c_str(vpp.pneum_path), vpp.c_str(vpp.cough_path))
|
||||
vpp.pneum = vpp.cough
|
||||
end
|
||||
end)
|
||||
else
|
||||
vpp.pneum = ffi.load(vpp.pneum_path)
|
||||
end
|
||||
vpp.pneum = ffi.load(vpp.pneum_path)
|
||||
if (init_res < 0) then
|
||||
return nil
|
||||
end
|
||||
@ -463,9 +447,9 @@ void pneum_data_free(char *data);
|
||||
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")
|
||||
-- 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))
|
||||
-- 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
|
||||
@ -544,7 +528,7 @@ function vpp.connect(vpp, client_name)
|
||||
if client_name then
|
||||
name = client_name
|
||||
end
|
||||
local ret = vpp.pneum.pneum_connect_sync(vpp.c_str(client_name), nil)
|
||||
local ret = vpp.pneum.pneum_connect(vpp.c_str(client_name), nil, nil)
|
||||
if tonumber(ret) == 0 then
|
||||
vpp.is_connected = true
|
||||
end
|
||||
@ -712,7 +696,7 @@ function vpp.api_read(vpp)
|
||||
out["luaapi_message_name"] = reply_msg_name
|
||||
end
|
||||
|
||||
vpp.pneum.pneum_data_free(ffi.cast('void *',rep[0]))
|
||||
vpp.pneum.pneum_free(ffi.cast('void *',rep[0]))
|
||||
|
||||
return reply_msg_name, out
|
||||
end
|
||||
|
Reference in New Issue
Block a user