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