2 // Copyright (c) 2017 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <sys/queue.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
27 #include <rte_common.h>
28 #include <rte_memory.h>
29 #include <rte_memzone.h>
30 #include <rte_launch.h>
32 #include <rte_per_lcore.h>
33 #include <rte_lcore.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>
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>
51 #include "pipeline_common_fe.h"
52 #include "pipeline_arpicmp.h"
55 #include <json/json.h>
58 #include "interface.h"
62 #define MAX_PIPELINES 30
64 #define CFG_NAME_LEN 64
67 #define MAX_BUF_SIZE 2048
71 #define msleep(x) rte_delay_us(x * 1000)
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;
78 char value[MAX_BUF_SIZE];
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];
102 struct ether_addr mac_addr;
116 struct route_params {
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];
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];
154 uint8_t sock_cpus[MAX_SOCKET][MAX_CORES];
155 uint8_t sock_in = 0, sock0 = 0, sock1 = 0, sock_index = 0;
157 uint32_t flow_dir_cfg = 0;
158 struct app_params *rapp;
160 extern uint32_t nd_route_tbl_index;
161 extern struct arp_data *p_arp_data;
162 extern int USE_RTM_LOCKS;
163 extern rte_rwlock_t rwlock;
164 extern interface_main_t ifm;
165 extern struct cmdline *pipe_cl;
166 extern uint16_t str2flowtype(char *string);
167 extern void app_run_file(cmdline_parse_ctx_t *ctx, const char *file_name);
168 extern int parse_flexbytes(const char *q_arg, uint8_t *flexbytes,
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,
177 extern int app_routeadd_config_ipv6(__attribute__((unused))
178 struct app_params *app,
179 uint32_t port_id, uint8_t ipv6[],
182 enum rte_eth_input_set_field str2inset(char *string);
202 struct json_data static_cfg[40];
203 uint32_t post_not_received = 1;
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,
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);
258 int run_field_found(const char *key, const char *filename, char *path,
259 size_t pathlen, void *user_data)
261 struct mg_connection *conn = (struct mg_connection *)user_data;
263 mg_printf(conn, "\r\n\r\n%s:\r\n", key);
265 if (filename && *filename) {
266 snprintf(path, pathlen, "%s", filename);
269 /* Make sure file exists before clearing rules and actions */
270 fd = open(filename, O_RDONLY);
272 mg_printf(conn, "Cannot open file \"%s\"\n", filename);
273 return FORM_FIELD_STORAGE_GET;
277 mg_printf(conn, "file to be loaded is %s\n", filename);
278 app_run_file(pipe_cl->ctx, filename);
280 return FORM_FIELD_STORAGE_STORE;
283 return FORM_FIELD_STORAGE_GET;
286 int run_field_get(const char *key, const char *value, size_t valuelen,
289 struct mg_connection *conn = (struct mg_connection *)user_data;
292 mg_printf(conn, "%s = ", key);
294 mg_write(conn, value, valuelen);
299 int run_field_stored(const char *path, long long file_size, void *user_data)
301 struct mg_connection *conn = (struct mg_connection *)user_data;
304 "stored as %s (%lu bytes)\r\n\r\n",
306 (unsigned long)file_size);
311 int dbg_run_handler(struct mg_connection *conn, __rte_unused void *cbdata)
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};
318 if (strcmp(req_info->request_method, "POST")) {
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");
325 "%s method not allowed in the POST handler\n",
326 req_info->request_method);
331 /* It would be possible to check the request info here before calling
332 * mg_handle_form_request. */
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");
342 fdh.user_data = (void *)conn;
344 /* Call the form handler */
345 mg_handle_form_request(conn, &fdh);
346 mg_printf(conn, "\r\n script file handled");
351 int cmd_quit_handler(__rte_unused struct mg_connection *conn,
352 __rte_unused void *cbdata)
354 cmdline_quit(pipe_cl);
358 int dbg_handler(struct mg_connection *conn, __rte_unused void *cbdata)
361 const struct mg_request_info *ri = mg_get_request_info(conn);
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>");
378 int get_pipelines_tokens(char *buf)
383 token = strtok(buf, "/ ");
384 if (strcmp(token, "pipelines")) {
388 token = strtok(NULL, "/ ");
390 if (id > rapp->n_pipelines) {
398 int dbg_pipelines_id_handler(struct mg_connection *conn,
399 __rte_unused void *cbdata)
401 struct app_eal_params *p = &rapp->eal_params;
402 const struct mg_request_info *ri = mg_get_request_info(conn);
403 //uint32_t id = (uint32_t *)cbdata;
405 mg_printf(conn, "Inside dbg_pipelines_id_handler\n");
407 if (!strcmp(ri->request_method, "GET")) {
409 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
411 mg_printf(conn, "<html><body>");
412 if (p->log_level_present) {
413 mg_printf(conn, "<h2> The pipeline log level is %d</h2>",
416 mg_printf(conn, "<h2> No log level found in the\
419 mg_printf(conn, "</body></html>");
427 int dbg_pipelines_handler(struct mg_connection *conn, __rte_unused void *cbdata)
431 const struct mg_request_info *ri = mg_get_request_info(conn);
433 if (!strcmp(ri->request_method, "GET")) {
435 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
437 mg_printf(conn, "<html><body>");
438 mg_printf(conn, "<h2> These are pipelines available</h2>");
439 for (i = 0; i < rapp->n_pipelines; i++) {
440 mg_printf(conn, "<h3> pipeline %d: %s\n</h3>",i,
441 rapp->pipeline_params[i].type);
443 mg_printf(conn, "</body></html>");
450 int dbg_cmd_handler(struct mg_connection *conn, __rte_unused void *cbdata)
452 struct app_params *app = rapp;
455 const struct mg_request_info *req_info = mg_get_request_info(conn);
456 char buf[MAX_BUF_SIZE];
458 if (!strcmp(req_info->request_method, "GET")) {
460 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
462 mg_printf(conn, "<html><body>");
463 mg_printf(conn, "<h2> The last command executed </h2>");
464 mg_printf(conn, "<h3> cmd: %d\n </h3>", current_dbg.cmd);
465 mg_printf(conn, "<h3> d1 : %d\n </h3>", current_dbg.d1);
466 mg_printf(conn, "<h3> pipeline : %d\n </h3>",
467 current_dbg.pipe_num);
468 mg_printf(conn, "</body></html>\n");
472 if (strcmp(req_info->request_method, "POST")) {
474 "HTTP/1.1 405 Method Not Allowed\r\nConnection:");
475 mg_printf(conn, " close\r\n");
476 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
477 mg_printf(conn, "%s method not allowed in the POST handler\n",
478 req_info->request_method);
483 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
485 mg_printf(conn, "<html><body>");
486 mg_printf(conn, "</body></html>\n");
488 mg_read(conn, buf, sizeof(buf));
489 json_object * jobj = json_tokener_parse(buf);
490 json_object_object_foreach(jobj, key, val) {
491 if (!strcmp(key, "cmd")) {
492 current_dbg.cmd = atoi(json_object_get_string(val));
493 } else if (!strcmp(key, "d1")) {
494 current_dbg.d1 = atoi(json_object_get_string(val));
495 } else if (!strcmp(key, "pipeline")) {
496 current_dbg.pipe_num = atoi(json_object_get_string(val));
501 msg[0] = current_dbg.cmd;
502 msg[1] = current_dbg.d1;
503 status = app_pipeline_arpicmp_entry_dbg(app, current_dbg.pipe_num, msg);
506 mg_printf(conn, "Dbg Command failed\n");
513 int set_sym_hash_per_port(struct mg_connection *conn, uint32_t port_id)
516 struct rte_eth_hash_filter_info info;
518 if (rte_eth_dev_filter_supported(port_id,
519 RTE_ETH_FILTER_HASH) < 0) {
520 mg_printf(conn, "RTE_ETH_FILTER_HASH not supported on port: %d\n",
525 memset(&info, 0, sizeof(info));
526 info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT;
528 ret = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH,
529 RTE_ETH_FILTER_SET, &info);
531 mg_printf(conn, "Cannot set symmetric hash enable per port on "
532 "port %u\n", port_id);
539 int set_hash_input_set_4(struct mg_connection *conn, uint32_t port_id,
540 char *flow_type, char *inset_field0, char *inset_field1,
541 char *inset_field2, char *inset_field3, const char *select)
543 struct rte_eth_hash_filter_info info;
545 if (enable_flow_dir) {
546 mg_printf(conn, "FDIR Filter is Defined!\n");
547 mg_printf(conn, "Please undefine FDIR_FILTER flag and define "
552 memset(&info, 0, sizeof(info));
553 info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT;
554 info.info.input_set_conf.flow_type = str2flowtype(flow_type);
556 info.info.input_set_conf.field[0] = str2inset(inset_field0);
557 info.info.input_set_conf.field[1] = str2inset(inset_field1);
558 info.info.input_set_conf.field[2] = str2inset(inset_field2);
559 info.info.input_set_conf.field[3] = str2inset(inset_field3);
561 info.info.input_set_conf.inset_size = 4;
562 if (!strcmp(select, "select"))
563 info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
564 else if (!strcmp(select, "add"))
565 info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
567 rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH,
568 RTE_ETH_FILTER_SET, &info);
570 mg_printf(conn, "Command Passed!\n");
574 int set_hash_input_set_2(struct mg_connection *conn, uint32_t port_id,
575 const char *flow_type, const char *inset_field0,
576 const char *inset_field1, const char *select)
578 struct rte_eth_hash_filter_info info;
579 const struct mg_request_info *req_info = mg_get_request_info(conn);
581 if (strcmp(req_info->request_method, "POST")) {
583 "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
584 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
586 "%s method not allowed in the POST handler\n",
587 req_info->request_method);
592 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
594 mg_printf(conn, "<html><body>");
595 mg_printf(conn, "</body></html>\n");
597 if (enable_flow_dir) {
598 mg_printf(conn, "FDIR Filter is Defined!\n");
599 mg_printf(conn, "Please undefine FDIR_FILTER flag and define "
604 if (enable_flow_dir) {
605 mg_printf(conn, "FDIR Filter is Defined!\n");
606 mg_printf(conn, "Please undefine FDIR_FILTER flag and define "
611 memset(&info, 0, sizeof(info));
612 info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT;
613 info.info.input_set_conf.flow_type = str2flowtype(strdup(flow_type));
615 info.info.input_set_conf.field[0] = str2inset(strdup(inset_field0));
616 info.info.input_set_conf.field[1] = str2inset(strdup(inset_field1));
618 info.info.input_set_conf.inset_size = 2;
620 if (!strcmp(select, "select"))
621 info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
622 else if (!strcmp(select, "add"))
623 info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
625 rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH,
626 RTE_ETH_FILTER_SET, &info);
628 mg_printf(conn, "Command Passed!\n");
632 void print_interface_details_rest(struct mg_connection *conn, uint32_t link)
634 l2_phy_interface_t *port;
636 struct sockaddr_in ip;
637 mg_printf(conn, "\n\r");
642 rte_rwlock_read_lock(&rwlock);
645 port = ifm.port_list[i];
646 mg_printf(conn, "%u", port->pmdid);
647 if (port->ifname && strlen(port->ifname)) {
648 mg_printf(conn, " (%s)\t", port->ifname);
650 mg_printf(conn, "\t\t");
651 mg_printf(conn, "MAC:%02x:%02x:%02x:%02x:%02x:%02x Adminstate:%s"
652 " Operstate:%s \n\r<br/>",
653 port->macaddr[0], port->macaddr[1],
654 port->macaddr[2], port->macaddr[3],
655 port->macaddr[4], port->macaddr[5],
656 port->admin_status ? "UP" : "DOWN",
657 port->link_status ? "UP" : "DOWN");
658 mg_printf(conn, "\t\t");
659 mg_printf(conn, "Speed: %u, %s-duplex\n\r<br/>", port->link_speed,
660 port->link_duplex ? "full" : "half");
661 mg_printf(conn, "\t\t");
663 if (port->ipv4_list != NULL) {
665 (unsigned long)((ipv4list_t *) (port->ipv4_list))->
667 mg_printf(conn, "IP: %s/%d", inet_ntoa(ip.sin_addr),
668 ((ipv4list_t *) (port->ipv4_list))->addrlen);
670 mg_printf(conn, "IP: NA");
673 mg_printf(conn, "\r\n<br/>");
674 mg_printf(conn, "\t\t");
675 if (port->ipv6_list != NULL) {
677 ((ipv6list_t *) (port->ipv6_list))->ipaddr;
678 mg_printf(conn, "IPv6: %02x%02x:%02x%02x:%02x%02x:"
679 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
680 addr[0], addr[1], addr[2], addr[3], addr[4],
681 addr[5], addr[6], addr[7], addr[8], addr[9],
682 addr[10], addr[11], addr[12], addr[13], addr[14],
685 mg_printf(conn, "IPv6: NA");
688 if (port->flags & IFM_SLAVE) {
689 mg_printf(conn, " IFM_SLAVE ");
690 mg_printf(conn, " MasterPort: %u",
691 port->bond_config->bond_portid);
693 if (port->flags & IFM_MASTER) {
694 mg_printf(conn, " IFM_MASTER ");
695 mg_printf(conn, " Mode: %u", port->bond_config->mode);
696 mg_printf(conn, " PrimaryPort: %u",
697 port->bond_config->primary);
698 mg_printf(conn, "\n\r<br/>");
699 mg_printf(conn, "\t\tSlavePortCount: %u",
700 port->bond_config->slave_count);
701 mg_printf(conn, " SlavePorts:");
703 for (i = 0; i < port->bond_config->slave_count; i++) {
704 mg_printf(conn, " %u ",
705 port->bond_config->slaves[i]);
707 mg_printf(conn, " ActivePortCount: %u",
708 port->bond_config->active_slave_count);
709 mg_printf(conn, " ActivePorts:");
710 for (i = 0; i < port->bond_config->active_slave_count;
712 mg_printf(conn, " %u ",
713 port->bond_config->active_slaves[i]);
715 mg_printf(conn, "\n\r<br/>");
716 mg_printf(conn, "\t\t");
717 mg_printf(conn, "Link_monitor_freq: %u ms ",
718 port->bond_config->internal_ms);
719 mg_printf(conn, " Link_up_prop_delay: %u ms ",
720 port->bond_config->link_up_delay_ms);
721 mg_printf(conn, " Link_down_prop_delay: %u ms ",
722 port->bond_config->link_down_delay_ms);
723 mg_printf(conn, "\n\r<br/>");
724 mg_printf(conn, "\t\t");
725 mg_printf(conn, "Xmit_policy: %u",
726 port->bond_config->xmit_policy);
728 mg_printf(conn, "\n\r<br/>");
729 mg_printf(conn, "\t\t");
730 mg_printf(conn, "n_rxpkts: %" PRIu64 " ,n_txpkts: %" PRIu64 " ,",
731 port->n_rxpkts, port->n_txpkts);
732 struct rte_eth_stats eth_stats;
733 rte_eth_stats_get(port->pmdid, ð_stats);
734 mg_printf(conn, "pkts_in: %" PRIu64 " ,", eth_stats.ipackets);
735 mg_printf(conn, "pkts_out: %" PRIu64 " ", eth_stats.opackets);
736 mg_printf(conn, "\n\r<br/>");
737 mg_printf(conn, "\t\t");
738 mg_printf(conn, "in_errs: %" PRIu64 " ,", eth_stats.ierrors);
739 mg_printf(conn, "in_missed: %" PRIu64 " ,", eth_stats.imissed);
740 mg_printf(conn, "out_errs: %" PRIu64 " ,", eth_stats.oerrors);
741 mg_printf(conn, "mbuf_errs: %" PRIu64 " ", eth_stats.rx_nombuf);
742 mg_printf(conn, "\n\r<br/>");
743 mg_printf(conn, "\n\r");
748 rte_rwlock_read_unlock(&rwlock);
751 void print_link_info(struct app_link_params *p, struct mg_connection *conn)
753 struct rte_eth_stats stats;
754 struct ether_addr *mac_addr;
755 uint32_t netmask = (~0U) << (32 - p->depth);
756 uint32_t host = p->ip & netmask;
757 uint32_t bcast = host | (~netmask);
759 memset(&stats, 0, sizeof(stats));
760 rte_eth_stats_get(p->pmd_id, &stats);
762 mac_addr = (struct ether_addr *) &p->mac_addr;
764 if (strlen(p->pci_bdf))
765 mg_printf(conn, "%s(%s): flags=%s\r\n<br/>",
768 (p->state) ? "UP" : "DOWN");
770 mg_printf(conn, "%s: flags=%s\r\n<br/>",
772 (p->state) ? "UP" : "DOWN");
774 mg_printf(conn, "\tinet %" PRIu32 ".%" PRIu32
775 ".%" PRIu32 ".%" PRIu32
776 " netmask %" PRIu32 ".%" PRIu32
777 ".%" PRIu32 ".%" PRIu32 " "
778 "broadcast %" PRIu32 ".%" PRIu32
779 ".%" PRIu32 ".%" PRIu32 "\r\n<br/>",
780 (p->ip >> 24) & 0xFF,
781 (p->ip >> 16) & 0xFF,
784 (netmask >> 24) & 0xFF,
785 (netmask >> 16) & 0xFF,
786 (netmask >> 8) & 0xFF,
788 (bcast >> 24) & 0xFF,
789 (bcast >> 16) & 0xFF,
792 mg_printf(conn, "\tether %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32
793 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\r\n<br/>",
794 mac_addr->addr_bytes[0],
795 mac_addr->addr_bytes[1],
796 mac_addr->addr_bytes[2],
797 mac_addr->addr_bytes[3],
798 mac_addr->addr_bytes[4],
799 mac_addr->addr_bytes[5]);
801 mg_printf(conn, "\tRX packets %" PRIu64
807 mg_printf(conn, "\tRX errors %" PRIu64
815 mg_printf(conn, "\tTX packets %" PRIu64
816 " bytes %" PRIu64 "\r\n<br/>",
820 mg_printf(conn, "\tTX errors %" PRIu64
824 mg_printf(conn, "\r\n<br/>");
827 int get_link_tokens(char *buf)
832 token = strtok(buf, "/ ");
833 if (strcmp(token, "link")) {
837 token = strtok(NULL, "/ ");
838 linkid = atoi(token);
839 if (linkid > current_cfg.num_ports) {
846 int linkls_handler(struct mg_connection *conn, void *cbdata)
848 struct app_params *app = rapp;
850 struct app_link_params *p;
852 APP_PARAM_FIND_BY_ID(app->link_params, "LINK", *(uint32_t *)cbdata, p);
854 print_link_info(p, conn);
857 print_interface_details_rest(conn, *(uint32_t *)cbdata);
861 static const char* arp_status[] = {"INCOMPLETE", "COMPLETE", "PROBE", "STALE"};
864 int nd_handler(struct mg_connection *conn, __rte_unused void *cbdata)
866 const void *next_key;
870 mg_printf(conn, "----------------------------------------------------");
871 mg_printf(conn, "-------------------------------------------------\n<br/>");
872 mg_printf(conn, "\tport hw addr status ip addr\n<br/>");
874 mg_printf(conn, "-----------------------------------------------------");
875 mg_printf(conn, "-------------------------------------------------\n<br/>");
876 while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
879 struct nd_entry_data *tmp_nd_data =
880 (struct nd_entry_data *)next_data;
881 struct nd_key_ipv6 tmp_nd_key;
882 memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6));
883 mg_printf(conn, "\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s",
885 tmp_nd_data->eth_addr.addr_bytes[0],
886 tmp_nd_data->eth_addr.addr_bytes[1],
887 tmp_nd_data->eth_addr.addr_bytes[2],
888 tmp_nd_data->eth_addr.addr_bytes[3],
889 tmp_nd_data->eth_addr.addr_bytes[4],
890 tmp_nd_data->eth_addr.addr_bytes[5],
891 arp_status[tmp_nd_data->status]);
892 mg_printf(conn, "\t");
893 for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) {
894 mg_printf(conn, "%02X%02X ", tmp_nd_data->ipv6[ii],
895 tmp_nd_data->ipv6[ii + 1]);
897 mg_printf(conn, "\n<br/>");
900 mg_printf(conn, "\nND IPV6 Stats: \nTotal Queries %u, ok_NH %u,"
901 " no_NH %u, ok_Entry %u, "
902 "no_Entry %u, PopulateCall %u, Del %u, Dup %u\n<br/>",
903 lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found,
904 lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
905 lib_nd_populate_called, lib_nd_delete_called,
906 lib_nd_duplicate_found);
907 mg_printf(conn, "ND table key len is %lu\n\n<br/>", sizeof(struct nd_key_ipv6));
911 int arpls_handler(struct mg_connection *conn, __rte_unused void *cbdata)
913 const void *next_key;
915 uint32_t iter = 0, len = 0;
919 (buf + len, "---------------------- ARP CACHE ---------------------\n<br/>");
921 (buf + len, "------------------------------------------------------\n<br/>");
922 len += sprintf(buf + len, "\tport hw addr status ip addr\n<br/>");
924 (buf + len, "------------------------------------------------------\n<br/>");
926 while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
929 struct arp_entry_data *tmp_arp_data =
930 (struct arp_entry_data *)next_data;
931 struct arp_key_ipv4 tmp_arp_key;
932 memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4));
934 (buf + len, "\t%4d %02X:%02X:%02X:%02X:%02X:%02X"
935 " %10s %d.%d.%d.%d\n<br/>",
936 tmp_arp_data->port, tmp_arp_data->eth_addr.addr_bytes[0],
937 tmp_arp_data->eth_addr.addr_bytes[1],
938 tmp_arp_data->eth_addr.addr_bytes[2],
939 tmp_arp_data->eth_addr.addr_bytes[3],
940 tmp_arp_data->eth_addr.addr_bytes[4],
941 tmp_arp_data->eth_addr.addr_bytes[5],
942 arp_status[tmp_arp_data->status],
943 (tmp_arp_data->ip >> 24),
944 ((tmp_arp_data->ip & 0x00ff0000) >> 16),
945 ((tmp_arp_data->ip & 0x0000ff00) >> 8),
946 ((tmp_arp_data->ip & 0x000000ff)));
950 len += sprintf(buf + len, "\n<br/>IP_Address Mask Port\n<br/>");
951 for (j = 0; j < gw_get_num_ports(); j++) {
952 for (i = 0; i < p_route_data[j]->route_ent_cnt; i++) {
953 len += sprintf(buf + len, "0x%08x \t 0x%08x \t %d\n<br/>",
954 p_route_data[j]->route_table[i].nh,
955 p_route_data[j]->route_table[i].mask,
956 p_route_data[j]->route_table[i].port);
961 (buf + len, "\nARP Stats: Total Queries %u, ok_NH %u,"
962 " no_NH %u, ok_Entry %u, no_Entry %u, PopulateCall %u,"
963 " Del %u, Dup %u\n<br/>",
964 lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found,
965 lib_arp_arp_entry_found, lib_arp_no_arp_entry_found,
966 lib_arp_populate_called, lib_arp_delete_called,
967 lib_arp_duplicate_found);
969 len += sprintf(buf + len, "ARP table key len is %lu\n<br/>",
970 sizeof(struct arp_key_ipv4));
971 mg_printf(conn, "%s\n<br/>", &buf[0]);
975 void get_mac(struct ether_addr *mac_addr, char *buf)
977 uint32_t i = 0, j = 0, k = 0, MAC_NUM_BYTES = 6;
979 char byteStr[MAC_NUM_BYTES][3];
981 char *token = strtok(buf, " ");
984 for (i = 0; i < MAC_NUM_BYTES; i++) {
985 for (j = 0; j < 2; j++) {
986 byteStr[i][j] = token[k++];
988 byteStr[i][j] = '\0';
991 token = strtok(NULL, " ");
994 for (i = 0; i < MAC_NUM_BYTES; i++) {
995 mac_addr->addr_bytes[i] = strtoul(byteStr[i], NULL, 16);
999 int arp_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1001 const struct mg_request_info *req_info = mg_get_request_info(conn);
1002 char buf[MAX_BUF_SIZE];
1004 if (!strcmp(req_info->request_method, "GET")) {
1006 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1008 /* prints arp table */
1009 mg_printf(conn, "<html><body>");
1010 arpls_handler(conn, cbdata);
1012 /* prints nd table */
1013 nd_handler(conn, cbdata);
1014 mg_printf(conn, "</body></html>");
1018 if (strcmp(req_info->request_method, "POST")) {
1020 "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
1021 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
1023 "%s method not allowed in the POST handler\n",
1024 req_info->request_method);
1029 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1031 mg_printf(conn, "<html><body>");
1033 mg_read(conn, buf, sizeof(buf));
1034 json_object * jobj = json_tokener_parse(buf);
1035 json_object_object_foreach(jobj, key, val) {
1036 if (!strcmp(key, "ipv4")) {
1037 current_arp_parms.ip = rte_bswap32(inet_addr(
1038 json_object_get_string(val)));
1039 current_arp_parms.family = AF_INET;
1040 } else if (!strcmp(key, "ipv6")) {
1041 my_inet_pton_ipv6(AF_INET6,
1042 json_object_get_string(val),
1043 ¤t_arp_parms.ipv6[0]);
1044 current_arp_parms.family = AF_INET6;
1045 } else if (!strcmp(key, "action")) {
1046 if (!strcmp(json_object_get_string(val), "add"))
1047 current_arp_parms.action = 1;
1048 else if (!strcmp(json_object_get_string(val), "del"))
1049 current_arp_parms.action = 2;
1050 else if (!strcmp(json_object_get_string(val), "req"))
1051 current_arp_parms.action = 3;
1052 } else if (!strcmp(key, "portid")) {
1053 current_arp_parms.portid =
1054 atoi(json_object_get_string(val));
1055 } else if (!strcmp(key, "macaddr")) {
1056 get_mac(¤t_arp_parms.mac_addr,
1057 strdup(json_object_get_string(val)));
1061 struct arp_key_ipv4 arp_key;
1062 struct arp_timer_key *callback_key;
1063 struct arp_entry_data *new_arp_data;
1064 struct nd_key_ipv6 nd_key;
1065 struct nd_entry_data *new_nd_data;
1067 if (current_arp_parms.family == AF_INET) {
1068 switch(current_arp_parms.action) {
1070 populate_arp_entry(¤t_arp_parms.mac_addr,
1071 current_arp_parms.ip, current_arp_parms.portid,
1076 (struct arp_timer_key*) rte_malloc(NULL,
1077 sizeof(struct arp_timer_key*),
1078 RTE_CACHE_LINE_SIZE);
1079 arp_key.port_id = current_arp_parms.portid;
1080 arp_key.ip = current_arp_parms.ip;
1081 arp_key.filler1 = 0;
1082 arp_key.filler2 = 0;
1083 arp_key.filler3 = 0;
1084 new_arp_data = retrieve_arp_entry(arp_key,
1086 callback_key->port_id = current_arp_parms.portid;
1087 callback_key->ip = current_arp_parms.ip;
1089 mg_printf(conn, "removing entry now\n");
1090 remove_arp_entry(new_arp_data, callback_key);
1093 arp_key.ip = current_arp_parms.ip;
1094 arp_key.port_id = current_arp_parms.portid;
1095 arp_key.filler1 = 0;
1096 arp_key.filler2 = 0;
1097 arp_key.filler3 = 0;
1099 new_arp_data = retrieve_arp_entry(arp_key, STATIC_ARP);
1102 mg_printf(conn, "<p>ARP entry exists for"
1103 " ip 0x%x, port %d</p>",
1104 current_arp_parms.ip, current_arp_parms.portid);
1108 mg_printf(conn, "<p>ARP - requesting arp for ip 0x%x, port %d</p>",
1109 current_arp_parms.ip, current_arp_parms.portid);
1111 request_arp(current_arp_parms.portid, current_arp_parms.ip);
1117 switch(current_arp_parms.action) {
1119 populate_nd_entry(¤t_arp_parms.mac_addr,
1120 current_arp_parms.ipv6, current_arp_parms.portid, STATIC_ND);
1123 nd_key.port_id = current_arp_parms.portid;
1124 memcpy(&nd_key.ipv6[0], ¤t_arp_parms.ipv6[0], 16);
1128 new_nd_data = retrieve_nd_entry(nd_key, STATIC_ND);
1129 remove_nd_entry_ipv6(new_nd_data, &nd_key);
1131 mg_printf(conn, "<p>ND REQ is not supported Yet!!!</p>");
1138 mg_printf(conn, "<p>Command Passed</p>");
1139 mg_printf(conn, "</body></html>\n");
1143 int route_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1145 /* Handler may access the request info using mg_get_request_info */
1146 const struct mg_request_info *req_info = mg_get_request_info(conn);
1147 uint32_t portid = 0;
1148 uint32_t i, j, status;
1149 char buf[MAX_BUF_SIZE];
1150 uint32_t mask = 0, num = 31;
1152 if (!strcmp(req_info->request_method, "GET")) {
1154 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1156 mg_printf(conn, "<pre>\nIP_Address Mask Port\n<br/>");
1158 for (j = 0; j < gw_get_num_ports(); j++) {
1159 for (i = 0; i < p_route_data[j]->route_ent_cnt; i++) {
1160 mg_printf(conn, "0x%08x \t 0x%08x \t %d\n<br/>",
1161 p_route_data[j]->route_table[i].nh,
1162 p_route_data[j]->route_table[i].mask,
1163 p_route_data[j]->route_table[i].port);
1167 mg_printf(conn, "\n\nND IPV6 routing table ...\n<br/>");
1168 mg_printf(conn, "\nNH_IP_Address "
1169 " Depth Port \n<br/>");
1170 for(uint32_t p = 0; p < gw_get_num_ports(); p++ ) {
1171 for (i = 0; i < p_nd_route_data[p]->nd_route_ent_cnt; i++) {
1172 for (j = 0; j < ND_IPV6_ADDR_SIZE; j += 2) {
1173 mg_printf(conn, "%02X%02X ",
1174 p_nd_route_data[p]->nd_route_table[i].nhipv6[j],
1175 p_nd_route_data[p]->nd_route_table[i].nhipv6[j + 1]);
1178 mg_printf(conn, "\t%d %d "
1180 p_nd_route_data[p]->nd_route_table[i].depth,
1181 p_nd_route_data[p]->nd_route_table[i].port);
1188 if (strcmp(req_info->request_method, "POST")) {
1190 "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
1191 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
1193 "%s method not allowed in the POST handler\n",
1194 req_info->request_method);
1199 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1201 mg_printf(conn, "<html><body>");
1203 mg_read(conn, buf, sizeof(buf));
1204 json_object * jobj = json_tokener_parse(buf);
1205 json_object_object_foreach(jobj, key, val) {
1206 if (!strcmp(key, "portid")) {
1207 portid = atoi(json_object_get_string(val));
1209 mg_printf(conn, "Port not supported!!!\n");
1211 } else if (current_route_parms[portid].enable) {
1212 mg_printf(conn, "Already configured\n");
1214 } else if (!strcmp(key, "nhipv4")) {
1215 current_route_parms[portid].ip =
1216 rte_bswap32(inet_addr(json_object_get_string(val)));
1217 current_route_parms[portid].family = AF_INET;
1218 } else if (!strcmp(key, "nhipv6")) {
1219 my_inet_pton_ipv6(AF_INET6,
1220 json_object_get_string(val), ¤t_route_parms[portid].ipv6[0]);
1221 current_route_parms[portid].family = AF_INET6;
1222 } else if (!strcmp(key, "depth")) {
1223 current_route_parms[portid].depth = atoi(json_object_get_string(val));
1224 current_route_parms[portid].enable = 1;
1225 } else if (!strcmp(key, "type")) {
1226 memcpy(current_route_parms[portid].type, json_object_get_string(val),
1227 strlen(json_object_get_string(val)));
1231 if (current_route_parms[portid].family == AF_INET) {
1232 if (!strcmp(current_route_parms[portid].type, "net")) {
1233 for (i = 0; i < current_route_parms[portid].depth; i++) {
1240 status = app_routeadd_config_ipv4(rapp, portid,
1241 current_route_parms[portid].ip,
1244 mg_printf(conn, "Setting route entry failed\n");
1247 if (!strcmp(current_route_parms[portid].type, "host")) {
1248 current_route_parms[portid].depth = 128;
1250 status = app_routeadd_config_ipv6(rapp, portid,
1251 current_route_parms[portid].ipv6,
1252 current_route_parms[portid].depth);
1254 mg_printf(conn, "Setting route entry failed\n");
1258 mg_printf(conn, "</body></html>\n");
1262 int link_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1264 /* Handler may access the request info using mg_get_request_info */
1265 const struct mg_request_info *req_info = mg_get_request_info(conn);
1266 int i, status = 0, link = 0, link_read = 0;
1267 char buf[MAX_BUF_SIZE];
1269 if (!strcmp(req_info->request_method, "GET")) {
1271 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1273 mg_printf(conn, "<html><body>\n");
1274 for (i = 0; i < MAX_LINKS; i++) {
1275 if (current_link_parms[i].state)
1276 mg_printf(conn, "link %d is enabled\r\n", i);
1278 mg_printf(conn, "</body></html>\n");
1282 if (strcmp(req_info->request_method, "POST")) {
1284 "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
1285 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
1287 "%s method not allowed in the POST handler\n",
1288 req_info->request_method);
1292 mg_read(conn, buf, sizeof(buf));
1293 json_object * jobj = json_tokener_parse(buf);
1294 json_object_object_foreach(jobj, key, val) {
1295 if (!strcmp(key, "linkid")) {
1296 link = atoi(json_object_get_string(val));
1297 mg_printf(conn, "linkid:%d \n", link);
1299 mg_printf(conn, "Link id not supported beyond 64\n");
1302 current_link_parms[link].id = link;
1304 } else if (!strcmp(key, "state")) {
1306 current_link_parms[link].state =
1307 atoi(json_object_get_string(val));
1309 mg_printf(conn, "state:%d \n", current_link_parms[link].state);
1315 if (current_link_parms[link].state == 0) {
1317 status = app_link_down(rapp, current_link_parms[link].id);
1319 mg_printf(conn, "<p>command failed</p>");
1321 mg_printf(conn, "<p>command Passed</p>");
1323 } else if (current_link_parms[link].state == 1) {
1325 mg_printf(conn, "setting up the link \n");
1326 status = app_link_up(rapp, current_link_parms[link].id);
1328 mg_printf(conn, "<p>command failed</p>");
1330 mg_printf(conn, "<p>command Passed</p>");
1335 sprintf(buf, "/vnf/config/link/%d", link);
1336 mg_set_request_handler(ctx, buf, linkid_handler, (void *)&link);
1339 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1344 int linkid_handler(struct mg_connection *conn, void *cbdata)
1346 /* Handler may access the request info using mg_get_request_info */
1347 const struct mg_request_info *req_info = mg_get_request_info(conn);
1349 char buf[MAX_BUF_SIZE];
1351 if (!strcmp(req_info->request_method, "GET")) {
1353 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1355 mg_printf(conn, "<html><body>\n");
1356 linkls_handler(conn, cbdata);
1357 mg_printf(conn, "</body></html>\n");
1361 if (strcmp(req_info->request_method, "POST")) {
1363 "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
1364 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
1366 "%s method not allowed in the POST handler\n",
1367 req_info->request_method);
1372 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1374 mg_printf(conn, "<html><body>");
1376 uint32_t linkid = *(uint32_t *)cbdata;
1377 mg_printf(conn, "link id :%d ", linkid);
1379 if (!current_link_parms[linkid].state) {
1380 mg_printf(conn, "<p>link not enabled!! </p>");
1381 mg_printf(conn, "</body></html>\n");
1385 mg_read(conn, buf, sizeof(buf));
1386 json_object * jobj = json_tokener_parse(buf);
1387 json_object_object_foreach(jobj, key, val) {
1388 if (!strcmp(key, "ipv4")) {
1389 current_link_parms[linkid].ip =
1390 rte_bswap32(inet_addr(json_object_get_string(val)));
1391 current_link_parms[linkid].family = AF_INET;
1392 } else if (!strcmp(key, "ipv6")) {
1393 my_inet_pton_ipv6(AF_INET6,
1394 json_object_get_string(val), ¤t_link_parms[linkid].ipv6[0]);
1395 current_link_parms[linkid].family = AF_INET6;
1396 } else if (!strcmp(key, "depth")) {
1397 current_link_parms[linkid].depth = atoi(json_object_get_string(val));
1402 /* bring the link down */
1403 status = app_link_down(rapp, linkid);
1405 mg_printf(conn, "<p>command down failed</p>");
1407 mg_printf(conn, "<p>command Passed</p>");
1410 /* configure the ip address */
1411 if (current_link_parms[linkid].family == AF_INET) {
1412 status = app_link_config(rapp, linkid, current_link_parms[linkid].ip,
1413 current_link_parms[linkid].depth);
1415 status = app_link_config_ipv6(rapp, linkid,
1416 current_link_parms[linkid].ipv6, current_link_parms[linkid].depth);
1420 mg_printf(conn, "<p>command config failed</p>");
1422 mg_printf(conn, "<p>command Passed</p>");
1425 /* bring the link up */
1426 status = app_link_up(rapp, linkid);
1428 mg_printf(conn, "<p>command up failed</p>");
1430 mg_printf(conn, "<p>command Passed</p>");
1434 mg_printf(conn, "</body></html>\n");
1438 void set_vnf_type(const char *type)
1440 memcpy(current_cfg.vnf_type, type, strlen(type));
1443 void init_stat_cfg(void)
1445 char buf[256] = "98103214:(1, 65535)";
1448 current_cfg.num_workers = 4;
1449 current_cfg.num_lb = 1;
1450 current_cfg.num_ports = 2;
1451 current_cfg.hyper_thread = 0;
1452 current_cfg.sock_in = 0;
1453 current_cfg.sw_lb = 1;
1454 memcpy(current_cfg.pkt_type, "ipv4", 4);
1456 for (i=0;i<MAX_LB;i++) {
1457 memcpy(current_cfg.ip_range[i].value, &buf,
1462 void bind_the_ports(struct mg_connection *conn, char *pci_white_list)
1465 char buf[MAX_BUF_SIZE];
1468 token = strtok(pci_white_list, " ");
1470 while(token != NULL) {
1471 mg_printf(conn, "%s ****\n", token);
1472 sprintf(buf, "$RTE_SDK/usertools/dpdk-devbind.py -u %s", token);
1475 mg_printf(conn, "wrong parameter sent\n");
1477 sprintf(buf, "$RTE_SDK/usertools/dpdk-devbind.py -b igb_uio %s", token);
1480 mg_printf(conn, "wrong parameter sent\n");
1482 token = strtok(NULL, " ");
1486 current_cfg.num_ports = x;
1489 int static_cfg_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1493 char buf[MAX_BUF_SIZE];
1495 const struct mg_request_info *ri = mg_get_request_info(conn);
1497 if (!strcmp(ri->request_method, "GET")) {
1499 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1501 mg_printf(conn, "<html><body>");
1502 mg_printf(conn, "<h2> These are the values set in config</h2>");
1503 mg_printf(conn, "<h3> num_workers: %d\n</h3>",
1504 current_cfg.num_workers);
1505 mg_printf(conn, "<h3> num_lb: %d\n</h3>",
1506 current_cfg.num_lb);
1507 mg_printf(conn, "<h3> num_ports: %d\n</h3>",
1508 current_cfg.num_ports);
1509 mg_printf(conn, "<h3> hyper_thread: %d\n</h3>",
1510 current_cfg.hyper_thread);
1511 mg_printf(conn, "<h3> socket_id : %d\n</h3>",
1512 current_cfg.sock_in);
1513 mg_printf(conn, "<h3> sw_lb: %d\n</h3>",
1515 mg_printf(conn, "<h3> vnf_type: %s\n</h3>",
1516 current_cfg.vnf_type);
1517 mg_printf(conn, "<h3> pkt_type: %s\n</h3>",
1518 current_cfg.pkt_type);
1519 mg_printf(conn, "<h3> pci_white_list: %s\n</h3>",
1520 current_cfg.pci_white_list);
1521 mg_printf(conn, "</body></html>\n");
1525 if (strcmp(ri->request_method, "POST")) {
1527 "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
1528 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
1530 "%s method not allowed in the POST handler\n",
1531 ri->request_method);
1535 if (static_cfg_set) {
1537 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1542 mg_read(conn, buf, sizeof(buf));
1543 json_object * jobj = json_tokener_parse(buf);
1545 struct json_object *values;
1549 json_object_object_foreach(jobj, key, val) {
1550 memcpy(static_cfg[i].key, key, strlen(key));
1551 memcpy(static_cfg[i].value, json_object_get_string(val),
1552 strlen(json_object_get_string(val)));
1553 sprintf(buf, "public_ip_port_range_%d", pub_ip);
1554 if (!strcmp(static_cfg[i].key, buf)) {
1555 memcpy(¤t_cfg.ip_range[pub_ip].value,
1556 static_cfg[i].value,
1557 sizeof(static_cfg[i].value));
1564 json_object_object_get_ex(jobj, "num_worker", &values);
1566 str = strdup(json_object_get_string(values));
1568 memcpy(¤t_cfg.ip_range[pub_ip++].value, str,
1572 json_object_object_get_ex(jobj, "num_worker", &values);
1574 str = strdup(json_object_get_string(values));
1576 current_cfg.num_workers = atoi(str);
1579 json_object_object_get_ex(jobj, "pkt_type", &values);
1581 str = strdup(json_object_get_string(values));
1583 memcpy(¤t_cfg.pkt_type, str,
1584 sizeof(current_cfg.pkt_type));
1587 json_object_object_get_ex(jobj, "num_lb", &values);
1589 str = strdup(json_object_get_string(values));
1591 current_cfg.num_lb = atoi(str);
1594 json_object_object_get_ex(jobj, "num_ports", &values);
1596 str = strdup(json_object_get_string(values));
1598 current_cfg.num_ports = atoi(str);
1601 json_object_object_get_ex(jobj, "sw_lb", &values);
1603 str = strdup(json_object_get_string(values));
1605 current_cfg.sw_lb = atoi(str);
1608 json_object_object_get_ex(jobj, "sock_in", &values);
1610 str = strdup(json_object_get_string(values));
1612 current_cfg.sock_in = atoi(str);
1615 json_object_object_get_ex(jobj, "hyperthread", &values);
1617 str = strdup(json_object_get_string(values));
1619 current_cfg.hyper_thread = atoi(str);
1622 json_object_object_get_ex(jobj, "vnf_type", &values);
1624 str = strdup(json_object_get_string(values));
1626 memcpy(¤t_cfg.vnf_type, str,
1627 sizeof(current_cfg.vnf_type));
1630 json_object_object_get_ex(jobj, "pci_white_list", &values);
1632 str = strdup(json_object_get_string(values));
1634 memcpy(¤t_cfg.pci_white_list, str,
1635 sizeof(current_cfg.pci_white_list));
1636 mg_printf(conn, " Binding the ports \n");
1637 bind_the_ports(conn, ¤t_cfg.pci_white_list[0]);
1640 len = sprintf(buf, "POST DATA RECEIVED\n");
1643 "HTTP/1.1 200 OK\r\n"
1644 "Content-Length: %u\r\n"
1645 "Content-Type: text/plain\r\n"
1646 "Connection: close\r\n\r\n",
1649 mg_write(conn, buf, len);
1650 post_not_received = 0;
1655 int vnf_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1657 /* Handler may access the request info using mg_get_request_info */
1658 const struct mg_request_info *req_info = mg_get_request_info(conn);
1660 if (!strcmp(req_info->request_method, "GET")) {
1662 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1664 mg_printf(conn, "<html><body>");
1665 mg_printf(conn, "<h2>These are the methods that are supported</h2>");
1666 mg_printf(conn, "<h3> /vnf/config</h3>");
1667 mg_printf(conn, "<h3> /vnf/config/arp</h3>");
1668 mg_printf(conn, "<h3> /vnf/config/link</h3>");
1669 mg_printf(conn, "<h3> /vnf/config/route</h3>");
1670 mg_printf(conn, "<h3> /vnf/config/rules(vFW/vACL only)</h3>");
1671 mg_printf(conn, "<h3> /vnf/config/rules/load(vFW/vACL only)</h3>");
1672 mg_printf(conn, "<h3> /vnf/config/rules/clear(vFW/vACL only)</h3>");
1673 mg_printf(conn, "<h3> /vnf/config/nat(vCGNAPT only)</h3>");
1674 mg_printf(conn, "<h3> /vnf/config/nat/load(vFW/vACL only)</h3>");
1675 mg_printf(conn, "<h3> /vnf/config/dbg</h3>");
1676 mg_printf(conn, "<h3> /vnf/config/dbg/pipelines</h3>");
1677 mg_printf(conn, "<h3> /vnf/config/dbg/cmd</h3>");
1678 mg_printf(conn, "<h3> /vnf/log</h3>");
1679 mg_printf(conn, "<h3> /vnf/flowdirector</h3>");
1680 mg_printf(conn, "<h3> /vnf/status</h3>");
1681 mg_printf(conn, "<h3> /vnf/stats</h3>");
1682 mg_printf(conn, "<h3> /vnf/quit</h3>");
1683 mg_printf(conn, "</body></html>");
1689 if (strcmp(req_info->request_method, "POST")) {
1691 "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
1692 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
1694 "%s method not allowed in the POST handler\n",
1695 req_info->request_method);
1702 void get_pktq_in_prv(char *buf)
1706 for (j = 0; j < current_cfg.num_ports; j+=2) {
1707 len += sprintf(buf + len, "RXQ%d.0 ", j);
1711 void fix_pipelines_data_types(FILE *f, const char *sect_name, struct rte_cfgfile *tcfg)
1713 int i, j, n_entries, tmp = 0;
1714 char str[256], str1[40];
1716 n_entries = rte_cfgfile_section_num_entries(tcfg, sect_name);
1718 rte_cfgfile_section_entries(tcfg, sect_name, entries, n_entries);
1720 for (i = 0; i < n_entries; i++) {
1721 for (j = 0; j < n_entries1; j++) {
1722 if (strncmp(entries[i].name, static_cfg[i].key,
1723 strlen(entries[i].name)) == 0) {
1724 memcpy(entries[i].value, static_cfg[i].value,
1725 strlen(entries[i].value));
1729 if (strncmp(entries[i].name, "pkt_type",
1730 strlen("pkt_type")) == 0) {
1731 memcpy(entries[i].value, current_cfg.pkt_type,
1732 strlen(entries[i].value));
1733 if (!strcmp(current_cfg.pkt_type, "ipv4"))
1734 memcpy(&traffic_type, "4", 1);
1736 memcpy(&traffic_type, "6", 1);
1739 if (strncmp(entries[i].name, "traffic_type",
1740 sizeof("traffic_type")) == 0) {
1741 memcpy(entries[i].value, &traffic_type, 4);
1745 if (strncmp(entries[i].name, "core", strlen(entries[i].name)) == 0) {
1746 if ((strncmp(sect_name, "MASTER", strlen(sect_name)) == 0) &&
1747 !current_cfg.sock_in) {
1751 if ((current_cfg.hyper_thread) && hyper) {
1752 sprintf(str, "s%dc%dh", current_cfg.sock_in,
1753 sock_cpus[current_cfg.sock_in][sock_index]);
1754 memcpy(entries[i].value, &str, 8);
1760 sprintf(str, "s%dc%d", current_cfg.sock_in,
1761 sock_cpus[current_cfg.sock_in][sock_index]);
1763 if (!current_cfg.hyper_thread)
1768 if (current_cfg.sock_in) {
1769 if (sock_index == sock1)
1772 if (sock_index == sock0)
1775 memcpy(entries[i].value, &str, 8);
1780 if (strncmp(sect_name, "ARPICMP", strlen(sect_name)) == 0) {
1781 for (j = 0; j < n_entries1; j++) {
1782 if ((strncmp(static_cfg[j].key, "arp_route_tbl",
1783 strlen(static_cfg[j].key)) == 0) ||
1784 (strncmp(static_cfg[j].key, "nd_route_tbl",
1785 strlen(static_cfg[j].key)) == 0)) {
1786 memcpy(&entries[i].name, &static_cfg[j].key,
1787 strlen(static_cfg[j].key));
1788 memcpy(&entries[i].value, &static_cfg[j].value,
1789 strlen(static_cfg[j].value));
1794 /* update pktq_in/pktq_out */
1795 for (i=0; i < n_entries; i++) {
1796 memset(str, 0, 256);
1797 if (strncmp(entries[i].name, "pktq_in",
1798 strlen(entries[i].name)) == 0) {
1799 tmp = (current_cfg.sw_lb)? current_cfg.num_lb: current_cfg.num_workers;
1800 get_swq(tmp, &str[0]);
1801 memcpy(&entries[i].value, &str, strlen(str));
1805 if (strncmp(entries[i].name, "pktq_out",
1806 strlen(entries[i].name)) == 0) {
1807 //tmp = (current_cfg.sw_lb)? current_cfg.num_lb: current_cfg.num_workers / 2;
1808 //tmp = (current_cfg.sw_lb)? current_cfg.num_lb: current_cfg.num_ports;
1809 get_txq(0, 1, current_cfg.num_ports, &str[0]);
1810 memcpy(&entries[i].value, &str, strlen(str));
1814 if (strncmp(entries[i].name, "pktq_in_prv",
1815 strlen(entries[i].name)) == 0) {
1816 get_pktq_in_prv(&str[0]);
1817 memset(&entries[i].value, 0, sizeof(entries[i].value));
1818 memcpy(&entries[i].value, &str, strlen(str));
1822 if (strncmp(entries[i].name, "prv_to_pub_map",
1823 strlen(entries[i].name)) == 0) {
1824 get_prv_to_pub_map(&str[0]);
1825 memcpy(&entries[i].value, &str, strlen(str));
1829 if (strncmp(entries[i].name, "prv_que_handler",
1830 strlen(entries[i].name)) == 0) {
1831 get_prv_que_handler(&str[0]);
1832 memcpy(&entries[i].value, &str, strlen(str));
1838 if (strncmp(sect_name, "TXRX-BEGIN", strlen(sect_name)) == 0) {
1839 for (i=0; i < n_entries; i++) {
1840 if (strncmp(entries[i].name, "pktq_in",
1841 strlen(entries[i].name)) == 0) {
1842 get_rxq(0, 1, 2, &str[0]);
1843 memcpy(entries[i].value, &str, sizeof(str));
1846 if (strncmp(entries[i].name, "pktq_out",
1847 strlen(entries[i].name)) == 0) {
1848 get_swq(2, &str[0]);
1849 memcpy(loadb_in, str, sizeof(str));
1850 sprintf(str1," SWQ%d", arp_index++);
1852 memcpy(entries[i].value, &str, sizeof(str));
1857 if (strncmp(sect_name, "LOADB", strlen(sect_name)) == 0) {
1858 for (i=0; i < n_entries; i++) {
1859 if (strncmp(entries[i].name, "pktq_in",
1860 strlen(entries[i].name)) == 0) {
1861 memcpy(entries[i].value, &loadb_in, sizeof(str));
1864 if (strncmp(entries[i].name, "pktq_out",
1865 strlen(entries[i].name)) == 0) {
1866 if (current_cfg.num_ports > 2)
1867 tmp = (current_cfg.num_workers/current_cfg.num_lb * 2);
1869 tmp = current_cfg.num_workers * 2;
1870 start_lb = swq_index;
1872 start_lbout = start_lb + end_lb;
1873 get_swq(tmp, &str[0]);
1874 memcpy(entries[i].value, &str, sizeof(str));
1876 if (strncmp(entries[i].name, "n_vnf_threads",
1877 strlen(entries[i].name)) == 0) {
1878 sprintf(str1, "%d", current_cfg.num_workers/current_cfg.num_lb);
1879 memcpy(entries[i].value, &str1, sizeof(str1));
1884 if (strncmp(sect_name, "VACL", strlen(sect_name)) == 0) {
1885 for (i=0; i < n_entries; i++) {
1886 if (strncmp(entries[i].name, "pktq_in",
1887 strlen(entries[i].name)) == 0) {
1888 if (current_cfg.sw_lb) {
1889 get_swq_offset(start_lb, 2, &str[0]);
1892 get_rxq(workers, 1, 2, &str[0]);
1894 memcpy(entries[i].value, &str, sizeof(str));
1897 if (strncmp(entries[i].name, "pktq_out",
1898 strlen(entries[i].name)) == 0) {
1899 if (current_cfg.sw_lb)
1900 get_swq(2, &str[0]);
1902 get_txq(workers+1, 1, 2, &str[0]);
1903 sprintf(str1," SWQ%d", arp_index++);
1906 memcpy(entries[i].value, &str, sizeof(str));
1911 if (current_cfg.sw_lb) {
1912 if (((workers % current_cfg.num_workers/current_cfg.num_lb) == 0) &&
1913 (workers != current_cfg.num_workers)) {
1917 if ((workers % current_cfg.num_workers/current_cfg.num_lb) == 0) {
1925 if (strncmp(sect_name, "VCGNAPT", strlen(sect_name)) == 0) {
1926 for (i=0; i < n_entries; i++) {
1927 if (strncmp(entries[i].name, "pktq_in",
1928 strlen(entries[i].name)) == 0) {
1929 if (current_cfg.sw_lb) {
1930 get_swq_offset(start_lb, 2, &str[0]);
1933 get_rxq(workers, 1, 2, &str[0]);
1935 memcpy(entries[i].value, &str, sizeof(str));
1938 if (strncmp(entries[i].name, "pktq_out",
1939 strlen(entries[i].name)) == 0) {
1940 if (current_cfg.sw_lb)
1941 get_swq(2, &str[0]);
1943 get_txq(workers+1, 1, 2, &str[0]);
1944 sprintf(str1," SWQ%d", arp_index++);
1947 memcpy(entries[i].value, &str, sizeof(str));
1953 sprintf(str1, "vnf_set");
1954 memcpy(entries[i].name, &str1, sizeof(str1));
1955 sprintf(str1, "(3,4,5)");
1956 memcpy(entries[i].value, &str1, sizeof(str1));
1960 token = strtok(current_cfg.ip_range[ip_range].value, "/");
1962 sprintf(str1, "public_ip_port_range");
1963 memcpy(entries[i].name, &str1, sizeof(str1));
1964 memcpy(entries[i].value, token, strlen(token));
1967 token = strtok(NULL, "/");
1973 if (current_cfg.sw_lb) {
1974 if (((workers % (current_cfg.num_workers/current_cfg.num_lb)) == 0) &&
1975 (workers != current_cfg.num_workers)) {
1979 //if (((workers % (current_cfg.num_workers/current_cfg.num_lb)) == 0) &&
1980 // (workers != current_cfg.num_workers)) {
1981 if (workers == (current_cfg.num_workers/current_cfg.num_lb)) {
1989 if (strncmp(sect_name, "VFW", strlen(sect_name)) == 0) {
1990 for (i=0; i < n_entries; i++) {
1991 if (strncmp(entries[i].name, "pktq_in",
1992 strlen(entries[i].name)) == 0) {
1993 if (current_cfg.sw_lb) {
1994 get_swq_offset(start_lb, 2, &str[0]);
1997 get_rxq(workers, 1, 2, &str[0]);
1999 memcpy(entries[i].value, &str, sizeof(str));
2002 if (strncmp(entries[i].name, "pktq_out",
2003 strlen(entries[i].name)) == 0) {
2004 if (current_cfg.sw_lb)
2005 get_swq(2, &str[0]);
2007 get_txq(workers+1, 1, 2, &str[0]);
2008 sprintf(str1," SWQ%d", arp_index++);
2011 memcpy(entries[i].value, &str, sizeof(str));
2016 if (current_cfg.sw_lb) {
2017 if (((workers % current_cfg.num_workers/current_cfg.num_lb) == 0)
2018 && (workers != current_cfg.num_workers)) {
2022 if (current_cfg.num_ports > 2) {
2030 if (strncmp(sect_name, "TXRX-END", strlen(sect_name)) == 0) {
2031 for (i=0; i < n_entries; i++) {
2032 if (strncmp(entries[i].name, "pktq_in",
2033 strlen(entries[i].name)) == 0) {
2034 get_swq_offset(start_lbout, end_lb, &str[0]);
2035 memcpy(entries[i].value, &str, sizeof(str));
2038 if (strncmp(entries[i].name, "pktq_out",
2039 strlen(entries[i].name)) == 0) {
2040 get_txq(1, end_lb / 2, 2, &str[0]);
2041 memcpy(entries[i].value, &str, sizeof(str));
2048 fprintf(f, "[PIPELINE%d]\n", pipenum);
2049 for (i=0;i<num_entries;i++) {
2050 fprintf(f, "%s = %s\n", entries[i].name, entries[i].value);
2056 void print_to_file(FILE *f, struct rte_cfgfile *tcfg)
2059 for (i=0;i<num_pipelines;i++) {
2060 fix_pipelines_data_types(f, pipelines[pipe_arr[i]], tcfg);
2065 int get_vnf_index(void)
2070 for (i = 0; i < PIPE_MAX; i++) {
2071 if (strncmp(pipelines[i], current_cfg.vnf_type,
2072 strlen(current_cfg.vnf_type)) == 0)
2078 void build_pipeline(void)
2080 int i = 2, j, k, vnf_index;
2084 vnf_index = get_vnf_index();
2085 if (vnf_index == -1)
2086 printf("Wrong VNF TYPE\n");
2088 if (vnf_index == VNF_VCGNAPT)
2091 if (!current_cfg.sw_lb) {
2092 for (k = 0; k < current_cfg.num_workers; k++)
2093 pipe_arr[i++] = vnf_index;
2098 for (j = 0; j < current_cfg.num_lb; j++) {
2099 /* put TXRX-BEGIN & LOADB pipelines */
2100 pipe_arr[i++] = TXRX_BEGIN;
2101 pipe_arr[i++] = LOADB;
2103 /* place the worker threads */
2104 int limit = current_cfg.num_workers / current_cfg.num_lb;
2105 for (k = 0; k < limit; k++)
2106 pipe_arr[i++] = vnf_index;
2108 /* end the TXRX pipeline */
2109 pipe_arr[i++] = TXRX_END;
2114 int set_hash_global_config(struct mg_connection *conn, uint32_t port_id,
2115 char *flow_type, const char *hash_func, const char *enable)
2117 struct rte_eth_hash_filter_info info;
2118 uint32_t ftype, idx, offset;
2121 if (rte_eth_dev_filter_supported(port_id,
2122 RTE_ETH_FILTER_HASH) < 0) {
2123 mg_printf(conn, "RTE_ETH_FILTER_HASH not supported on port %d\n",
2127 memset(&info, 0, sizeof(info));
2128 info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG;
2129 if (!strcmp(hash_func, "toeplitz"))
2130 info.info.global_conf.hash_func =
2131 RTE_ETH_HASH_FUNCTION_TOEPLITZ;
2132 else if (!strcmp(hash_func, "simple_xor"))
2133 info.info.global_conf.hash_func =
2134 RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
2135 else if (!strcmp(hash_func, "default"))
2136 info.info.global_conf.hash_func =
2137 RTE_ETH_HASH_FUNCTION_DEFAULT;
2139 ftype = str2flowtype(flow_type);
2140 idx = ftype / (CHAR_BIT * sizeof(uint32_t));
2141 offset = ftype % (CHAR_BIT * sizeof(uint32_t));
2142 info.info.global_conf.valid_bit_mask[idx] |= (1UL << offset);
2143 if (!strcmp(enable, "enable"))
2144 if(idx < RTE_SYM_HASH_MASK_ARRAY_SIZE)
2145 info.info.global_conf.sym_hash_enable_mask[idx] |=
2147 ret = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH,
2148 RTE_ETH_FILTER_SET, &info);
2150 mg_printf(conn, "Cannot set global hash configurations by port %d\n",
2153 mg_printf(conn, "Global hash configurations have been set "
2154 "succcessfully by port %d\n", port_id);
2158 int flow_director_handler(struct mg_connection *conn, __rte_unused void *cbdata)
2160 /* Handler may access the request info using mg_get_request_info */
2161 const struct mg_request_info *req_info = mg_get_request_info(conn);
2162 uint32_t port_id = 0, tuple = 0;
2163 char trans_type[24], buf[MAX_BUF_SIZE];
2164 char *str, field0[MAX_SIZE], field1[MAX_SIZE], field2[MAX_SIZE],
2165 field3[MAX_SIZE], flow_type[MAX_SIZE];
2167 if (!strcmp(req_info->request_method, "GET")) {
2169 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
2171 mg_printf(conn, "<html><body>");
2173 mg_printf(conn, "<h3> Flow is configured </h3>");
2175 mg_printf(conn, "<h3> Flow is NOT configured </h3>");
2176 mg_printf(conn, "</body></html>");
2180 if (strcmp(req_info->request_method, "POST")) {
2182 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
2184 mg_printf(conn, "<html><body>");
2185 mg_printf(conn, "This method is not supported\n");
2186 mg_printf(conn, "</body></html>");
2191 mg_read(conn, buf, sizeof(buf));
2192 json_object * jobj = json_tokener_parse(buf);
2193 json_object_object_foreach(jobj, key, val) {
2194 if (!strcmp(key, "trans_type")) {
2195 memcpy(&trans_type, str, sizeof(trans_type));
2196 if (!strcmp(key, "udp")) {
2197 memcpy(field2,"udp-src-port", sizeof("udp-src-port"));
2198 memcpy(field3,"udp-dst-port", sizeof("udp-dst-port"));
2199 if (!strcmp(current_cfg.pkt_type, "ipv4")) {
2200 memcpy(flow_type,"ipv4-udp", sizeof("ipv4-udp"));
2201 memcpy(field0,"src-ipv4", sizeof("src-ipv4"));
2202 memcpy(field1,"dst-ipv4", sizeof("dst-ipv4"));
2203 } else if (!strcmp(current_cfg.pkt_type, "ipv6")) {
2204 memcpy(flow_type,"ipv6-udp", sizeof("ipv6-udp"));
2205 memcpy(field0,"src-ipv6", sizeof("src-ipv6"));
2206 memcpy(field1,"dst-ipv6", sizeof("dst-ipv6"));
2208 } else if (!strcmp(key, "tcp")) {
2209 memcpy(field2,"tcp-src-port", sizeof("tcp-src-port"));
2210 memcpy(field3,"tcp-dst-port", sizeof("tcp-dst-port"));
2211 if (!strcmp(current_cfg.pkt_type, "ipv4")) {
2212 memcpy(flow_type,"ipv4-tcp", sizeof("ipv4-tcp"));
2213 memcpy(field0,"src-ipv4", sizeof("src-ipv4"));
2214 memcpy(field1,"dst-ipv4", sizeof("dst-ipv4"));
2215 } else if (!strcmp(current_cfg.pkt_type, "ipv6")) {
2216 memcpy(flow_type,"ipv6-tcp", sizeof("ipv6-tcp"));
2217 memcpy(field0,"src-ipv6", sizeof("src-ipv6"));
2218 memcpy(field1,"dst-ipv6", sizeof("dst-ipv6"));
2221 } else if (!strcmp(key, "tuple")) {
2222 tuple = atoi(json_object_get_string(val));
2223 if ((tuple != 2) || (tuple != 5))
2229 set_pkt_forwarding_mode("rxonly");
2230 for (port_id = 0; port_id < current_cfg.num_ports; port_id++) {
2231 set_sym_hash_per_port(conn, port_id);
2232 set_hash_global_config(conn, port_id, flow_type,
2233 "simple_xor", "enable");
2236 for (port_id = 0; port_id < current_cfg.num_ports; port_id+=2) {
2237 set_hash_input_set_2(conn, port_id, "ipv4-udp", "src-ipv4",
2238 "udp-src-port", "add");
2239 set_hash_input_set_2(conn, port_id, "ipv4-udp", "dst-ipv4",
2240 "udp-dst-port", "add");
2241 set_hash_input_set_2(conn, port_id, "ipv4-udp", "src-ipv6",
2242 "udp-src-port", "add");
2243 set_hash_input_set_2(conn, port_id, "ipv4-udp", "dst-ipv6",
2244 "udp-dst-port", "add");
2246 } else if (tuple == 5) {
2247 set_pkt_forwarding_mode("rxonly");
2248 for (port_id = 0; port_id < current_cfg.num_ports; port_id++) {
2249 set_sym_hash_per_port(conn, port_id);
2250 set_hash_global_config(conn, port_id, flow_type,
2251 "simple_xor", "enable");
2254 for (port_id = 0; port_id < current_cfg.num_ports; port_id+=2) {
2255 set_hash_input_set_4(conn, port_id, flow_type, field0, field1,
2256 field2, field3, "add");
2263 void get_swq_offset(uint8_t start, uint8_t num, char *buf)
2268 for (i = start; i < start+num; i++) {
2269 sprintf(buf + len, "SWQ%d ", i);
2274 void get_swq(uint8_t num, char *buf)
2279 for (i=0;i<num;i++) {
2280 sprintf(buf + len, "SWQ%d ", swq_index++);
2285 void get_prv_to_pub_map(char *buf)
2289 for (j = 0; j < current_cfg.num_ports; j+=2) {
2290 sprintf(buf + len, "(%d,%d)", j, j+1);
2295 void get_prv_que_handler(char *buf)
2299 sprintf(buf + len, "(");
2301 for (j = 0; j < current_cfg.num_ports; j+=2) {
2302 sprintf(buf + len, "%d,", j);
2305 sprintf(buf + len, ")");
2308 void get_txq(uint8_t start_q, uint8_t queue_num, uint8_t ports, char *buf)
2312 for (i=tx_start_port;i<tx_start_port + ports;i+=2)
2314 for (j=start_q;j<(start_q + queue_num);j++)
2316 sprintf(buf + len, " TXQ%d.%d TXQ%d.%d", i, j, i+1, j);
2323 void get_rxq(uint8_t start_q, uint8_t queue_num, uint8_t ports, char *buf)
2328 for (i=rx_start_port;i<rx_start_port + ports;i+=2)
2330 for (j=start_q;j<(start_q + queue_num);j++)
2332 sprintf(buf + len, " RXQ%d.%d RXQ%d.%d", i, j, i+1, j);
2340 rest_api_init(struct app_params *app)
2342 struct rte_cfgfile *tcfg;
2345 const char *options[] = {"listening_ports", "80", NULL};
2346 uint32_t i, lcore_id = 0;
2347 uint32_t sock, index;
2349 /* Server context handle */
2352 for (lcore_id=0;lcore_id<64;lcore_id++) {
2353 //lcore_id = rte_get_next_lcore(lcore_id, 0, 0);
2354 sock = eal_cpu_socket_id(lcore_id);
2355 index = (sock == 0)? sock0++ : sock1++;
2356 sock_cpus[sock][index] = lcore_id;
2360 /* Initialize the icivetweb library */
2363 /* Start the server */
2364 ctx = mg_start(NULL, 0, options);
2366 printf("REST server did not start\n");
2367 printf("REST services will not be supported.. Try again ");
2368 printf("by disabling other webservers\n");
2372 /* init handlers being called here */
2375 /* static config handler */
2376 mg_set_request_handler(ctx, "/vnf", vnf_handler, 0);
2377 mg_set_request_handler(ctx, "/vnf/config", static_cfg_handler, 0);
2380 mg_set_request_handler(ctx, "/vnf/config/arp", arp_handler, 0);
2383 mg_set_request_handler(ctx, "/vnf/config/route", route_handler, 0);
2386 /* link related handlers */
2387 mg_set_request_handler(ctx, "/vnf/config/link", link_handler, 0);
2388 //mg_set_request_handler(ctx, "/vnf/config/link/*", linkid_handler, 0);
2390 /* dbg related handlers */
2391 mg_set_request_handler(ctx, "/vnf/config/dbg", dbg_handler, 0);
2392 mg_set_request_handler(ctx, "/vnf/config/dbg/pipelines", dbg_pipelines_handler, 0);
2393 mg_set_request_handler(ctx, "/vnf/config/dbg/cmd", dbg_cmd_handler, 0);
2394 mg_set_request_handler(ctx, "/vnf/config/dbg/run", dbg_run_handler, 0);
2396 mg_set_request_handler(ctx, "/vnf/quit", cmd_quit_handler, 0);
2398 printf("Waiting for config input for 30 secs\n");
2401 if (post_not_received == 0 || (index == 30))
2407 if (index == 30 && (post_not_received != 0))
2408 printf("Input not received for 30 secs, going with default");
2410 const char *name = "vnf_template.txt";
2411 /* Load application configuration file */
2412 tcfg = rte_cfgfile_load(name, 0);
2414 printf("File could not be loaded\n");
2416 // if (!current_cfg.sw_lb)
2417 // current_cfg.num_lb = 1;
2419 /* build pipelines based on the input given */
2422 for (i = 0; i < num_pipelines; i++) {
2423 sprintf(buf, "/vnf/config/dbg/pipelines/%d", i);
2424 mg_set_request_handler(ctx, buf, dbg_pipelines_id_handler, (void *)&i);
2427 /* create a file for writing the config */
2428 if (!current_cfg.sw_lb) {
2429 mg_set_request_handler(ctx, "/vnf/flowdirector", flow_director_handler, 0);
2430 sprintf(buf, "%s_%s_%dP_%dT.cfg", current_cfg.vnf_type, "HWLB",
2431 current_cfg.num_ports, current_cfg.num_workers);
2433 sprintf(buf, "%s_%s_%dP_%dLB_%dT.cfg", current_cfg.vnf_type, "SWLB",
2434 current_cfg.num_ports, current_cfg.num_lb, current_cfg.num_workers);
2436 /* create a file which is more readable */
2437 f = fopen(buf, "w");
2439 print_to_file(f, tcfg);
2441 app->config_file = strdup(buf);
2442 app->parser_file = strdup(buf);
2444 printf("Config file loaded :%s %s\n", app->config_file, traffic_type);