Merge "Fix latency accuracy and dumping latencies to file"
[samplevnf.git] / VNFs / DPPD-PROX / prox_lua.c
1 /*
2 // Copyright (c) 2010-2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include <string.h>
18 #include <stdlib.h>
19
20 #include "prox_lua.h"
21 #include "lua_compat.h"
22 #include "parse_utils.h"
23
24 static struct lua_State *lua_instance;
25
26 static int l_mask(lua_State *L)
27 {
28         uint32_t val, mask;
29
30         if (lua_gettop(L) != 2) {
31                 return luaL_error(L, "Expecting 2 argument and got %d\n", lua_gettop(L));
32         }
33         if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2)) {
34                 return luaL_error(L, "Expecting (integer, integer) as arguments\n");
35         }
36         val = lua_tonumber(L, -1);
37         mask = lua_tonumber(L, -2);
38
39         lua_pushinteger(L, val & mask);
40
41         return 1;
42 }
43
44 static int l_server_content(lua_State *L)
45 {
46         uint32_t beg, len;
47
48         if (lua_gettop(L) != 2) {
49                 return luaL_error(L, "Expecting 2 argument and got %d\n", lua_gettop(L));
50         }
51         if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2)) {
52                 return luaL_error(L, "Expecting (integer, integer) as arguments\n");
53         }
54         len = lua_tonumber(L, -1);
55         beg = lua_tonumber(L, -2);
56
57         lua_createtable(L, 0, 3);
58
59         lua_pushinteger(L, beg);
60         lua_setfield(L, -2, "beg");
61         lua_pushinteger(L, len);
62         lua_setfield(L, -2, "len");
63         lua_pushinteger(L, 0);
64         lua_setfield(L, -2, "peer");
65
66         return 1;
67 }
68
69 static int l_client_content(lua_State *L)
70 {
71         uint32_t beg, len;
72
73         if (lua_gettop(L) != 2) {
74                 return luaL_error(L, "Expecting 2 argument and got %d\n", lua_gettop(L));
75         }
76         if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2)) {
77                 return luaL_error(L, "Expecting (integer, integer) as arguments\n");
78         }
79         len = lua_tonumber(L, -1);
80         beg = lua_tonumber(L, -2);
81
82         lua_createtable(L, 0, 3);
83
84         lua_pushinteger(L, beg);
85         lua_setfield(L, -2, "beg");
86         lua_pushinteger(L, len);
87         lua_setfield(L, -2, "len");
88         lua_pushinteger(L, 1);
89         lua_setfield(L, -2, "peer");
90
91         return 1;
92 }
93
94 static int l_bin_read(lua_State *L)
95 {
96         const char *file_name = lua_tostring(L, -1);
97         int beg = lua_tonumber(L, -2);
98         int len = lua_gettop(L) == 3? lua_tonumber(L, -3) : -1;
99
100         if (lua_gettop(L) == 2) {
101                 if (!lua_isnumber(L, -1) || !lua_isstring(L, -2)) {
102                         return luaL_error(L, "Expecting (string, integer) as arguments\n");
103                 }
104
105                 file_name = lua_tostring(L, -2);
106                 beg = lua_tonumber(L, -1);
107                 len = -1;
108         }
109         else if (lua_gettop(L) == 3) {
110                 if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2) || !lua_isstring(L, 3)) {
111                         return luaL_error(L, "Expecting (string, integer, integer) as arguments\n");
112                 }
113
114                 file_name = lua_tostring(L, -3);
115                 beg = lua_tonumber(L, -2);
116                 len = lua_tonumber(L, -1);
117         }
118         else
119                 return luaL_error(L, "Expecting 2 or 3 arguments\n");
120
121         lua_createtable(L, 0, 3);
122
123         lua_pushstring(L, file_name);
124         lua_setfield(L, -2, "file_name");
125         lua_pushinteger(L, beg);
126         lua_setfield(L, -2, "beg");
127         lua_pushinteger(L, len);
128         lua_setfield(L, -2, "len");
129
130         return 1;
131 }
132
133 static int l_mac(lua_State *L)
134 {
135         int mac[6];
136
137         if (lua_isstring(L, -1)) {
138                 const char *arg = lua_tostring(L, -1);
139                 char arg2[128];
140                 strncpy(arg2, arg, sizeof(arg2));
141
142                 char *p = arg2;
143                 int count = 0;
144
145                 while ((p = strchr(p, ':'))) {
146                         count++;
147                         p++;
148                 }
149                 p = arg2;
150                 if (count != 5)
151                         return luaL_error(L, "Invalid MAC format\n");
152
153                 lua_createtable(L, 6, 0);
154                 for (size_t i = 0; i < 6; ++i) {
155                         char *n = strchr(p, ':');
156                         if (n)
157                                 *n = 0;
158                         if (strlen(p) != 2) {
159                                 return luaL_error(L, "Invalid MAC format\n");
160                         }
161
162                         lua_pushinteger(L, strtol(p, NULL, 16));
163                         lua_rawseti(L, -2, i + 1);
164                         p = n + 1;
165                 }
166                 return 1;
167         }
168
169         return luaL_error(L, "Invalid argument\n");
170 }
171
172 static int l_ip(lua_State *L)
173 {
174         int ip[4];
175         if (lua_isnumber(L, -1)) {
176                 uint32_t arg = lua_tointeger(L, -1);
177
178                 ip[0] = arg >> 24 & 0xff;
179                 ip[1] = arg >> 16 & 0xff;
180                 ip[2] = arg >>  8 & 0xff;
181                 ip[3] = arg >>  0 & 0xff;
182
183                 lua_createtable(L, 4, 0);
184                 for (size_t i = 0; i < 4; ++i) {
185                         lua_pushinteger(L, ip[i]);
186                         lua_rawseti(L, -2, i + 1);
187                 }
188
189                 return 1;
190         }
191         if (lua_isstring(L, -1)) {
192                 const char *arg = lua_tostring(L, -1);
193
194                 if (sscanf(arg, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]) != 4) {
195                         return luaL_error(L, "Invalid IP address format\n");
196                 }
197
198                 lua_createtable(L, 4, 0);
199                 for (size_t i = 0; i < 4; ++i) {
200                         lua_pushinteger(L, ip[i]);
201                         lua_rawseti(L, -2, i + 1);
202                 }
203
204                 return 1;
205         }
206
207         return luaL_error(L, "Invalid argument\n");
208 }
209
210 static int l_ip6(lua_State *L)
211 {
212         int ip[16];
213
214         if (!lua_isstring(L, -1)) {
215                 return luaL_error(L, "Invalid argument type\n");
216         }
217
218         const char *arg = lua_tostring(L, -1);
219         char arg2[64];
220         char *addr_parts[8];
221         int n_parts = 0;
222         size_t str_len = strlen(arg);
223         int next_str = 1;
224         int ret;
225
226         strncpy(arg2, arg, sizeof(arg2));
227
228         for (size_t i = 0; i < str_len; ++i) {
229                 if (next_str) {
230                         if (n_parts == 8)
231                                 return luaL_error(L, "IPv6 address can't be longer than 16 bytes\n");
232                         addr_parts[n_parts++] = &arg2[i];
233                         next_str = 0;
234
235                 }
236                 if (arg2[i] == ':') {
237                         arg2[i] = 0;
238                         next_str = 1;
239                 }
240         }
241
242         int omitted = 0;
243
244         for (int i = 0, j = 0; i < n_parts; ++i) {
245                 if (*addr_parts[i] == 0) {
246                         if (omitted == 0) {
247                                 return luaL_error(L, "Can omit zeros only once\n");
248                         }
249                         omitted = 1;
250                         j += 8 - n_parts;
251                 }
252                 else {
253                         uint16_t w = strtoll(addr_parts[i], NULL, 16);
254                         ip[j++] = (w >> 8) & 0xff;
255                         ip[j++] = w & 0xff;
256                 }
257         }
258
259         lua_createtable(L, 16, 0);
260         for (size_t i = 0; i < 16; ++i) {
261                 lua_pushinteger(L, ip[i]);
262                 lua_rawseti(L, -2, i + 1);
263         }
264
265         return 1;
266 }
267
268 static int l_cidr(lua_State *L)
269 {
270         const char *arg = lua_tostring(L, -1);
271
272         char tmp[128];
273         strncpy(tmp, arg, sizeof(tmp));
274
275         char *slash = strchr(tmp, '/');
276         *slash = 0;
277         slash++;
278
279         lua_createtable(L, 0, 2);
280         lua_pushstring(L, "ip");
281
282         lua_pushstring(L, tmp);
283         l_ip(L);
284         lua_remove(L, -2);
285
286         lua_settable(L, -3);
287
288         lua_pushstring(L, "depth");
289         lua_pushinteger(L, atoi(slash));
290         lua_settable(L, -3);
291         return 1;
292 }
293
294 static int l_cidr6(lua_State *L)
295 {
296         const char *arg = lua_tostring(L, -1);
297
298         char tmp[128];
299         strncpy(tmp, arg, sizeof(tmp));
300
301         char *slash = strchr(tmp, '/');
302         *slash = 0;
303         slash++;
304
305         lua_createtable(L, 0, 2);
306         lua_pushstring(L, "ip6");
307
308         lua_pushstring(L, tmp);
309         l_ip6(L);
310         lua_remove(L, -2);
311
312         lua_settable(L, -3);
313
314         lua_pushstring(L, "depth");
315         lua_pushinteger(L, atoi(slash));
316         lua_settable(L, -3);
317         return 1;
318 }
319
320 static int l_val_mask(lua_State *L)
321 {
322         if (!lua_isinteger(L, -2))
323                 return luaL_error(L, "Argument 1 is not an integer\n");
324         if (!lua_isinteger(L, -1))
325                 return luaL_error(L, "Argument 2 is not an integer\n");
326
327         uint32_t val = lua_tointeger(L, -2);
328         uint32_t mask = lua_tointeger(L, -1);
329
330         lua_createtable(L, 0, 2);
331         lua_pushstring(L, "val");
332         lua_pushinteger(L, val);
333         lua_settable(L, -3);
334
335         lua_pushstring(L, "mask");
336         lua_pushinteger(L, mask);
337         lua_settable(L, -3);
338
339         return 1;
340 }
341
342 static int l_val_range(lua_State *L)
343 {
344         if (!lua_isinteger(L, -2))
345                 return luaL_error(L, "Argument 1 is not an integer\n");
346         if (!lua_isinteger(L, -1))
347                 return luaL_error(L, "Argument 2 is not an integer\n");
348
349         uint32_t beg = lua_tointeger(L, -2);
350         uint32_t end = lua_tointeger(L, -1);
351
352         lua_createtable(L, 0, 2);
353         lua_pushstring(L, "beg");
354         lua_pushinteger(L, beg);
355         lua_settable(L, -3);
356
357         lua_pushstring(L, "end");
358         lua_pushinteger(L, end);
359         lua_settable(L, -3);
360
361         return 1;
362 }
363
364 static int l_task_count(lua_State *L)
365 {
366         struct core_task_set cts;
367         const char *str;
368
369         if (!lua_isstring(L, -1))
370                 return luaL_error(L, "Argument 1 is not an string\n");
371         str = lua_tostring(L, -1);
372         if (parse_task_set(&cts, str))
373                 return luaL_error(L, "Invalid core task set syntax\n");
374         lua_pushinteger(L, cts.n_elems);
375         return 1;
376 }
377
378 struct lua_State *prox_lua(void)
379 {
380         if (!lua_instance) {
381                 lua_instance = luaL_newstate();
382
383                 luaL_openlibs(lua_instance);
384
385                 lua_pushcfunction(lua_instance, l_ip);
386                 lua_setglobal(lua_instance, "ip");
387                 lua_pushcfunction(lua_instance, l_ip6);
388                 lua_setglobal(lua_instance, "ip6");
389                 lua_pushcfunction(lua_instance, l_cidr);
390                 lua_setglobal(lua_instance, "cidr");
391                 lua_pushcfunction(lua_instance, l_cidr6);
392                 lua_setglobal(lua_instance, "cidr6");
393                 lua_pushcfunction(lua_instance, l_mac);
394                 lua_setglobal(lua_instance, "mac");
395                 lua_pushcfunction(lua_instance, l_mask);
396                 lua_setglobal(lua_instance, "mask");
397                 lua_pushcfunction(lua_instance, l_val_mask);
398                 lua_setglobal(lua_instance, "val_mask");
399                 lua_pushcfunction(lua_instance, l_val_range);
400                 lua_setglobal(lua_instance, "val_range");
401                 lua_pushcfunction(lua_instance, l_bin_read);
402                 lua_setglobal(lua_instance, "bin_read");
403                 lua_pushcfunction(lua_instance, l_client_content);
404                 lua_setglobal(lua_instance, "client_content");
405                 lua_pushcfunction(lua_instance, l_server_content);
406                 lua_setglobal(lua_instance, "server_content");
407                 lua_pushcfunction(lua_instance, l_task_count);
408                 lua_setglobal(lua_instance, "task_count");
409         }
410         return lua_instance;
411 }