Added support for mis-ordered packets in rapid
[samplevnf.git] / VNFs / vCGNAPT / pipeline / cgnapt_pcp_be.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 #include <rte_mbuf.h>
18 #include "cgnapt_pcp_be.h"
19 #include "pipeline_cgnapt_be.h"
20 #include "pipeline_cgnapt_common.h"
21
22 /**
23  * @file
24  * Pipeline CG-NAPT PCP BE Implementation.
25  *
26  * Implementation of Pipeline CG-NAPT PCP Back End (BE).
27  * Handles PCP requests for both IPv4 & IPv6
28  * Constructs PCP responses for both IPv4 & IPv6
29  * Provides backend CLI support.
30  * Runs on CGNAPT pipeline core
31  *
32  *
33  */
34
35 #ifdef PCP_ENABLE
36
37 uint32_t pcp_lifetime = 60;
38 uint8_t pcp_ipv4_format[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39                                 0x00, 0x00, 0x00, 0x00, 0xff, 0xff };
40 /**
41  * Function to initialize PCP stuff
42  *
43  */
44 enum PCP_RET pcp_init(void)
45 {
46     /* Init of PCP mempool */
47         if (!pcp_pool_init) {
48                 pcp_pool_init = 1;
49                 pcp_mbuf_pool = rte_pktmbuf_pool_create(
50                                 "pcp_mbuf_pool", 64, 32, 0,
51                                 RTE_MBUF_DEFAULT_BUF_SIZE,
52                                 rte_socket_id());
53
54                 if (pcp_mbuf_pool == NULL) {
55                         printf("PCP mbuf pool creation failed\n");
56                         return PCP_INIT_UNSUCCESS;
57                 }
58         }
59         printf("In pcp_init: success\n");
60         return PCP_INIT_SUCCESS;
61 }
62
63 /**
64  * Function to handle PCP CLI commands
65  *
66  * @param p
67  *      Pipieline struct associated with each pipeline
68  * @param msg
69  *      CLI message enqueued by master thread
70  */
71
72 void *pipeline_cgnapt_msg_req_pcp_handler(
73         __rte_unused struct pipeline *p,
74         void *msg)
75 {
76
77         struct pipeline_cgnapt_pcp_msg_rsp *rsp = msg;
78         struct pipeline_cgnapt_pcp_msg_req *req = msg;
79
80         req = msg;
81         rsp->status = 0;
82         if (req->cmd == CGNAPT_PCP_CMD_STATS) {
83                 printf("pcp_success_count:%d\n", pcp_success_count);
84                 printf("pcp_error_count:%d\n", pcp_error_count);
85                 printf("pcp_entry_count:%d\n", pcp_entry_count);
86
87                 return rsp;
88         }
89         if (req->cmd == CGNAPT_PCP_CMD_PCP_ENABLE) {
90                 if (req->lifetime) {
91                         pcp_enable = 1;
92                         printf("PCP option is enabled\n");
93                 } else{
94                         pcp_enable = 0;
95                         printf("PCP option is disabled\n");
96                 }
97                 return rsp;
98         }
99         if (req->cmd == CGNAPT_PCP_CMD_SET_LIFETIME) {
100                 pcp_lifetime = req->lifetime;
101                 printf("pcp_lifetime:%" PRIu32 "\n", pcp_lifetime);
102                 return rsp;
103         }
104         if (req->cmd == CGNAPT_PCP_CMD_GET_LIFETIME) {
105                 printf("pcp_lifetime:%" PRIu32 "\n", pcp_lifetime);
106                 return rsp;
107         }
108
109         printf("CG-NAPT PCP handler called with wrong args %x %x\n",
110                          req->cmd, req->lifetime);
111         printf("\n");
112         return rsp;
113 }
114
115 void clone_data(
116         struct rte_mbuf *rx_pkt,
117         struct rte_mbuf *tx_pkt);
118
119 /**
120  * Function to copy Rx pkt data to Tx pkt data
121  *
122  * @param rx_pkt
123  *  Received PCP pkt
124  * @param tx_pkt
125  *  Transmitting PCP pkt
126  */
127
128 void clone_data(
129         struct rte_mbuf *rx_pkt,
130         struct rte_mbuf *tx_pkt)
131 {
132         char *buf1;
133         char *buf2;
134
135         buf1 = rte_pktmbuf_mtod(rx_pkt, char *);
136         buf2 = rte_pktmbuf_append(tx_pkt, rx_pkt->data_len);
137
138         rte_memcpy(buf2, buf1, rx_pkt->data_len);
139 }
140
141 /**
142  * Function to construct L2,L3,L4 in pkt and to send out
143  *
144  * @param rx_pkt
145  *      Received PCP pkt
146  * @param tx_pkt
147  *      Transmitting PCP pkt
148  * @param ver
149  *      Version of pkt : IPv4 or IPv6
150  * @param p_nat
151  *      A pointer to struct rte_pipeline
152  */
153
154 void construct_pcp_resp(
155         struct rte_mbuf *rx_pkt,
156         struct rte_mbuf *tx_pkt,
157         uint8_t ver, struct rte_pipeline *rte_p)
158 {
159         struct ether_hdr *eth_tx, *eth_rx;
160         struct ipv4_hdr *ipv4_tx, *ipv4_rx;
161         struct ipv6_hdr *ipv6_tx, *ipv6_rx;
162         struct udp_hdr *udp_tx, *udp_rx;
163         struct pcp_resp_hdr *pcp_resp;
164         struct pcp_req_hdr *pcp_req;
165
166         tx_pkt->port = rx_pkt->port;
167
168         if (ver == 4) {
169                 pcp_req = (struct pcp_req_hdr *)
170                                 ((uint8_t *) rx_pkt + IPV4_PCP_OFST);
171                 pcp_resp = (struct pcp_resp_hdr *)
172                                 ((uint8_t *) tx_pkt + IPV4_PCP_OFST);
173         } else {
174                 pcp_req = (struct pcp_req_hdr *)
175                                 ((uint8_t *) rx_pkt + IPV6_PCP_OFST);
176                 pcp_resp = (struct pcp_resp_hdr *)
177                                 ((uint8_t *) tx_pkt + IPV6_PCP_OFST);
178         }
179
180         if (pcp_resp->result_code == PCP_SUCCESS) {
181                 memset(pcp_resp->reserve, 0, 12);
182                 pcp_success_count++;
183         } else {
184                 memcpy(pcp_resp->reserve, &pcp_req->cli_ip[1], 12);
185                 pcp_error_count++;
186         }
187
188         pcp_resp->req_resp = PCP_RESP;
189         pcp_resp->res_unuse = 0x00;
190         /* Epoch time */
191         pcp_resp->epoch_time = rte_bswap32(time(NULL));
192
193         /* swap L2 identities */
194         eth_rx = rte_pktmbuf_mtod(rx_pkt, struct ether_hdr *);
195         eth_tx = rte_pktmbuf_mtod(tx_pkt, struct ether_hdr *);
196
197         memcpy(&eth_tx->s_addr, &eth_rx->d_addr, sizeof(struct ether_addr));
198         memcpy(&eth_tx->d_addr, &eth_rx->s_addr, sizeof(struct ether_addr));
199
200         /* swap L3 identities */
201
202         if (ver == 4) {
203                 ipv4_rx = (struct ipv4_hdr *)((uint8_t *) rx_pkt + IP_OFFSET);
204                 udp_rx = (struct udp_hdr *)((uint8_t *) rx_pkt + IPV4_UDP_OFST);
205
206                 ipv4_tx = (struct ipv4_hdr *)((uint8_t *) tx_pkt + IP_OFFSET);
207                 udp_tx = (struct udp_hdr *)((uint8_t *) tx_pkt + IPV4_UDP_OFST);
208
209                 ipv4_tx->src_addr = ipv4_rx->dst_addr;
210                 ipv4_tx->dst_addr = ipv4_rx->src_addr;
211
212                 /* swap L4 identities */
213
214                 udp_tx->src_port = udp_rx->dst_port;
215                 udp_tx->dst_port = udp_rx->src_port;
216                 udp_tx->dgram_cksum = 0;
217                 udp_tx->dgram_cksum =
218                         rte_ipv4_udptcp_cksum(ipv4_tx, (void *)udp_tx);
219
220                 ipv4_tx->total_length =
221                         rte_cpu_to_be_16(pcp_resp->result_code ==
222                                          PCP_MAP ? IPV4_PCP_MAP_PL_LEN :
223                                          IPV4_PCP_PEER_PL_LEN);
224
225                 ipv4_tx->packet_id = 0xaabb;
226                 ipv4_tx->fragment_offset = 0x0000;
227                 ipv4_tx->time_to_live = 64;
228                 ipv4_tx->next_proto_id = IP_PROTOCOL_UDP;
229                 ipv4_tx->hdr_checksum = 0;
230                 ipv4_tx->hdr_checksum = rte_ipv4_cksum(ipv4_tx);
231
232         } else {
233                 ipv6_rx = (struct ipv6_hdr *)((uint8_t *) rx_pkt + IP_OFFSET);
234                 udp_rx = (struct udp_hdr *)((uint8_t *) rx_pkt + IPV6_UDP_OFST);
235
236                 ipv6_tx = (struct ipv6_hdr *)((uint8_t *) tx_pkt + IP_OFFSET);
237                 udp_tx = (struct udp_hdr *)((uint8_t *) tx_pkt + IPV6_UDP_OFST);
238
239                 memcpy((uint8_t *)&ipv6_tx->src_addr[0],
240                         (uint8_t *)&ipv6_rx->dst_addr[0], 16);
241                 memcpy((uint8_t *)&ipv6_tx->dst_addr[0],
242                         (uint8_t *)&ipv6_rx->src_addr[0], 16);
243
244                 /* swap L4 identities */
245
246                 udp_tx->src_port = udp_rx->dst_port;
247                 udp_tx->dst_port = udp_rx->src_port;
248
249                 udp_tx->dgram_cksum = 0;
250                 udp_tx->dgram_cksum =
251                         rte_ipv6_udptcp_cksum(ipv6_tx, (void *)udp_tx);
252                 ipv6_tx->payload_len =
253                         rte_cpu_to_be_16(pcp_resp->result_code ==
254                                          PCP_MAP ? IPV6_PCP_MAP_PL_LEN :
255                                          IPV6_PCP_PEER_PL_LEN);
256
257                 ipv6_tx->proto = IP_PROTOCOL_UDP;
258                 ipv6_tx->hop_limits = 64;
259         }
260
261         #ifdef PCP_DEBUG
262         rte_hexdump(stdout, "Transferring PCP Pkt", tx_pkt, 400);
263         #endif
264
265         rte_pipeline_port_out_packet_insert(rte_p, tx_pkt->port, tx_pkt);
266 }
267
268 /**
269  * Function to handle PCP requests
270  *
271  * @param rx_pkt
272  *      Received PCP pkt
273  * @param ver
274  *      Version of pkt : IPv4 or IPv6
275  * @param p_nat
276  *      A pointer to struct pipeline_cgnapt
277  */
278
279 void handle_pcp_req(struct rte_mbuf *rx_pkt,
280                                         uint8_t ver,
281                                         void *pipeline_cgnapt_ptr)
282 {
283         struct ipv4_hdr *ipv4 = NULL;
284         struct ipv6_hdr *ipv6 = NULL;
285         struct udp_hdr *udp_rx = NULL;
286         struct pcp_req_hdr *pcp_req = NULL;
287         struct pcp_resp_hdr *pcp_resp = NULL;
288         struct rte_mbuf *tx_pkt = NULL;
289         struct pipeline_cgnapt *p_nat = pipeline_cgnapt_ptr;
290
291         if (pcp_mbuf_pool == NULL)
292                 printf("handle PCP: PCP pool is NULL\n");
293         tx_pkt = rte_pktmbuf_alloc(pcp_mbuf_pool);
294         if (tx_pkt == NULL) {
295                 printf("unable to allocate mem from PCP pool\n");
296                 return;
297         }
298         /* clone the pkt */
299
300         clone_data(rx_pkt, tx_pkt);
301
302         #ifdef PCP_DEBUG
303         rte_hexdump(stdout, "cloned PCP Pkt", tx_pkt, 400);
304         #endif
305
306         if (ver == 4) {
307                 pcp_req = (struct pcp_req_hdr *)
308                                 ((uint8_t *) rx_pkt + IPV4_PCP_OFST);
309                 pcp_resp = (struct pcp_resp_hdr *)
310                                 ((uint8_t *) tx_pkt + IPV4_PCP_OFST);
311                 udp_rx = (struct udp_hdr *)
312                                 ((uint8_t *) rx_pkt + IPV4_UDP_OFST);
313         } else {
314                 pcp_req = (struct pcp_req_hdr *)
315                                 ((uint8_t *) rx_pkt + IPV6_PCP_OFST);
316                 pcp_resp = (struct pcp_resp_hdr *)
317                                 ((uint8_t *) tx_pkt + IPV6_PCP_OFST);
318                 udp_rx = (struct udp_hdr *)
319                                 ((uint8_t *) rx_pkt + IPV6_UDP_OFST);
320         }
321
322         /* Check for all conditions to drop the packet */
323
324         /* Check the PCP version */
325
326         if (pcp_req->ver != 2) {
327                 #ifdef PCP_DEBUG
328                 printf("PCP version mismatch\n");
329                 #endif
330                 pcp_resp->result_code = PCP_UNSUPP_VERSION;
331                 pcp_resp->life_time = rte_bswap32(PCP_LONG_LTIME);
332                 construct_pcp_resp(rx_pkt, tx_pkt, ver, p_nat->p.p);
333                 return;
334         }
335
336         /* If req msg is less than 2 octects */
337
338         if (rte_bswap16(udp_rx->dgram_len) > 1100) {
339                 #ifdef PCP_DEBUG
340                 printf("PCP len > 1000\n");
341                 #endif
342                 pcp_resp->result_code = PCP_MALFORMED_REQUEST;
343                 pcp_resp->life_time = rte_bswap32(PCP_LONG_LTIME);
344                 construct_pcp_resp(rx_pkt, tx_pkt, ver, p_nat->p.p);
345                 return;
346         }
347
348         /* Silently drop the response pkt */
349         if (pcp_req->req_resp == PCP_RESP) {
350                 #ifdef PCP_DEBUG
351                 printf("Its PCP Resp\n");
352                 #endif
353                 return;
354         }
355
356         /* Check for supported PCP opcode */
357
358         if ((pcp_req->opcode != PCP_MAP) && (pcp_req->opcode != PCP_PEER)) {
359                 #ifdef PCP_DEBUG
360                 printf("Neither PCP_MAP not PCP_PEER\n");
361                 #endif
362                 pcp_resp->result_code = PCP_UNSUPP_OPCODE;
363                 printf("result code:%d\n", PCP_UNSUPP_OPCODE);
364                 pcp_resp->life_time = rte_bswap32(PCP_LONG_LTIME);
365                 construct_pcp_resp(rx_pkt, tx_pkt, ver, p_nat->p.p);
366                 return;
367         }
368
369         /* To check whether options are using in PCP */
370
371         {
372                 uint8_t *option =
373                         (uint8_t *) ((uint8_t *) udp_rx + PCP_REQ_RESP_HDR_SZ +
374                                  PCP_MAP_REQ_RESP_SZ);
375                 if (*option) {
376                 #ifdef PCP_DEBUG
377                 printf("No PCP option support\n");
378                 #endif
379                         pcp_resp->result_code = PCP_UNSUPP_OPTION;
380                         pcp_resp->life_time = rte_bswap32(PCP_LONG_LTIME);
381                         construct_pcp_resp(rx_pkt, tx_pkt, ver, p_nat->p.p);
382                         return;
383                 }
384         }
385
386         if (ver == 4) {
387                 ipv4 = (struct ipv4_hdr *)((uint8_t *) rx_pkt + IP_OFFSET);
388                 /* Check whether 3rd party host is requesting */
389                 if (ipv4->src_addr != pcp_req->cli_ip[3]) {
390
391                         #ifdef PCP_DEBUG
392                         printf("PCP client IP & req IP mismatch\n");
393                         #endif
394
395                         printf("src addr:%x req addr:%x\n", ipv4->src_addr,
396                         pcp_req->cli_ip[3]);
397
398                         pcp_resp->result_code = PCP_ADDRESS_MISMATCH;
399                         pcp_resp->life_time = rte_bswap32(PCP_LONG_LTIME);
400                         construct_pcp_resp(rx_pkt, tx_pkt, ver, p_nat->p.p);
401                         return;
402                 }
403
404         } else {
405                 ipv6 = (struct ipv6_hdr *)((uint8_t *) rx_pkt + IP_OFFSET);
406                 /*              5. Check whether 3rd party host is requesting */
407                 if (memcmp(ipv6->src_addr, pcp_req->cli_ip, IPV6_SZ) != 0) {
408                 #ifdef PCP_DEBUG
409                 printf("PCP client IP & req IP mismatch\n");
410                 #endif
411
412                         pcp_resp->result_code = PCP_ADDRESS_MISMATCH;
413                         pcp_resp->life_time = rte_bswap32(PCP_LONG_LTIME);
414                         construct_pcp_resp(rx_pkt, tx_pkt, ver, p_nat->p.p);
415                         return;
416                 }
417         }
418
419         struct pipeline_cgnapt_entry_key key;
420         memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
421         int pos = 0;
422
423         switch (pcp_req->opcode) {
424
425         case PCP_MAP:
426                 {
427                         struct pcp_map_req *map_req;
428                         struct pcp_map_resp *map_resp;
429
430                         /* Not a PCP MAP Request(36) */
431
432                         if ((rte_be_to_cpu_16(udp_rx->dgram_len) -
433                                  sizeof(struct pcp_req_hdr)) <= 35)
434                                 return;
435
436                         if (ver == 4) {
437                                 map_req = (struct pcp_map_req *)
438                                                 ((uint8_t *) rx_pkt +
439                                                 IPV4_PCP_MAP_OFST);
440                                 map_resp = (struct pcp_map_resp *)
441                                                 ((uint8_t *) tx_pkt +
442                                                 IPV4_PCP_MAP_OFST);
443                         } else {
444                                 map_req = (struct pcp_map_req *)
445                                                 ((uint8_t *) rx_pkt +
446                                                 IPV6_PCP_MAP_OFST);
447                                 map_resp = (struct pcp_map_resp *)
448                                                 ((uint8_t *) tx_pkt +
449                                                 IPV6_PCP_MAP_OFST);
450                         }
451
452                         /* 4. Check for supported protocol */
453
454                         if (map_req->protocol != IP_PROTOCOL_TCP &&
455                                 map_req->protocol != IP_PROTOCOL_UDP) {
456                                 #ifdef PCP_DEBUG
457                                 printf("PCP Req is neither TCP nor "
458                                 "UDP protocol\n");
459                                 #endif
460
461                                 pcp_resp->result_code = PCP_UNSUPP_PROTOCOL;
462                                 pcp_resp->life_time =
463                                         rte_bswap32(PCP_LONG_LTIME);
464                                 construct_pcp_resp(rx_pkt, tx_pkt,
465                                         ver, p_nat->p.p);
466                                 return;
467                         }
468
469                         /* Preparing key to search the entry */
470
471                         key.pid = rx_pkt->port;
472                         key.ip = rte_bswap32(pcp_req->cli_ip[3]);
473                         key.port = rte_bswap16(map_req->int_port);
474
475                         #ifdef NAT_ONLY_CONFIG_REQ
476                         if (nat_only_config_flag)
477                                 key.port = 0xffff;
478                         #endif
479
480                         #ifdef PCP_DEBUG
481                         rte_hexdump(stdout, "key", &key,
482                                 sizeof(struct pipeline_cgnapt_entry_key));
483                         #endif
484
485                         pos = rte_hash_lookup(napt_common_table, &key);
486
487                         /* PCP request for deleting the CGNAPT entry */
488                         if (rte_bswap32(pcp_req->life_time) == 0) {
489
490                                 if (pos != -ENOENT) {
491
492                                 long long int time_out;
493                                 time_out =
494                                         napt_hash_tbl_entries[pos].
495                                         data.timeout;
496
497                                 /* Check for PCP entry first */
498                                 if (time_out > 0) {
499                                         rte_hash_del_key
500                                                 (napt_common_table, &key);
501                                         pcp_resp->life_time = 0;
502                                         pcp_resp->result_code =
503                                                 PCP_SUCCESS;
504                                         memset(pcp_resp->reserve, 0, 12);
505                                 #ifdef PCP_DEBUG
506                                 printf("PCP SUCCESS : PCP MAP req for "
507                                 "deleting entry\n");
508                                 #endif
509
510                                 construct_pcp_resp(rx_pkt, tx_pkt,
511                                         ver, p_nat->p.p);
512
513                                 return;
514
515                                 }
516
517                                 if (time_out == STATIC_CGNAPT_TIMEOUT)
518                                         pcp_resp->life_time = 0xffffffff;
519                                 else if (time_out == DYNAMIC_CGNAPT_TIMEOUT)
520                                         pcp_resp->life_time =
521                                         rte_bswap32(PCP_LONG_LTIME);
522
523                                 pcp_resp->result_code = PCP_NOT_AUTHORIZED;
524
525                                 #ifdef PCP_DEBUG
526                                 printf("PCP Failed : Not a PCP request "
527                                 "created entry\n");
528                                 #endif
529
530                                 construct_pcp_resp(rx_pkt, tx_pkt,
531                                         ver, p_nat->p.p);
532                                 return;
533
534                                 } else {
535                                 pcp_resp->life_time = 0;
536                                 pcp_resp->result_code = PCP_SUCCESS;
537                                 memset(pcp_resp->reserve, 0, 12);
538
539                                 #ifdef PCP_DEBUG
540                                 printf("PCP SUCCESS : MAP req entry not "
541                                 "found for deletion\n");
542                                 #endif
543
544                                 construct_pcp_resp(rx_pkt, tx_pkt,
545                                         ver, p_nat->p.p);
546                                 return;
547                                 }
548                         }
549
550                         /* PCP request for adding the CGNAPT entry */
551                         struct cgnapt_table_entry *entry = NULL;
552
553                         if ((pos == -ENOENT)) {
554                                 uint8_t err = 0;
555                                 entry = add_dynamic_cgnapt_entry(&p_nat->p,
556                                         &key,
557                                         rte_bswap32(pcp_req->life_time) <=
558                                                 pcp_lifetime?
559                                         rte_bswap32(pcp_req->life_time):
560                                                 pcp_lifetime,
561                                         ver == 4 ?
562                                         CGNAPT_ENTRY_IPV4 :
563                                         CGNAPT_ENTRY_IPV6,
564                                         ipv6->src_addr, &err);
565                                 /* Ignore klocwork issue in above calling */
566
567                                 /* MAP Err : unable to allocate
568                                 * requested resources
569                                 */
570                                 if (!entry) {
571
572                                         #ifdef PCP_DEBUG
573                                         printf("PCP Failure : unable to "
574                                         "create PCP req entry\n");
575                                         #endif
576
577                                         pcp_resp->result_code =
578                                                 PCP_NO_RESOURCES;
579                                         pcp_resp->life_time =
580                                                 rte_bswap32(PCP_SHORT_LTIME);
581                                         construct_pcp_resp(rx_pkt, tx_pkt,
582                                                 ver, p_nat->p.p);
583                                         return;
584                                 }
585                                 #ifdef PCP_DEBUG
586                                 printf("PCP dynamic entry created "
587                                 "successfully\n");
588                                 #endif
589
590                                 pcp_entry_count++;
591                         } else {
592                                 /* Check whether PCP request created
593                                 * entry or not
594                                 */
595                                 if (napt_hash_tbl_entries[pos].data.
596                                         timeout > 0) {
597
598                                 napt_hash_tbl_entries[pos].
599                                         data.timeout = pcp_lifetime;
600
601                                 struct cgnapt_table_entry *p_entry, *s_entry;
602                                 struct pipeline_cgnapt_entry_key s_key;
603
604                                 p_entry = &napt_hash_tbl_entries[pos];
605                                 entry = &napt_hash_tbl_entries[pos];
606                                 s_key.port = napt_hash_tbl_entries[pos].
607                                                 data.pub_port;
608                                 s_key.ip = napt_hash_tbl_entries[pos].
609                                                 data.pub_ip;
610                                 s_key.pid = napt_hash_tbl_entries[pos].
611                                                 data.pub_phy_port;
612
613                                 /* Getting ingress or second entry
614                                 * from the table
615                                 */
616
617                                 pos = rte_hash_lookup(napt_common_table,
618                                                                 &s_key);
619                                 s_entry = &napt_hash_tbl_entries[pos];
620
621                                 /* Enqueue the info to
622                                 * restart the timer
623                                 */
624                                 timer_thread_enqueue(&key, &s_key,
625                                                 p_entry, s_entry,
626                                                 (struct pipeline *)p_nat);
627
628                         } else {
629                                         // if dynamic
630                                 if (!napt_hash_tbl_entries[pos].
631                                                 data.timeout)
632                                         pcp_resp->life_time =
633                                                 rte_bswap32(PCP_LONG_LTIME);
634                                 else    // if static entry
635                                         pcp_resp->life_time =
636                                                 0xffffffff;
637
638                                 pcp_resp->result_code =
639                                         PCP_NOT_AUTHORIZED;
640
641                                 #ifdef PCP_DEBUG
642                                 printf("PCP Failure : Not authorized "
643                                 "to delete entry\n");
644                                 printf("Not a PCP request "
645                                 "created entry\n");
646                                 #endif
647                                 construct_pcp_resp(rx_pkt, tx_pkt,
648                                         ver, p_nat->p.p);
649                                         return;
650                                 }
651
652                         }
653
654                         /* Fill PCP Resp fields */
655                         pcp_resp->result_code = PCP_SUCCESS;
656
657                         rte_bswap32(pcp_req->life_time) < pcp_lifetime?
658                         (pcp_resp->life_time = pcp_req->life_time):
659                         (pcp_resp->life_time = rte_bswap32(pcp_lifetime));
660
661                         /* Fill PCP MAP Resp fields */
662                         memcpy(map_resp->nonce, map_req->nonce, 12);
663                         map_resp->protocol = map_req->protocol;
664                         map_resp->res_unuse1 = 0;
665                         map_resp->int_port = map_req->int_port;
666
667                         /* Ignore klockwork issue for below stmt */
668                         map_resp->ext_port =
669                                 rte_be_to_cpu_16(entry->data.pub_port);
670                         memcpy(map_resp->ext_ip, pcp_ipv4_format, 12);
671                         map_resp->ext_ip[3] = rte_bswap32(entry->data.pub_ip);
672
673                         construct_pcp_resp(rx_pkt, tx_pkt, ver, p_nat->p.p);
674                         return;
675                 }
676                 break;
677
678         case PCP_PEER:
679                 {
680
681                         /* Not a PCP PEER Request(56) */
682
683                         if ((rte_be_to_cpu_16(udp_rx->dgram_len) -
684                                  sizeof(struct pcp_req_hdr)) <= 55)
685                                 return;
686
687                         struct cgnapt_table_entry *p_entry, *s_entry;
688                         struct pipeline_cgnapt_entry_key s_key;
689
690                         struct pcp_peer_req *peer_req;
691                         struct pcp_peer_resp *peer_resp;
692
693                         peer_req =
694                                 (struct pcp_peer_req *)((uint8_t *) rx_pkt +
695                                                         IPV4_PCP_PEER_OFST);
696                         peer_resp =
697                                 (struct pcp_peer_resp *)((uint8_t *) rx_pkt +
698                                                          IPV4_PCP_PEER_OFST);
699
700                         /* PEER Err : Creation not supporting */
701                         if (pcp_req->life_time == 0) {
702                                 pcp_resp->life_time = 0;
703                                 pcp_resp->result_code = PCP_MALFORMED_REQUEST;
704
705                                 #ifdef PCP_DEBUG
706                                 printf("PCP Failure : PEER creation not "
707                                 "supported\n");
708                                 #endif
709
710                                 construct_pcp_resp(rx_pkt, tx_pkt, ver,
711                                         p_nat->p.p);
712                                 return;
713                         }
714
715                         /* Preparing key to search the entry */
716                         key.pid = rx_pkt->port;
717                         /* For both IPv4 & IPv6, key is last 32 bits
718                         * due to NAT64
719                         */
720                         key.ip = rte_bswap32(pcp_req->cli_ip[3]);
721                         key.port = rte_bswap16(peer_req->int_port);
722
723                         #ifdef NAT_ONLY_CONFIG_REQ
724                         if (nat_only_config_flag)
725                                 key.port = 0xffff;
726                         #endif
727
728                         /* PEER Err : If no requested entry is found */
729                         pos = rte_hash_lookup(napt_common_table, &key);
730                         if (pos == -ENOENT) {
731                                 pcp_resp->life_time =
732                                         rte_bswap32(PCP_LONG_LTIME);
733                                 pcp_resp->result_code = PCP_MALFORMED_REQUEST;
734
735                                 #ifdef PCP_DEBUG
736                                 printf("PCP Failure : unable to find entry\n");
737                                 #endif
738
739                                 construct_pcp_resp(rx_pkt, tx_pkt, ver,
740                                         p_nat->p.p);
741                                 return;
742                         }
743                         /*      If requested created entry */
744
745                         if (napt_hash_tbl_entries[pos].data.
746                                 timeout > 0) {
747
748                         napt_hash_tbl_entries[pos].
749                                 data.timeout = pcp_lifetime;
750
751                         p_entry = &napt_hash_tbl_entries[pos];
752
753                         s_key.port = napt_hash_tbl_entries[pos].
754                                         data.pub_port;
755                         s_key.ip = napt_hash_tbl_entries[pos].
756                                         data.pub_ip;
757                         s_key.pid = napt_hash_tbl_entries[pos].
758                                         data.pub_phy_port;
759
760                         /* Getting ingress or second entry
761                         * from the table
762                         */
763
764                         pos = rte_hash_lookup(napt_common_table,
765                                 &s_key);
766                         s_entry = &napt_hash_tbl_entries[pos];
767
768                         /* Enqueue the info to restart the timer */
769                         timer_thread_enqueue(&key, &s_key,
770                                          p_entry, s_entry,
771                                                  (struct pipeline *)p_nat);
772
773                         } else{
774                                         // dynamic entry
775                                 if (!napt_hash_tbl_entries[pos].data.timeout)
776                                         pcp_resp->life_time =
777                                                 rte_bswap32(PCP_LONG_LTIME);
778                                 else    // if static entry
779                                         pcp_resp->life_time = 0xffffffff;
780
781                                         pcp_resp->result_code =
782                                                 PCP_NOT_AUTHORIZED;
783                                 #ifdef PCP_DEBUG
784                                 printf("PCP Failure : Not a PCP request "
785                                 "created entry\n");
786                                 #endif
787                                 construct_pcp_resp(rx_pkt, tx_pkt, ver,
788                                         p_nat->p.p);
789
790                                 return;
791                         }
792
793                         /* PEER Success */
794                         /* Fill PCP Response */
795                         rte_bswap16(pcp_req->life_time) < pcp_lifetime?
796                         (pcp_resp->life_time = pcp_req->life_time):
797                         (pcp_resp->life_time = rte_bswap32(pcp_lifetime));
798
799                         pcp_resp->result_code = PCP_SUCCESS;
800                         /* Fill PCP PEER Resonse */
801                         memcpy(peer_resp->nonce, peer_req->nonce, 12);
802                         peer_resp->protocol = peer_req->protocol;
803                         peer_resp->res_unuse1 = 0;
804
805                         peer_resp->int_port =
806                                 rte_be_to_cpu_16(peer_req->int_port);
807                         peer_resp->ext_port =
808                                 rte_be_to_cpu_16(peer_req->ext_port);
809                         memcpy(peer_resp->ext_ip, peer_req->ext_ip, 16);
810                         memcpy(peer_resp->ext_ip, pcp_ipv4_format, 12);
811                         peer_resp->ext_ip[3] =
812                                 rte_bswap32(p_entry->data.pub_ip);
813                         peer_resp->rpeer_port =
814                                 rte_be_to_cpu_16(peer_req->rpeer_port);
815                         peer_resp->res_unuse2 = 0x0000;
816                         memcpy(peer_resp->rpeer_ip, peer_req->rpeer_ip, 16);
817                         construct_pcp_resp(rx_pkt, tx_pkt, ver, p_nat->p.p);
818                         return;
819                 }
820         default:
821                 printf("This never hits\n");
822         }
823
824 }
825 #endif