l2l3_stack: fixing the arp_route_tbl/nd_route_tbl
[samplevnf.git] / common / vnf_common / rest_api.c
1 /*
2 // Copyright (c) 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 #include <stdio.h>
17 #include <string.h>
18 #include <stdint.h>
19 #include <stdlib.h>
20 #include <errno.h>
21 #include <sys/queue.h>
22
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <netdb.h>
26
27 #include <rte_common.h>
28 #include <rte_memory.h>
29 #include <rte_memzone.h>
30 #include <rte_launch.h>
31 #include <rte_eal.h>
32 #include <rte_per_lcore.h>
33 #include <rte_lcore.h>
34 #include <rte_hash.h>
35 #include <rte_ethdev.h>
36 #include <rte_cycles.h>
37 #include <rte_timer.h>
38 #include <rte_debug.h>
39 #include <rte_cfgfile.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42 #include <cmdline_rdline.h>
43 #include <cmdline_parse.h>
44 #include <cmdline_parse_num.h>
45 #include <cmdline_parse_string.h>
46 #include <cmdline_parse_ipaddr.h>
47 #include <cmdline_parse_etheraddr.h>
48 #include <cmdline_socket.h>
49 #include <cmdline.h>
50
51 #include "pipeline_common_fe.h"
52 #include "pipeline_arpicmp.h"
53
54 #include <civetweb.h>
55 #include <json/json.h>
56 #include "app.h"
57 #include "lib_arp.h"
58 #include "interface.h"
59 #include "tsx.h"
60 #include "gateway.h"
61
62 #define MAX_PIPELINES           30
63 #define MAX_VNFS                3
64 #define CFG_NAME_LEN            64
65 #define MAX_CORES               64
66 #define MAX_SOCKET              2
67 #define MAX_BUF_SIZE            2048
68 #define MAX_SIZE                24
69 #define MAX_LINKS               64
70 #define MAX_LB                  20
71 #define        msleep(x)               rte_delay_us(x * 1000)
72
73 const char *pipelines[9] = {"MASTER", "ARPICMP", "TIMER", "TXRX-BEGIN",
74                          "TXRX-END", "LOADB", "VACL", "VCGNAPT", "VFW"};
75 const char *VNFS[] = {"VACL", "VCGNAPT", "VFW"};
76 struct mg_context *ctx;
77 struct pub_ip_range {
78         char value[MAX_BUF_SIZE];
79 };
80
81 struct stat_cfg {
82         uint8_t num_workers;
83         uint8_t num_lb;
84         uint8_t num_ports;
85         uint8_t hyper_thread;
86         uint8_t sock_in;
87         uint8_t sw_lb;
88         char vnf_type[MAX_SIZE];
89         char pkt_type[MAX_SIZE];
90         char pci_white_list[MAX_BUF_SIZE];
91         struct pub_ip_range ip_range[MAX_LB];
92 };
93
94 struct arp_params {
95         uint8_t family;
96         uint8_t action;
97         union {
98                 uint32_t ip;
99                 uint8_t ipv6[16];
100         };
101         uint32_t portid;
102         struct ether_addr mac_addr;
103 };
104
105 struct link_params {
106         uint32_t id;
107         uint32_t state;
108         union {
109                 uint32_t ip;
110                 uint8_t ipv6[16];
111         };
112         uint32_t depth;
113         uint32_t family;
114 };
115
116 struct route_params {
117         uint32_t enable;
118         union {
119                 uint32_t ip;
120                 uint8_t ipv6[16];
121         };
122         uint32_t depth;
123         uint32_t family;
124         char type[255];
125 };
126
127 struct dbg_mode {
128         uint32_t  cmd;
129         uint32_t  d1;
130         uint32_t  pipe_num;
131 };
132
133 struct dbg_mode         current_dbg;
134 struct link_params      current_link_parms[MAX_LINKS];
135 struct stat_cfg         current_cfg;
136 struct arp_params       current_arp_parms;
137 struct route_params     current_route_parms[MAX_LINKS];
138
139 static int static_cfg_set = 0;
140 uint8_t pipe_arr[MAX_PIPELINES];
141 uint8_t num_pipelines;
142 uint8_t num_workers, pub_ip = 0, ip_range = 0, num_lb = 1, num_ports;
143 uint8_t num_entries, start_lb, end_lb, start_lbout;
144 uint8_t swq_index = 0, workers = 0;
145 uint8_t txq_index = 0, sw_lb = 1;
146 uint8_t rxq_index = 0;
147 uint8_t arp_index = 0, tx_start_port = 0, rx_start_port = 0;
148 uint8_t pipenum = 0, hyper_thread = 0;
149 char traffic_type[4] = "4";
150 struct rte_cfgfile_entry entries[30];
151 int n_entries1 = 0;
152 char loadb_in[256];
153 char vnf_type[256];
154 uint8_t sock_cpus[MAX_SOCKET][MAX_CORES];
155 uint8_t sock_in = 0, sock0 = 0, sock1 = 0, sock_index = 0;
156 int hyper = 0;
157 uint32_t flow_dir_cfg = 0;
158 struct app_params *rapp;
159
160 extern uint32_t nd_route_tbl_index;
161 extern struct arp_data *p_arp_data;
162 extern int USE_RTM_LOCKS;
163 extern rte_rwlock_t rwlock;
164 extern interface_main_t ifm;
165 extern struct cmdline *pipe_cl;
166 extern uint16_t str2flowtype(char *string);
167 extern void app_run_file(cmdline_parse_ctx_t *ctx, const char *file_name);
168 extern int parse_flexbytes(const char *q_arg, uint8_t *flexbytes,
169                          uint16_t max_num);
170 extern int app_pipeline_arpicmp_entry_dbg(struct app_params *app,
171                                     uint32_t pipeline_id, uint8_t *msg);
172 extern unsigned eal_cpu_socket_id(unsigned cpu_id);
173 extern int app_routeadd_config_ipv4(__attribute__((unused))
174                                          struct app_params *app,
175                                         uint32_t port_id, uint32_t ip,
176                                          uint32_t mask);
177 extern int app_routeadd_config_ipv6(__attribute__((unused))
178                                          struct app_params *app,
179                                         uint32_t port_id, uint8_t ipv6[],
180                                          uint32_t depth);
181
182 enum rte_eth_input_set_field str2inset(char *string);
183
184 enum {
185         MASTER = 0,
186         ARPICMP,
187         TIMER,
188         TXRX_BEGIN,
189         TXRX_END,
190         LOADB,
191         VNF_VACL,
192         VNF_VCGNAPT,
193         VNF_VFW,
194         PIPE_MAX
195 };
196
197 struct json_data {
198         char key[256];
199         char value[256];
200 };
201
202 struct json_data static_cfg[40];
203 uint32_t post_not_received = 1;
204
205 int flow_director_handler(struct mg_connection *conn,
206          __rte_unused void *cbdata);
207 int vnf_handler(struct mg_connection *conn, __rte_unused void *cbdata);
208 void init_stat_cfg(void);
209 void bind_the_ports(struct mg_connection *conn, char *pci_white_list);
210 int route_handler(struct mg_connection *conn, __rte_unused void *cbdata);
211 int dbg_pipelines_handler(struct mg_connection *conn,
212          __rte_unused void *cbdata);
213 int dbg_pipelines_id_handler(struct mg_connection *conn,
214          __rte_unused void *cbdata);
215 int get_pipelines_tokens(char *buf);
216 void get_swq_offset(uint8_t start, uint8_t num, char *buf);
217 void get_swq(uint8_t num, char *buf);
218 void get_txq(uint8_t start_q, uint8_t queue_num, uint8_t ports, char *buf);
219 void get_rxq(uint8_t start_q, uint8_t queue_num, uint8_t ports, char *buf);
220 void fix_pipelines_data_types(FILE *f, const char *sect_name,
221                          struct rte_cfgfile *tcfg);
222 void print_to_file(FILE *f, struct rte_cfgfile *tcfg);
223 int get_vnf_index(void);
224 void build_pipeline(void);
225 void get_pktq_in_prv(char *buf);
226 void get_prv_to_pub_map(char *buf);
227 void get_prv_que_handler(char *buf);
228 int static_cfg_handler(struct mg_connection *conn, void *cbdata);
229 int link_handler(struct mg_connection *conn, void *cbdata);
230 int linkid_handler(struct mg_connection *conn, __rte_unused void *cbdata);
231 int arp_handler(struct mg_connection *conn, void *cbdata);
232 int arpls_handler(struct mg_connection *conn, void *cbdata);
233 int nd_handler(struct mg_connection *conn, void *cbdata);
234 int linkls_handler(struct mg_connection *conn, void *cbdata);
235 int set_hash_input_set_2(struct mg_connection *conn, uint32_t port_id,
236          const char *flow_type, const char *inset_field0,
237          const char *inset_field1, const char *select);
238 int set_hash_input_set_4(struct mg_connection *conn, uint32_t port_id,
239         char *flow_type, char *inset_field0, char *inset_field1,
240         char *inset_field2, char *inset_field3, const char *select);
241 int set_hash_global_config(struct mg_connection *conn, uint32_t port_id,
242         char *flow_type, const char *hash_func, const char *enable);
243 int set_sym_hash_per_port(struct mg_connection *conn, uint32_t port_id);
244 int cmd_quit_handler(struct mg_connection *conn, void *cbdata);
245 int dbg_run_handler(struct mg_connection *conn, void *cbdata);
246 int dbg_handler(struct mg_connection *conn, __rte_unused void *cbdata);
247 int dbg_cmd_handler(struct mg_connection *conn, void *cbdata);
248 int run_field_found(const char *key, const char *filename, char *path,
249             size_t pathlen, void *user_data);
250 int run_field_get(const char *key, const char *value, size_t valuelen,
251          void *user_data);
252 int run_field_stored(const char *path, long long file_size, void *user_data);
253 void print_interface_details_rest(struct mg_connection *conn, uint32_t link);
254 void print_link_info(struct app_link_params *p, struct mg_connection *conn);
255 int get_link_tokens(char *buf);
256 void get_mac(struct ether_addr *mac_addr, char *buf);
257
258 int run_field_found(const char *key, const char *filename, char *path,
259         size_t pathlen, void *user_data)
260 {
261         struct mg_connection *conn = (struct mg_connection *)user_data;
262
263         mg_printf(conn, "\r\n\r\n%s:\r\n", key);
264
265         if (filename && *filename) {
266                 snprintf(path, pathlen, "%s", filename);
267                 int fd;
268
269                 /* Make sure file exists before clearing rules and actions */
270                 fd = open(filename, O_RDONLY);
271                 if (fd < 0) {
272                         mg_printf(conn, "Cannot open file \"%s\"\n", filename);
273                         return FORM_FIELD_STORAGE_GET;
274                 }
275
276                 close(fd);
277                 mg_printf(conn, "file to be loaded is %s\n", filename);
278                 app_run_file(pipe_cl->ctx, filename);
279
280                 return FORM_FIELD_STORAGE_STORE;
281         }
282         
283         return FORM_FIELD_STORAGE_GET;
284 }
285
286 int run_field_get(const char *key, const char *value, size_t valuelen,
287          void *user_data)
288 {
289         struct mg_connection *conn = (struct mg_connection *)user_data;
290
291         if (key[0]) {
292                 mg_printf(conn, "%s = ", key);
293         }
294         mg_write(conn, value, valuelen);
295
296         return 0;
297 }
298
299 int run_field_stored(const char *path, long long file_size, void *user_data)
300 {
301         struct mg_connection *conn = (struct mg_connection *)user_data;
302
303         mg_printf(conn,
304                   "stored as %s (%lu bytes)\r\n\r\n",
305                   path,
306                   (unsigned long)file_size);
307
308         return 0;
309 }
310
311 int dbg_run_handler(struct mg_connection *conn, __rte_unused void *cbdata)
312 {
313         /* Handler may access the request info using mg_get_request_info */
314         const struct mg_request_info *req_info = mg_get_request_info(conn);
315         struct mg_form_data_handler fdh = {run_field_found, run_field_get,
316                                          run_field_stored, NULL};
317
318         if (strcmp(req_info->request_method, "POST")) {
319
320                 mg_printf(conn,
321                           "HTTP/1.1 405 Method Not Allowed\r\nConnection:");
322                 mg_printf(conn," close\r\n");
323                 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
324                 mg_printf(conn,
325                           "%s method not allowed in the POST handler\n",
326                           req_info->request_method);
327                 return 1; 
328         }
329
330
331         /* It would be possible to check the request info here before calling
332          * mg_handle_form_request. */
333         (void)req_info;
334
335         mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: ");
336         mg_printf(conn, "text/plain\r\nConnection: close\r\n\r\n");
337         if (strcmp(req_info->request_method, "PUT")) {
338                 mg_printf(conn, "Only PUT method allowed");
339                 return 1;
340         }
341
342         fdh.user_data = (void *)conn;
343
344         /* Call the form handler */
345         mg_handle_form_request(conn, &fdh);
346         mg_printf(conn, "\r\n script file handled");
347
348         return 1;
349 }
350
351 int cmd_quit_handler(__rte_unused struct mg_connection *conn,
352                  __rte_unused void *cbdata)
353 {
354         cmdline_quit(pipe_cl);
355         return 0;
356 }
357
358 int dbg_handler(struct mg_connection *conn, __rte_unused void *cbdata)
359 {
360
361         const struct mg_request_info *ri = mg_get_request_info(conn);
362
363         if (!strcmp(ri->request_method, "GET")) {
364                 mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n");
365                 mg_printf(conn, "Connection: close\r\n\r\n");
366                 mg_printf(conn, "<html><body>");
367                 mg_printf(conn, "<h2> These are the methods supported</h2>");
368                 mg_printf(conn, "<h3>     /pipelines\n</h3>");
369                 mg_printf(conn, "<h3>     /cmd \n</h3>");
370                 mg_printf(conn, "<h3>     /run\n</h3>");
371                 mg_printf(conn, "</body></html>");
372         }
373
374         return 1;
375
376 }
377
378 int get_pipelines_tokens(char *buf)
379 {
380         char *token;
381         uint32_t id;
382
383         token = strtok(buf, "/ ");
384         if (strcmp(token, "pipelines")) {
385                 return -1;
386         }
387
388         token = strtok(NULL, "/ ");
389         id = atoi(token);
390         if (id > rapp->n_pipelines) {
391                 return -1;
392         }
393
394         return id;
395 }
396
397
398 int dbg_pipelines_id_handler(struct mg_connection *conn,
399                          __rte_unused void *cbdata)
400 {
401         struct app_eal_params *p = &rapp->eal_params;
402         const struct mg_request_info *ri = mg_get_request_info(conn);
403         //uint32_t id = (uint32_t *)cbdata;
404
405         mg_printf(conn, "Inside dbg_pipelines_id_handler\n");
406
407         if (!strcmp(ri->request_method, "GET")) {
408                 mg_printf(conn,
409                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
410                   "close\r\n\r\n");
411                 mg_printf(conn, "<html><body>");
412                 if (p->log_level_present) {
413                        mg_printf(conn, "<h2> The pipeline log level is %d</h2>",
414                                 p->log_level);
415                 } else {
416                        mg_printf(conn, "<h2> No log level found in the\
417                                 pipeline</h2>");
418                 }
419                 mg_printf(conn, "</body></html>");
420         }
421
422         return 1;
423
424 }
425
426
427 int dbg_pipelines_handler(struct mg_connection *conn, __rte_unused void *cbdata)
428 {
429
430         uint32_t i;
431         const struct mg_request_info *ri = mg_get_request_info(conn);
432
433         if (!strcmp(ri->request_method, "GET")) {
434                 mg_printf(conn,
435                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
436                   "close\r\n\r\n");
437                 mg_printf(conn, "<html><body>");
438                 mg_printf(conn, "<h2> These are pipelines available</h2>");
439                 for (i = 0; i < rapp->n_pipelines; i++) {
440                         mg_printf(conn, "<h3> pipeline %d:      %s\n</h3>",i,
441                                 rapp->pipeline_params[i].type);
442                 }
443                 mg_printf(conn, "</body></html>");
444         }
445
446         return 1;
447
448 }
449
450 int dbg_cmd_handler(struct mg_connection *conn, __rte_unused void *cbdata)
451 {
452         struct app_params *app = rapp;
453         uint8_t msg[2];
454         int status;
455         const struct mg_request_info *req_info = mg_get_request_info(conn);
456         char buf[MAX_BUF_SIZE];
457         
458         if (!strcmp(req_info->request_method, "GET")) {
459                 mg_printf(conn,
460                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
461                   "close\r\n\r\n");
462                 mg_printf(conn, "<html><body>");
463                 mg_printf(conn, "<h2> The last command executed </h2>");
464                 mg_printf(conn, "<h3>     cmd: %d\n </h3>", current_dbg.cmd);
465                 mg_printf(conn, "<h3>     d1 : %d\n </h3>", current_dbg.d1);
466                 mg_printf(conn, "<h3>     pipeline : %d\n </h3>",
467                                  current_dbg.pipe_num);
468                 mg_printf(conn, "</body></html>\n");
469
470         }
471
472         if (strcmp(req_info->request_method, "POST")) {
473                 mg_printf(conn,
474                        "HTTP/1.1 405 Method Not Allowed\r\nConnection:");
475                 mg_printf(conn, " close\r\n");
476                 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
477                 mg_printf(conn, "%s method not allowed in the POST handler\n",
478                           req_info->request_method);
479                 return 1; 
480         }
481
482         mg_printf(conn,
483                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
484                   "close\r\n\r\n");
485         mg_printf(conn, "<html><body>");
486         mg_printf(conn, "</body></html>\n");
487         
488         mg_read(conn, buf, sizeof(buf));
489         json_object * jobj = json_tokener_parse(buf);
490         json_object_object_foreach(jobj, key, val) {
491                 if (!strcmp(key, "cmd")) {
492                         current_dbg.cmd = atoi(json_object_get_string(val));
493                 } else if (!strcmp(key, "d1")) {
494                         current_dbg.d1 = atoi(json_object_get_string(val));
495                 } else if (!strcmp(key, "pipeline")) {
496                         current_dbg.pipe_num = atoi(json_object_get_string(val));
497                 }
498         }
499
500
501         msg[0] = current_dbg.cmd;
502         msg[1] = current_dbg.d1;
503         status = app_pipeline_arpicmp_entry_dbg(app, current_dbg.pipe_num, msg);
504
505         if (status != 0) {
506                 mg_printf(conn, "Dbg Command failed\n");
507                 return 1;
508         }
509
510         return 1;
511 }
512
513 int set_sym_hash_per_port(struct mg_connection *conn, uint32_t port_id)
514 {
515         int ret;
516         struct rte_eth_hash_filter_info info;
517
518         if (rte_eth_dev_filter_supported(port_id,
519                  RTE_ETH_FILTER_HASH) < 0) {
520                 mg_printf(conn, "RTE_ETH_FILTER_HASH not supported on port: %d\n",
521                         port_id);
522                 return 1;
523         }
524
525         memset(&info, 0, sizeof(info));
526         info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT;
527
528         ret = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH,
529                                  RTE_ETH_FILTER_SET, &info);
530         if (ret < 0) {
531                 mg_printf(conn, "Cannot set symmetric hash enable per port on "
532                         "port %u\n", port_id);
533                 return 1;
534         }
535
536         return 1;
537 }
538
539 int set_hash_input_set_4(struct mg_connection *conn, uint32_t port_id,
540         char *flow_type, char *inset_field0, char *inset_field1,
541         char *inset_field2, char *inset_field3, const char *select)
542 {
543         struct rte_eth_hash_filter_info info;
544
545         if (enable_flow_dir) {
546                 mg_printf(conn, "FDIR Filter is Defined!\n");
547                 mg_printf(conn, "Please undefine FDIR_FILTER flag and define "
548                         "HWLD flag\n");
549                 return 1;
550         }
551
552         memset(&info, 0, sizeof(info));
553         info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT;
554         info.info.input_set_conf.flow_type = str2flowtype(flow_type);
555
556         info.info.input_set_conf.field[0] = str2inset(inset_field0);
557         info.info.input_set_conf.field[1] = str2inset(inset_field1);
558         info.info.input_set_conf.field[2] = str2inset(inset_field2);
559         info.info.input_set_conf.field[3] = str2inset(inset_field3);
560
561         info.info.input_set_conf.inset_size = 4;
562         if (!strcmp(select, "select"))
563                 info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
564         else if (!strcmp(select, "add"))
565                 info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
566
567         rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH,
568                 RTE_ETH_FILTER_SET, &info);
569
570         mg_printf(conn, "Command Passed!\n");
571         return 1;
572 }
573
574 int set_hash_input_set_2(struct mg_connection *conn, uint32_t port_id,
575          const char *flow_type, const char *inset_field0,
576          const char *inset_field1, const char *select)
577 {
578         struct rte_eth_hash_filter_info info;
579         const struct mg_request_info *req_info = mg_get_request_info(conn);
580
581         if (strcmp(req_info->request_method, "POST")) {
582                 mg_printf(conn,
583                     "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
584                 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
585                 mg_printf(conn,
586                           "%s method not allowed in the POST handler\n",
587                           req_info->request_method);
588                 return 1; 
589         }
590
591         mg_printf(conn,
592                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
593                   "close\r\n\r\n");
594         mg_printf(conn, "<html><body>");
595         mg_printf(conn, "</body></html>\n");
596
597         if (enable_flow_dir) {
598                 mg_printf(conn, "FDIR Filter is Defined!\n");
599                 mg_printf(conn, "Please undefine FDIR_FILTER flag and define "
600                         "HWLD flag\n");
601                 return 1;
602         }
603
604         if (enable_flow_dir) {
605                 mg_printf(conn, "FDIR Filter is Defined!\n");
606                 mg_printf(conn, "Please undefine FDIR_FILTER flag and define "
607                         "HWLD flag\n");
608                 return 1;
609         }
610
611         memset(&info, 0, sizeof(info));
612         info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT;
613         info.info.input_set_conf.flow_type = str2flowtype(strdup(flow_type));
614
615         info.info.input_set_conf.field[0] = str2inset(strdup(inset_field0));
616         info.info.input_set_conf.field[1] = str2inset(strdup(inset_field1));
617
618         info.info.input_set_conf.inset_size = 2;
619
620         if (!strcmp(select, "select"))
621                 info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
622         else if (!strcmp(select, "add"))
623                 info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
624
625         rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH,
626                 RTE_ETH_FILTER_SET, &info);
627
628         mg_printf(conn, "Command Passed!\n");
629         return 1;
630 }
631
632 void print_interface_details_rest(struct mg_connection *conn, uint32_t link)
633 {
634         l2_phy_interface_t *port;
635         int i = 0;
636         struct sockaddr_in ip;
637         mg_printf(conn, "\n\r");
638
639         if (USE_RTM_LOCKS)
640                 rtm_lock();
641         else
642                 rte_rwlock_read_lock(&rwlock);
643
644         i = link;
645         port = ifm.port_list[i];
646         mg_printf(conn, "%u", port->pmdid);
647         if (port->ifname && strlen(port->ifname)) {
648                 mg_printf(conn, " (%s)\t", port->ifname);
649         } else
650                 mg_printf(conn, "\t\t");
651         mg_printf(conn, "MAC:%02x:%02x:%02x:%02x:%02x:%02x Adminstate:%s"
652                                  " Operstate:%s \n\r<br/>",
653                                  port->macaddr[0], port->macaddr[1],
654                                  port->macaddr[2], port->macaddr[3],
655                                  port->macaddr[4], port->macaddr[5],
656                                  port->admin_status ? "UP" : "DOWN",
657                                  port->link_status ? "UP" : "DOWN");
658         mg_printf(conn, "\t\t");
659         mg_printf(conn, "Speed: %u, %s-duplex\n\r<br/>", port->link_speed,
660                                  port->link_duplex ? "full" : "half");
661         mg_printf(conn, "\t\t");
662
663         if (port->ipv4_list != NULL) {
664                 ip.sin_addr.s_addr =
665                                 (unsigned long)((ipv4list_t *) (port->ipv4_list))->
666                                 ipaddr;
667                 mg_printf(conn, "IP: %s/%d", inet_ntoa(ip.sin_addr),
668                                          ((ipv4list_t *) (port->ipv4_list))->addrlen);
669         } else {
670                 mg_printf(conn, "IP: NA");
671         }
672
673         mg_printf(conn, "\r\n<br/>");
674         mg_printf(conn, "\t\t");
675         if (port->ipv6_list != NULL) {
676                 uint8_t *addr =
677                                 ((ipv6list_t *) (port->ipv6_list))->ipaddr;
678                 mg_printf(conn, "IPv6: %02x%02x:%02x%02x:%02x%02x:"
679                                 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
680                                  addr[0], addr[1], addr[2], addr[3], addr[4],
681                                  addr[5], addr[6], addr[7], addr[8], addr[9],
682                                  addr[10], addr[11], addr[12], addr[13], addr[14],
683                                  addr[15]);
684         } else {
685                 mg_printf(conn, "IPv6: NA");
686         }
687
688         if (port->flags & IFM_SLAVE) {
689                 mg_printf(conn, "  IFM_SLAVE ");
690                 mg_printf(conn, " MasterPort: %u",
691                                          port->bond_config->bond_portid);
692         }
693         if (port->flags & IFM_MASTER) {
694                 mg_printf(conn, "  IFM_MASTER ");
695                 mg_printf(conn, "  Mode: %u", port->bond_config->mode);
696                 mg_printf(conn, "  PrimaryPort: %u",
697                                  port->bond_config->primary);
698                 mg_printf(conn, "\n\r<br/>");
699                 mg_printf(conn, "\t\tSlavePortCount: %u",
700                                          port->bond_config->slave_count);
701                 mg_printf(conn, " SlavePorts:");
702                 int i;
703                 for (i = 0; i < port->bond_config->slave_count; i++) {
704                         mg_printf(conn, " %u ",
705                                  port->bond_config->slaves[i]);
706                 }
707                 mg_printf(conn, " ActivePortCount: %u",
708                                          port->bond_config->active_slave_count);
709                 mg_printf(conn, " ActivePorts:");
710                 for (i = 0; i < port->bond_config->active_slave_count;
711                                  i++) {
712                         mg_printf(conn, " %u ",
713                                          port->bond_config->active_slaves[i]);
714                 }
715                 mg_printf(conn, "\n\r<br/>");
716                 mg_printf(conn, "\t\t");
717                 mg_printf(conn, "Link_monitor_freq: %u ms ",
718                                          port->bond_config->internal_ms);
719                 mg_printf(conn, " Link_up_prop_delay: %u ms ",
720                                          port->bond_config->link_up_delay_ms);
721                 mg_printf(conn, " Link_down_prop_delay: %u ms ",
722                                          port->bond_config->link_down_delay_ms);
723                 mg_printf(conn, "\n\r<br/>");
724                 mg_printf(conn, "\t\t");
725                 mg_printf(conn, "Xmit_policy: %u",
726                                          port->bond_config->xmit_policy);
727         }
728         mg_printf(conn, "\n\r<br/>");
729         mg_printf(conn, "\t\t");
730         mg_printf(conn, "n_rxpkts: %" PRIu64 " ,n_txpkts: %" PRIu64 " ,",
731                                  port->n_rxpkts, port->n_txpkts);
732         struct rte_eth_stats eth_stats;
733         rte_eth_stats_get(port->pmdid, &eth_stats);
734         mg_printf(conn, "pkts_in: %" PRIu64 " ,", eth_stats.ipackets);
735         mg_printf(conn, "pkts_out: %" PRIu64 " ", eth_stats.opackets);
736         mg_printf(conn, "\n\r<br/>");
737         mg_printf(conn, "\t\t");
738         mg_printf(conn, "in_errs: %" PRIu64 " ,", eth_stats.ierrors);
739         mg_printf(conn, "in_missed: %" PRIu64 " ,", eth_stats.imissed);
740         mg_printf(conn, "out_errs: %" PRIu64 " ,", eth_stats.oerrors);
741         mg_printf(conn, "mbuf_errs: %" PRIu64 " ", eth_stats.rx_nombuf);
742         mg_printf(conn, "\n\r<br/>");
743         mg_printf(conn, "\n\r");
744
745         if (USE_RTM_LOCKS)
746                 rtm_unlock();
747         else
748                 rte_rwlock_read_unlock(&rwlock);
749 }
750
751 void print_link_info(struct app_link_params *p, struct mg_connection *conn)
752 {
753         struct rte_eth_stats stats;
754         struct ether_addr *mac_addr;
755         uint32_t netmask = (~0U) << (32 - p->depth);
756         uint32_t host = p->ip & netmask;
757         uint32_t bcast = host | (~netmask);
758
759         memset(&stats, 0, sizeof(stats));
760         rte_eth_stats_get(p->pmd_id, &stats);
761
762         mac_addr = (struct ether_addr *) &p->mac_addr;
763
764         if (strlen(p->pci_bdf))
765                 mg_printf(conn, "%s(%s): flags=%s\r\n<br/>",
766                         p->name,
767                         p->pci_bdf,
768                         (p->state) ? "UP" : "DOWN");
769         else
770                 mg_printf(conn, "%s: flags=%s\r\n<br/>",
771                         p->name,
772                         (p->state) ? "UP" : "DOWN");
773         if (p->ip)
774                 mg_printf(conn, "\tinet %" PRIu32 ".%" PRIu32
775                         ".%" PRIu32 ".%" PRIu32
776                         " netmask %" PRIu32 ".%" PRIu32
777                         ".%" PRIu32 ".%" PRIu32 " "
778                         "broadcast %" PRIu32 ".%" PRIu32
779                         ".%" PRIu32 ".%" PRIu32 "\r\n<br/>",
780                         (p->ip >> 24) & 0xFF,
781                         (p->ip >> 16) & 0xFF,
782                         (p->ip >> 8) & 0xFF,
783                         p->ip & 0xFF,
784                         (netmask >> 24) & 0xFF,
785                         (netmask >> 16) & 0xFF,
786                         (netmask >> 8) & 0xFF,
787                         netmask & 0xFF,
788                         (bcast >> 24) & 0xFF,
789                         (bcast >> 16) & 0xFF,
790                         (bcast >> 8) & 0xFF,
791                         bcast & 0xFF);
792         mg_printf(conn, "\tether %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32
793                 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\r\n<br/>",
794                 mac_addr->addr_bytes[0],
795                 mac_addr->addr_bytes[1],
796                 mac_addr->addr_bytes[2],
797                 mac_addr->addr_bytes[3],
798                 mac_addr->addr_bytes[4],
799                 mac_addr->addr_bytes[5]);
800
801         mg_printf(conn, "\tRX packets %" PRIu64
802                 "  bytes %" PRIu64
803                 "\r\n<br/>",
804                 stats.ipackets,
805                 stats.ibytes);
806
807         mg_printf(conn, "\tRX errors %" PRIu64
808                 "  missed %" PRIu64
809                 "  no-mbuf %" PRIu64
810                 "\r\n<br/>",
811                 stats.ierrors,
812                 stats.imissed,
813                 stats.rx_nombuf);
814
815         mg_printf(conn, "\tTX packets %" PRIu64
816                 "  bytes %" PRIu64 "\r\n<br/>",
817                 stats.opackets,
818                 stats.obytes);
819
820         mg_printf(conn, "\tTX errors %" PRIu64
821                 "\r\n<br/>",
822                 stats.oerrors);
823
824         mg_printf(conn, "\r\n<br/>");
825 }
826
827 int get_link_tokens(char *buf)
828 {
829         char *token;
830         int linkid;
831
832         token = strtok(buf, "/ ");
833         if (strcmp(token, "link")) {
834                 return -1;
835         }
836
837         token = strtok(NULL, "/ ");
838         linkid = atoi(token);
839         if (linkid > current_cfg.num_ports) {
840                 return -1;
841         }
842
843         return linkid;
844 }
845
846 int linkls_handler(struct mg_connection *conn, void *cbdata)
847 {
848         struct app_params *app = rapp;
849
850         struct app_link_params *p;
851
852         APP_PARAM_FIND_BY_ID(app->link_params, "LINK", *(uint32_t *)cbdata, p);
853         if (p) {
854                 print_link_info(p, conn);
855         }
856
857         print_interface_details_rest(conn, *(uint32_t *)cbdata);
858         return 1;
859 }
860
861 static const char* arp_status[] = {"INCOMPLETE", "COMPLETE", "PROBE", "STALE"};
862
863 /* ND IPv6 */
864 int nd_handler(struct mg_connection *conn, __rte_unused void *cbdata)
865 {
866         const void *next_key;
867         void *next_data;
868         uint32_t iter = 0;
869         uint8_t ii = 0;
870         mg_printf(conn, "----------------------------------------------------");
871         mg_printf(conn, "-------------------------------------------------\n<br/>");
872         mg_printf(conn, "\tport  hw addr            status         ip addr\n<br/>");
873
874         mg_printf(conn, "-----------------------------------------------------");
875         mg_printf(conn, "-------------------------------------------------\n<br/>");
876         while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
877                                  0) {
878
879                 struct nd_entry_data *tmp_nd_data =
880                                 (struct nd_entry_data *)next_data;
881                 struct nd_key_ipv6 tmp_nd_key;
882                 memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6));
883                 mg_printf(conn, "\t%4d  %02X:%02X:%02X:%02X:%02X:%02X  %10s",
884                                          tmp_nd_data->port,
885                                          tmp_nd_data->eth_addr.addr_bytes[0],
886                                          tmp_nd_data->eth_addr.addr_bytes[1],
887                                          tmp_nd_data->eth_addr.addr_bytes[2],
888                                          tmp_nd_data->eth_addr.addr_bytes[3],
889                                          tmp_nd_data->eth_addr.addr_bytes[4],
890                                          tmp_nd_data->eth_addr.addr_bytes[5],
891                                          arp_status[tmp_nd_data->status]);
892                 mg_printf(conn, "\t");
893                 for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) {
894                         mg_printf(conn, "%02X%02X ", tmp_nd_data->ipv6[ii],
895                                                  tmp_nd_data->ipv6[ii + 1]);
896                 }
897                 mg_printf(conn, "\n<br/>");
898         }
899
900         mg_printf(conn, "\nND IPV6 Stats: \nTotal Queries %u, ok_NH %u,"
901                         " no_NH %u, ok_Entry %u, "
902                         "no_Entry %u, PopulateCall %u, Del %u, Dup %u\n<br/>",
903                          lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found,
904                          lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
905                          lib_nd_populate_called, lib_nd_delete_called,
906                          lib_nd_duplicate_found);
907         mg_printf(conn, "ND table key len is %lu\n\n<br/>", sizeof(struct nd_key_ipv6));
908         return 0;
909 }
910
911 int arpls_handler(struct mg_connection *conn, __rte_unused void *cbdata)
912 {
913         const void *next_key;
914         void *next_data;
915         uint32_t iter = 0, len = 0;
916         char buf[1024];
917         
918         len += sprintf
919         (buf + len, "---------------------- ARP CACHE ---------------------\n<br/>");
920         len += sprintf
921         (buf + len, "------------------------------------------------------\n<br/>");
922         len += sprintf(buf + len, "\tport  hw addr            status     ip addr\n<br/>");
923         len += sprintf
924         (buf + len, "------------------------------------------------------\n<br/>");
925
926         while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
927                                  >= 0) {
928
929                 struct arp_entry_data *tmp_arp_data =
930                                 (struct arp_entry_data *)next_data;
931                 struct arp_key_ipv4 tmp_arp_key;
932                 memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4));
933                 len += sprintf
934                         (buf + len, "\t%4d  %02X:%02X:%02X:%02X:%02X:%02X"
935                         "  %10s %d.%d.%d.%d\n<br/>",
936                          tmp_arp_data->port, tmp_arp_data->eth_addr.addr_bytes[0],
937                          tmp_arp_data->eth_addr.addr_bytes[1],
938                          tmp_arp_data->eth_addr.addr_bytes[2],
939                          tmp_arp_data->eth_addr.addr_bytes[3],
940                          tmp_arp_data->eth_addr.addr_bytes[4],
941                          tmp_arp_data->eth_addr.addr_bytes[5],
942                          arp_status[tmp_arp_data->status],
943                          (tmp_arp_data->ip >> 24),
944                          ((tmp_arp_data->ip & 0x00ff0000) >> 16),
945                          ((tmp_arp_data->ip & 0x0000ff00) >> 8),
946                          ((tmp_arp_data->ip & 0x000000ff)));
947         }
948
949         uint32_t i = 0, j;
950         len += sprintf(buf + len, "\n<br/>IP_Address    Mask          Port\n<br/>");
951         for (j = 0; j < gw_get_num_ports(); j++) {
952                 for (i = 0; i < p_route_data[j]->route_ent_cnt; i++) {
953                         len += sprintf(buf + len, "0x%08x \t 0x%08x \t %d\n<br/>",
954                         p_route_data[j]->route_table[i].nh,
955                         p_route_data[j]->route_table[i].mask,
956                         p_route_data[j]->route_table[i].port);
957                 }
958         }
959
960         len += sprintf
961                         (buf + len, "\nARP Stats: Total Queries %u, ok_NH %u,"
962                         " no_NH %u, ok_Entry %u, no_Entry %u, PopulateCall %u,"
963                         " Del %u, Dup %u\n<br/>",
964                          lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found,
965                          lib_arp_arp_entry_found, lib_arp_no_arp_entry_found,
966                          lib_arp_populate_called, lib_arp_delete_called,
967                          lib_arp_duplicate_found);
968
969         len += sprintf(buf + len, "ARP table key len is %lu\n<br/>",
970                          sizeof(struct arp_key_ipv4));
971         mg_printf(conn, "%s\n<br/>", &buf[0]);
972         return 1; 
973 }
974
975 void get_mac(struct ether_addr *mac_addr, char *buf)
976 {
977         uint32_t i = 0, j = 0, k = 0, MAC_NUM_BYTES = 6;
978
979         char byteStr[MAC_NUM_BYTES][3];
980
981         char *token = strtok(buf, " ");
982         while (token) {
983                 k = 0;
984                 for (i = 0; i < MAC_NUM_BYTES; i++) {
985                         for (j = 0; j < 2; j++) {
986                                 byteStr[i][j] = token[k++];
987                         }
988                         byteStr[i][j] = '\0';
989                 k++;
990                 }
991                 token = strtok(NULL, " ");
992         }
993
994         for (i = 0; i < MAC_NUM_BYTES; i++) {
995                 mac_addr->addr_bytes[i] = strtoul(byteStr[i], NULL, 16);
996         }
997 }
998
999 int arp_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1000 {
1001         const struct mg_request_info *req_info = mg_get_request_info(conn);
1002         char buf[MAX_BUF_SIZE];
1003
1004         if (!strcmp(req_info->request_method, "GET")) {
1005                 mg_printf(conn,
1006                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1007                   "close\r\n\r\n");
1008                 /* prints arp table */
1009                 mg_printf(conn, "<html><body>");
1010                 arpls_handler(conn, cbdata);
1011
1012                 /* prints nd table */
1013                 nd_handler(conn, cbdata);
1014                 mg_printf(conn, "</body></html>");
1015                 return 1;
1016         }
1017
1018         if (strcmp(req_info->request_method, "POST")) {
1019                 mg_printf(conn,
1020                     "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
1021                 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
1022                 mg_printf(conn,
1023                           "%s method not allowed in the POST handler\n",
1024                           req_info->request_method);
1025                 return 1; 
1026         }
1027
1028         mg_printf(conn,
1029                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1030                   "close\r\n\r\n");
1031         mg_printf(conn, "<html><body>");
1032
1033         mg_read(conn, buf, sizeof(buf));
1034         json_object * jobj = json_tokener_parse(buf);
1035         json_object_object_foreach(jobj, key, val) {
1036                 if (!strcmp(key, "ipv4")) {
1037                         current_arp_parms.ip = rte_bswap32(inet_addr(
1038                                 json_object_get_string(val)));
1039                         current_arp_parms.family = AF_INET;
1040                 } else if (!strcmp(key, "ipv6")) {
1041                         my_inet_pton_ipv6(AF_INET6,
1042                         json_object_get_string(val),
1043                                  &current_arp_parms.ipv6[0]);
1044                         current_arp_parms.family = AF_INET6;
1045                 } else if (!strcmp(key, "action")) {
1046                         if (!strcmp(json_object_get_string(val), "add"))
1047                                 current_arp_parms.action = 1;
1048                         else if (!strcmp(json_object_get_string(val), "del"))
1049                                 current_arp_parms.action = 2;
1050                         else if (!strcmp(json_object_get_string(val), "req"))
1051                                 current_arp_parms.action = 3;
1052                 } else if (!strcmp(key, "portid")) {
1053                         current_arp_parms.portid =
1054                                  atoi(json_object_get_string(val));
1055                 } else if (!strcmp(key, "macaddr")) {
1056                         get_mac(&current_arp_parms.mac_addr,
1057                                  strdup(json_object_get_string(val)));
1058                 }
1059         }
1060
1061         struct arp_key_ipv4 arp_key;
1062         struct arp_timer_key *callback_key;
1063         struct arp_entry_data *new_arp_data;
1064         struct nd_key_ipv6 nd_key;
1065         struct nd_entry_data *new_nd_data;
1066
1067         if (current_arp_parms.family == AF_INET) {
1068                 switch(current_arp_parms.action) {
1069                         case 1:
1070                                 populate_arp_entry(&current_arp_parms.mac_addr,
1071                                 current_arp_parms.ip, current_arp_parms.portid,
1072                                                  STATIC_ARP);
1073                                 break;
1074                         case 2:
1075                                 callback_key =
1076                                  (struct arp_timer_key*) rte_malloc(NULL,
1077                                 sizeof(struct  arp_timer_key*),
1078                                 RTE_CACHE_LINE_SIZE);
1079                                 arp_key.port_id = current_arp_parms.portid;
1080                                 arp_key.ip = current_arp_parms.ip;
1081                                 arp_key.filler1 = 0;
1082                                 arp_key.filler2 = 0;
1083                                 arp_key.filler3 = 0;
1084                                 new_arp_data = retrieve_arp_entry(arp_key,
1085                                                          STATIC_ARP);
1086                                 callback_key->port_id = current_arp_parms.portid;
1087                                 callback_key->ip = current_arp_parms.ip;
1088
1089                                 mg_printf(conn, "removing entry now\n");
1090                                 remove_arp_entry(new_arp_data, callback_key);
1091                                 break;
1092                         case 3:
1093                                 arp_key.ip = current_arp_parms.ip;
1094                                 arp_key.port_id = current_arp_parms.portid;
1095                                 arp_key.filler1 = 0;
1096                                 arp_key.filler2 = 0;
1097                                 arp_key.filler3 = 0;
1098
1099                                 new_arp_data = retrieve_arp_entry(arp_key, STATIC_ARP);
1100
1101                                 if (new_arp_data) {
1102                                         mg_printf(conn, "<p>ARP entry exists for"
1103                                                 " ip 0x%x, port %d</p>",
1104                                                  current_arp_parms.ip, current_arp_parms.portid);
1105                                         return 1;
1106                                 }
1107
1108                                 mg_printf(conn, "<p>ARP - requesting arp for ip 0x%x, port %d</p>",
1109                                         current_arp_parms.ip, current_arp_parms.portid);
1110
1111                                 request_arp(current_arp_parms.portid, current_arp_parms.ip);
1112                                 break;
1113                         default:
1114                                 break;
1115                 };
1116         } else {
1117                 switch(current_arp_parms.action) {
1118                         case 1:
1119                                 populate_nd_entry(&current_arp_parms.mac_addr,
1120                                 current_arp_parms.ipv6, current_arp_parms.portid, STATIC_ND);
1121                                 break;
1122                         case 2:
1123                                 nd_key.port_id = current_arp_parms.portid;
1124                                 memcpy(&nd_key.ipv6[0], &current_arp_parms.ipv6[0], 16);
1125                                 nd_key.filler1 = 0;
1126                                 nd_key.filler2 = 0;
1127                                 nd_key.filler3 = 0;
1128                                 new_nd_data = retrieve_nd_entry(nd_key, STATIC_ND);
1129                                 remove_nd_entry_ipv6(new_nd_data, &nd_key);
1130                         case 3:
1131                                 mg_printf(conn, "<p>ND REQ is not supported Yet!!!</p>");
1132                                 break;
1133                         default:
1134                                 break;
1135                 };
1136         }
1137
1138         mg_printf(conn, "<p>Command Passed</p>");
1139         mg_printf(conn, "</body></html>\n");
1140         return 1;
1141 }
1142
1143 int route_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1144 {
1145         /* Handler may access the request info using mg_get_request_info */
1146         const struct mg_request_info *req_info = mg_get_request_info(conn);
1147         uint32_t portid = 0;
1148         uint32_t i, j, status;
1149         char buf[MAX_BUF_SIZE];
1150         uint32_t mask = 0, num = 31;
1151
1152         if (!strcmp(req_info->request_method, "GET")) {
1153                 mg_printf(conn,
1154                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1155                   "close\r\n\r\n");
1156                 mg_printf(conn, "<pre>\nIP_Address    Mask          Port\n<br/>");
1157
1158                 for (j = 0; j < gw_get_num_ports(); j++) {
1159                         for (i = 0; i < p_route_data[j]->route_ent_cnt; i++) {
1160                                 mg_printf(conn, "0x%08x \t 0x%08x \t %d\n<br/>",
1161                                 p_route_data[j]->route_table[i].nh,
1162                                 p_route_data[j]->route_table[i].mask,
1163                                 p_route_data[j]->route_table[i].port);
1164                         }
1165                 }
1166
1167                 mg_printf(conn, "\n\nND IPV6 routing table ...\n<br/>");
1168                 mg_printf(conn, "\nNH_IP_Address                                "
1169                                 "       Depth          Port \n<br/>");
1170                 for(uint32_t p = 0; p < gw_get_num_ports(); p++ ) {
1171                         for (i = 0; i < p_nd_route_data[p]->nd_route_ent_cnt; i++) {
1172                                 for (j = 0; j < ND_IPV6_ADDR_SIZE; j += 2) {
1173                                         mg_printf(conn, "%02X%02X ",
1174                                          p_nd_route_data[p]->nd_route_table[i].nhipv6[j],
1175                                         p_nd_route_data[p]->nd_route_table[i].nhipv6[j + 1]);
1176                                 }
1177
1178                                 mg_printf(conn, "\t%d           %d              "
1179                                         "                       \n<br/></pre>",
1180                                         p_nd_route_data[p]->nd_route_table[i].depth,
1181                                         p_nd_route_data[p]->nd_route_table[i].port);
1182                         }
1183                 }
1184
1185                 return 1;
1186         }
1187
1188         if (strcmp(req_info->request_method, "POST")) {
1189                 mg_printf(conn,
1190                           "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
1191                 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
1192                 mg_printf(conn,
1193                           "%s method not allowed in the POST handler\n",
1194                           req_info->request_method);
1195                 return 1; 
1196         }
1197
1198         mg_printf(conn,
1199                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1200                   "close\r\n\r\n");
1201         mg_printf(conn, "<html><body>");
1202         
1203         mg_read(conn, buf, sizeof(buf));
1204         json_object * jobj = json_tokener_parse(buf);
1205         json_object_object_foreach(jobj, key, val) {
1206                 if (!strcmp(key, "portid")) {
1207                         portid = atoi(json_object_get_string(val));
1208                         if (portid > 64) {
1209                                 mg_printf(conn, "Port not supported!!!\n");
1210                                 return 1;
1211                         } else if (current_route_parms[portid].enable) {
1212                                 mg_printf(conn, "Already configured\n");
1213                         }
1214                 } else if (!strcmp(key, "nhipv4")) {
1215                         current_route_parms[portid].ip =
1216                                  rte_bswap32(inet_addr(json_object_get_string(val)));
1217                         current_route_parms[portid].family = AF_INET;
1218                 } else if (!strcmp(key, "nhipv6")) {
1219                         my_inet_pton_ipv6(AF_INET6,
1220                         json_object_get_string(val), &current_route_parms[portid].ipv6[0]);
1221                         current_route_parms[portid].family = AF_INET6;
1222                 } else if (!strcmp(key, "depth")) {
1223                         current_route_parms[portid].depth = atoi(json_object_get_string(val));
1224                         current_route_parms[portid].enable = 1; 
1225                 } else if (!strcmp(key, "type")) {
1226                         memcpy(current_route_parms[portid].type, json_object_get_string(val), 
1227                                 strlen(json_object_get_string(val)));
1228                 } 
1229         }
1230
1231         if (current_route_parms[portid].family == AF_INET) {
1232                 if (!strcmp(current_route_parms[portid].type, "net"))  {
1233                         for (i = 0; i < current_route_parms[portid].depth; i++) {
1234                                 mask |= (1 << num);
1235                                 num--;
1236                         }
1237                 } else
1238                         mask = 0xFFFFFFFF;
1239
1240                 status = app_routeadd_config_ipv4(rapp, portid,
1241                                  current_route_parms[portid].ip,
1242                                  mask);
1243                 if (status != 0)
1244                         mg_printf(conn, "Setting route entry failed\n");
1245         } else {
1246
1247                 if (!strcmp(current_route_parms[portid].type, "host"))  {
1248                         current_route_parms[portid].depth = 128;
1249                 }
1250                 status = app_routeadd_config_ipv6(rapp, portid,
1251                          current_route_parms[portid].ipv6,
1252                          current_route_parms[portid].depth);
1253                 if (status != 0)
1254                         mg_printf(conn, "Setting route entry failed\n");
1255         }
1256
1257
1258         mg_printf(conn, "</body></html>\n");
1259         return 1;
1260 }
1261
1262 int link_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1263 {
1264         /* Handler may access the request info using mg_get_request_info */
1265         const struct mg_request_info *req_info = mg_get_request_info(conn);
1266         int i, status = 0, link = 0, link_read = 0;
1267         char buf[MAX_BUF_SIZE];
1268
1269         if (!strcmp(req_info->request_method, "GET")) {
1270                 mg_printf(conn,
1271                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1272                   "close\r\n\r\n");
1273                 mg_printf(conn, "<html><body>\n");
1274                 for (i = 0; i < MAX_LINKS; i++) {
1275                         if (current_link_parms[i].state)
1276                                 mg_printf(conn, "link %d is enabled\r\n", i);
1277                 }
1278                 mg_printf(conn, "</body></html>\n");
1279                 return 1;
1280         }
1281
1282         if (strcmp(req_info->request_method, "POST")) {
1283                 mg_printf(conn,
1284                           "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
1285                 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
1286                 mg_printf(conn,
1287                           "%s method not allowed in the POST handler\n",
1288                           req_info->request_method);
1289                 return 1; 
1290         }
1291
1292         mg_read(conn, buf, sizeof(buf));
1293         json_object * jobj = json_tokener_parse(buf);
1294         json_object_object_foreach(jobj, key, val) {
1295                 if (!strcmp(key, "linkid")) {
1296                         link = atoi(json_object_get_string(val));
1297                         mg_printf(conn, "linkid:%d \n", link);
1298                         if (link > 64) {
1299                                 mg_printf(conn, "Link id not supported beyond 64\n");
1300                                 return 1;
1301                         }
1302                         current_link_parms[link].id = link;
1303                         link_read = 1;
1304                 } else if (!strcmp(key, "state")) {
1305                         if (link_read) {
1306                                 current_link_parms[link].state =
1307                                          atoi(json_object_get_string(val));
1308                         }
1309                         mg_printf(conn, "state:%d \n", current_link_parms[link].state);
1310                 } 
1311
1312         }
1313
1314
1315         if (current_link_parms[link].state == 0) {
1316                 /* link down */
1317                 status = app_link_down(rapp, current_link_parms[link].id);
1318                 if (status != 0) {
1319                         mg_printf(conn, "<p>command failed</p>");
1320                 } else {
1321                         mg_printf(conn, "<p>command Passed</p>");
1322                 }
1323         } else if (current_link_parms[link].state == 1) {
1324                 /* link up */
1325                 mg_printf(conn, "setting up the link \n");
1326                 status = app_link_up(rapp, current_link_parms[link].id);
1327                 if (status != 0) {
1328                         mg_printf(conn, "<p>command failed</p>");
1329                 } else {
1330                         mg_printf(conn, "<p>command Passed</p>");
1331                 }
1332
1333         }
1334
1335         sprintf(buf, "/vnf/config/link/%d", link);
1336         mg_set_request_handler(ctx, buf, linkid_handler, (void *)&link);
1337
1338         mg_printf(conn,
1339                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1340                   "close\r\n\r\n");
1341         return 1;
1342 }
1343
1344 int linkid_handler(struct mg_connection *conn, void *cbdata)
1345 {
1346         /* Handler may access the request info using mg_get_request_info */
1347         const struct mg_request_info *req_info = mg_get_request_info(conn);
1348         int status = 0;
1349         char buf[MAX_BUF_SIZE];
1350
1351         if (!strcmp(req_info->request_method, "GET")) {
1352                 mg_printf(conn,
1353                         "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1354                         "close\r\n\r\n");
1355                 mg_printf(conn, "<html><body>\n");
1356                 linkls_handler(conn, cbdata);
1357                 mg_printf(conn, "</body></html>\n");
1358                 return 1;
1359         }
1360
1361         if (strcmp(req_info->request_method, "POST")) {
1362                 mg_printf(conn,
1363                           "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
1364                 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
1365                 mg_printf(conn,
1366                           "%s method not allowed in the POST handler\n",
1367                           req_info->request_method);
1368                 return 1; 
1369         }
1370
1371         mg_printf(conn,
1372                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1373                   "close\r\n\r\n");
1374         mg_printf(conn, "<html><body>");
1375         
1376         uint32_t linkid = *(uint32_t *)cbdata;
1377         mg_printf(conn, "link id :%d ", linkid);
1378
1379         if (!current_link_parms[linkid].state) {
1380                 mg_printf(conn, "<p>link not enabled!! </p>");
1381                 mg_printf(conn, "</body></html>\n");
1382                 return 1;
1383         }
1384                 
1385         mg_read(conn, buf, sizeof(buf));
1386         json_object * jobj = json_tokener_parse(buf);
1387         json_object_object_foreach(jobj, key, val) {
1388                 if (!strcmp(key, "ipv4")) {
1389                         current_link_parms[linkid].ip =
1390                                  rte_bswap32(inet_addr(json_object_get_string(val)));
1391                         current_link_parms[linkid].family = AF_INET;
1392                 } else if (!strcmp(key, "ipv6")) {
1393                         my_inet_pton_ipv6(AF_INET6,
1394                         json_object_get_string(val), &current_link_parms[linkid].ipv6[0]);
1395                         current_link_parms[linkid].family = AF_INET6;
1396                 } else if (!strcmp(key, "depth")) {
1397                         current_link_parms[linkid].depth = atoi(json_object_get_string(val));
1398                 } 
1399         }
1400
1401
1402         /* bring the link down */
1403         status = app_link_down(rapp, linkid);
1404         if (status != 0) {
1405                 mg_printf(conn, "<p>command down failed</p>");
1406         } else {
1407                 mg_printf(conn, "<p>command Passed</p>");
1408         }
1409
1410         /* configure the ip address */
1411         if (current_link_parms[linkid].family == AF_INET) {
1412                 status = app_link_config(rapp, linkid, current_link_parms[linkid].ip,
1413                         current_link_parms[linkid].depth);
1414         } else {
1415                 status = app_link_config_ipv6(rapp, linkid,
1416                         current_link_parms[linkid].ipv6, current_link_parms[linkid].depth);
1417         }
1418
1419         if (status != 0) {
1420                 mg_printf(conn, "<p>command config failed</p>");
1421         } else {
1422                 mg_printf(conn, "<p>command Passed</p>");
1423         }
1424
1425         /* bring the link up */
1426         status = app_link_up(rapp, linkid);
1427         if (status != 0) {
1428                 mg_printf(conn, "<p>command up failed</p>");
1429         } else {
1430                 mg_printf(conn, "<p>command Passed</p>");
1431         }
1432
1433
1434         mg_printf(conn, "</body></html>\n");
1435         return 1;
1436 }
1437
1438 void set_vnf_type(const char *type)
1439 {
1440         memcpy(current_cfg.vnf_type, type, strlen(type));
1441 }
1442
1443 void init_stat_cfg(void)
1444 {
1445         char buf[256] = "98103214:(1, 65535)";
1446         uint32_t i;
1447
1448         current_cfg.num_workers = 4;
1449         current_cfg.num_lb = 1;
1450         current_cfg.num_ports = 2;
1451         current_cfg.hyper_thread = 0;
1452         current_cfg.sock_in = 0;
1453         current_cfg.sw_lb = 1;
1454         memcpy(current_cfg.pkt_type, "ipv4", 4);
1455
1456         for (i=0;i<MAX_LB;i++) {
1457                 memcpy(current_cfg.ip_range[i].value, &buf,
1458                         sizeof(buf));
1459         }
1460 }
1461
1462 void bind_the_ports(struct mg_connection *conn, char *pci_white_list)
1463 {
1464         char *token;
1465         char buf[MAX_BUF_SIZE];
1466         int x = 0, ret;
1467
1468         token = strtok(pci_white_list, " ");
1469
1470         while(token != NULL) {
1471                 mg_printf(conn, "%s ****\n", token);
1472                 sprintf(buf, "$RTE_SDK/usertools/dpdk-devbind.py -u %s", token);
1473                 ret = system(buf);
1474                 if (ret)
1475                         mg_printf(conn, "wrong parameter sent\n");
1476
1477                 sprintf(buf, "$RTE_SDK/usertools/dpdk-devbind.py -b igb_uio %s", token);
1478                 ret = system(buf);
1479                 if (ret)
1480                         mg_printf(conn, "wrong parameter sent\n");
1481
1482                 token = strtok(NULL, " ");
1483
1484                 x++;
1485         }
1486         current_cfg.num_ports = x;
1487 }
1488
1489 int static_cfg_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1490 {
1491         int i;
1492         unsigned int len;
1493         char buf[MAX_BUF_SIZE];
1494
1495         const struct mg_request_info *ri = mg_get_request_info(conn);
1496
1497         if (!strcmp(ri->request_method, "GET")) {
1498                 mg_printf(conn,
1499                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1500                   "close\r\n\r\n");
1501                 mg_printf(conn, "<html><body>");
1502                 mg_printf(conn, "<h2> These are the values set in config</h2>");
1503                 mg_printf(conn, "<h3> num_workers: %d\n</h3>",
1504                                          current_cfg.num_workers);
1505                 mg_printf(conn, "<h3> num_lb: %d\n</h3>",
1506                                          current_cfg.num_lb);
1507                 mg_printf(conn, "<h3> num_ports: %d\n</h3>",
1508                                          current_cfg.num_ports);
1509                 mg_printf(conn, "<h3> hyper_thread: %d\n</h3>",
1510                                          current_cfg.hyper_thread);
1511                 mg_printf(conn, "<h3> socket_id : %d\n</h3>",
1512                                          current_cfg.sock_in);
1513                 mg_printf(conn, "<h3> sw_lb: %d\n</h3>",
1514                                          current_cfg.sw_lb);
1515                 mg_printf(conn, "<h3> vnf_type: %s\n</h3>",
1516                                         current_cfg.vnf_type);
1517                 mg_printf(conn, "<h3> pkt_type: %s\n</h3>",
1518                                          current_cfg.pkt_type);
1519                 mg_printf(conn, "<h3> pci_white_list: %s\n</h3>",
1520                                          current_cfg.pci_white_list);
1521                 mg_printf(conn, "</body></html>\n");
1522                 return 1;
1523         }
1524
1525         if (strcmp(ri->request_method, "POST")) {
1526                 mg_printf(conn,
1527                           "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
1528                 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
1529                 mg_printf(conn,
1530                           "%s method not allowed in the POST handler\n",
1531                           ri->request_method);
1532                 return 1; 
1533         }
1534
1535         if (static_cfg_set) {
1536                 mg_printf(conn,
1537                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1538                   "close\r\n\r\n");
1539                 return 1;
1540         }
1541                 
1542         mg_read(conn, buf, sizeof(buf));
1543         json_object * jobj = json_tokener_parse(buf);
1544         len = 0;
1545         struct json_object *values;
1546         char *str;
1547
1548         i = 0;
1549         json_object_object_foreach(jobj, key, val) {
1550                 memcpy(static_cfg[i].key, key, strlen(key));
1551                 memcpy(static_cfg[i].value, json_object_get_string(val),
1552                                  strlen(json_object_get_string(val)));
1553                 sprintf(buf, "public_ip_port_range_%d", pub_ip);
1554                 if (!strcmp(static_cfg[i].key, buf)) {
1555                         memcpy(&current_cfg.ip_range[pub_ip].value,
1556                                 static_cfg[i].value,
1557                                  sizeof(static_cfg[i].value));
1558                         pub_ip++;
1559                 }
1560                 i++;
1561         }
1562         n_entries1 = i;
1563
1564         json_object_object_get_ex(jobj, "num_worker", &values);
1565         if (values) {
1566                 str = strdup(json_object_get_string(values));
1567                 if (str)
1568                         memcpy(&current_cfg.ip_range[pub_ip++].value, str,
1569                                  sizeof(str));
1570         }
1571
1572         json_object_object_get_ex(jobj, "num_worker", &values);
1573         if (values) {
1574                 str = strdup(json_object_get_string(values));
1575                 if (str)
1576                         current_cfg.num_workers = atoi(str);
1577         }
1578
1579         json_object_object_get_ex(jobj, "pkt_type", &values);
1580         if (values) {
1581                 str = strdup(json_object_get_string(values));
1582                 if (str)
1583                         memcpy(&current_cfg.pkt_type, str,
1584                                  sizeof(current_cfg.pkt_type));
1585         }
1586
1587         json_object_object_get_ex(jobj, "num_lb", &values);
1588         if (values) {
1589                 str = strdup(json_object_get_string(values));
1590                 if (str)
1591                         current_cfg.num_lb = atoi(str);
1592         }
1593
1594         json_object_object_get_ex(jobj, "num_ports", &values);
1595         if (values) {
1596                 str = strdup(json_object_get_string(values));
1597                 if (str)
1598                         current_cfg.num_ports = atoi(str);
1599         }
1600         
1601         json_object_object_get_ex(jobj, "sw_lb", &values);
1602         if (values) {
1603                 str = strdup(json_object_get_string(values));
1604                 if (str)
1605                         current_cfg.sw_lb = atoi(str);
1606         }
1607
1608         json_object_object_get_ex(jobj, "sock_in", &values);
1609         if (values) {
1610                 str = strdup(json_object_get_string(values));
1611                 if (str)
1612                         current_cfg.sock_in = atoi(str);
1613         }
1614
1615         json_object_object_get_ex(jobj, "hyperthread", &values);
1616         if (values) {
1617                 str = strdup(json_object_get_string(values));
1618                 if (str)
1619                         current_cfg.hyper_thread = atoi(str);
1620         }
1621
1622         json_object_object_get_ex(jobj, "vnf_type", &values);
1623         if (values) {
1624                 str = strdup(json_object_get_string(values));
1625                 if (str)
1626                         memcpy(&current_cfg.vnf_type, str,
1627                                  sizeof(current_cfg.vnf_type));
1628         }
1629
1630         json_object_object_get_ex(jobj, "pci_white_list", &values);
1631         if (values) {
1632                 str = strdup(json_object_get_string(values));
1633                 if (str)
1634                         memcpy(&current_cfg.pci_white_list, str,
1635                         sizeof(current_cfg.pci_white_list));
1636                 mg_printf(conn, " Binding the ports \n");
1637                 bind_the_ports(conn, &current_cfg.pci_white_list[0]);
1638         }
1639
1640         len = sprintf(buf, "POST DATA RECEIVED\n");
1641         
1642         mg_printf(conn,
1643                   "HTTP/1.1 200 OK\r\n"
1644                   "Content-Length: %u\r\n"
1645                   "Content-Type: text/plain\r\n"
1646                   "Connection: close\r\n\r\n",
1647                   len);
1648
1649         mg_write(conn, buf, len);
1650         post_not_received = 0;
1651         static_cfg_set++;
1652         return 1;
1653 }
1654
1655 int vnf_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1656 {
1657         /* Handler may access the request info using mg_get_request_info */
1658         const struct mg_request_info *req_info = mg_get_request_info(conn);
1659
1660         if (!strcmp(req_info->request_method, "GET")) {
1661                 mg_printf(conn,
1662                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1663                   "close\r\n\r\n");
1664                 mg_printf(conn, "<html><body>");
1665                 mg_printf(conn, "<h2>These are the methods that are supported</h2>");
1666                 mg_printf(conn, "<h3> /vnf/config</h3>");
1667                 mg_printf(conn, "<h3> /vnf/config/arp</h3>");
1668                 mg_printf(conn, "<h3> /vnf/config/link</h3>");
1669                 mg_printf(conn, "<h3> /vnf/config/route</h3>");
1670                 mg_printf(conn, "<h3> /vnf/config/rules(vFW/vACL only)</h3>");
1671                 mg_printf(conn, "<h3> /vnf/config/rules/load(vFW/vACL only)</h3>");
1672                 mg_printf(conn, "<h3> /vnf/config/rules/clear(vFW/vACL only)</h3>");
1673                 mg_printf(conn, "<h3> /vnf/config/nat(vCGNAPT only)</h3>");
1674                 mg_printf(conn, "<h3> /vnf/config/nat/load(vFW/vACL only)</h3>");
1675                 mg_printf(conn, "<h3> /vnf/config/dbg</h3>");
1676                 mg_printf(conn, "<h3> /vnf/config/dbg/pipelines</h3>");
1677                 mg_printf(conn, "<h3> /vnf/config/dbg/cmd</h3>");
1678                 mg_printf(conn, "<h3> /vnf/log</h3>");
1679                 mg_printf(conn, "<h3> /vnf/flowdirector</h3>");
1680                 mg_printf(conn, "<h3> /vnf/status</h3>");
1681                 mg_printf(conn, "<h3> /vnf/stats</h3>");
1682                 mg_printf(conn, "<h3> /vnf/quit</h3>");
1683                 mg_printf(conn, "</body></html>");
1684
1685
1686                 return 1;
1687         }
1688
1689         if (strcmp(req_info->request_method, "POST")) {
1690                 mg_printf(conn,
1691                           "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
1692                 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
1693                 mg_printf(conn,
1694                           "%s method not allowed in the POST handler\n",
1695                           req_info->request_method);
1696                 return 1; 
1697         }
1698
1699         return 1;
1700 }
1701
1702 void get_pktq_in_prv(char *buf)
1703 {
1704         int j;
1705         uint32_t len = 0;
1706         for (j = 0; j < current_cfg.num_ports; j+=2) {
1707                 len += sprintf(buf + len, "RXQ%d.0 ", j);
1708         }
1709 }
1710
1711 void fix_pipelines_data_types(FILE *f, const char *sect_name, struct rte_cfgfile *tcfg)
1712 {
1713         int i, j, n_entries, tmp = 0;
1714         char str[256], str1[40];
1715
1716         n_entries = rte_cfgfile_section_num_entries(tcfg, sect_name);
1717
1718         rte_cfgfile_section_entries(tcfg, sect_name, entries, n_entries);
1719
1720         for (i = 0; i < n_entries; i++) {
1721                 for (j = 0; j < n_entries1; j++) {
1722                         if (strncmp(entries[i].name, static_cfg[i].key,
1723                                  strlen(entries[i].name)) == 0) {
1724                                 memcpy(entries[i].value, static_cfg[i].value,
1725                                  strlen(entries[i].value));
1726                                 tmp++;
1727                         }
1728
1729                         if (strncmp(entries[i].name, "pkt_type",
1730                                  strlen("pkt_type")) == 0) {
1731                                 memcpy(entries[i].value, current_cfg.pkt_type,
1732                                  strlen(entries[i].value));
1733                                 if (!strcmp(current_cfg.pkt_type, "ipv4"))
1734                                         memcpy(&traffic_type, "4", 1);
1735                                 else
1736                                         memcpy(&traffic_type, "6", 1);
1737                         }
1738
1739                         if (strncmp(entries[i].name, "traffic_type",
1740                                  sizeof("traffic_type")) == 0) {
1741                                 memcpy(entries[i].value, &traffic_type, 4);
1742                         }
1743                 }
1744
1745                 if (strncmp(entries[i].name, "core", strlen(entries[i].name)) == 0) {
1746                         if ((strncmp(sect_name, "MASTER", strlen(sect_name)) == 0) &&
1747                                 !current_cfg.sock_in) {
1748                                 continue;
1749                         }
1750
1751                         if ((current_cfg.hyper_thread) && hyper) {
1752                                 sprintf(str, "s%dc%dh", current_cfg.sock_in,
1753                                          sock_cpus[current_cfg.sock_in][sock_index]);
1754                                 memcpy(entries[i].value, &str, 8);
1755                                 sock_index++;
1756                                 hyper = 0;
1757                                 continue;
1758                         }
1759         
1760                         sprintf(str, "s%dc%d", current_cfg.sock_in,
1761                                  sock_cpus[current_cfg.sock_in][sock_index]);
1762
1763                         if (!current_cfg.hyper_thread)
1764                                 sock_index++;
1765                         else
1766                                 hyper = 1;
1767
1768                         if (current_cfg.sock_in) {
1769                                 if (sock_index == sock1)
1770                                         sock_index = 1;
1771                         } else {
1772                                 if (sock_index == sock0)
1773                                         sock_index = 1;
1774                         }
1775                         memcpy(entries[i].value, &str, 8);
1776                 }
1777         }
1778         num_entries = i;
1779
1780         if (strncmp(sect_name, "ARPICMP", strlen(sect_name)) == 0) {
1781                 for (j = 0; j < n_entries1; j++) {
1782                         if ((strncmp(static_cfg[j].key, "arp_route_tbl",
1783                                  strlen(static_cfg[j].key)) == 0) ||
1784                                 (strncmp(static_cfg[j].key, "nd_route_tbl",
1785                                  strlen(static_cfg[j].key)) == 0)) {
1786                                 memcpy(&entries[i].name, &static_cfg[j].key,
1787                                          strlen(static_cfg[j].key));
1788                                 memcpy(&entries[i].value, &static_cfg[j].value,
1789                                  strlen(static_cfg[j].value));
1790                                 i++;
1791                         }
1792                 }
1793                 num_entries = i;
1794                 /* update pktq_in/pktq_out */
1795                 for (i=0; i < n_entries; i++) {
1796                         memset(str, 0, 256);
1797                         if (strncmp(entries[i].name, "pktq_in",
1798                                  strlen(entries[i].name)) == 0) {
1799                                 tmp = (current_cfg.sw_lb)? current_cfg.num_lb: current_cfg.num_workers;
1800                                 get_swq(tmp, &str[0]);
1801                                 memcpy(&entries[i].value, &str, strlen(str));
1802                                 continue;
1803                         }
1804
1805                         if (strncmp(entries[i].name, "pktq_out",
1806                                  strlen(entries[i].name)) == 0) {
1807                                 //tmp = (current_cfg.sw_lb)? current_cfg.num_lb: current_cfg.num_workers / 2;
1808                                 //tmp = (current_cfg.sw_lb)? current_cfg.num_lb: current_cfg.num_ports;
1809                                 get_txq(0, 1, current_cfg.num_ports, &str[0]);
1810                                 memcpy(&entries[i].value, &str, strlen(str));
1811                                 continue;
1812                         }
1813
1814                         if (strncmp(entries[i].name, "pktq_in_prv",
1815                                  strlen(entries[i].name)) == 0) {
1816                                 get_pktq_in_prv(&str[0]);
1817                                 memset(&entries[i].value, 0, sizeof(entries[i].value));
1818                                 memcpy(&entries[i].value, &str, strlen(str));
1819                                 continue;
1820                         }
1821
1822                         if (strncmp(entries[i].name, "prv_to_pub_map",
1823                                  strlen(entries[i].name)) == 0) {
1824                                 get_prv_to_pub_map(&str[0]);
1825                                 memcpy(&entries[i].value, &str, strlen(str));
1826                                 continue;
1827                         }
1828
1829                         if (strncmp(entries[i].name, "prv_que_handler",
1830                                  strlen(entries[i].name)) == 0) {
1831                                 get_prv_que_handler(&str[0]);
1832                                 memcpy(&entries[i].value, &str, strlen(str));
1833                                 continue;
1834                         }
1835                 }
1836         }
1837
1838         if (strncmp(sect_name, "TXRX-BEGIN", strlen(sect_name)) == 0) {
1839                 for (i=0; i < n_entries; i++) {
1840                         if (strncmp(entries[i].name, "pktq_in",
1841                                  strlen(entries[i].name)) == 0) {
1842                                 get_rxq(0, 1, 2, &str[0]);
1843                                 memcpy(entries[i].value, &str, sizeof(str));
1844                         }
1845
1846                         if (strncmp(entries[i].name, "pktq_out",
1847                                  strlen(entries[i].name)) == 0) {
1848                                 get_swq(2, &str[0]);
1849                                 memcpy(loadb_in, str, sizeof(str));
1850                                 sprintf(str1," SWQ%d", arp_index++);
1851                                 strcat(str, str1);      
1852                                 memcpy(entries[i].value, &str, sizeof(str));
1853                         }
1854                 }
1855         }
1856
1857         if (strncmp(sect_name, "LOADB", strlen(sect_name)) == 0) {
1858                 for (i=0; i < n_entries; i++) {
1859                         if (strncmp(entries[i].name, "pktq_in",
1860                                  strlen(entries[i].name)) == 0) {
1861                                 memcpy(entries[i].value, &loadb_in, sizeof(str));
1862                         }
1863
1864                         if (strncmp(entries[i].name, "pktq_out",
1865                                  strlen(entries[i].name)) == 0) {
1866                                 if (current_cfg.num_ports > 2)
1867                                         tmp = (current_cfg.num_workers/current_cfg.num_lb * 2);
1868                                 else
1869                                         tmp = current_cfg.num_workers * 2;
1870                                 start_lb = swq_index;
1871                                 end_lb = tmp;
1872                                 start_lbout = start_lb + end_lb;
1873                                 get_swq(tmp, &str[0]);
1874                                 memcpy(entries[i].value, &str, sizeof(str));
1875                         }
1876                         if (strncmp(entries[i].name, "n_vnf_threads",
1877                                  strlen(entries[i].name)) == 0) {
1878                                 sprintf(str1, "%d", current_cfg.num_workers/current_cfg.num_lb);
1879                                 memcpy(entries[i].value, &str1, sizeof(str1));
1880                         }
1881                 }
1882         }
1883
1884         if (strncmp(sect_name, "VACL", strlen(sect_name)) == 0) {
1885                 for (i=0; i < n_entries; i++) {
1886                         if (strncmp(entries[i].name, "pktq_in",
1887                                  strlen(entries[i].name)) == 0) {
1888                                 if (current_cfg.sw_lb) {
1889                                         get_swq_offset(start_lb, 2, &str[0]);
1890                                         start_lb += 2;
1891                                 } else
1892                                         get_rxq(workers, 1, 2, &str[0]);
1893
1894                                 memcpy(entries[i].value, &str, sizeof(str));
1895                         }
1896
1897                         if (strncmp(entries[i].name, "pktq_out",
1898                                  strlen(entries[i].name)) == 0) {
1899                                 if (current_cfg.sw_lb)
1900                                         get_swq(2, &str[0]);
1901                                 else {
1902                                         get_txq(workers+1, 1, 2, &str[0]);
1903                                         sprintf(str1," SWQ%d", arp_index++);
1904                                         strcat(str, str1);
1905                                 }
1906                                 memcpy(entries[i].value, &str, sizeof(str));
1907                         }
1908                 }
1909
1910                 workers++;
1911                 if (current_cfg.sw_lb) {
1912                         if (((workers % current_cfg.num_workers/current_cfg.num_lb) == 0) &&
1913                                  (workers != current_cfg.num_workers)) {
1914                                 workers = 0;
1915                         }
1916                 } else {
1917                         if ((workers % current_cfg.num_workers/current_cfg.num_lb) == 0) {
1918                                 tx_start_port += 2;
1919                                 rx_start_port += 2;
1920                                 workers = 0;
1921                         }
1922                 }
1923         }
1924
1925         if (strncmp(sect_name, "VCGNAPT", strlen(sect_name)) == 0) {
1926                 for (i=0; i < n_entries; i++) {
1927                         if (strncmp(entries[i].name, "pktq_in",
1928                                  strlen(entries[i].name)) == 0) {
1929                                 if (current_cfg.sw_lb) {
1930                                         get_swq_offset(start_lb, 2, &str[0]);
1931                                         start_lb += 2;
1932                                 } else
1933                                         get_rxq(workers, 1, 2, &str[0]);
1934
1935                                 memcpy(entries[i].value, &str, sizeof(str));
1936                         }
1937
1938                         if (strncmp(entries[i].name, "pktq_out",
1939                                  strlen(entries[i].name)) == 0) {
1940                                 if (current_cfg.sw_lb)
1941                                         get_swq(2, &str[0]);
1942                                 else {
1943                                         get_txq(workers+1, 1, 2, &str[0]);
1944                                         sprintf(str1," SWQ%d", arp_index++);
1945                                         strcat(str, str1);
1946                                 }
1947                                 memcpy(entries[i].value, &str, sizeof(str));
1948                         }
1949                 }
1950
1951                 if (workers == 0) {
1952                         char *token;
1953                         sprintf(str1, "vnf_set");
1954                         memcpy(entries[i].name, &str1, sizeof(str1));
1955                         sprintf(str1, "(3,4,5)");
1956                         memcpy(entries[i].value, &str1, sizeof(str1));
1957                         num_entries++;
1958                         i++;
1959
1960                         token = strtok(current_cfg.ip_range[ip_range].value, "/");
1961                         while(token) {
1962                                 sprintf(str1, "public_ip_port_range");
1963                                 memcpy(entries[i].name, &str1, sizeof(str1));
1964                                 memcpy(entries[i].value, token, strlen(token));
1965                                 i++;
1966                                 num_entries++;
1967                                 token = strtok(NULL, "/");
1968                         }
1969                         ip_range++;
1970                 }
1971
1972                 workers++;
1973                 if (current_cfg.sw_lb) {
1974                         if (((workers % (current_cfg.num_workers/current_cfg.num_lb)) == 0) &&
1975                                  (workers != current_cfg.num_workers)) {
1976                                 workers = 0;
1977                         }
1978                 } else {
1979                         //if (((workers % (current_cfg.num_workers/current_cfg.num_lb)) == 0) &&
1980                         //       (workers != current_cfg.num_workers)) {
1981                         if (workers == (current_cfg.num_workers/current_cfg.num_lb)) {
1982                                 tx_start_port += 2;
1983                                 rx_start_port += 2;
1984                                 workers = 0;
1985                         }
1986                 }
1987         }
1988
1989         if (strncmp(sect_name, "VFW", strlen(sect_name)) == 0) {
1990                 for (i=0; i < n_entries; i++) {
1991                         if (strncmp(entries[i].name, "pktq_in",
1992                                  strlen(entries[i].name)) == 0) {
1993                                 if (current_cfg.sw_lb) {
1994                                         get_swq_offset(start_lb, 2, &str[0]);
1995                                         start_lb += 2;
1996                                 } else
1997                                         get_rxq(workers, 1, 2, &str[0]);
1998
1999                                 memcpy(entries[i].value, &str, sizeof(str));
2000                         }
2001
2002                         if (strncmp(entries[i].name, "pktq_out",
2003                                  strlen(entries[i].name)) == 0) {
2004                                 if (current_cfg.sw_lb)
2005                                         get_swq(2, &str[0]);
2006                                 else {
2007                                         get_txq(workers+1, 1, 2, &str[0]);
2008                                         sprintf(str1," SWQ%d", arp_index++);
2009                                         strcat(str, str1);
2010                                 }
2011                                 memcpy(entries[i].value, &str, sizeof(str));
2012                         }
2013                 }
2014
2015                 workers++;
2016                 if (current_cfg.sw_lb) {
2017                         if (((workers % current_cfg.num_workers/current_cfg.num_lb) == 0)
2018                                  && (workers != current_cfg.num_workers)) {
2019                                 workers = 0;
2020                         }
2021                 } else {
2022                         if (current_cfg.num_ports > 2) {
2023                                 tx_start_port += 2;
2024                                 rx_start_port += 2;
2025                                 workers = 0;
2026                         }
2027                 }
2028         }
2029
2030         if (strncmp(sect_name, "TXRX-END", strlen(sect_name)) == 0) {
2031                 for (i=0; i < n_entries; i++) {
2032                         if (strncmp(entries[i].name, "pktq_in",
2033                                  strlen(entries[i].name)) == 0) {
2034                                 get_swq_offset(start_lbout, end_lb, &str[0]);
2035                                 memcpy(entries[i].value, &str, sizeof(str));
2036                         }
2037
2038                         if (strncmp(entries[i].name, "pktq_out",
2039                                  strlen(entries[i].name)) == 0) {
2040                                 get_txq(1, end_lb / 2, 2, &str[0]);
2041                                 memcpy(entries[i].value, &str, sizeof(str));
2042                         }
2043                 }
2044                 tx_start_port += 2;
2045                 rx_start_port += 2;
2046         }
2047
2048         fprintf(f, "[PIPELINE%d]\n", pipenum);
2049         for (i=0;i<num_entries;i++) {
2050                 fprintf(f, "%s = %s\n", entries[i].name, entries[i].value);
2051         }
2052         fprintf(f, "\n");
2053         pipenum++;
2054 }
2055
2056 void print_to_file(FILE *f, struct rte_cfgfile *tcfg)
2057 {
2058         int i;
2059         for (i=0;i<num_pipelines;i++) {
2060                 fix_pipelines_data_types(f, pipelines[pipe_arr[i]], tcfg);
2061         }
2062         fclose(f);
2063 }
2064
2065 int get_vnf_index(void)
2066 {
2067
2068         int i;
2069
2070         for (i = 0; i < PIPE_MAX; i++) {
2071                 if (strncmp(pipelines[i], current_cfg.vnf_type,
2072                                  strlen(current_cfg.vnf_type)) == 0)
2073                         return i;
2074         }
2075         return -1;
2076 }
2077
2078 void build_pipeline(void)
2079 {
2080         int i = 2, j, k, vnf_index;
2081
2082         pipe_arr[0] = 0;
2083         pipe_arr[1] = 1;
2084         vnf_index = get_vnf_index();
2085         if (vnf_index == -1)
2086                 printf("Wrong VNF TYPE\n");
2087
2088         if (vnf_index == VNF_VCGNAPT)
2089                 pipe_arr[i++] = 2;
2090
2091         if (!current_cfg.sw_lb) {
2092                 for (k = 0; k < current_cfg.num_workers; k++)
2093                         pipe_arr[i++] = vnf_index;
2094                 num_pipelines = i;
2095                 return;
2096         }
2097
2098         for (j = 0; j < current_cfg.num_lb; j++) {
2099                         /* put TXRX-BEGIN & LOADB pipelines */
2100                 pipe_arr[i++] = TXRX_BEGIN;
2101                 pipe_arr[i++] = LOADB;
2102
2103                 /* place the worker threads */
2104                 int limit = current_cfg.num_workers / current_cfg.num_lb;
2105                 for (k = 0; k < limit; k++)
2106                         pipe_arr[i++] = vnf_index;
2107
2108                 /* end the TXRX pipeline */
2109                 pipe_arr[i++] = TXRX_END;
2110         }
2111         num_pipelines = i;
2112 }
2113
2114 int set_hash_global_config(struct mg_connection *conn, uint32_t port_id,
2115          char *flow_type, const char *hash_func, const char *enable)
2116 {
2117         struct rte_eth_hash_filter_info info;
2118         uint32_t ftype, idx, offset;
2119         int ret;
2120
2121         if (rte_eth_dev_filter_supported(port_id,
2122                                 RTE_ETH_FILTER_HASH) < 0) {
2123                 mg_printf(conn, "RTE_ETH_FILTER_HASH not supported on port %d\n",
2124                                 port_id);
2125                 return 1;
2126         }
2127         memset(&info, 0, sizeof(info));
2128         info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG;
2129         if (!strcmp(hash_func, "toeplitz"))
2130                 info.info.global_conf.hash_func =
2131                         RTE_ETH_HASH_FUNCTION_TOEPLITZ;
2132         else if (!strcmp(hash_func, "simple_xor"))
2133                 info.info.global_conf.hash_func =
2134                         RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
2135         else if (!strcmp(hash_func, "default"))
2136                 info.info.global_conf.hash_func =
2137                         RTE_ETH_HASH_FUNCTION_DEFAULT;
2138
2139         ftype = str2flowtype(flow_type);
2140         idx = ftype / (CHAR_BIT * sizeof(uint32_t));
2141         offset = ftype % (CHAR_BIT * sizeof(uint32_t));
2142         info.info.global_conf.valid_bit_mask[idx] |= (1UL << offset);
2143         if (!strcmp(enable, "enable"))
2144                 if(idx < RTE_SYM_HASH_MASK_ARRAY_SIZE)
2145                 info.info.global_conf.sym_hash_enable_mask[idx] |=
2146                         (1UL << offset);
2147         ret = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH,
2148                         RTE_ETH_FILTER_SET, &info);
2149         if (ret < 0)
2150                 mg_printf(conn, "Cannot set global hash configurations by port %d\n",
2151                                 port_id);
2152         else
2153                 mg_printf(conn, "Global hash configurations have been set "
2154                                 "succcessfully by port %d\n", port_id);
2155         return 1;
2156 }
2157
2158 int flow_director_handler(struct mg_connection *conn, __rte_unused void *cbdata)
2159 {
2160         /* Handler may access the request info using mg_get_request_info */
2161         const struct mg_request_info *req_info = mg_get_request_info(conn);
2162         uint32_t port_id = 0, tuple = 0;
2163         char trans_type[24], buf[MAX_BUF_SIZE];
2164         char *str, field0[MAX_SIZE], field1[MAX_SIZE], field2[MAX_SIZE],
2165                  field3[MAX_SIZE], flow_type[MAX_SIZE];
2166
2167         if (!strcmp(req_info->request_method, "GET")) {
2168                 mg_printf(conn,
2169                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
2170                   "close\r\n\r\n");
2171                 mg_printf(conn, "<html><body>");
2172                 if (flow_dir_cfg)
2173                         mg_printf(conn, "<h3> Flow is configured </h3>");
2174                 else
2175                         mg_printf(conn, "<h3> Flow is NOT configured </h3>");
2176                 mg_printf(conn, "</body></html>");
2177                 return 1;
2178         }
2179
2180         if (strcmp(req_info->request_method, "POST")) {
2181                 mg_printf(conn,
2182                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
2183                   "close\r\n\r\n");
2184                 mg_printf(conn, "<html><body>");
2185                 mg_printf(conn, "This method is not supported\n");
2186                 mg_printf(conn, "</body></html>");
2187                 return 1;
2188
2189         }
2190
2191         mg_read(conn, buf, sizeof(buf));
2192         json_object * jobj = json_tokener_parse(buf);
2193         json_object_object_foreach(jobj, key, val) {
2194                 if (!strcmp(key, "trans_type")) {
2195                         memcpy(&trans_type, str, sizeof(trans_type));
2196                         if (!strcmp(key, "udp")) {
2197                                 memcpy(field2,"udp-src-port", sizeof("udp-src-port"));
2198                                 memcpy(field3,"udp-dst-port", sizeof("udp-dst-port"));
2199                                 if (!strcmp(current_cfg.pkt_type, "ipv4")) {
2200                                         memcpy(flow_type,"ipv4-udp", sizeof("ipv4-udp"));
2201                                         memcpy(field0,"src-ipv4", sizeof("src-ipv4"));
2202                                         memcpy(field1,"dst-ipv4", sizeof("dst-ipv4"));
2203                                 } else if (!strcmp(current_cfg.pkt_type, "ipv6")) {
2204                                         memcpy(flow_type,"ipv6-udp", sizeof("ipv6-udp"));
2205                                         memcpy(field0,"src-ipv6", sizeof("src-ipv6"));
2206                                         memcpy(field1,"dst-ipv6", sizeof("dst-ipv6"));
2207                                 }
2208                         } else if (!strcmp(key, "tcp")) {
2209                                 memcpy(field2,"tcp-src-port", sizeof("tcp-src-port"));
2210                                 memcpy(field3,"tcp-dst-port", sizeof("tcp-dst-port"));
2211                                 if (!strcmp(current_cfg.pkt_type, "ipv4")) {
2212                                         memcpy(flow_type,"ipv4-tcp", sizeof("ipv4-tcp"));
2213                                         memcpy(field0,"src-ipv4", sizeof("src-ipv4"));
2214                                         memcpy(field1,"dst-ipv4", sizeof("dst-ipv4"));
2215                                 } else if (!strcmp(current_cfg.pkt_type, "ipv6")) {
2216                                         memcpy(flow_type,"ipv6-tcp", sizeof("ipv6-tcp"));
2217                                         memcpy(field0,"src-ipv6", sizeof("src-ipv6"));
2218                                         memcpy(field1,"dst-ipv6", sizeof("dst-ipv6"));
2219                                 }
2220                         }
2221                 } else if (!strcmp(key, "tuple")) {
2222                         tuple = atoi(json_object_get_string(val));
2223                         if ((tuple != 2) || (tuple != 5))
2224                                 return 1;
2225                 } 
2226         }
2227
2228         if (tuple == 2) {
2229                 set_pkt_forwarding_mode("rxonly");
2230                 for (port_id = 0; port_id < current_cfg.num_ports; port_id++) {
2231                         set_sym_hash_per_port(conn, port_id);
2232                         set_hash_global_config(conn, port_id, flow_type,
2233                          "simple_xor", "enable");
2234                 }
2235
2236                 for (port_id = 0; port_id < current_cfg.num_ports; port_id+=2) {
2237                         set_hash_input_set_2(conn, port_id, "ipv4-udp", "src-ipv4",
2238                                  "udp-src-port", "add"); 
2239                         set_hash_input_set_2(conn, port_id, "ipv4-udp", "dst-ipv4",
2240                                  "udp-dst-port", "add"); 
2241                         set_hash_input_set_2(conn, port_id, "ipv4-udp", "src-ipv6",
2242                                  "udp-src-port", "add"); 
2243                         set_hash_input_set_2(conn, port_id, "ipv4-udp", "dst-ipv6",
2244                                  "udp-dst-port", "add");
2245                 }
2246         } else if (tuple == 5) {
2247                 set_pkt_forwarding_mode("rxonly");
2248                 for (port_id = 0; port_id < current_cfg.num_ports; port_id++) {
2249                         set_sym_hash_per_port(conn, port_id);
2250                         set_hash_global_config(conn, port_id, flow_type,
2251                         "simple_xor", "enable");
2252                 }
2253
2254                 for (port_id = 0; port_id < current_cfg.num_ports; port_id+=2) {
2255                         set_hash_input_set_4(conn, port_id, flow_type, field0, field1,
2256                                 field2, field3, "add");
2257                 }
2258         }
2259         flow_dir_cfg = 1;
2260         return 1;
2261 }
2262
2263 void get_swq_offset(uint8_t start, uint8_t num, char *buf)
2264 {
2265         int i;
2266         uint32_t len = 0;
2267
2268         for (i = start; i < start+num; i++) {
2269                 sprintf(buf + len, "SWQ%d ", i);
2270                 len = strlen(buf);
2271         }
2272 }
2273
2274 void get_swq(uint8_t num, char *buf)
2275 {
2276         int i;
2277         uint32_t len = 0;
2278
2279         for (i=0;i<num;i++) {
2280                 sprintf(buf + len, "SWQ%d ", swq_index++);
2281                 len = strlen(buf);
2282         }
2283 }
2284
2285 void get_prv_to_pub_map(char *buf)
2286 {
2287         int j;
2288         uint32_t len = 0;
2289         for (j = 0; j < current_cfg.num_ports; j+=2) {
2290                 sprintf(buf + len, "(%d,%d)", j, j+1);
2291                 len = strlen(buf);
2292         }
2293 }
2294
2295 void get_prv_que_handler(char *buf)
2296 {
2297         int j;
2298         uint32_t len = 0;
2299         sprintf(buf + len, "(");
2300         len = strlen(buf);
2301         for (j = 0; j < current_cfg.num_ports; j+=2) {
2302                 sprintf(buf + len, "%d,", j);
2303                 len = strlen(buf);
2304         }
2305         sprintf(buf + len, ")");
2306 }
2307
2308 void get_txq(uint8_t start_q, uint8_t queue_num, uint8_t ports, char *buf)
2309 {
2310         int i, j;
2311         uint32_t len = 0;
2312         for (i=tx_start_port;i<tx_start_port + ports;i+=2)
2313         {
2314                 for (j=start_q;j<(start_q + queue_num);j++)
2315                 {
2316                         sprintf(buf + len, " TXQ%d.%d TXQ%d.%d", i, j, i+1, j);
2317                         len = strlen(buf);
2318                 }
2319         }
2320
2321 }
2322
2323 void get_rxq(uint8_t start_q, uint8_t queue_num, uint8_t ports, char *buf)
2324 {
2325         int i, j;
2326         uint32_t len = 0;
2327
2328         for (i=rx_start_port;i<rx_start_port + ports;i+=2)
2329         {
2330                 for (j=start_q;j<(start_q + queue_num);j++)
2331                 {
2332                         sprintf(buf + len, " RXQ%d.%d RXQ%d.%d", i, j, i+1, j);
2333                         len = strlen(buf);
2334                 }
2335         }
2336
2337 }
2338
2339 struct mg_context *
2340 rest_api_init(struct app_params *app)
2341 {
2342         struct rte_cfgfile *tcfg;
2343         FILE *f;
2344         char buf[256];
2345         const char *options[] = {"listening_ports", "80", NULL};
2346         uint32_t i, lcore_id = 0;
2347         uint32_t sock, index;
2348         
2349         /* Server context handle */
2350         rapp = app;
2351
2352         for (lcore_id=0;lcore_id<64;lcore_id++) {
2353                 //lcore_id = rte_get_next_lcore(lcore_id, 0, 0);
2354                 sock = eal_cpu_socket_id(lcore_id);
2355                 index = (sock == 0)? sock0++ : sock1++;
2356                 sock_cpus[sock][index] = lcore_id;
2357         }
2358
2359
2360         /* Initialize the icivetweb library */
2361         mg_init_library(0);
2362
2363         /* Start the server */
2364         ctx = mg_start(NULL, 0, options);
2365         if (ctx == NULL) {
2366                 printf("REST server did not start\n");
2367                 printf("REST services will not be supported.. Try again ");
2368                 printf("by disabling other webservers\n");
2369                 goto end;
2370         }
2371         
2372         /* init handlers being called here */
2373         init_stat_cfg();
2374
2375         /* static config handler */
2376         mg_set_request_handler(ctx, "/vnf", vnf_handler, 0);
2377         mg_set_request_handler(ctx, "/vnf/config", static_cfg_handler, 0);
2378         
2379         /* arp handler */
2380         mg_set_request_handler(ctx, "/vnf/config/arp", arp_handler, 0);
2381
2382         /* route handler */
2383         mg_set_request_handler(ctx, "/vnf/config/route", route_handler, 0);
2384
2385
2386         /* link related handlers */
2387         mg_set_request_handler(ctx, "/vnf/config/link", link_handler, 0);
2388         //mg_set_request_handler(ctx, "/vnf/config/link/*", linkid_handler, 0);
2389
2390         /* dbg related handlers */
2391         mg_set_request_handler(ctx, "/vnf/config/dbg", dbg_handler, 0);
2392         mg_set_request_handler(ctx, "/vnf/config/dbg/pipelines", dbg_pipelines_handler, 0);
2393         mg_set_request_handler(ctx, "/vnf/config/dbg/cmd", dbg_cmd_handler, 0);
2394         mg_set_request_handler(ctx, "/vnf/config/dbg/run", dbg_run_handler, 0);
2395
2396         mg_set_request_handler(ctx, "/vnf/quit", cmd_quit_handler, 0);
2397
2398         printf("Waiting for config input for 30 secs\n");
2399         index = 0;
2400         while(1) {
2401                 if (post_not_received == 0 || (index == 30))
2402                         break;
2403                 sleep(1);
2404                 index++;
2405         }
2406
2407         if (index == 30 && (post_not_received != 0))
2408                 printf("Input not received for 30 secs, going with default");
2409
2410         const char *name = "vnf_template.txt";
2411         /* Load application configuration file */
2412         tcfg = rte_cfgfile_load(name, 0);
2413         if (tcfg == NULL)
2414                 printf("File could not be loaded\n");
2415
2416 //      if (!current_cfg.sw_lb)
2417 //              current_cfg.num_lb = 1;
2418
2419         /* build pipelines based on the input given */
2420         build_pipeline();
2421
2422         for (i = 0; i < num_pipelines; i++) {
2423                 sprintf(buf, "/vnf/config/dbg/pipelines/%d", i);
2424                 mg_set_request_handler(ctx, buf, dbg_pipelines_id_handler, (void *)&i);
2425         }
2426
2427         /* create a file for writing the config */
2428         if (!current_cfg.sw_lb) {
2429                 mg_set_request_handler(ctx, "/vnf/flowdirector", flow_director_handler, 0);
2430                 sprintf(buf, "%s_%s_%dP_%dT.cfg", current_cfg.vnf_type, "HWLB",
2431                          current_cfg.num_ports, current_cfg.num_workers);
2432         } else
2433                 sprintf(buf, "%s_%s_%dP_%dLB_%dT.cfg", current_cfg.vnf_type, "SWLB",
2434                          current_cfg.num_ports, current_cfg.num_lb, current_cfg.num_workers);
2435
2436         /* create a file which is more readable */
2437         f = fopen(buf, "w");
2438
2439         print_to_file(f, tcfg);
2440
2441         app->config_file = strdup(buf);
2442         app->parser_file = strdup(buf);
2443
2444         printf("Config file loaded :%s %s\n", app->config_file, traffic_type);
2445
2446 end:
2447         return ctx;
2448 }