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:
Andrew Yourtchenko
2016-11-25 13:29:30 +00:00
committed by Damjan Marion
parent 085f5c0066
commit 985f3d11fa
5 changed files with 28 additions and 240 deletions

View File

@ -1,2 +0,0 @@
# A .gitignore to avoid ignoring the Makefile
!Makefile

View File

@ -1,6 +0,0 @@
all: libcough.so
libcough.so: cough.c
gcc -o libcough.so -shared -fPIC cough.c
clean:
rm -f libcough.so

View File

@ -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 :)

View File

@ -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);
}
}

View File

@ -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