blob: 5b042e2350327ca0443314d8c7d199390cb0a49c [file] [log] [blame]
Ole Troandf87f802020-11-18 19:17:48 +01001/*
2 * Copyright (c) 2020 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <stdio.h>
17#include <stdbool.h>
18#include <ctype.h>
19#include <vlib/vlib.h>
20#include <vlibapi/api_types.h>
21#include <vppinfra/cJSON.h>
22
23/* VPP API client includes */
24#include <vpp-api/client/vppapiclient.h>
25
26#include <limits.h>
27#include "vat2.h"
28
29uword *function_by_name;
30bool debug = false;
31
32char *vat2_plugin_path;
33static void
34vat2_find_plugin_path ()
35{
36 char *p, path[PATH_MAX];
37 int rv;
38 u8 *s;
39
40 /* find executable path */
41 if ((rv = readlink ("/proc/self/exe", path, PATH_MAX - 1)) == -1)
42 return;
43
44 /* readlink doesn't provide null termination */
45 path[rv] = 0;
46
47 /* strip filename */
48 if ((p = strrchr (path, '/')) == 0)
49 return;
50 *p = 0;
51
52 /* strip bin/ */
53 if ((p = strrchr (path, '/')) == 0)
54 return;
55 *p = 0;
56
57 s = format (0, "%s/lib/" CLIB_TARGET_TRIPLET "/vat2_plugins:"
58 "%s/lib/vat2_plugins", path, path);
59 vec_add1 (s, 0);
60 vat2_plugin_path = (char *) s;
61}
62
63void
64vac_callback (unsigned char *data, int len)
65{
66 u16 result_msg_id = ntohs(*((u16 *)data));
67 DBG("Received something async: %d\n", result_msg_id);
68}
69
70int vat2_load_plugins (char *path, char *filter, int *loaded);
71
72static int
73register_function (void)
74{
75 int loaded;
76
77 vat2_find_plugin_path();
78 DBG("Plugin Path %s\n", vat2_plugin_path);
79 int rv = vat2_load_plugins(vat2_plugin_path, 0, &loaded);
80 DBG("Loaded %u plugins\n", loaded);
81 return rv;
82}
83
84void
85vat2_register_function(char *name, cJSON (*f)(cJSON *))
86{
87 hash_set_mem(function_by_name, name, f);
88}
89
90int main (int argc, char **argv)
91{
92 /* Create a heap of 64MB */
93 clib_mem_init (0, 64 << 20);
94 char *filename = 0;
95 int index;
96 int c;
97 opterr = 0;
98 cJSON *o = 0;
99 uword *p = 0;
100
101 while ((c = getopt (argc, argv, "df:")) != -1) {
102 switch (c) {
103 case 'd':
104 debug = true;
105 break;
106 case 'f':
107 filename = optarg;
108 break;
109 case '?':
110 if (optopt == 'f')
111 fprintf (stderr, "Option -%c requires an argument.\n", optopt);
112 else if (isprint (optopt))
113 fprintf (stderr, "Unknown option `-%c'.\n", optopt);
114 else
115 fprintf (stderr,
116 "Unknown option character `\\x%x'.\n",
117 optopt);
118 return 1;
119 default:
120 abort ();
121 }
122 }
123
124 DBG("debug = %d, filename = %s\n", debug, filename);
125
126 for (index = optind; index < argc; index++)
127 DBG ("Non-option argument %s\n", argv[index]);
128
129 index = optind;
130
131 /* Load plugins */
132 function_by_name = hash_create_string (0, sizeof (uword));
133 int res = register_function();
134 if (res < 0) {
135 fprintf(stderr, "%s: loading plugins failed\n", argv[0]);
136 exit(-1);
137 }
138
139 if (argc > index + 2) {
140 fprintf(stderr, "%s: Too many arguments\n", argv[0]);
141 exit(-1);
142 }
143
144 /* Read JSON from stdin, command line or file */
145 if (argc >= (index + 1)) {
146 p = hash_get_mem (function_by_name, argv[index]);
147 if (p == 0) {
148 fprintf(stderr, "%s: Unknown command: %s\n", argv[0], argv[index]);
149 exit(-1);
150 }
151 }
152
153 if (argc == (index + 2)) {
154 o = cJSON_Parse(argv[index+1]);
155 if (!o) {
156 fprintf(stderr, "%s: Failed parsing JSON input: %s\n", argv[0], cJSON_GetErrorPtr());
157 exit(-1);
158 }
159 }
160
161 if (filename) {
162 if (argc > index + 1) {
163 fprintf(stderr, "%s: Superfluous arguments when filename given\n", argv[0]);
164 exit(-1);
165 }
166
167 FILE *f = fopen(filename, "r");
168 size_t bufsize = 1024;
169 size_t n_read = 0;
170 size_t n;
171
172 if (!f) {
173 fprintf(stderr, "%s: can't open file: %s\n", argv[0], filename);
174 exit(-1);
175 }
176 char *buf = malloc(bufsize);
177 while ((n = fread(buf, 1, bufsize, f))) {
178 n_read += n;
179 if (n == bufsize)
180 buf = realloc(buf, bufsize);
181 }
182 fclose(f);
183 if (n_read) {
184 o = cJSON_Parse(buf);
185 free(buf);
186 if (!o) {
187 fprintf(stderr, "%s: Failed parsing JSON input: %s\n", argv[0], cJSON_GetErrorPtr());
188 exit(-1);
189 }
190 }
191 }
192
193 if (!o) {
194 fprintf(stderr, "%s: Failed parsing JSON input\n", argv[0]);
195 exit(-1);
196 }
197
198 if (vac_connect("vat2", 0, 0, 1024)) {
199 fprintf(stderr, "Failed connecting to VPP\n");
200 exit(-1);
201 }
202 if (!p) {
203 fprintf(stderr, "No such command\n");
204 exit(-1);
205 }
206
207 cJSON * (*fp) (cJSON *);
208 fp = (void *) p[0];
209 cJSON *r = (*fp) (o);
210
211 if (o)
212 cJSON_Delete(o);
213
214 if (r) {
215 char *output = cJSON_Print(r);
216 cJSON_Delete(r);
217 printf("%s\n", output);
218 free(output);
219 } else {
220 fprintf(stderr, "Call failed\n");
221 exit(-1);
222 }
223
224 vac_disconnect();
225 exit (0);
226
227}