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(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,
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(const 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, "/ ");
387 if (strcmp(token, "pipelines")) {
391 token = strtok(NULL, "/ ");
396 if (id > rapp->n_pipelines) {
404 int dbg_pipelines_id_handler(struct mg_connection *conn,
405 __rte_unused void *cbdata)
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;
411 mg_printf(conn, "Inside dbg_pipelines_id_handler\n");
413 if (!strcmp(ri->request_method, "GET")) {
415 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
417 mg_printf(conn, "<html><body>");
418 if (p->log_level_present) {
419 mg_printf(conn, "<h2> The pipeline log level is %d</h2>",
422 mg_printf(conn, "<h2> No log level found in the\
425 mg_printf(conn, "</body></html>");
433 int dbg_pipelines_handler(struct mg_connection *conn, __rte_unused void *cbdata)
437 const struct mg_request_info *ri = mg_get_request_info(conn);
439 if (!strcmp(ri->request_method, "GET")) {
441 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
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);
449 mg_printf(conn, "</body></html>");
456 int dbg_cmd_handler(struct mg_connection *conn, __rte_unused void *cbdata)
458 struct app_params *app = rapp;
461 const struct mg_request_info *req_info = mg_get_request_info(conn);
462 char buf[MAX_BUF_SIZE];
464 if (!strcmp(req_info->request_method, "GET")) {
466 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
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");
478 if (strcmp(req_info->request_method, "POST")) {
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);
489 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
491 mg_printf(conn, "<html><body>");
492 mg_printf(conn, "</body></html>\n");
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));
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);
512 mg_printf(conn, "Dbg Command failed\n");
519 int set_sym_hash_per_port(struct mg_connection *conn, uint32_t port_id)
522 struct rte_eth_hash_filter_info info;
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",
531 memset(&info, 0, sizeof(info));
532 info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT;
534 ret = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH,
535 RTE_ETH_FILTER_SET, &info);
537 mg_printf(conn, "Cannot set symmetric hash enable per port on "
538 "port %u\n", port_id);
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)
549 struct rte_eth_hash_filter_info info;
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 "
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);
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);
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;
573 rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH,
574 RTE_ETH_FILTER_SET, &info);
576 mg_printf(conn, "Command Passed!\n");
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)
584 struct rte_eth_hash_filter_info info;
585 const struct mg_request_info *req_info = mg_get_request_info(conn);
587 if (strcmp(req_info->request_method, "POST")) {
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");
592 "%s method not allowed in the POST handler\n",
593 req_info->request_method);
598 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
600 mg_printf(conn, "<html><body>");
601 mg_printf(conn, "</body></html>\n");
603 if (!inset_field0 || !inset_field1 || !flow_type) {
604 mg_printf(conn, "inset_field0/1 or flow_type may be NULL!\n");
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 "
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 "
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);
627 info.info.input_set_conf.field[0] = str2inset(inset_field0);
630 info.info.input_set_conf.field[1] = str2inset(inset_field1);
632 info.info.input_set_conf.inset_size = 2;
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;
639 rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH,
640 RTE_ETH_FILTER_SET, &info);
642 mg_printf(conn, "Command Passed!\n");
646 void print_interface_details_rest(struct mg_connection *conn, uint32_t link)
648 l2_phy_interface_t *port;
650 struct sockaddr_in ip;
651 mg_printf(conn, "\n\r");
656 rte_rwlock_read_lock(&rwlock);
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);
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");
677 if (port->ipv4_list != NULL) {
679 (unsigned long)((ipv4list_t *) (port->ipv4_list))->
681 mg_printf(conn, "IP: %s/%d", inet_ntoa(ip.sin_addr),
682 ((ipv4list_t *) (port->ipv4_list))->addrlen);
684 mg_printf(conn, "IP: NA");
687 mg_printf(conn, "\r\n<br/>");
688 mg_printf(conn, "\t\t");
689 if (port->ipv6_list != NULL) {
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],
699 mg_printf(conn, "IPv6: NA");
702 if (port->flags & IFM_SLAVE) {
703 mg_printf(conn, " IFM_SLAVE ");
704 mg_printf(conn, " MasterPort: %u",
705 port->bond_config->bond_portid);
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:");
717 for (i = 0; i < port->bond_config->slave_count; i++) {
718 mg_printf(conn, " %u ",
719 port->bond_config->slaves[i]);
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;
726 mg_printf(conn, " %u ",
727 port->bond_config->active_slaves[i]);
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);
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, ð_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");
762 rte_rwlock_read_unlock(&rwlock);
765 void print_link_info(struct app_link_params *p, struct mg_connection *conn)
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);
773 memset(&stats, 0, sizeof(stats));
774 rte_eth_stats_get(p->pmd_id, &stats);
776 mac_addr = (struct ether_addr *) &p->mac_addr;
778 if (strlen(p->pci_bdf))
779 mg_printf(conn, "%s(%s): flags=%s\r\n<br/>",
782 (p->state) ? "UP" : "DOWN");
784 mg_printf(conn, "%s: flags=%s\r\n<br/>",
786 (p->state) ? "UP" : "DOWN");
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,
798 (netmask >> 24) & 0xFF,
799 (netmask >> 16) & 0xFF,
800 (netmask >> 8) & 0xFF,
802 (bcast >> 24) & 0xFF,
803 (bcast >> 16) & 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]);
815 mg_printf(conn, "\tRX packets %" PRIu64
821 mg_printf(conn, "\tRX errors %" PRIu64
829 mg_printf(conn, "\tTX packets %" PRIu64
830 " bytes %" PRIu64 "\r\n<br/>",
834 mg_printf(conn, "\tTX errors %" PRIu64
838 mg_printf(conn, "\r\n<br/>");
841 int get_link_tokens(char *buf)
846 token = strtok(buf, "/ ");
850 if (strcmp(token, "link")) {
854 token = strtok(NULL, "/ ");
858 linkid = atoi(token);
859 if (linkid > current_cfg.num_ports) {
866 int linkls_handler(struct mg_connection *conn, void *cbdata)
868 struct app_params *app = rapp;
870 struct app_link_params *p;
872 APP_PARAM_FIND_BY_ID(app->link_params, "LINK", *(uint32_t *)cbdata, p);
874 print_link_info(p, conn);
877 print_interface_details_rest(conn, *(uint32_t *)cbdata);
881 static const char* arp_status[] = {"INCOMPLETE", "COMPLETE", "PROBE", "STALE"};
884 int nd_handler(struct mg_connection *conn, __rte_unused void *cbdata)
886 const void *next_key;
890 mg_printf(conn, "----------------------------------------------------");
891 mg_printf(conn, "-------------------------------------------------\n<br/>");
892 mg_printf(conn, "\tport hw addr status ip addr\n<br/>");
894 mg_printf(conn, "-----------------------------------------------------");
895 mg_printf(conn, "-------------------------------------------------\n<br/>");
896 while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
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",
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]);
917 mg_printf(conn, "\n<br/>");
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));
931 int arpls_handler(struct mg_connection *conn, __rte_unused void *cbdata)
933 const void *next_key;
935 uint32_t iter = 0, len = 0;
939 (buf + len, "---------------------- ARP CACHE ---------------------\n<br/>");
941 (buf + len, "------------------------------------------------------\n<br/>");
942 len += sprintf(buf + len, "\tport hw addr status ip addr\n<br/>");
944 (buf + len, "------------------------------------------------------\n<br/>");
946 while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
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));
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)));
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);
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);
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]);
995 void get_mac(struct ether_addr *mac_addr, char *buf)
997 uint32_t i = 0, j = 0, k = 0, MAC_NUM_BYTES = 6;
999 char byteStr[MAC_NUM_BYTES][3];
1001 char *token = strtok(buf, " ");
1004 for (i = 0; i < MAC_NUM_BYTES; i++) {
1005 for (j = 0; j < 2; j++) {
1006 byteStr[i][j] = token[k++];
1008 byteStr[i][j] = '\0';
1011 token = strtok(NULL, " ");
1014 for (i = 0; i < MAC_NUM_BYTES; i++) {
1015 mac_addr->addr_bytes[i] = strtoul(byteStr[i], NULL, 16);
1020 int arp_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1022 const struct mg_request_info *req_info = mg_get_request_info(conn);
1023 char buf[MAX_BUF_SIZE];
1025 if (!strcmp(req_info->request_method, "GET")) {
1027 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1029 /* prints arp table */
1030 mg_printf(conn, "<html><body>");
1031 arpls_handler(conn, cbdata);
1033 /* prints nd table */
1034 nd_handler(conn, cbdata);
1035 mg_printf(conn, "</body></html>");
1039 if (strcmp(req_info->request_method, "POST")) {
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");
1044 "%s method not allowed in the POST handler\n",
1045 req_info->request_method);
1050 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1052 mg_printf(conn, "<html><body>");
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 ¤t_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(¤t_arp_parms.mac_addr,
1078 strdup(json_object_get_string(val)));
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;
1088 if (current_arp_parms.family == AF_INET) {
1089 switch(current_arp_parms.action) {
1091 populate_arp_entry(¤t_arp_parms.mac_addr,
1092 current_arp_parms.ip, current_arp_parms.portid,
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,
1107 callback_key->port_id = current_arp_parms.portid;
1108 callback_key->ip = current_arp_parms.ip;
1110 mg_printf(conn, "removing entry now\n");
1111 remove_arp_entry(new_arp_data, callback_key);
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;
1120 new_arp_data = retrieve_arp_entry(arp_key, STATIC_ARP);
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);
1129 mg_printf(conn, "<p>ARP - requesting arp for ip 0x%x, port %d</p>",
1130 current_arp_parms.ip, current_arp_parms.portid);
1132 request_arp(current_arp_parms.portid, current_arp_parms.ip);
1138 switch(current_arp_parms.action) {
1140 populate_nd_entry(¤t_arp_parms.mac_addr,
1141 current_arp_parms.ipv6, current_arp_parms.portid, STATIC_ND);
1144 nd_key.port_id = current_arp_parms.portid;
1145 memcpy(&nd_key.ipv6[0], ¤t_arp_parms.ipv6[0], 16);
1149 new_nd_data = retrieve_nd_entry(nd_key, STATIC_ND);
1151 if(new_nd_data == NULL) {
1153 mg_printf(conn,"Retrieve ND returned NULL\n");
1156 remove_nd_entry_ipv6(new_nd_data, &nd_key);
1159 mg_printf(conn, "<p>ND REQ is not supported Yet!!!</p>");
1166 mg_printf(conn, "<p>Command Passed</p>");
1167 mg_printf(conn, "</body></html>\n");
1171 int route_handler(struct mg_connection *conn, __rte_unused void *cbdata)
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;
1180 if (!strcmp(req_info->request_method, "GET")) {
1182 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1184 mg_printf(conn, "<pre>\nIP_Address Mask Port\n<br/>");
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);
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]);
1206 mg_printf(conn, "\t%d %d "
1208 p_nd_route_data[p]->nd_route_table[i].depth,
1209 p_nd_route_data[p]->nd_route_table[i].port);
1216 if (strcmp(req_info->request_method, "POST")) {
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");
1221 "%s method not allowed in the POST handler\n",
1222 req_info->request_method);
1227 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1229 mg_printf(conn, "<html><body>");
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));
1237 mg_printf(conn, "Port not supported!!!\n");
1239 } else if (current_route_parms[portid].enable) {
1240 mg_printf(conn, "Already configured\n");
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), ¤t_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)));
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++) {
1268 status = app_routeadd_config_ipv4(rapp, portid,
1269 current_route_parms[portid].ip,
1272 mg_printf(conn, "Setting route entry failed\n");
1275 if (!strcmp(current_route_parms[portid].type, "host")) {
1276 current_route_parms[portid].depth = 128;
1278 status = app_routeadd_config_ipv6(rapp, portid,
1279 current_route_parms[portid].ipv6,
1280 current_route_parms[portid].depth);
1282 mg_printf(conn, "Setting route entry failed\n");
1286 mg_printf(conn, "</body></html>\n");
1290 int link_handler(struct mg_connection *conn, __rte_unused void *cbdata)
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];
1297 if (!strcmp(req_info->request_method, "GET")) {
1299 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
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);
1306 mg_printf(conn, "</body></html>\n");
1310 if (strcmp(req_info->request_method, "POST")) {
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");
1315 "%s method not allowed in the POST handler\n",
1316 req_info->request_method);
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);
1327 mg_printf(conn, "Link id not supported beyond 64\n");
1330 current_link_parms[link].id = link;
1332 } else if (!strcmp(key, "state")) {
1334 current_link_parms[link].state =
1335 atoi(json_object_get_string(val));
1337 mg_printf(conn, "state:%d \n", current_link_parms[link].state);
1343 if (current_link_parms[link].state == 0) {
1345 status = app_link_down(rapp, current_link_parms[link].id);
1347 mg_printf(conn, "<p>command failed</p>");
1349 mg_printf(conn, "<p>command Passed</p>");
1351 } else if (current_link_parms[link].state == 1) {
1353 mg_printf(conn, "setting up the link \n");
1354 status = app_link_up(rapp, current_link_parms[link].id);
1356 mg_printf(conn, "<p>command failed</p>");
1358 mg_printf(conn, "<p>command Passed</p>");
1363 sprintf(buf, "/vnf/config/link/%d", link);
1364 mg_set_request_handler(ctx, buf, linkid_handler, (void *)&link);
1367 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1372 int linkid_handler(struct mg_connection *conn, void *cbdata)
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);
1377 char buf[MAX_BUF_SIZE];
1379 if (!strcmp(req_info->request_method, "GET")) {
1381 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1383 mg_printf(conn, "<html><body>\n");
1384 linkls_handler(conn, cbdata);
1385 mg_printf(conn, "</body></html>\n");
1389 if (strcmp(req_info->request_method, "POST")) {
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");
1394 "%s method not allowed in the POST handler\n",
1395 req_info->request_method);
1400 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1402 mg_printf(conn, "<html><body>");
1404 uint32_t linkid = *(uint32_t *)cbdata;
1405 mg_printf(conn, "link id :%d ", linkid);
1407 if (!current_link_parms[linkid].state) {
1408 mg_printf(conn, "<p>link not enabled!! </p>");
1409 mg_printf(conn, "</body></html>\n");
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), ¤t_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));
1430 /* bring the link down */
1431 status = app_link_down(rapp, linkid);
1433 mg_printf(conn, "<p>command down failed</p>");
1435 mg_printf(conn, "<p>command Passed</p>");
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);
1443 status = app_link_config_ipv6(rapp, linkid,
1444 current_link_parms[linkid].ipv6, current_link_parms[linkid].depth);
1448 mg_printf(conn, "<p>command config failed</p>");
1450 mg_printf(conn, "<p>command Passed</p>");
1453 /* bring the link up */
1454 status = app_link_up(rapp, linkid);
1456 mg_printf(conn, "<p>command up failed</p>");
1458 mg_printf(conn, "<p>command Passed</p>");
1462 mg_printf(conn, "</body></html>\n");
1466 void set_vnf_type(const char *type)
1468 memcpy(current_cfg.vnf_type, type, strlen(type));
1471 void init_stat_cfg(void)
1473 char buf[256] = "98103214:(1, 65535)";
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);
1484 for (i=0;i<MAX_LB;i++) {
1485 memcpy(current_cfg.ip_range[i].value, &buf,
1490 static void set_port_mask(uint64_t num_ports)
1495 for (i = 0; i < num_ports; i++) {
1498 rapp->port_mask = mask;
1501 void bind_the_ports(struct mg_connection *conn, char *pci_white_list)
1504 char buf[MAX_BUF_SIZE];
1507 token = strtok(pci_white_list, " ");
1509 while(token != NULL) {
1510 mg_printf(conn, "%s ****\n", token);
1511 sprintf(buf, "dpdk-devbind -u %s", token);
1514 mg_printf(conn, "wrong parameter sent\n");
1516 sprintf(buf, "dpdk-devbind -b igb_uio %s", token);
1519 mg_printf(conn, "wrong parameter sent\n");
1521 token = strtok(NULL, " ");
1525 current_cfg.num_ports = x;
1529 int static_cfg_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1533 char buf[MAX_BUF_SIZE];
1535 const struct mg_request_info *ri = mg_get_request_info(conn);
1537 if (!strcmp(ri->request_method, "GET")) {
1539 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
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>",
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");
1565 if (strcmp(ri->request_method, "POST")) {
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");
1570 "%s method not allowed in the POST handler\n",
1571 ri->request_method);
1575 if (static_cfg_set) {
1577 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1582 mg_read(conn, buf, sizeof(buf));
1583 json_object * jobj = json_tokener_parse(buf);
1585 struct json_object *values;
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(¤t_cfg.ip_range[pub_ip].value,
1595 static_cfg[i].value,
1596 sizeof(static_cfg[i].value));
1603 json_object_object_get_ex(jobj, "num_worker", &values);
1605 memcpy(¤t_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));
1610 json_object_object_get_ex(jobj, "pkt_type", &values);
1612 memcpy(¤t_cfg.pkt_type, json_object_get_string(values),
1613 sizeof(current_cfg.pkt_type));
1616 json_object_object_get_ex(jobj, "num_lb", &values);
1618 current_cfg.num_lb = atoi(json_object_get_string(values));
1621 json_object_object_get_ex(jobj, "num_ports", &values);
1623 current_cfg.num_ports = atoi(json_object_get_string(values));
1626 json_object_object_get_ex(jobj, "sw_lb", &values);
1628 current_cfg.sw_lb = atoi(json_object_get_string(values));
1631 json_object_object_get_ex(jobj, "sock_in", &values);
1633 current_cfg.sock_in = atoi(json_object_get_string(values));
1636 json_object_object_get_ex(jobj, "hyperthread", &values);
1638 current_cfg.hyper_thread = atoi(json_object_get_string(values));
1641 json_object_object_get_ex(jobj, "vnf_type", &values);
1643 memcpy(¤t_cfg.vnf_type, json_object_get_string(values),
1644 sizeof(current_cfg.vnf_type));
1647 json_object_object_get_ex(jobj, "pci_white_list", &values);
1649 memcpy(¤t_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, ¤t_cfg.pci_white_list[0]);
1655 len = sprintf(buf, "POST DATA RECEIVED\n");
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",
1664 mg_write(conn, buf, len);
1665 post_not_received = 0;
1670 int vnf_handler(struct mg_connection *conn, __rte_unused void *cbdata)
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);
1675 if (!strcmp(req_info->request_method, "GET")) {
1677 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
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>");
1704 if (strcmp(req_info->request_method, "POST")) {
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");
1709 "%s method not allowed in the POST handler\n",
1710 req_info->request_method);
1717 void get_pktq_in_prv(char *buf)
1721 for (j = 0; j < current_cfg.num_ports; j+=2) {
1722 len += sprintf(buf + len, "RXQ%d.0 ", j);
1726 void fix_pipelines_data_types(FILE *f, const char *sect_name, struct rte_cfgfile *tcfg)
1728 int i, j, n_entries, tmp = 0;
1729 char str[256], str1[40];
1731 n_entries = rte_cfgfile_section_num_entries(tcfg, sect_name);
1733 rte_cfgfile_section_entries(tcfg, sect_name, entries, n_entries);
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));
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);
1750 memcpy(&traffic_type, "6", 1);
1753 if (strncmp(entries[i].name, "traffic_type",
1754 sizeof("traffic_type")) == 0) {
1755 memcpy(entries[i].value, &traffic_type, 4);
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);
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)) {
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);
1782 sprintf(str, "s%dc%d", current_cfg.sock_in, sock_cpus[current_cfg.sock_in][sock_index]);
1783 if (current_cfg.hyper_thread)
1786 sprintf(str, "s%dc%dh", current_cfg.sock_in, sock_cpus[current_cfg.sock_in][sock_index]);
1790 memcpy(entries[i].value, &str, 8);
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));
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));
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));
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));
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));
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));
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));
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++);
1867 memcpy(entries[i].value, &str, sizeof(str));
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));
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);
1884 tmp = current_cfg.num_workers * 2;
1885 start_lb = swq_index;
1887 start_lbout = start_lb + end_lb;
1888 get_swq(tmp, &str[0]);
1889 memcpy(entries[i].value, &str, sizeof(str));
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));
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]);
1907 get_rxq(workers, 1, 2, &str[0]);
1909 memcpy(entries[i].value, &str, sizeof(str));
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]);
1917 get_txq(workers+1, 1, 2, &str[0]);
1918 sprintf(str1," SWQ%d", arp_index++);
1921 memcpy(entries[i].value, &str, sizeof(str));
1926 if (current_cfg.sw_lb) {
1927 if (((workers % current_cfg.num_workers/current_cfg.num_lb) == 0) &&
1928 (workers != current_cfg.num_workers)) {
1932 if ((workers % current_cfg.num_workers/current_cfg.num_lb) == 0) {
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]);
1948 get_rxq(workers, 1, 2, &str[0]);
1950 memcpy(entries[i].value, &str, sizeof(str));
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]);
1958 get_txq(workers+1, 1, 2, &str[0]);
1959 sprintf(str1," SWQ%d", arp_index++);
1962 memcpy(entries[i].value, &str, sizeof(str));
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));
1975 token = strtok(current_cfg.ip_range[ip_range].value, "/");
1977 sprintf(str1, "public_ip_port_range");
1978 memcpy(entries[i].name, &str1, sizeof(str1));
1979 memcpy(entries[i].value, token, strlen(token));
1982 token = strtok(NULL, "/");
1988 if (current_cfg.sw_lb) {
1989 if (((workers % (current_cfg.num_workers/current_cfg.num_lb)) == 0) &&
1990 (workers != current_cfg.num_workers)) {
1994 if (workers == (current_cfg.num_workers/current_cfg.num_lb)) {
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]);
2010 get_rxq(workers, 1, 2, &str[0]);
2012 memcpy(entries[i].value, &str, sizeof(str));
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]);
2020 get_txq(workers+1, 1, 2, &str[0]);
2021 sprintf(str1," SWQ%d", arp_index++);
2024 memcpy(entries[i].value, &str, sizeof(str));
2029 if (current_cfg.sw_lb) {
2030 if (((workers % current_cfg.num_workers/current_cfg.num_lb) == 0)
2031 && (workers != current_cfg.num_workers)) {
2035 if (workers == (current_cfg.num_workers/current_cfg.num_lb)) {
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));
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));
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);
2069 void print_to_file(FILE *f, struct rte_cfgfile *tcfg)
2072 for (i=0;i<num_pipelines;i++) {
2073 fix_pipelines_data_types(f, pipelines[pipe_arr[i]], tcfg);
2078 int get_vnf_index(void)
2083 for (i = 0; i < PIPE_MAX; i++) {
2084 if (strncmp(pipelines[i], current_cfg.vnf_type,
2085 strlen(current_cfg.vnf_type)) == 0)
2091 void build_pipeline(void)
2093 int i = 2, j, k, vnf_index;
2097 vnf_index = get_vnf_index();
2098 if (vnf_index == -1)
2099 printf("Wrong VNF TYPE\n");
2101 if (vnf_index == VNF_VCGNAPT)
2104 if (!current_cfg.sw_lb) {
2105 for (k = 0; k < current_cfg.num_workers; k++)
2106 pipe_arr[i++] = vnf_index;
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;
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;
2121 /* end the TXRX pipeline */
2122 pipe_arr[i++] = TXRX_END;
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)
2130 struct rte_eth_hash_filter_info info;
2131 uint32_t ftype, idx, offset;
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",
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;
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] |=
2160 ret = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH,
2161 RTE_ETH_FILTER_SET, &info);
2163 mg_printf(conn, "Cannot set global hash configurations by port %d\n",
2166 mg_printf(conn, "Global hash configurations have been set "
2167 "succcessfully by port %d\n", port_id);
2171 int flow_director_handler(struct mg_connection *conn, __rte_unused void *cbdata)
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];
2180 if (!strcmp(req_info->request_method, "GET")) {
2182 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
2184 mg_printf(conn, "<html><body>");
2186 mg_printf(conn, "<h3> Flow is configured </h3>");
2188 mg_printf(conn, "<h3> Flow is NOT configured </h3>");
2189 mg_printf(conn, "</body></html>");
2193 if (strcmp(req_info->request_method, "POST")) {
2195 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
2197 mg_printf(conn, "<html><body>");
2198 mg_printf(conn, "This method is not supported\n");
2199 mg_printf(conn, "</body></html>");
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"));
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"));
2233 } else if (!strcmp(key, "tuple")) {
2234 tuple = atoi(json_object_get_string(val));
2235 if ((tuple != 2) || (tuple != 5))
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");
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");
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");
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");
2275 void get_swq_offset(uint8_t start, uint8_t num, char *buf)
2280 for (i = start; i < start+num; i++) {
2281 sprintf(buf + len, "SWQ%d ", i);
2286 void get_swq(uint8_t num, char *buf)
2291 for (i=0;i<num;i++) {
2292 sprintf(buf + len, "SWQ%d ", swq_index++);
2297 void get_prv_to_pub_map(char *buf)
2301 for (j = 0; j < current_cfg.num_ports; j+=2) {
2302 sprintf(buf + len, "(%d,%d)", j, j+1);
2307 void get_prv_que_handler(char *buf)
2311 sprintf(buf + len, "(");
2313 for (j = 0; j < current_cfg.num_ports; j+=2) {
2314 sprintf(buf + len, "%d,", j);
2317 sprintf(buf + len, ")");
2320 void get_txq(uint8_t start_q, uint8_t queue_num, uint8_t ports, char *buf)
2324 for (i=tx_start_port;i<tx_start_port + ports;i+=2)
2326 for (j=start_q;j<(start_q + queue_num);j++)
2328 sprintf(buf + len, " TXQ%d.%d TXQ%d.%d", i, j, i+1, j);
2335 void get_rxq(uint8_t start_q, uint8_t queue_num, uint8_t ports, char *buf)
2340 for (i=rx_start_port;i<rx_start_port + ports;i+=2)
2342 for (j=start_q;j<(start_q + queue_num);j++)
2344 sprintf(buf + len, " RXQ%d.%d RXQ%d.%d", i, j, i+1, j);
2352 rest_api_init(struct app_params *app)
2354 struct rte_cfgfile *tcfg;
2357 const char *options[] = {"listening_ports", "80", NULL};
2358 uint32_t i, lcore_id = 0;
2359 uint32_t sock, index;
2361 /* Server context handle */
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;
2372 /* Initialize the icivetweb library */
2375 /* Start the server */
2376 ctx = mg_start(NULL, 0, options);
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");
2384 /* init handlers being called here */
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);
2392 mg_set_request_handler(ctx, "/vnf/config/arp", arp_handler, 0);
2395 mg_set_request_handler(ctx, "/vnf/config/route", route_handler, 0);
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);
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);
2408 mg_set_request_handler(ctx, "/vnf/quit", cmd_quit_handler, 0);
2410 printf("Waiting for config input.... via rest\n");
2413 if (post_not_received == 0)
2419 if (index == 30 && (post_not_received != 0))
2420 printf("Input not received for 30 secs, going with default");
2422 const char *name = "vnf_template.txt";
2423 /* Load application configuration file */
2424 tcfg = rte_cfgfile_load(name, 0);
2426 printf("File could not be loaded\n");
2428 // if (!current_cfg.sw_lb)
2429 // current_cfg.num_lb = 1;
2431 /* build pipelines based on the input given */
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);
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);
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);
2448 /* create a file which is more readable */
2449 f = fopen(buf, "w");
2451 print_to_file(f, tcfg);
2453 app->config_file = strdup(buf);
2454 app->parser_file = strdup(buf);