Merge "update userguide alignment"
[samplevnf.git] / VNFs / vCGNAPT / pipeline / pipeline_cgnapt.c
1 /*
2 // Copyright (c) 2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 /**
18  * @file
19  * Pipeline CG-NAPT FE Implementation.
20  *
21  * Implementation of Pipeline CG-NAPT Front End (FE).
22  * Provides CLI support.
23  * Runs on master core.
24  *
25  */
26
27 #include <cmdline_parse.h>
28 #include <cmdline_parse_num.h>
29 #include <cmdline_parse_string.h>
30 #include <cmdline_parse_ipaddr.h>
31 #include <cmdline_parse_etheraddr.h>
32 #include <cmdline_rdline.h>
33 #include <cmdline_socket.h>
34 #include <cmdline.h>
35
36 #include <fcntl.h>
37 #include <unistd.h>
38
39 #include "app.h"
40 #include "pipeline_common_fe.h"
41 #include "pipeline_cgnapt.h"
42 #include "pipeline_cgnapt_common.h"
43 #include "pipeline_common_be.h"
44 #include "pipeline_cgnapt_be.h"
45 #ifdef PCP_ENABLE
46 #include "cgnapt_pcp_fe.h"
47 #endif
48
49 #define MAX_BUF_SIZE    2048
50
51 /**
52  * A structure defining the CG-NAPT entry that is stored on
53  * front end.
54  */
55 struct app_pipeline_cgnapt_entry {
56         struct pipeline_cgnapt_entry_key key;
57         struct app_pipeline_cgnapt_entry_params params;
58         void *entry_ptr;
59
60          TAILQ_ENTRY(app_pipeline_cgnapt_entry) node;
61 };
62
63 /**
64  * A structure defining the FE representation of a CG-NAPT pipeline
65  */
66 struct pipeline_cgnapt_t {
67         /* Parameters */
68         uint32_t n_ports_in;
69         uint32_t n_ports_out;
70
71         /* entries */
72          TAILQ_HEAD(, app_pipeline_cgnapt_entry) entries;
73         uint32_t n_entries;
74
75 };
76
77 int nat_load_handler(struct mg_connection *conn, __rte_unused void *cbdata);
78 int nat_handler(struct mg_connection *conn, __rte_unused void *cbdata);
79 uint32_t rules_loaded = 0;
80 extern struct cmdline *pipe_cl;
81 struct app_params *myapp;
82
83 /**
84  * Init function for CG-NAPT FE.
85  *
86  * @param params
87  *  A pointer to the pipeline params.
88  *
89  */
90 static void *pipeline_cgnapt_init(struct pipeline_params *params,
91                                         __rte_unused void *arg)
92 {
93         struct pipeline_cgnapt_t *p;
94         uint32_t size;
95
96         /* Check input arguments */
97         if ((params == NULL) ||
98                         (params->n_ports_in == 0) || (params->n_ports_out == 0))
99                 return NULL;
100
101         /* Memory allocation */
102         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_cgnapt_t));
103         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
104         if (p == NULL)
105                 return NULL;
106
107         /* Initialization */
108         p->n_ports_in = params->n_ports_in;
109         p->n_ports_out = params->n_ports_out;
110
111         TAILQ_INIT(&p->entries);
112         p->n_entries = 0;
113
114         return p;
115 }
116
117 /**
118  * Function for CG-NAPT FE cleanup.
119  *
120  * @param pipeline
121  *  A pointer to the pipeline.
122  *
123  */
124 static int app_pipeline_cgnapt_free(void *pipeline)
125 {
126         struct pipeline_cgnapt_t *p = pipeline;
127
128         /* Check input arguments */
129         if (p == NULL)
130                 return -1;
131
132         /* Free resources */
133         while (!TAILQ_EMPTY(&p->entries)) {
134                 struct app_pipeline_cgnapt_entry *entry;
135
136                 entry = TAILQ_FIRST(&p->entries);
137                 TAILQ_REMOVE(&p->entries, entry, node);
138                 rte_free(entry);
139         }
140
141         rte_free(p);
142         return 0;
143 }
144
145 /**
146  * Function to print an IPv6 address
147  *
148  * @param ipv6_addr
149  *  A uint8_t array containing an IPv6 address
150  */
151 static void print_ipv6_address_u8(uint8_t ipv6_addr[16])
152 {
153         printf("Ipv6Address-%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x\n",
154                                  ipv6_addr[0], ipv6_addr[1], ipv6_addr[2], ipv6_addr[3],
155                                  ipv6_addr[4], ipv6_addr[5], ipv6_addr[6], ipv6_addr[7],
156                                  ipv6_addr[8], ipv6_addr[9], ipv6_addr[10], ipv6_addr[11],
157                                  ipv6_addr[12], ipv6_addr[13], ipv6_addr[14], ipv6_addr[15]);
158 }
159
160 /**
161  * Function to print an IPv6 address
162  *
163  * @param ipv6_addr
164  *  A uint16_t array containing an IPv6 address
165  */
166 static void print_ipv6_address_u16(uint16_t ipv6_addr[8])
167 {
168         printf("Ipv6Address-%x:%x:%x:%x:%x:%x:%x:%x\n", ipv6_addr[0],
169                                  ipv6_addr[1], ipv6_addr[2], ipv6_addr[3], ipv6_addr[4],
170                                  ipv6_addr[5], ipv6_addr[6], ipv6_addr[7]);
171 }
172
173 /**
174  * Function to print an IPv6 address
175  *
176  * @param ipv6_addr
177  *  A uint32_t array containing an IPv6 address
178  */
179 static void print_ipv6_address_u32(uint32_t ipv6_addr[4])
180 {
181         printf("Ipv6Address: %x:%x:%x:%x\n", ipv6_addr[0], ipv6_addr[1],
182                 ipv6_addr[2], ipv6_addr[3]);
183 }
184
185 /**
186  * Function to print a NAPT entry
187  *
188  * @param entry
189  *  A pointer to a NAPT entry
190  */
191 static void print_entry(const struct app_pipeline_cgnapt_entry *entry)
192 {
193         const struct pipeline_cgnapt_entry_key *key = &entry->key;
194
195         if (entry->params.type == CGNAPT_ENTRY_IPV4) {
196                 printf("CGNAPT Entry: Key = %" PRIu32 ".%" PRIu32 ".%" PRIu32
197                                          ".%" PRIu32 ":%" PRIu32 ":%" PRIu16 " => Prv = %" PRIu32
198                                          ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ":%" PRIu32
199                                          " => Pub = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32
200                                          ":%" PRIu32 " => ttl = %" PRIu32 "\n",
201                                          (key->ip >> 24) & 0xFF, (key->ip >> 16) & 0xFF,
202                                          (key->ip >> 8) & 0xFF, key->ip & 0xFF, key->port,
203                                          key->pid, (entry->params.u.prv_ip >> 24) & 0xFF,
204                                          (entry->params.u.prv_ip >> 16) & 0xFF,
205                                          (entry->params.u.prv_ip >> 8) & 0xFF,
206                                          entry->params.u.prv_ip & 0xFF, entry->params.prv_port,
207                                          (entry->params.pub_ip >> 24) & 0xFF,
208                                          (entry->params.pub_ip >> 16) & 0xFF,
209                                          (entry->params.pub_ip >> 8) & 0xFF,
210                                          entry->params.pub_ip & 0xFF, entry->params.pub_port,
211                                          entry->params.ttl);
212         } else {
213                 printf("CGNAPT Entry: Key = %" PRIu32 ".%" PRIu32 ".%" PRIu32
214                                          ".%" PRIu32 ":%" PRIu32 ":%" PRIu16 " => Prv = %" PRIu32
215                                          "%" PRIu32 ":%" PRIu32 "%" PRIu32 ":%" PRIu32 "%" PRIu32
216                                          ":%" PRIu32 "%" PRIu32 ":%" PRIu32 "%" PRIu32 ":%" PRIu32
217                                          "%" PRIu32 ":%" PRIu32 "%" PRIu32 ":%" PRIu32 "%" PRIu32
218                                          ":%" PRIu32 " => Pub = %" PRIu32 ".%" PRIu32 ".%"
219                                          PRIu32 ".%" PRIu32 ":%" PRIu32 " => ttl = %" PRIu32
220                                          "\n", (key->ip >> 24) & 0xFF, (key->ip >> 16) & 0xFF,
221                                          (key->ip >> 8) & 0xFF, key->ip & 0xFF, key->port,
222                                          key->pid, entry->params.u.prv_ipv6[0],
223                                          entry->params.u.prv_ipv6[1], entry->params.u.prv_ipv6[2],
224                                          entry->params.u.prv_ipv6[3], entry->params.u.prv_ipv6[4],
225                                          entry->params.u.prv_ipv6[5], entry->params.u.prv_ipv6[6],
226                                          entry->params.u.prv_ipv6[7], entry->params.u.prv_ipv6[8],
227                                          entry->params.u.prv_ipv6[9],
228                                          entry->params.u.prv_ipv6[10],
229                                          entry->params.u.prv_ipv6[11],
230                                          entry->params.u.prv_ipv6[12],
231                                          entry->params.u.prv_ipv6[13],
232                                          entry->params.u.prv_ipv6[14],
233                                          entry->params.u.prv_ipv6[15], entry->params.prv_port,
234                                          (entry->params.pub_ip >> 24) & 0xFF,
235                                          (entry->params.pub_ip >> 16) & 0xFF,
236                                          (entry->params.pub_ip >> 8) & 0xFF,
237                                          entry->params.pub_ip & 0xFF, entry->params.pub_port,
238                                          entry->params.ttl);
239
240         }
241 }
242
243 /**
244  * Function to list NAPT entries from FE storage
245  *
246  * @param app
247  *  A pointer to pipeline app
248  * @param pipeline_id
249  *  Pipeline id
250  *
251  * @return
252  *  0 on success, negative on error.
253  */
254 static int
255 app_pipeline_cgnapt_entry_ls(struct app_params *app, uint32_t pipeline_id)
256 {
257         struct pipeline_cgnapt_t *p;
258         struct app_pipeline_cgnapt_entry *it;
259
260         p = app_pipeline_data_fe(app, pipeline_id,
261                                  (struct pipeline_type *)&pipeline_cgnapt);
262         if (p == NULL)
263                 return -EINVAL;
264
265         TAILQ_FOREACH(it, &p->entries, node)
266                         print_entry(it);
267         print_static_cgnapt_entries();
268         printf(" - end of napt fe entry list -\n");
269         return 0;
270 }
271
272 /**
273  * Function to send a debug message to BE
274  *
275  * @param app
276  *  A pointer to pipeline app
277  * @param pipeline_id
278  *  Pipeline id
279  * @param msg
280  *  debug message contents
281  *
282  * @return
283  *  0 on success, negative on error.
284  */
285 static int
286 app_pipeline_cgnapt_entry_dbg(struct app_params *app,
287                                                 uint32_t pipeline_id, uint8_t *msg)
288 {
289         struct pipeline_cgnapt_t *p;
290
291         struct pipeline_cgnapt_entry_dbg_msg_req *req;
292         struct pipeline_cgnapt_entry_dbg_msg_rsp *rsp;
293
294         /* Check input arguments */
295         if (app == NULL)
296                 return -1;
297
298         p = app_pipeline_data_fe(app, pipeline_id,
299                                  (struct pipeline_type *)&pipeline_cgnapt);
300         if (p == NULL)
301                 return -1;
302
303         /* Allocate and write request */
304         req = app_msg_alloc(app);
305         if (req == NULL)
306                 return -1;
307
308         req->type = PIPELINE_MSG_REQ_CUSTOM;
309         req->subtype = PIPELINE_CGNAPT_MSG_REQ_ENTRY_DBG;
310         req->data[0] = msg[0];
311         req->data[1] = msg[1];
312         req->data[2] = msg[2];
313
314         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
315         if (rsp == NULL)
316                 return -1;
317
318         /* Read response */
319         if (rsp->status) {
320                 app_msg_free(app, rsp);
321                 printf("Error rsp->status %d\n", rsp->status);
322                 return -1;
323         }
324
325         /* Free response */
326         app_msg_free(app, rsp);
327
328         return 0;
329 }
330
331 /**
332  * Function to send a NAPT entry add message to BE
333  *
334  * @param app
335  *  A pointer to pipeline app
336  * @param pipeline_id
337  *  Pipeline id
338  * @param key
339  *  A pointer to NAPT entry key
340  * @param entry_params
341  *  A pointer to NAPT entry params
342  *
343  * @return
344  *  0 on success, negative on error.
345  */
346 int app_pipeline_cgnapt_add_entry(
347         struct app_params *app,
348         uint32_t pipeline_id,
349         struct app_pipeline_cgnapt_entry_params *entry_params)
350 {
351         struct pipeline_cgnapt_t *p;
352
353         struct pipeline_cgnapt_entry_add_msg_req *req;
354         struct pipeline_cgnapt_entry_add_msg_rsp *rsp;
355
356         /* Check input arguments */
357         if ((app == NULL) || (entry_params == NULL))
358                 return -1;
359
360         p = app_pipeline_data_fe(app, pipeline_id,
361                                  (struct pipeline_type *)&pipeline_cgnapt);
362         if (p == NULL)
363                 return -2;
364
365         /* Allocate and write request */
366         req = app_msg_alloc(app);
367         if (req == NULL)
368                 return -4;
369
370         req->type = PIPELINE_MSG_REQ_CUSTOM;
371         req->subtype = PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADD;
372         memcpy(&req->data, entry_params, sizeof(*entry_params));
373
374         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
375         if (rsp == NULL)
376                 return -5;
377
378         /* Message buffer free */
379         app_msg_free(app, rsp);
380         return 0;
381 }
382
383 /**
384  * Function to send a multiple NAPT entry add message to BE
385  *
386  * @param app
387  *  A pointer to pipeline app
388  * @param pipeline_id
389  *  Pipeline id
390  * @param key
391  *  A pointer to NAPT entry key
392  * @param entry_params
393  *  A pointer to multiple NAPT entry params
394  *
395  * @return
396  *  0 on success, negative on error.
397  */
398 int app_pipeline_cgnapt_addm_entry(
399         struct app_params *app,
400         uint32_t pipeline_id,
401         struct app_pipeline_cgnapt_mentry_params *entry_params)
402 {
403         struct pipeline_cgnapt_t *p;
404
405         struct pipeline_cgnapt_entry_addm_msg_req *req;
406         struct pipeline_cgnapt_entry_addm_msg_rsp *rsp;
407
408         /* Check input arguments */
409         if ((app == NULL) || (entry_params == NULL))
410                 return -1;
411
412         p = app_pipeline_data_fe(app, pipeline_id,
413                                  (struct pipeline_type *)&pipeline_cgnapt);
414         if (p == NULL)
415                 return -2;
416
417         /* Allocate and write request */
418         req = app_msg_alloc(app);
419         if (req == NULL)
420                 return -4;
421
422         req->type = PIPELINE_MSG_REQ_CUSTOM;
423         req->subtype = PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADDM;
424         memcpy(&req->data, entry_params, sizeof(*entry_params));
425
426         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
427         if (rsp == NULL)
428                 return -5;
429
430         /* Message buffer free */
431         app_msg_free(app, rsp);
432         return 0;
433 }
434
435 /**
436  * Function to send a NAPT entry delete message to BE
437  *
438  * @param app
439  *  A pointer to pipeline app
440  * @param pipeline_id
441  *  Pipeline id
442  * @param key
443  *  A pointer to NAPT entry key
444  *
445  * @return
446  *  0 on success, negative on error.
447  */
448 int
449 app_pipeline_cgnapt_delete_entry(struct app_params *app,
450                                  uint32_t pipeline_id,
451                                  struct pipeline_cgnapt_entry_key *key)
452 {
453         struct pipeline_cgnapt_t *p;
454
455         struct pipeline_cgnapt_entry_delete_msg_req *req;
456         struct pipeline_cgnapt_entry_delete_msg_rsp *rsp;
457
458         if (CGNAPT_DEBUG) {
459                 uint8_t *KeyP = (uint8_t *) key;
460                 int i = 0;
461
462                 printf("app_pipeline_cgnapt_delete_entry - Key: ");
463                 for (i = 0; i < (int)sizeof(*key); i++)
464                         printf(" %02x", KeyP[i]);
465                 printf(" ,KeySize %u\n", (int)sizeof(*key));
466         }
467         /* Check input arguments */
468         if ((app == NULL) || (key == NULL))
469                 return -1;
470
471         p = app_pipeline_data_fe(app, pipeline_id,
472                                  (struct pipeline_type *)&pipeline_cgnapt);
473         if (p == NULL)
474                 return -1;
475
476         /* Allocate and write request */
477         req = app_msg_alloc(app);
478         if (req == NULL)
479                 return -1;
480
481         req->type = PIPELINE_MSG_REQ_CUSTOM;
482         req->subtype = PIPELINE_CGNAPT_MSG_REQ_ENTRY_DEL;
483         memcpy(&req->key, key, sizeof(*key));
484
485         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
486         if (rsp == NULL)
487                 return -1;
488
489         /* Read response */
490         if (rsp->status || !rsp->key_found) {
491                 app_msg_free(app, rsp);
492   #ifdef CGNAPT_DBG_PRNT
493                     printf("Successfully deleted the entry\n");
494                 #endif
495                 return 0;
496         }
497
498         /* Free response */
499         app_msg_free(app, rsp);
500
501         return 0;
502 }
503
504 /**
505  * A structure defining the entry add parse arguments.
506  */
507 struct cmd_entry_add_result {
508         cmdline_fixed_string_t p_string;
509         uint32_t p;
510         cmdline_fixed_string_t entry_string;
511         cmdline_fixed_string_t add_string;
512         cmdline_ipaddr_t prv_ip;
513         uint16_t prv_port;
514         cmdline_ipaddr_t pub_ip;
515         uint16_t pub_port;
516         uint16_t pid;
517         uint32_t ttl;
518 };
519 /**
520  * Helping function for add entry
521  *
522  * @param parsed_result
523  *  A pointer parsed add arguments
524  * @param cl
525  *  unused pointer to struct cmdline
526  * @param msg
527  *  void pointer data
528  *
529  */
530 static void
531 cmd_entry_add_parsed(void *parsed_result,
532                                         __rte_unused struct cmdline *cl, void *data)
533 {
534         struct cmd_entry_add_result *params = parsed_result;
535         struct app_params *app = data;
536         struct app_pipeline_cgnapt_entry_params ent_params;
537         int status;
538
539         if (params->prv_ip.family == AF_INET) {
540                 ent_params.type = CGNAPT_ENTRY_IPV4;
541                 ent_params.u.prv_ip =
542                                 rte_bswap32((uint32_t) params->prv_ip.addr.ipv4.s_addr);
543         } else {
544                 print_ipv6_address_u8(params->prv_ip.addr.ipv6.s6_addr);
545                 print_ipv6_address_u16(params->prv_ip.addr.ipv6.s6_addr16);
546                 print_ipv6_address_u32(params->prv_ip.addr.ipv6.s6_addr32);
547                 ent_params.type = CGNAPT_ENTRY_IPV6;
548                 memcpy(ent_params.u.prv_ipv6, params->prv_ip.addr.ipv6.s6_addr,
549                                          16);
550         }
551
552         ent_params.prv_port = params->prv_port;
553         ent_params.pub_ip =
554                         rte_bswap32((uint32_t) params->pub_ip.addr.ipv4.s_addr);
555         ent_params.pub_port = params->pub_port;
556         ent_params.prv_phy_port = params->pid;
557         ent_params.ttl = params->ttl;
558
559         status = app_pipeline_cgnapt_add_entry(app, params->p, &ent_params);
560
561         if (status != 0) {
562                 printf("CG-NAPT add multiple entry command failed, %d\n",
563                                          status);
564                 return;
565         }
566 }
567
568 static cmdline_parse_token_string_t cmd_entry_add_p_string =
569 TOKEN_STRING_INITIALIZER(struct cmd_entry_add_result, p_string,
570                          "p");
571
572 static cmdline_parse_token_num_t cmd_entry_add_p =
573 TOKEN_NUM_INITIALIZER(struct cmd_entry_add_result, p, UINT32);
574
575 static cmdline_parse_token_string_t cmd_entry_add_entry_string =
576 TOKEN_STRING_INITIALIZER(struct cmd_entry_add_result, entry_string,
577                          "entry");
578
579 static cmdline_parse_token_string_t cmd_entry_add_add_string =
580 TOKEN_STRING_INITIALIZER(struct cmd_entry_add_result, add_string,
581                          "add");
582
583 static cmdline_parse_token_ipaddr_t cmd_entry_add_prv_ip =
584 TOKEN_IPADDR_INITIALIZER(struct cmd_entry_add_result, prv_ip);
585
586 static cmdline_parse_token_num_t cmd_entry_add_prv_port =
587 TOKEN_NUM_INITIALIZER(struct cmd_entry_add_result, prv_port, UINT16);
588
589 static cmdline_parse_token_ipaddr_t cmd_entry_add_pub_ip =
590 TOKEN_IPV4_INITIALIZER(struct cmd_entry_add_result, pub_ip);
591
592 static cmdline_parse_token_num_t cmd_entry_add_pub_port =
593 TOKEN_NUM_INITIALIZER(struct cmd_entry_add_result, pub_port, UINT16);
594
595 static cmdline_parse_token_num_t cmd_entry_add_pid =
596 TOKEN_NUM_INITIALIZER(struct cmd_entry_add_result, pid, UINT16);
597
598 static cmdline_parse_token_num_t cmd_entry_add_ttl =
599 TOKEN_NUM_INITIALIZER(struct cmd_entry_add_result, ttl, UINT32);
600
601 static cmdline_parse_inst_t cmd_entry_add = {
602         .f = cmd_entry_add_parsed,
603         .data = NULL,
604         .help_str = "NAPT entry add",
605         .tokens = {
606                          (void *)&cmd_entry_add_p_string,
607                          (void *)&cmd_entry_add_p,
608                          (void *)&cmd_entry_add_entry_string,
609                          (void *)&cmd_entry_add_add_string,
610                          (void *)&cmd_entry_add_prv_ip,
611                          (void *)&cmd_entry_add_prv_port,
612                          (void *)&cmd_entry_add_pub_ip,
613                          (void *)&cmd_entry_add_pub_port,
614                          (void *)&cmd_entry_add_pid,
615                          (void *)&cmd_entry_add_ttl,
616                          NULL,
617                          },
618 };
619
620 /**
621  * A structure defining the multiple entry add parse arguments.
622  */
623 struct cmd_entry_addm_result {
624         cmdline_fixed_string_t p_string;
625         uint32_t p;
626         cmdline_fixed_string_t entry_string;
627         cmdline_fixed_string_t addm_string;
628         cmdline_ipaddr_t prv_ip;
629         uint16_t prv_port;
630         cmdline_ipaddr_t pub_ip;
631         uint16_t pub_port;
632         uint16_t pid;
633         uint32_t ttl;
634         uint32_t num_ue;
635         uint16_t prv_port_max;
636         uint16_t pub_port_max;
637 };
638
639 /**
640  * Helping function for add multiple entries
641  *
642  * @param parsed_result
643  *  A pointer parsed add arguments
644  * @param cl
645  *  unused pointer to struct cmdline
646  * @param msg
647  *  void pointer data
648  */
649 static void
650 cmd_entry_addm_parsed(void *parsed_result,
651                                         __rte_unused struct cmdline *cl, void *data)
652 {
653         struct cmd_entry_addm_result *params = parsed_result;
654         struct app_params *app = data;
655         struct app_pipeline_cgnapt_mentry_params ent_params;
656         int status;
657
658         if (params->prv_ip.family == AF_INET) {
659                 ent_params.type = CGNAPT_ENTRY_IPV4;
660                 ent_params.u.prv_ip =
661                                 rte_bswap32((uint32_t) params->prv_ip.addr.ipv4.s_addr);
662         } else {
663                 print_ipv6_address_u8(params->prv_ip.addr.ipv6.s6_addr);
664                 print_ipv6_address_u16(params->prv_ip.addr.ipv6.s6_addr16);
665                 print_ipv6_address_u32(params->prv_ip.addr.ipv6.s6_addr32);
666                 ent_params.type = CGNAPT_ENTRY_IPV6;
667                 memcpy(ent_params.u.prv_ipv6, params->prv_ip.addr.ipv6.s6_addr,
668                                          16);
669         }
670
671         ent_params.prv_port = params->prv_port;
672         ent_params.pub_ip =
673                         rte_bswap32((uint32_t) params->pub_ip.addr.ipv4.s_addr);
674         ent_params.pub_port = params->pub_port;
675         ent_params.prv_phy_port = params->pid;
676         ent_params.ttl = params->ttl;
677         ent_params.num_ue = params->num_ue;
678         ent_params.prv_port_max = params->prv_port_max;
679         ent_params.pub_port_max = params->pub_port_max;
680
681         status = app_pipeline_cgnapt_addm_entry(app, params->p, &ent_params);
682
683         if (status != 0) {
684                 printf("CG-NAPT add multiple entry command failed, %d\n",
685                                          status);
686                 return;
687         }
688 }
689
690 static cmdline_parse_token_string_t cmd_entry_add_addm_string =
691 TOKEN_STRING_INITIALIZER(struct cmd_entry_addm_result, addm_string,
692                          "addm");
693
694 static cmdline_parse_token_num_t cmd_entry_addm_prv_port =
695 TOKEN_NUM_INITIALIZER(struct cmd_entry_addm_result, prv_port_max, UINT16);
696
697 static cmdline_parse_token_num_t cmd_entry_addm_pub_port =
698 TOKEN_NUM_INITIALIZER(struct cmd_entry_addm_result, pub_port_max, UINT16);
699
700 static cmdline_parse_token_num_t cmd_entry_addm_max_ue =
701 TOKEN_NUM_INITIALIZER(struct cmd_entry_addm_result, num_ue, UINT32);
702
703 static cmdline_parse_inst_t cmd_entry_addm = {
704         .f = cmd_entry_addm_parsed,
705         .data = NULL,
706         .help_str = "NAPT entry add multiple",
707         .tokens = {
708                          (void *)&cmd_entry_add_p_string,
709                          (void *)&cmd_entry_add_p,
710                          (void *)&cmd_entry_add_entry_string,
711                          (void *)&cmd_entry_add_addm_string,
712                          (void *)&cmd_entry_add_prv_ip,
713                          (void *)&cmd_entry_add_prv_port,
714                          (void *)&cmd_entry_add_pub_ip,
715                          (void *)&cmd_entry_add_pub_port,
716                          (void *)&cmd_entry_add_pid,
717                          (void *)&cmd_entry_add_ttl,
718                          (void *)&cmd_entry_addm_max_ue,
719                          (void *)&cmd_entry_addm_prv_port,
720                          (void *)&cmd_entry_addm_pub_port,
721                          NULL,
722                          },
723 };
724
725 /**
726  * A structure defining the entry delete parse arguments.
727  */
728 struct cmd_entry_del_result {
729         cmdline_fixed_string_t p_string;
730         uint32_t p;
731         cmdline_fixed_string_t entry_string;
732         cmdline_fixed_string_t del_string;
733         cmdline_ipaddr_t ip;
734         uint16_t port;
735         uint16_t pid;
736 };
737
738 /**
739  * Helping function for delete entry
740  *
741  * @param parsed_result
742  *  A pointer parsed add arguments
743  * @param cl
744  *  unused pointer to struct cmdline
745  * @param msg
746  *  void pointer data
747  */
748 static void
749 cmd_entry_del_parsed(void *parsed_result,
750                                  __rte_unused struct cmdline *cl, void *data)
751 {
752         struct cmd_entry_del_result *params = parsed_result;
753         struct app_params *app = data;
754         struct pipeline_cgnapt_entry_key key;
755
756         int status;
757
758         /* Create entry */
759         if (params->ip.family == AF_INET)
760                 key.ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr);
761         else
762                 key.ip =
763                                 rte_bswap32((uint32_t) params->ip.addr.ipv6.s6_addr32[3]);
764         key.port = params->port;
765         key.pid = params->pid;
766
767         status = app_pipeline_cgnapt_delete_entry(app, params->p, &key);
768
769         if (status != 0) {
770                 printf("CG-NAPT entry del command failed\n");
771                 return;
772         }
773 }
774
775 static cmdline_parse_token_string_t cmd_entry_del_p_string =
776 TOKEN_STRING_INITIALIZER(struct cmd_entry_del_result, p_string,
777                          "p");
778
779 static cmdline_parse_token_num_t cmd_entry_del_p =
780 TOKEN_NUM_INITIALIZER(struct cmd_entry_del_result, p, UINT32);
781
782 static cmdline_parse_token_string_t cmd_entry_del_entry_string =
783 TOKEN_STRING_INITIALIZER(struct cmd_entry_del_result, entry_string,
784                          "entry");
785
786 static cmdline_parse_token_string_t cmd_entry_del_del_string =
787 TOKEN_STRING_INITIALIZER(struct cmd_entry_del_result, del_string,
788                          "del");
789
790 static cmdline_parse_token_ipaddr_t cmd_entry_del_ip =
791 TOKEN_IPADDR_INITIALIZER(struct cmd_entry_del_result, ip);
792
793 static cmdline_parse_token_num_t cmd_entry_del_port =
794 TOKEN_NUM_INITIALIZER(struct cmd_entry_del_result, port, UINT16);
795
796 static cmdline_parse_token_num_t cmd_entry_del_pid =
797 TOKEN_NUM_INITIALIZER(struct cmd_entry_del_result, pid, UINT16);
798
799 static cmdline_parse_inst_t cmd_entry_del = {
800         .f = cmd_entry_del_parsed,
801         .data = NULL,
802         .help_str = "Entry delete",
803         .tokens = {
804                          (void *)&cmd_entry_del_p_string,
805                          (void *)&cmd_entry_del_p,
806                          (void *)&cmd_entry_del_entry_string,
807                          (void *)&cmd_entry_del_del_string,
808                          (void *)&cmd_entry_del_ip,
809                          (void *)&cmd_entry_del_port,
810                          (void *)&cmd_entry_del_pid,
811                          NULL,
812                          },
813 };
814
815 /**
816  * A structure defining the list entry parse arguments.
817  */
818 struct cmd_entry_ls_result {
819         cmdline_fixed_string_t p_string;
820         uint32_t p;
821         cmdline_fixed_string_t entry_string;
822         cmdline_fixed_string_t ls_string;
823 };
824
825 /**
826  * Helping function for list entry
827  *
828  * @param parsed_result
829  *  A pointer parsed add arguments
830  * @param cl
831  *  unused pointer to struct cmdline
832  * @param msg
833  *  void pointer data
834  */
835 static void
836 cmd_entry_ls_parsed(void *parsed_result,
837                                 __rte_unused struct cmdline *cl, void *data)
838 {
839         struct cmd_entry_ls_result *params = parsed_result;
840         struct app_params *app = data;
841         int status;
842
843         status = app_pipeline_cgnapt_entry_ls(app, params->p);
844
845         if (status != 0) {
846                 printf("Ls command failed\n");
847                 return;
848         }
849 }
850
851 static cmdline_parse_token_string_t cmd_entry_ls_p_string =
852 TOKEN_STRING_INITIALIZER(struct cmd_entry_ls_result, p_string, "p");
853
854 static cmdline_parse_token_num_t cmd_entry_ls_p =
855 TOKEN_NUM_INITIALIZER(struct cmd_entry_ls_result, p, UINT32);
856
857 static cmdline_parse_token_string_t cmd_entry_ls_entry_string =
858 TOKEN_STRING_INITIALIZER(struct cmd_entry_ls_result,
859                          entry_string, "entry");
860
861 static cmdline_parse_token_string_t cmd_entry_ls_ls_string =
862 TOKEN_STRING_INITIALIZER(struct cmd_entry_ls_result, ls_string,
863                          "ls");
864
865 static cmdline_parse_inst_t cmd_entry_ls = {
866         .f = cmd_entry_ls_parsed,
867         .data = NULL,
868         .help_str = "Entry list",
869         .tokens = {
870                          (void *)&cmd_entry_ls_p_string,
871                          (void *)&cmd_entry_ls_p,
872                          (void *)&cmd_entry_ls_entry_string,
873                          (void *)&cmd_entry_ls_ls_string,
874                          NULL,
875                          },
876 };
877
878 /**
879  * A structure defining the dbg cmd parse arguments.
880  */
881 struct cmd_entry_dbg_result {
882         cmdline_fixed_string_t p_string;
883         uint32_t p;
884         cmdline_fixed_string_t entry_string;
885         cmdline_fixed_string_t dbg_string;
886         uint8_t cmd;
887         uint8_t d1;
888         uint8_t d2;
889 };
890
891 /**
892  * Helping function for dbg cmd
893  *
894  * @param parsed_result
895  *  A pointer parsed add arguments
896  * @param cl
897  *  unused pointer to struct cmdline
898  * @param msg
899  *  void pointer data
900  */
901 static void
902 cmd_entry_dbg_parsed(void *parsed_result,
903                                  __rte_unused struct cmdline *cl, void *data)
904 {
905         struct cmd_entry_dbg_result *params = parsed_result;
906         struct app_params *app = data;
907         uint8_t msg[4];
908         int status;
909
910         msg[0] = params->cmd;
911         msg[1] = params->d1;
912         msg[2] = params->d2;
913         status = app_pipeline_cgnapt_entry_dbg(app, params->p, msg);
914
915         if (status != 0) {
916                 printf("Dbg Command failed\n");
917                 return;
918         }
919 }
920
921 static cmdline_parse_token_string_t cmd_entry_dbg_p_string =
922 TOKEN_STRING_INITIALIZER(struct cmd_entry_dbg_result, p_string, "p");
923
924 static cmdline_parse_token_num_t cmd_entry_dbg_p =
925 TOKEN_NUM_INITIALIZER(struct cmd_entry_dbg_result, p, UINT32);
926
927 static cmdline_parse_token_string_t cmd_entry_dbg_entry_string =
928 TOKEN_STRING_INITIALIZER(struct cmd_entry_dbg_result,
929                          entry_string, "entry");
930
931 static cmdline_parse_token_string_t cmd_entry_dbg_dbg_string =
932 TOKEN_STRING_INITIALIZER(struct cmd_entry_dbg_result, dbg_string,
933                          "dbg");
934
935 static cmdline_parse_token_num_t cmd_entry_dbg_cmd =
936 TOKEN_NUM_INITIALIZER(struct cmd_entry_dbg_result, cmd, UINT8);
937
938 static cmdline_parse_token_num_t cmd_entry_dbg_d1 =
939 TOKEN_NUM_INITIALIZER(struct cmd_entry_dbg_result, d1, UINT8);
940
941 static cmdline_parse_token_num_t cmd_entry_dbg_d2 =
942 TOKEN_NUM_INITIALIZER(struct cmd_entry_dbg_result, d2, UINT8);
943
944 static cmdline_parse_inst_t cmd_entry_dbg = {
945         .f = cmd_entry_dbg_parsed,
946         .data = NULL,
947         .help_str = "NAPT dbg cmd",
948         .tokens = {
949                          (void *)&cmd_entry_dbg_p_string,
950                          (void *)&cmd_entry_dbg_p,
951                          (void *)&cmd_entry_dbg_entry_string,
952                          (void *)&cmd_entry_dbg_dbg_string,
953                          (void *)&cmd_entry_dbg_cmd,
954                          (void *)&cmd_entry_dbg_d1,
955                          (void *)&cmd_entry_dbg_d2,
956                          NULL,
957                          },
958 };
959
960 /**
961  * A structure defining num ip clients cmd parse arguments.
962  */
963 struct cmd_numipcli_result {
964         cmdline_fixed_string_t p_string;
965         uint32_t p;
966         cmdline_fixed_string_t numipcli_string;
967 };
968
969 /**
970  * Helping function for printing num ip clients
971  *
972  * @param parsed_result
973  *  Unused pointer parsed add arguments
974  * @param cl
975  *  unused pointer to struct cmdline
976  * @param msg
977  *  Unused void pointer data
978  */
979 static void
980 cmd_numipcli_parsed(__rte_unused void *parsed_result,
981                                 __rte_unused struct cmdline *cl, __rte_unused void *data)
982 {
983         print_num_ip_clients();
984 }
985
986 static cmdline_parse_token_string_t cmd_numipcli_p_string =
987 TOKEN_STRING_INITIALIZER(struct cmd_numipcli_result, p_string, "p");
988
989 static cmdline_parse_token_num_t cmd_numipcli_p =
990 TOKEN_NUM_INITIALIZER(struct cmd_numipcli_result, p, UINT32);
991
992 static cmdline_parse_token_string_t cmd_numipcli_string =
993 TOKEN_STRING_INITIALIZER(struct cmd_numipcli_result,
994                          numipcli_string, "numipcli");
995
996 static cmdline_parse_inst_t cmd_numipcli = {
997         .f = cmd_numipcli_parsed,
998         .data = NULL,
999         .help_str = "Num IP Clients command",
1000         .tokens = {
1001                          (void *)&cmd_numipcli_p_string,
1002                          (void *)&cmd_numipcli_p,
1003                          (void *)&cmd_numipcli_string,
1004                          NULL,
1005                          },
1006 };
1007
1008 /**
1009  * Function to send a ver cmd message to BE
1010  *
1011  * @param app
1012  *  A pointer to pipeline app
1013  * @param pipeline_id
1014  *  Pipeline id
1015  * @param msg
1016  *  debug message contents
1017  *
1018  * @return
1019  *  0 on success, negative on error.
1020  */
1021 static int
1022 app_pipeline_cgnapt_ver(struct app_params *app,
1023                         uint32_t pipeline_id, uint8_t *msg)
1024 {
1025
1026         struct pipeline_cgnapt_t *p;
1027         struct pipeline_cgnapt_entry_dbg_msg_req *req;
1028         struct pipeline_cgnapt_entry_dbg_msg_rsp *rsp;
1029
1030         /* Check input arguments */
1031         if (app == NULL)
1032                 return -1;
1033
1034         p = app_pipeline_data_fe(app, pipeline_id,
1035                                  (struct pipeline_type *)&pipeline_cgnapt);
1036         if (p == NULL)
1037                 return -1;
1038
1039         /* Allocate and write request */
1040         req = app_msg_alloc(app);
1041         if (req == NULL)
1042                 return -1;
1043
1044         req->type = PIPELINE_MSG_REQ_CUSTOM;
1045         req->subtype = PIPELINE_CGNAPT_MSG_REQ_VER;
1046         req->data[0] = msg[0];
1047         req->data[1] = msg[1];
1048
1049         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
1050         if (rsp == NULL)
1051                 return -1;
1052
1053         /* Read response */
1054         if (rsp->status) {
1055                 app_msg_free(app, rsp);
1056                 printf("Error rsp->status %d\n", rsp->status);
1057                 return -1;
1058         }
1059
1060         /* Free response */
1061         app_msg_free(app, rsp);
1062
1063         return 0;
1064 }
1065
1066 /**
1067  * A structure defining ver cmd parse arguments.
1068  */
1069 struct cmd_ver_result {
1070         cmdline_fixed_string_t p_string;
1071         uint32_t p;
1072         cmdline_fixed_string_t ver_string;
1073         uint8_t cmd;
1074         uint8_t d1;
1075 };
1076
1077 /**
1078  * Helping function for ver cmd
1079  *
1080  * @param parsed_result
1081  *  A pointer parsed add arguments
1082  * @param cl
1083  *  unused pointer to struct cmdline
1084  * @param msg
1085  *  void pointer data
1086  */
1087 static void
1088 cmd_ver_parsed(void *parsed_result, __rte_unused struct cmdline *cl, void *data)
1089 {
1090         struct cmd_ver_result *params = parsed_result;
1091         struct app_params *app = data;
1092         uint8_t msg[4];
1093         int status;
1094
1095         msg[0] = params->cmd;
1096         msg[1] = params->d1;
1097         status = app_pipeline_cgnapt_ver(app, params->p, msg);
1098
1099         if (status != 0) {
1100                 printf("Version Command failed\n");
1101                 return;
1102         }
1103 }
1104
1105 static cmdline_parse_token_string_t cmd_ver_p_string =
1106 TOKEN_STRING_INITIALIZER(struct cmd_ver_result, p_string, "p");
1107
1108 static cmdline_parse_token_num_t cmd_ver_p =
1109 TOKEN_NUM_INITIALIZER(struct cmd_ver_result, p, UINT32);
1110
1111 static cmdline_parse_token_string_t cmd_ver_string =
1112 TOKEN_STRING_INITIALIZER(struct cmd_ver_result,
1113                          ver_string, "ver");
1114
1115 static cmdline_parse_token_num_t cmd_ver_cmd =
1116 TOKEN_NUM_INITIALIZER(struct cmd_ver_result, cmd, UINT8);
1117
1118 static cmdline_parse_token_num_t cmd_ver_d1 =
1119 TOKEN_NUM_INITIALIZER(struct cmd_ver_result, d1, UINT8);
1120
1121 static cmdline_parse_inst_t cmd_ver = {
1122         .f = cmd_ver_parsed,
1123         .data = NULL,
1124         .help_str = "NAPT ver cmd",
1125         .tokens = {
1126                          (void *)&cmd_ver_p_string,
1127                          (void *)&cmd_ver_p,
1128                          (void *)&cmd_ver_string,
1129                          (void *)&cmd_ver_cmd,
1130                          (void *)&cmd_ver_d1,
1131                          NULL,
1132                          },
1133 };
1134
1135 /**
1136  * Function to send a nsp add cmd message to BE
1137  *
1138  * @param app
1139  *  A pointer to pipeline app
1140  * @param pipeline_id
1141  *  Pipeline id
1142  * @param nsp
1143  *  A pointer to struct pipeline_cgnapt_nsp_t
1144  *
1145  * @return
1146  *  0 on success, negative on error.
1147  */
1148 static int
1149 app_pipeline_cgnapt_add_nsp(struct app_params *app,
1150                                         uint32_t pipeline_id,
1151                                         struct pipeline_cgnapt_nsp_t *nsp)
1152 {
1153
1154         struct pipeline_cgnapt_t *p;
1155         struct pipeline_cgnapt_nsp_add_msg_req *req;
1156         struct pipeline_cgnapt_nsp_add_msg_rsp *rsp;
1157
1158         /* Check input arguments */
1159         if (app == NULL)
1160                 return -1;
1161
1162         printf("1st if condition\n");
1163
1164         p = app_pipeline_data_fe(app, pipeline_id,
1165                                  (struct pipeline_type *)&pipeline_cgnapt);
1166         if (p == NULL)
1167                 return -1;
1168
1169         printf("2st if condition\n");
1170         /* Allocate and write request */
1171         req = app_msg_alloc(app);
1172         if (req == NULL)
1173                 return -1;
1174
1175         printf("3st if condition\n");
1176         req->type = PIPELINE_MSG_REQ_CUSTOM;
1177         req->subtype = PIPELINE_CGNAPT_MSG_REQ_NSP_ADD;
1178         memcpy(&req->nsp, nsp, sizeof(struct pipeline_cgnapt_nsp_t));
1179
1180         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
1181         if (rsp == NULL)
1182                 return -1;
1183
1184         printf("4st if condition\n");
1185         /* Read response */
1186         if (rsp->status) {
1187                 app_msg_free(app, rsp);
1188                 printf("Error rsp->status %d\n", rsp->status);
1189                 return -1;
1190         }
1191
1192         /* Free response */
1193         app_msg_free(app, rsp);
1194
1195         return 0;
1196 }
1197
1198 /**
1199  * A structure defining nsp add cmd parse arguments.
1200  */
1201 struct cmd_nsp_add_result {
1202         cmdline_fixed_string_t p_string;
1203         uint32_t p;
1204         cmdline_fixed_string_t nsp_string;
1205         cmdline_fixed_string_t add_string;
1206         cmdline_ipaddr_t ip;
1207 };
1208
1209 /**
1210  * Helping function for nsp add cmd
1211  *
1212  * @param parsed_result
1213  *  A pointer parsed add arguments
1214  * @param cl
1215  *  unused pointer to struct cmdline
1216  * @param msg
1217  *  void pointer data
1218  */
1219 static void
1220 cmd_nsp_add_parsed(void *parsed_result, __rte_unused struct cmdline *cl,
1221                          void *data)
1222 {
1223         struct cmd_nsp_add_result *params = parsed_result;
1224         struct app_params *app = data;
1225         int status;
1226         struct pipeline_cgnapt_nsp_t nsp;
1227
1228         memcpy(&nsp.prefix, &params->ip.addr.ipv6.s6_addr, 16);
1229         nsp.depth = params->ip.prefixlen;
1230         status = app_pipeline_cgnapt_add_nsp(app, params->p, &nsp);
1231         if (status != 0) {
1232                 printf("NSP ADD Command failed\n");
1233                 return;
1234         }
1235 }
1236
1237 static cmdline_parse_token_string_t cmd_add_nsp_p_string =
1238 TOKEN_STRING_INITIALIZER(struct cmd_nsp_add_result, p_string, "p");
1239
1240 static cmdline_parse_token_num_t cmd_add_nsp_p =
1241 TOKEN_NUM_INITIALIZER(struct cmd_nsp_add_result, p, UINT32);
1242
1243 static cmdline_parse_token_string_t cmd_add_nsp_string =
1244 TOKEN_STRING_INITIALIZER(struct cmd_nsp_add_result,
1245                          nsp_string, "nsp");
1246
1247 static cmdline_parse_token_string_t cmd_add_nsp_add_string =
1248 TOKEN_STRING_INITIALIZER(struct cmd_nsp_add_result,
1249                          add_string, "add");
1250
1251 static cmdline_parse_token_ipaddr_t cmd_add_nsp_ip =
1252 TOKEN_IPNET_INITIALIZER(struct cmd_nsp_add_result, ip);
1253
1254 static cmdline_parse_inst_t cmd_nsp_add = {
1255         .f = cmd_nsp_add_parsed,
1256         .data = NULL,
1257         .help_str = "NAPT NSP ADD cmd",
1258         .tokens = {
1259                          (void *)&cmd_add_nsp_p_string,
1260                          (void *)&cmd_add_nsp_p,
1261                          (void *)&cmd_add_nsp_string,
1262                          (void *)&cmd_add_nsp_add_string,
1263                          (void *)&cmd_add_nsp_ip,
1264                          NULL,
1265                          },
1266 };
1267
1268 /**
1269  * Function to send a nsp del cmd message to BE
1270  *
1271  * @param app
1272  *  A pointer to pipeline app
1273  * @param pipeline_id
1274  *  Pipeline id
1275  * @param nsp
1276  *  A pointer to struct pipeline_cgnapt_nsp_t
1277  *
1278  * @return
1279  *  0 on success, negative on error.
1280  */
1281 static int
1282 app_pipeline_cgnapt_del_nsp(struct app_params *app,
1283                                         uint32_t pipeline_id,
1284                                         struct pipeline_cgnapt_nsp_t *nsp)
1285 {
1286
1287         struct pipeline_cgnapt_t *p;
1288         struct pipeline_cgnapt_nsp_del_msg_req *req;
1289         struct pipeline_cgnapt_nsp_del_msg_rsp *rsp;
1290
1291         /* Check input arguments */
1292         if (app == NULL)
1293                 return -1;
1294
1295         p = app_pipeline_data_fe(app, pipeline_id,
1296                                  (struct pipeline_type *)&pipeline_cgnapt);
1297         if (p == NULL)
1298                 return -1;
1299
1300         /* Allocate and write request */
1301         req = app_msg_alloc(app);
1302         if (req == NULL)
1303                 return -1;
1304
1305         req->type = PIPELINE_MSG_REQ_CUSTOM;
1306         req->subtype = PIPELINE_CGNAPT_MSG_REQ_NSP_DEL;
1307         memcpy(&req->nsp, nsp, sizeof(struct pipeline_cgnapt_nsp_t));
1308
1309         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
1310         if (rsp == NULL)
1311                 return -1;
1312
1313         /* Read response */
1314         if (rsp->status) {
1315                 app_msg_free(app, rsp);
1316                 printf("Error rsp->status %d\n", rsp->status);
1317                 return -1;
1318         }
1319
1320         /* Free response */
1321         app_msg_free(app, rsp);
1322
1323         return 0;
1324 }
1325
1326 /**
1327  * A structure defining nsp del cmd parse arguments.
1328  */
1329 struct cmd_nsp_del_result {
1330         cmdline_fixed_string_t p_string;
1331         uint32_t p;
1332         cmdline_fixed_string_t nsp_string;
1333         cmdline_fixed_string_t del_string;
1334         cmdline_ipaddr_t ip;
1335 };
1336
1337 /**
1338  * Helping function for nsp del cmd
1339  *
1340  * @param parsed_result
1341  *  A pointer parsed add arguments
1342  * @param cl
1343  *  unused pointer to struct cmdline
1344  * @param msg
1345  *  void pointer data
1346  */
1347 static void
1348 cmd_nsp_del_parsed(void *parsed_result, __rte_unused struct cmdline *cl,
1349                          void *data)
1350 {
1351         struct cmd_nsp_del_result *params = parsed_result;
1352         struct app_params *app = data;
1353         int status;
1354         struct pipeline_cgnapt_nsp_t nsp;
1355
1356         memcpy(&nsp.prefix, &params->ip.addr.ipv6.s6_addr, 16);
1357         nsp.depth = params->ip.prefixlen;
1358         status = app_pipeline_cgnapt_del_nsp(app, params->p, &nsp);
1359
1360         if (status != 0) {
1361                 printf("NSP DEL Command failed\n");
1362                 return;
1363         }
1364 }
1365
1366 static cmdline_parse_token_string_t cmd_del_nsp_p_string =
1367 TOKEN_STRING_INITIALIZER(struct cmd_nsp_del_result, p_string, "p");
1368
1369 static cmdline_parse_token_num_t cmd_del_nsp_p =
1370 TOKEN_NUM_INITIALIZER(struct cmd_nsp_del_result, p, UINT32);
1371
1372 static cmdline_parse_token_string_t cmd_del_nsp_string =
1373 TOKEN_STRING_INITIALIZER(struct cmd_nsp_del_result,
1374                          nsp_string, "nsp");
1375
1376 static cmdline_parse_token_string_t cmd_del_nsp_del_string =
1377 TOKEN_STRING_INITIALIZER(struct cmd_nsp_del_result,
1378                          del_string, "del");
1379
1380 static cmdline_parse_token_ipaddr_t cmd_del_nsp_ip =
1381 TOKEN_IPNET_INITIALIZER(struct cmd_nsp_del_result, ip);
1382
1383 static cmdline_parse_inst_t cmd_nsp_del = {
1384         .f = cmd_nsp_del_parsed,
1385         .data = NULL,
1386         .help_str = "NAPT NSP DEL cmd",
1387         .tokens = {
1388                          (void *)&cmd_del_nsp_p_string,
1389                          (void *)&cmd_del_nsp_p,
1390                          (void *)&cmd_del_nsp_string,
1391                          (void *)&cmd_del_nsp_del_string,
1392                          (void *)&cmd_del_nsp_ip,
1393                          NULL,
1394                          },
1395 };
1396
1397 /**
1398  * A structure defining the cgnapt stats cmd parse arguments.
1399  */
1400 struct cmd_cgnapt_stats_result {
1401         cmdline_fixed_string_t p_string;
1402         cmdline_fixed_string_t cgnapt_string;
1403         cmdline_fixed_string_t stats_string;
1404 };
1405
1406 /**
1407  * Helping function for cgnapt stats cmd
1408  *
1409  * @param parsed_result
1410  *  A pointer parsed add arguments
1411  * @param cl
1412  *  unused pointer to struct cmdline
1413  * @param msg
1414  *  void pointer data
1415  */
1416 static void
1417 cmd_cgnapt_stats_parsed(
1418         __rte_unused void *parsed_result,
1419         __rte_unused struct cmdline *cl,
1420         __rte_unused void *data)
1421 {
1422         char buf[2048];
1423         all_cgnapt_stats(&buf[0]);
1424 }
1425
1426 static cmdline_parse_token_string_t cmd_cgnapt_stats_p_string =
1427 TOKEN_STRING_INITIALIZER(struct cmd_cgnapt_stats_result, p_string, "p");
1428
1429 static cmdline_parse_token_string_t cmd_cgnapt_stats_cgnapt_string =
1430 TOKEN_STRING_INITIALIZER(struct cmd_cgnapt_stats_result,
1431                                 cgnapt_string, "cgnapt");
1432
1433 static cmdline_parse_token_string_t cmd_cgnapt_stats_stats_string =
1434 TOKEN_STRING_INITIALIZER(struct cmd_cgnapt_stats_result, stats_string,
1435                                 "stats");
1436
1437 static cmdline_parse_inst_t cmd_stats = {
1438         .f = cmd_cgnapt_stats_parsed,
1439         .data = NULL,
1440         .help_str = "CGNAPT stats cmd",
1441         .tokens = {
1442                 (void *)&cmd_cgnapt_stats_p_string,
1443                 (void *)&cmd_cgnapt_stats_cgnapt_string,
1444                 (void *)&cmd_cgnapt_stats_stats_string,
1445                 NULL,
1446         },
1447 };
1448
1449 /**
1450  * A structure defining the cgnapt clear stats cmd parse arguments.
1451  */
1452 struct cmd_cgnapt_clear_stats_result {
1453         cmdline_fixed_string_t p_string;
1454         cmdline_fixed_string_t cgnapt_string;
1455         cmdline_fixed_string_t clear_string;
1456         cmdline_fixed_string_t stats_string;
1457 };
1458
1459 /**
1460  * Helping function for cgnapt clear stats cmd
1461  *
1462  * @param parsed_result
1463  *  A pointer parsed add arguments
1464  * @param cl
1465  *  unused pointer to struct cmdline
1466  * @param msg
1467  *  void pointer data
1468  */
1469 static void
1470 cmd_cgnapt_clear_stats_parsed(
1471         __rte_unused void *parsed_result,
1472         __rte_unused struct cmdline *cl,
1473         __rte_unused void *data)
1474 {
1475         char buf[2048];
1476         all_cgnapt_clear_stats(&buf[0]);
1477 }
1478
1479 static cmdline_parse_token_string_t cmd_cgnapt_clear_stats_p_string =
1480 TOKEN_STRING_INITIALIZER(struct cmd_cgnapt_clear_stats_result, p_string, "p");
1481
1482 static cmdline_parse_token_string_t cmd_cgnapt_clear_stats_cgnapt_string =
1483 TOKEN_STRING_INITIALIZER(struct cmd_cgnapt_clear_stats_result,
1484                                 cgnapt_string, "cgnapt");
1485
1486 static cmdline_parse_token_string_t cmd_cgnapt_clear_stats_clear_string =
1487 TOKEN_STRING_INITIALIZER(struct cmd_cgnapt_clear_stats_result,
1488                                 clear_string, "clear");
1489
1490 static cmdline_parse_token_string_t cmd_cgnapt_clear_stats_stats_string =
1491 TOKEN_STRING_INITIALIZER(struct cmd_cgnapt_clear_stats_result, stats_string,
1492                                 "stats");
1493
1494 int cgnapt_stats_handler(struct mg_connection *conn, void *cbdata)
1495 {
1496         uint32_t num_links = 0, len = 0;
1497         char buf[1024];
1498         const struct mg_request_info *ri = mg_get_request_info(conn);
1499         struct app_params *app = myapp;
1500         int i;
1501
1502         if (!strcmp(ri->request_method, "GET")) {
1503                 all_cgnapt_stats(&buf[0]);
1504                 mg_printf(conn, "%s\n", &buf[0]);
1505                 return 1; 
1506         }
1507
1508         if (strcmp(ri->request_method, "POST")) {
1509                 mg_printf(conn,
1510                     "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
1511                 mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
1512                 mg_printf(conn,
1513                           "%s method not allowed in the GET handler\n",
1514                           ri->request_method);
1515         }
1516
1517         all_cgnapt_clear_stats(&buf[0]);
1518         mg_printf(conn, "%s\n", &buf[0]);
1519         return 1;
1520
1521 }
1522
1523 int cgnapt_cmd_ver_handler(struct mg_connection *conn, void *cbdata)
1524 {
1525         const struct mg_request_info *req_info = mg_get_request_info(conn);
1526
1527         mg_printf(conn,
1528                   "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1529                   "close\r\n\r\n");
1530         mg_printf(conn, "<html><body>");
1531         mg_printf(conn, "<p>Command Passed</p>");
1532         mg_printf(conn, "</body></html>\n");
1533
1534         return 1;
1535 }
1536
1537 /*
1538  * loadrules
1539  */
1540
1541 /**
1542  * Open file and process all commands in the file.
1543  *
1544  * @param ctx
1545  *  A pointer to the CLI context
1546  * @param file_name
1547  *  A pointer to the file to process.
1548  *
1549  */
1550 static void cgnapt_loadrules_file(cmdline_parse_ctx_t *ctx, const char *file_name)
1551 {
1552        struct cmdline *file_cl;
1553        int fd;
1554
1555        fd = open(file_name, O_RDONLY);
1556        if (fd < 0) {
1557               printf("Cannot open file \"%s\"\n", file_name);
1558               return;
1559        }
1560
1561        file_cl = cmdline_new(ctx, "", fd, 1);
1562        cmdline_interact(file_cl);
1563        close(fd);
1564 }
1565
1566
1567 int nat_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1568 {
1569
1570         const struct mg_request_info *req_info = mg_get_request_info(conn);
1571         if (strcmp(req_info->request_method, "GET")) {
1572                 mg_printf(conn, "Only GET method allowed");
1573                 return 1;
1574         }
1575
1576         mg_printf(conn,
1577                  "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
1578                  "close\r\n\r\n");
1579         mg_printf(conn, "<html><body>");
1580         mg_printf(conn, "<h2> These are the methods that are supported </h2>");
1581         mg_printf(conn, "<h3>     /load  </h3>");
1582         mg_printf(conn, "<html><body>");
1583
1584         mg_printf(conn, "</body></html>\n");
1585
1586         return 1;
1587 }
1588
1589 static int nat_field_found(const char *key,
1590         const char *filename,
1591         char *path,
1592         size_t pathlen,
1593         void *user_data)
1594 {
1595         struct mg_connection *conn = (struct mg_connection *)user_data;
1596
1597         mg_printf(conn, "\r\n\r\n%s:\r\n", key);
1598         mg_printf(conn, "Inside vfw_field_found %s \n", filename);
1599
1600         if (filename && *filename) {
1601                 snprintf(path, pathlen, "/tmp/%s", filename);
1602                 struct app_params *app = myapp;
1603                 int status;
1604                 int fd;
1605
1606                 mg_printf(conn, "path: %s\n", path);
1607
1608                 /* Make sure the file exists before clearing rules and actions */
1609                 fd = open(path, O_RDONLY);
1610                 if (fd < 0) {
1611                         mg_printf(conn, "Cannot open file \"%s\"\n", filename);
1612                         return FORM_FIELD_STORAGE_GET;
1613                 }
1614
1615                 close(fd);
1616                 return FORM_FIELD_STORAGE_STORE;
1617         }
1618
1619         return FORM_FIELD_STORAGE_GET;
1620 }
1621
1622 static int nat_field_get(const char *key, const char *value, size_t valuelen,
1623         void *user_data)
1624 {
1625         struct mg_connection *conn = (struct mg_connection *)user_data;
1626
1627         if (key[0]) {
1628                 mg_printf(conn, "%s = ", key);
1629         }
1630         mg_write(conn, value, valuelen);
1631
1632         return 0;
1633 }
1634
1635 static int nat_field_stored(const char *path, long long file_size,
1636         void *user_data)
1637 {
1638         struct mg_connection *conn = (struct mg_connection *)user_data;
1639         int status;
1640
1641         mg_printf(conn,
1642                   "stored as %s (%lu bytes)\r\n\r\n",
1643                   path,
1644                   (unsigned long)file_size);
1645
1646         /* Process commands in script file */
1647         cgnapt_loadrules_file(pipe_cl->ctx, path);
1648         rules_loaded = 1;
1649
1650         return 0;
1651 }
1652
1653 int nat_load_handler(struct mg_connection *conn, __rte_unused void *cbdata)
1654 {
1655         /* Handler may access the request info using mg_get_request_info */
1656         int ret;
1657         const struct mg_request_info *req_info = mg_get_request_info(conn);
1658         struct mg_form_data_handler fdh = {nat_field_found, nat_field_get,
1659                                  nat_field_stored, 0};
1660
1661         /* It would be possible to check the request info here before calling
1662          * mg_handle_form_request. */
1663         (void)req_info;
1664
1665         mg_printf(conn,
1666                   "HTTP/1.1 200 OK\r\nContent-Type: "
1667                   "text/plain\r\nConnection: close\r\n\r\n");
1668
1669         if (!strcmp(req_info->request_method, "GET")) {
1670                 mg_printf(conn, "Rule file is %s\n", rules_loaded? "LOADED":"NOT LOADED");
1671         }
1672
1673         if (strcmp(req_info->request_method, "PUT")) {
1674                 mg_printf(conn, "Only PUT method allowed");
1675                 return 1;
1676         }
1677
1678         fdh.user_data = (void *)conn;
1679
1680         /* Call the form handler */
1681         mg_printf(conn, "Form data:");
1682         ret = mg_handle_form_request(conn, &fdh);
1683         mg_printf(conn, "\r\n%i fields found", ret);
1684
1685         return 1;
1686 }
1687
1688 void rest_api_cgnapt_init(struct mg_context *ctx, struct app_params *app)
1689 {
1690         myapp = app;
1691
1692         /* vCGNAPT commands */
1693         mg_set_request_handler(ctx, "/vnf/config/nat", nat_handler, 0);
1694         mg_set_request_handler(ctx, "/vnf/config/nat/load", nat_load_handler, 0);
1695         mg_set_request_handler(ctx, "/vnf/status", cgnapt_cmd_ver_handler, 0);
1696         mg_set_request_handler(ctx, "/vnf/stats", cgnapt_stats_handler, 0);
1697
1698 }
1699
1700 static cmdline_parse_inst_t cmd_clear_stats = {
1701          .f = cmd_cgnapt_clear_stats_parsed,
1702          .data = NULL,
1703          .help_str = "CGNAPT clear stats cmd",
1704          .tokens = {
1705                                 (void *)&cmd_cgnapt_clear_stats_p_string,
1706                                 (void *)&cmd_cgnapt_clear_stats_cgnapt_string,
1707                                 (void *)&cmd_cgnapt_clear_stats_clear_string,
1708                                 (void *)&cmd_cgnapt_clear_stats_stats_string,
1709                                 NULL,
1710                                 },
1711 };
1712
1713
1714 static cmdline_parse_ctx_t pipeline_cmds[] = {
1715         (cmdline_parse_inst_t *) &cmd_entry_add,
1716         (cmdline_parse_inst_t *) &cmd_entry_del,
1717         (cmdline_parse_inst_t *) &cmd_entry_ls,
1718         (cmdline_parse_inst_t *) &cmd_entry_dbg,
1719         (cmdline_parse_inst_t *) &cmd_entry_addm,
1720         (cmdline_parse_inst_t *) &cmd_ver,
1721         (cmdline_parse_inst_t *) &cmd_nsp_add,
1722         (cmdline_parse_inst_t *) &cmd_nsp_del,
1723         (cmdline_parse_inst_t *) &cmd_numipcli,
1724         #ifdef PCP_ENABLE
1725         (cmdline_parse_inst_t *) &cmd_pcp,
1726         #endif
1727         (cmdline_parse_inst_t *) &cmd_stats,
1728         (cmdline_parse_inst_t *) &cmd_clear_stats,
1729         NULL,
1730 };
1731
1732 static struct pipeline_fe_ops pipeline_cgnapt_fe_ops = {
1733         .f_init = pipeline_cgnapt_init,
1734         .f_free = app_pipeline_cgnapt_free,
1735         .cmds = pipeline_cmds,
1736 };
1737
1738 struct pipeline_type pipeline_cgnapt = {
1739         .name = "CGNAPT",
1740         .be_ops = &pipeline_cgnapt_be_ops,
1741         .fe_ops = &pipeline_cgnapt_fe_ops,
1742 };