[l2l3 stack] implements new arp state machine & arp buffering
[samplevnf.git] / common / VIL / l2l3_stack / l3fwd_lpm4.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 "l3fwd_common.h"
18 #include "interface.h"
19 #include "l2_proto.h"
20 #include "l3fwd_lpm4.h"
21 #include "l3fwd_lpm6.h"
22 #include "lib_arp.h"
23 #include "lib_icmpv6.h"
24 #include <inttypes.h>
25
26 /* Declare Global variables */
27
28 /* Global for IPV6 */
29 void *lpm4_table; /**< lpm4_table handler */
30
31 /*Hash table for L2 adjacency */
32 struct rte_hash *l2_adj_hash_handle;  /**< l2 adjacency hash table handler */
33 struct rte_hash *fib_path_hash_handle;  /**< fib path hash table handler */
34
35 l3_stats_t stats; /**< L3 statistics */
36
37 /* Global load balancing hash table for ECMP*/
38 uint8_t nh_links[MAX_SUPPORTED_FIB_PATHS][HASH_BUCKET_SIZE] = /**< Round Robin Hash entries for ECMP only*/
39 {
40         /* 1 path, No Load balancing is required */
41         {0},
42
43         /* 2 path */
44         {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
45          0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
46          0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
47          0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1},
48
49         /* 3 path */
50         {0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0,
51          1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1,
52          2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2,
53          0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0},
54
55         /* 4 path */
56         {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
57          0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
58          0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
59          0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3},
60
61         /* 5 path */
62         {0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0,
63          1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1,
64          2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2,
65          3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3},
66
67         /* 6 path */
68         {0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3,
69          4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1,
70          2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5,
71          0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3},
72
73         /* 7 path */
74         {0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1,
75          2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3,
76          4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5,
77          6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0},
78
79         /* 8 path */
80         {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
81          0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
82          0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
83          0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7}
84 };
85
86 #if 0
87 #define META_DATA_OFFSET 128
88
89 #define RTE_PKTMBUF_HEADROOM 128        /* where is this defined ? */
90 #define ETHERNET_START (META_DATA_OFFSET + RTE_PKTMBUF_HEADROOM)
91 #define ETH_HDR_SIZE 14
92 #define IP_START (ETHERNET_START + ETH_HDR_SIZE)
93 #define TCP_START (IP_START + 20)
94
95 static void print_pkt(struct rte_mbuf *pkt)
96 {
97         int i;
98         int size = 14;
99         uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, ETHERNET_START);
100
101         printf("Meta-data:\n");
102         for (i = 0; i < size; i++) {
103                 printf("%02x ", rd[i]);
104                 if ((i & 3) == 3)
105                         printf("\n");
106         }
107         printf("\n");
108         printf("IP and TCP/UDP headers:\n");
109         rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, IP_START);
110         for (i = 0; i < 40; i++) {
111                 printf("%02x ", rd[i]);
112                 if ((i & 3) == 3)
113                         printf("\n");
114         }
115
116 }
117 #endif
118 static struct ip_protocol_type *proto_type[2];
119 int lpm_init(void)
120 {
121
122         /* Initiliaze LPMv4 params */
123         struct rte_table_lpm_params lpm_params = {
124                 .name = "LPMv4",
125                 .n_rules = IPV4_L3FWD_LPM_MAX_RULES,
126                 .number_tbl8s = IPV4_L3FWD_LPM_NUMBER_TBL8S,
127                 .flags = 0,
128                 .entry_unique_size = sizeof(struct fib_info),
129                 .offset = 128,
130         };
131
132         /* Create LPMv4 tables */
133         lpm4_table =
134                         rte_table_lpm_ops.f_create(&lpm_params, rte_socket_id(),
135                                                          sizeof(struct fib_info));
136         if (lpm4_table == NULL) {
137                 printf("Failed to create LPM IPV4 table\n");
138                 return 0;
139         }
140
141         /*Initialize L2 ADJ hash params  */
142         struct rte_hash_parameters l2_adj_ipv4_params = {
143                 .name = "l2_ADJ_HASH",
144                 .entries = 64,
145                 .key_len = sizeof(struct l2_adj_key_ipv4),
146                 .hash_func = rte_jhash,
147                 .hash_func_init_val = 0,
148         };
149
150         /* Create IPv4 L2 Adj Hash tables */
151         l2_adj_hash_handle = rte_hash_create(&l2_adj_ipv4_params);
152
153         if (l2_adj_hash_handle == NULL) {
154                 printf("L2 ADJ rte_hash_create failed\n");
155                 return 0;
156         } else {
157                 printf("l2_adj_hash_handle %p\n\n", (void *)l2_adj_hash_handle);
158         }
159
160         /*Initialize Fib PAth hassh params  */
161         struct rte_hash_parameters fib_path_ipv4_params = {
162                 .name = "FIB_PATH_HASH",
163                 .entries = 64,
164                 .key_len = sizeof(struct fib_path_key_ipv4),
165                 .hash_func = rte_jhash,
166                 .hash_func_init_val = 0,
167         };
168
169         /* Create FIB PATH Hash tables */
170         fib_path_hash_handle = rte_hash_create(&fib_path_ipv4_params);
171
172         if (fib_path_hash_handle == NULL) {
173                 printf("FIB path rte_hash_create failed\n");
174                 return 0;
175         }
176         return 1;
177 }
178
179 int lpm4_table_route_add(struct routing_info *data)
180 {
181
182         struct routing_info *fib = data;
183         struct rte_table_lpm_key lpm_key = {
184                 .ip = fib->dst_ip_addr,
185                 .depth = fib->depth,
186         };
187         uint8_t i;
188         static int Total_route_count;
189         struct fib_info entry;
190         entry.dst_ip_addr = rte_bswap32(fib->dst_ip_addr);
191         entry.depth = fib->depth;
192         entry.fib_nh_size = fib->fib_nh_size;                   /**< For Single Path, greater then 1 for Multipath(ECMP)*/
193
194 #if MULTIPATH_FEAT
195         if (entry.fib_nh_size == 0 || entry.fib_nh_size > MAX_FIB_PATHS)
196 #else
197         if (entry.fib_nh_size != 1)     /**< For Single FIB_PATH */
198 #endif
199         {
200                 printf("Route can't be configured!!, entry.fib_nh_size = %d\n",
201                                          entry.fib_nh_size);
202                 return 0;
203         }
204         /* Populate L2 adj and precomputes l2 encap string */
205 #if MULTIPATH_FEAT
206         for (i = 0; i < entry.fib_nh_size; i++)
207 #else
208         for (i = 0; i < 1; i++)
209 #endif
210         {
211                 struct fib_path *fib_path_addr = NULL;
212
213                 fib_path_addr =
214                                 populate_fib_path(fib->nh_ip_addr[i], fib->out_port[i]);
215                 if (fib_path_addr) {
216
217                         entry.path[i] = fib_path_addr;
218                         printf("Fib info for the Dest IP");
219                         printf(" : %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32
220                                                  "/%" PRIu8
221                                                  " => fib_path Addr: %p, l2_adj Addr: %p\n",
222                                                  (fib->dst_ip_addr & 0xFF000000) >> 24,
223                                                  (fib->dst_ip_addr & 0x00FF0000) >> 16,
224                                                  (fib->dst_ip_addr & 0x0000FF00) >> 8,
225                                                  (fib->dst_ip_addr & 0x000000FF), fib->depth,
226                                                  fib_path_addr,
227                                                  (void *)entry.path[i]->l2_adj_ptr);
228                 } else {
229                         printf("Fib info for the Dest IP :\
230                                         %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 "/%" PRIu8 " => fib_path Addr: NULL \n", (fib->dst_ip_addr & 0xFF000000) >> 24, (fib->dst_ip_addr & 0x00FF0000) >> 16, (fib->dst_ip_addr & 0x0000FF00) >> 8, (fib->dst_ip_addr & 0x000000FF), fib->depth);
231                         entry.path[i] = NULL;                            /**< setting all other fib_paths to NULL */
232                 }
233         }
234
235         int key_found, ret;
236         void *entry_ptr;
237         ret =
238                         rte_table_lpm_ops.f_add(lpm4_table, (void *)&lpm_key, &entry,
239                                                 &key_found, &entry_ptr);
240
241         if (ret != 0) {
242                 printf("Failed to Add IP route\n");
243                 return 0;
244         }
245         Total_route_count++;
246         printf("Total Routed Added : %u, Key_found: %d\n", Total_route_count,
247                                  key_found);
248         printf("Adding Route to LPM table...\n");
249
250         printf("Iterate with Cuckoo Hash table\n");
251         iterate_cuckoo_hash_table();
252         return 1;
253 }
254
255 int lpm4_table_route_delete(uint32_t dst_ip, uint8_t depth)
256 {
257
258         struct rte_table_lpm_key lpm_key = {
259                 .ip = dst_ip,
260                 .depth = depth,
261         };
262
263         int key_found, ret;
264         void *entry = NULL;
265
266         entry = rte_zmalloc(NULL, 512, RTE_CACHE_LINE_SIZE);
267
268         /* Deleting a IP route from LPMv4 table */
269         ret =
270                         rte_table_lpm_ops.f_delete(lpm4_table, &lpm_key, &key_found, entry);
271
272         if (ret) {
273                 printf("Failed to Delete IP route from LPMv4 table\n");
274                 return 0;
275         }
276
277         printf("Deleted route from LPM table (IPv4 Address = %"
278                                  PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32
279                                  "/%u , key_found = %d\n", (lpm_key.ip & 0xFF000000) >> 24,
280                                  (lpm_key.ip & 0x00FF0000) >> 16, (lpm_key.ip & 0x0000FF00) >> 8,
281                                  (lpm_key.ip & 0x000000FF), lpm_key.depth, key_found);
282
283         /* Deleting a L2 Adj entry if refcount is 1, Else decrement Refcount */
284         remove_fib_l2_adj_entry(entry);
285         rte_free(entry);
286         printf("Iterate with Cuckoo Hash table\n");
287         iterate_cuckoo_hash_table();
288         return 1;
289 }
290
291 int
292 lpm4_table_lookup(struct rte_mbuf **pkts_burst, uint16_t nb_pkts,
293                         uint64_t pkts_mask,
294                         l2_phy_interface_t *port_ptr[RTE_PORT_IN_BURST_SIZE_MAX],
295                         uint64_t *hit_mask)
296 {
297
298         struct routing_table_entry *ipv4_entries[RTE_PORT_IN_BURST_SIZE_MAX];
299         uint64_t lookup_hit_mask_ipv4 = 0;
300         int status;
301         uint64_t pkts_key_mask = pkts_mask;
302         uint64_t lookup_miss_mask_ipv4 = pkts_mask;
303
304         static uint64_t sent_count;
305         static uint64_t rcvd_count;
306         rcvd_count += nb_pkts;
307         if (L3FWD_DEBUG) {
308                 printf
309                                 (" Received IPv4 nb_pkts: %u, Rcvd_count: %lu\n, pkts_mask: %p\n",
310                                  nb_pkts, rcvd_count, (void *)pkts_mask);
311         }
312         uint32_t dst_addr_offset =
313                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
314
315         for (; pkts_key_mask;) {
316 /**< Populate key offset in META DATA for all valid pkts */
317                 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_key_mask);
318                 uint64_t pkt_mask = 1LLU << pos;
319                 pkts_key_mask &= ~pkt_mask;
320                 struct rte_mbuf *mbuf = pkts_burst[pos];
321                 uint32_t *lpm_key = NULL;
322                 uint32_t *dst_addr = NULL;
323                 lpm_key = (uint32_t *) RTE_MBUF_METADATA_UINT8_PTR(mbuf, 128);
324                 dst_addr =
325                                 (uint32_t *) RTE_MBUF_METADATA_UINT8_PTR(mbuf,
326                                                                          dst_addr_offset);
327                 *lpm_key = *dst_addr;
328                 if (L3FWD_DEBUG) {
329
330                         printf("Rcvd Pakt (IPv4 Address = %"
331                                                  PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ")\n",
332                                                  (rte_cpu_to_be_32(*lpm_key) & 0xFF000000) >> 24,
333                                                  (rte_cpu_to_be_32(*lpm_key) & 0x00FF0000) >> 16,
334                                                  (rte_cpu_to_be_32(*lpm_key) & 0x0000FF00) >> 8,
335                                                  (rte_cpu_to_be_32(*lpm_key) & 0x000000FF));
336                 }
337         }
338
339         /* Lookup for IP route in LPM table */
340         if (L3FWD_DEBUG)
341                 printf("\nIPV4 Lookup Mask Before = %p\n",
342                                          (void *)lookup_hit_mask_ipv4);
343         status =
344                         rte_table_lpm_ops.f_lookup(lpm4_table, pkts_burst, pkts_mask,
345                                                          &lookup_hit_mask_ipv4,
346                                                          (void **)ipv4_entries);
347
348         if (status) {
349                 printf("LPM Lookup failed for IP route\n");
350                 return 0;
351         }
352
353         lookup_miss_mask_ipv4 = lookup_miss_mask_ipv4 & (~lookup_hit_mask_ipv4);
354         if (L3FWD_DEBUG) {
355                 printf
356                                 ("AFTER lookup_hit_mask_ipv4 = %p, lookup_miss_mask_ipv4 =%p\n",
357                                  (void *)lookup_hit_mask_ipv4,
358                                  (void *)lookup_miss_mask_ipv4);
359         }
360
361         for (; lookup_miss_mask_ipv4;) {
362 /**< Drop packets for lookup_miss_mask */
363                 uint8_t pos = (uint8_t) __builtin_ctzll(lookup_miss_mask_ipv4);
364                 uint64_t pkt_mask = 1LLU << pos;
365                 lookup_miss_mask_ipv4 &= ~pkt_mask;
366                 rte_pktmbuf_free(pkts_burst[pos]);
367                 pkts_burst[pos] = NULL;
368                 stats.nb_l3_drop_pkt++;  /**< Peg the L3 Drop counter */
369                 if (L3FWD_DEBUG)
370                         printf("\n DROP PKT IPV4 Lookup_miss_Mask  = %p\n",
371                                                  (void *)lookup_miss_mask_ipv4);
372         }
373
374         *hit_mask = lookup_hit_mask_ipv4;
375         for (; lookup_hit_mask_ipv4;) {
376 /**< Process the packets for lookup_hit_mask*/
377                 uint8_t pos = (uint8_t) __builtin_ctzll(lookup_hit_mask_ipv4);
378                 uint64_t pkt_mask = 1LLU << pos;
379                 lookup_hit_mask_ipv4 &= ~pkt_mask;
380                 struct rte_mbuf *pkt = pkts_burst[pos];
381
382                 struct fib_info *entry = (struct fib_info *)ipv4_entries[pos];
383
384 #if MULTIPATH_FEAT
385
386                 uint8_t ecmp_path = 0;
387                 ecmp_path = ip_hash_load_balance(pkts_burst[pos]);
388                 uint8_t selected_path = 0;
389                 struct fib_path *fib_path = NULL;
390                 if (((entry->fib_nh_size != 0)
391                                  && (entry->fib_nh_size - 1) < MAX_SUPPORTED_FIB_PATHS)
392                                 && ((ecmp_path != 0) && (ecmp_path - 1) < HASH_BUCKET_SIZE))
393                         selected_path =
394                                         nh_links[entry->fib_nh_size - 1][ecmp_path - 1];
395                 if (selected_path < MAX_FIB_PATHS)
396                         fib_path = entry->path[selected_path];
397                 if (L3FWD_DEBUG) {
398                         printf
399                                         ("Total supported Path :%u, Hashed ECMP Key : %u, selected Fib_path: %u\n",
400                                          entry->fib_nh_size, ecmp_path, selected_path);
401                 }
402 #else
403                 struct fib_path *fib_path = entry->path[0];
404 #endif
405
406                 if (fib_path == NULL) {
407                         rte_pktmbuf_free(pkt);
408                         pkts_burst[pos] = NULL;
409                         stats.nb_l3_drop_pkt++;  /**< Peg the L3 Drop counter */
410                         *hit_mask &= ~pkt_mask; /**< Remove this pkt from port Mask */
411                         if (L3FWD_DEBUG)
412                                 printf
413                                                 ("Fib_path is NULL, ARP has not resolved, DROPPED UNKNOWN PKT\n");
414                         continue;
415                 }
416
417                 if (fib_path->l2_adj_ptr->flags == L2_ADJ_UNRESOLVED) {
418                         if (fib_path->l2_adj_ptr->phy_port->ipv4_list != NULL)
419                                 request_arp(fib_path->l2_adj_ptr->phy_port->
420                                                         pmdid, fib_path->nh_ip);
421
422                         rte_pktmbuf_free(pkts_burst[pos]);
423                         pkts_burst[pos] = NULL;
424                         *hit_mask &= ~pkt_mask; /**< Remove this pkt from port Mask */
425                         if (L3FWD_DEBUG)
426                                 printf
427                                                 ("L2_ADJ_UNRESOLVED, DROPPED UNKNOWN PKT\n");
428                         continue;
429                 }
430
431                 /* extract ip headers and MAC */
432                 uint8_t *eth_dest =
433                                 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
434                 uint8_t *eth_src =
435                                 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
436                 if (L3FWD_DEBUG) {
437                         printf
438                                         ("MAC BEFORE- DST MAC %02x:%02x:%02x:%02x:%02x:%02x, \
439                                         SRC MAC %02x:%02x:%02x:%02x:%02x:%02x \n",
440                                          eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3], eth_dest[4], eth_dest[5], eth_src[0], eth_src[1],
441                                          eth_src[2], eth_src[3], eth_src[4], eth_src[5]);
442                 }
443                 /* Rewrite the packet with L2 string  */
444                 memcpy(eth_dest, fib_path->l2_adj_ptr->l2_string, sizeof(struct ether_addr) * 2);       // For MAC
445                 if (L3FWD_DEBUG) {
446                         int k = 0;
447                         for (k = 0; k < 14; k++) {
448                                 printf("%02x ",
449                                                          fib_path->l2_adj_ptr->l2_string[k]);
450                                 printf("\n");
451                         }
452                         printf
453                                         ("MAC AFTER DST MAC %02x:%02x:%02x:%02x:%02x:%02x, \
454                                         SRC MAC %02x:%02x:%02x:%02x:%02x:%02x\n", eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3], eth_dest[4], eth_dest[5], eth_src[0], eth_src[1], eth_src[2], eth_src[3], eth_src[4], eth_src[5]);
455                 }
456                 port_ptr[pos] = fib_path->l2_adj_ptr->phy_port;
457                 if (L3FWD_DEBUG) {
458                         printf("l3fwd_lookup API!!!!\n");
459                         //print_pkt(pkt);
460                 }
461
462                 sent_count++;
463                 stats.nb_tx_l3_pkt++;
464                 if (L3FWD_DEBUG)
465                         printf
466                                         ("Successfully sent to port %u, sent_count : %lu\n\r",
467                                          fib_path->out_port, sent_count);
468         }
469         return 1;
470 }
471
472 int is_valid_ipv4_pkt(struct ipv4_hdr *pkt, uint32_t link_len)
473 {
474         if (link_len < sizeof(struct ipv4_hdr))
475                 return -1;
476         if (((pkt->version_ihl) >> 4) != 4)
477                 return -1;
478         if ((pkt->version_ihl & 0xf) < 5)
479                 return -1;
480         if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct ipv4_hdr))
481                 return -1;
482         return 0;
483 }
484
485 int
486 get_dest_mac_for_nexthop(uint32_t next_hop_ip,
487                          uint8_t out_phy_port, struct ether_addr *hw_addr)
488 {
489         struct arp_entry_data *arp_data = NULL;
490         struct arp_key_ipv4 arp_key;
491         arp_key.port_id = out_phy_port;
492         arp_key.ip = next_hop_ip;
493
494         arp_data = retrieve_arp_entry(arp_key, DYNAMIC_ARP);
495         if (arp_data == NULL) {
496                 printf("ARP entry is not found for ip %x, port %d\n",
497                                          next_hop_ip, out_phy_port);
498                 return 0;
499         }
500         ether_addr_copy(&arp_data->eth_addr, hw_addr);
501         return 1;
502 }
503
504 struct l2_adj_entry *retrieve_l2_adj_entry(struct l2_adj_key_ipv4 l2_adj_key)
505 {
506         struct l2_adj_entry *ret_l2_adj_data = NULL;
507         l2_adj_key.filler1 = 0;
508         l2_adj_key.filler2 = 0;
509         l2_adj_key.filler3 = 0;
510
511         int ret =
512                         rte_hash_lookup_data(l2_adj_hash_handle, &l2_adj_key,
513                                  (void **)&ret_l2_adj_data);
514         if (ret < 0) {
515                 #ifdef L2L3_DEBUG
516                 printf
517                                 ("L2 Adj hash lookup failed ret %d, EINVAL %d, ENOENT %d\n",
518                                  ret, EINVAL, ENOENT);
519                 #endif
520                 return NULL;
521         } else {
522                 #ifdef L2L3_DEBUG
523                 printf
524                                 ("L2 Adj hash lookup Success, Entry Already Exist ret %d, EINVAL %d, ENOENT %d\n",
525                                  ret, EINVAL, ENOENT);
526                 #endif
527                 return ret_l2_adj_data;
528         }
529 }
530
531 void remove_fib_l2_adj_entry(void *entry)
532 {
533         struct fib_info entry1;
534         memcpy(&entry1, entry, sizeof(struct fib_info));
535
536         struct fib_path *fib_path_addr = entry1.path[0];  /**< For Single path */
537         if (fib_path_addr->refcount > 1) {
538                 printf
539                                 (" BEFORE fib_path entry, nh_ip %x, port %d, refcount %d\n",
540                                  fib_path_addr->nh_ip, fib_path_addr->out_port,
541                                  fib_path_addr->refcount);
542                 fib_path_addr->refcount--;               /**< Just decrement the refcount this entry is still referred*/
543                 printf("AFTER fib_path entry, nh_ip %x, port %d, refcount %d\n",
544                                          fib_path_addr->nh_ip, fib_path_addr->out_port,
545                                          fib_path_addr->refcount);
546         } else {
547 /**< Refcount is 1 so delete both fib_path and l2_adj_entry */
548
549                 struct l2_adj_entry *adj_addr = NULL;
550                 adj_addr = fib_path_addr->l2_adj_ptr;
551
552                 if (adj_addr != NULL) {
553 /** < l2_adj_entry is has some entry in hash table*/
554                         struct l2_adj_key_ipv4 l2_adj_key = {
555                                 .Next_hop_ip = fib_path_addr->nh_ip,
556                                 .out_port_id = fib_path_addr->out_port,
557                         };
558                         #ifdef L3FWD_DEBUG
559                         printf
560                                         (" l2_adj_entry is removed for ip %x, port %d, refcount %d\n",
561                                          l2_adj_key.Next_hop_ip, l2_adj_key.out_port_id,
562                                          adj_addr->refcount);
563                         #endif
564
565                         rte_hash_del_key(l2_adj_hash_handle, &l2_adj_key);
566                         rte_free(adj_addr); /**< free the memory which was allocated for Hash entry */
567                         adj_addr = NULL;
568                 }
569
570                 struct fib_path_key_ipv4 path_key = {
571                         .nh_ip = fib_path_addr->nh_ip,
572                         .out_port = fib_path_addr->out_port,
573                 };
574
575                 printf
576                                 ("fib_path entry is removed for ip %x, port %d, refcount %d\n",
577                                  fib_path_addr->nh_ip, fib_path_addr->out_port,
578                                  fib_path_addr->refcount);
579                 rte_hash_del_key(fib_path_hash_handle, &path_key);
580                 rte_free(fib_path_addr); /**< Free the memory which was allocated for Hash entry*/
581                 fib_path_addr = NULL;
582         }
583 }
584
585 struct l2_adj_entry *populate_l2_adj(uint32_t ipaddr, uint8_t portid)
586 {
587
588         struct l2_adj_key_ipv4 l2_adj_key;
589         l2_adj_key.out_port_id = portid;
590         l2_adj_key.Next_hop_ip = ipaddr;
591         l2_adj_key.filler1 = 0;
592         l2_adj_key.filler2 = 0;
593         l2_adj_key.filler3 = 0;
594
595         struct ether_addr eth_dst;
596         struct l2_adj_entry *adj_data = NULL;
597
598         /* Populate L2 adj if the MAC Address is already present in L2 Adj HAsh Table */
599         adj_data = retrieve_l2_adj_entry(l2_adj_key);
600
601         if (adj_data) {  /**< L2 Adj Entry Exists*/
602
603                 printf
604                                 ("l2_adj_entry exists ip%x, port %d, Refcnt :%u Address :%p\n",
605                                  l2_adj_key.Next_hop_ip, l2_adj_key.out_port_id,
606                                  adj_data->refcount, adj_data);
607                 ether_addr_copy(&adj_data->eth_addr, &eth_dst);
608                 adj_data->refcount++;
609                 printf
610                                 ("l2_adj_entry UPDATED Refcount for NH ip%x, port %d, Refcnt :%u Address :%p\n",
611                                  l2_adj_key.Next_hop_ip, l2_adj_key.out_port_id,
612                                  adj_data->refcount, adj_data);
613                 return adj_data;
614         }
615
616         struct ether_addr eth_src;
617         l2_phy_interface_t *port;
618         //uint16_t ether_type = 0x0800;
619         port = ifm_get_port(portid);
620
621         if (port != NULL) {
622                 memcpy(&eth_src, &port->macaddr, sizeof(struct ether_addr));
623                 unsigned char *p = (unsigned char *)eth_src.addr_bytes;
624                 printf("S-MAC %x:%x:%x:%x:%x:%x\n\r", p[0], p[1], p[2], p[3],
625                                          p[4], p[5]);
626
627                 uint32_t size =
628                                 RTE_CACHE_LINE_ROUNDUP(sizeof(struct l2_adj_entry));
629                 adj_data = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
630                 if (adj_data == NULL) {
631                         printf("L2 Adjacency memory allocation failed !\n");
632                         return NULL;
633                 }
634
635                 adj_data->out_port_id = portid;
636                 adj_data->Next_hop_ip = ipaddr;
637                 adj_data->refcount++;
638
639                 adj_data->phy_port = port;
640                 memset(&adj_data->eth_addr, 0, sizeof(struct ether_addr));
641                 memset(&adj_data->l2_string, 0, 256);
642
643                 /**< Store the received MAC Address in L2 Adj HAsh Table */
644                 rte_hash_add_key_data(l2_adj_hash_handle, &l2_adj_key,
645                                                         adj_data);
646                 #ifdef L2L3_DEBUG
647                 printf
648                                 ("L2 adj data stored in l2_adj_entry hash table,Addr:%p\n",
649                                  adj_data);
650                 #endif
651         } else {
652                 #ifdef L2L3_DEBUG
653                 printf("\n PORT %u IS DOWN...\n", portid);
654                 #endif
655                 return NULL;
656         }
657         /* Query ARP to get L2 Adj */
658         if (get_dest_mac_for_nexthop(ipaddr, portid, &eth_dst)) {
659                 unsigned char *p = (unsigned char *)eth_dst.addr_bytes;
660                 printf
661                                 ("ARP resolution success and stored in l2_adj_entry hash table:D-MAC %x:%x:%x:%x:%x:%x\n\r",
662                                  p[0], p[1], p[2], p[3], p[4], p[5]);
663
664                 memcpy(adj_data->l2_string, &eth_dst, sizeof(struct ether_addr));       //** < Precompute the L2 String encap*/
665                 memcpy(&adj_data->l2_string[6], &eth_src,
666                                          sizeof(struct ether_addr));
667                 //memcpy(&adj_data->l2_string[12], &ether_type, 2);
668
669                 ether_addr_copy(&eth_dst, &adj_data->eth_addr);
670                 adj_data->flags = L2_ADJ_RESOLVED;
671         } else {
672                 adj_data->flags = L2_ADJ_UNRESOLVED;
673                 printf
674                                 (" ARP resolution Failed !! , unable to write in l2_adj_entry\n");
675         }
676         return adj_data;
677 }
678
679 struct fib_path *populate_fib_path(uint32_t nh_ip, uint8_t portid)
680 {
681
682         struct fib_path_key_ipv4 path_key;
683         path_key.out_port = portid;
684         path_key.nh_ip = nh_ip;
685         path_key.filler1 = 0;
686         path_key.filler2 = 0;
687         path_key.filler3 = 0;
688
689         struct fib_path *fib_data = NULL;
690
691         /* Populate fib_path */
692         fib_data = retrieve_fib_path_entry(path_key);
693
694         if (fib_data) {/**< fib_path entry already exists */
695
696                 /* Already present in FIB_PATH cuckoo HAsh Table */
697                 printf
698                                 ("fib_path_entry already exists for NextHop ip: %x, port %d\n, Refcount %u Addr:%p\n",
699                                  fib_data->nh_ip, fib_data->out_port, fib_data->refcount,
700                                  fib_data);
701                 fib_data->refcount++;
702                 fib_data->l2_adj_ptr->refcount++;
703                 printf
704                                 ("fib_path Refcount Updated NextHop :%x , port %u, Refcount %u\n\r",
705                                  fib_data->nh_ip, fib_data->out_port, fib_data->refcount);
706                 return fib_data;
707         } else {
708                 printf("fib_path entry Doesn't Exists.......\n");
709         }
710
711         fib_data = NULL;
712         struct l2_adj_entry *l2_adj_ptr = NULL;
713         l2_adj_ptr = populate_l2_adj(nh_ip, portid);
714
715         if (l2_adj_ptr) {
716
717                 uint32_t size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct fib_path));
718                 fib_data = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
719
720                 fib_data->out_port = portid;
721                 fib_data->nh_ip = nh_ip;
722                 fib_data->refcount++;
723                 fib_data->l2_adj_ptr = l2_adj_ptr;
724
725                 printf("%s: get port details %u %d\n\r", __FUNCTION__, portid,
726                                          __LINE__);
727                 /* Store the received MAC Address in L2 Adj HAsh Table */
728                 int status;
729                 status =
730                                 rte_hash_add_key_data(fib_path_hash_handle, &path_key,
731                                                 fib_data);
732                 if (status) {
733                         printf
734                                         ("fib_path entry addition to hash table FAILED!! NextHop :%x , port %u, Refcount %u\n\r",
735                                          fib_data->nh_ip, fib_data->out_port,
736                                          fib_data->refcount);
737
738                         rte_free(fib_data);
739                 } else {
740                         printf
741                                         ("fib_path entry Added into hash table for the NextHop :%x , port %u, Refcount %u\n\r",
742                                          fib_data->nh_ip, fib_data->out_port,
743                                          fib_data->refcount);
744                         printf
745                                         (" l2_adj_entry Addr: %p, Fib_path Addr: %p, FibPath->l2ADJ Addr:%p \n",
746                                          l2_adj_ptr, fib_data, fib_data->l2_adj_ptr);
747                         printf
748                                         (" ARP resolution success l2_adj_entry Addr: %p, Fib_path Addr: %p \n",
749                                          l2_adj_ptr, fib_data);
750                         return fib_data;
751                 }
752         } else {
753                 printf
754                                 (" ARP resolution failed and unable to write fib path in fib_path cuckoo hash\n");
755         }
756         return NULL;
757 }
758
759 struct fib_path *retrieve_fib_path_entry(struct fib_path_key_ipv4 path_key)
760 {
761         printf("FIB PATH for NExtHOP IP : %x, port :%u\n", path_key.nh_ip,
762                                  path_key.out_port);
763
764         struct fib_path *ret_fib_path_data = NULL;
765         int ret =
766                         rte_hash_lookup_data(fib_path_hash_handle, &path_key,
767                                  (void **)&ret_fib_path_data);
768         if (ret < 0) {
769                 printf
770                                 ("FIB PATH hash lookup Failed!! ret %d, EINVAL %d, ENOENT %d\n",
771                                  ret, EINVAL, ENOENT);
772                 return NULL;
773         } else {
774                 printf("FIB PATH ALREADY Exists for NExtHOP IP: %x, port: %u\n",
775                                          path_key.nh_ip, path_key.out_port);
776                 return ret_fib_path_data;
777         }
778 }
779
780 void iterate_cuckoo_hash_table(void)
781 {
782         const void *next_key;
783         void *next_data;
784         uint32_t iter = 0;
785
786         printf("\n\t\t\t FIB_path Cache table....");
787         printf
788                         ("\n----------------------------------------------------------------");
789         printf("\n\tNextHop IP    Port   Refcount   l2_adj_ptr_addrress\n");
790         printf
791                         ("\n----------------------------------------------------------------\n");
792
793         while (rte_hash_iterate
794                                  (fib_path_hash_handle, &next_key, &next_data, &iter) >= 0) {
795                 struct fib_path *tmp_data = (struct fib_path *)next_data;
796                 struct fib_path_key_ipv4 tmp_key;
797                 memcpy(&tmp_key, next_key, sizeof(tmp_key));
798                 printf("\t %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32
799                                          " \t %u \t %u \t %p\n",
800                                          (tmp_data->nh_ip & 0xFF000000) >> 24,
801                                          (tmp_data->nh_ip & 0x00FF0000) >> 16,
802                                          (tmp_data->nh_ip & 0x0000FF00) >> 8,
803                                          (tmp_data->nh_ip & 0x000000FF), tmp_data->out_port,
804                                          tmp_data->refcount, tmp_data->l2_adj_ptr);
805
806         }
807         iter = 0;
808
809         printf("\n\t\t\t L2 ADJ Cache table.....");
810         printf
811                         ("\n------------------------------------------------------------------------------------");
812         printf
813                         ("\n\tNextHop IP    Port  \t l2 Encap string \t l2_Phy_interface\n");
814         printf
815                         ("\n------------------------------------------------------------------------------------\n");
816
817         while (rte_hash_iterate
818                                  (l2_adj_hash_handle, &next_key, &next_data, &iter) >= 0) {
819                 struct l2_adj_entry *l2_data = (struct l2_adj_entry *)next_data;
820                 struct l2_adj_key_ipv4 l2_key;
821                 memcpy(&l2_key, next_key, sizeof(l2_key));
822                 printf("\t %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32
823                                          "\t %u \t%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x\t%p\n",
824                                          (l2_data->Next_hop_ip & 0xFF000000) >> 24,
825                                          (l2_data->Next_hop_ip & 0x00FF0000) >> 16,
826                                          (l2_data->Next_hop_ip & 0x0000FF00) >> 8,
827                                          (l2_data->Next_hop_ip & 0x000000FF),
828                                          l2_data->out_port_id, l2_data->l2_string[0],
829                                          l2_data->l2_string[1], l2_data->l2_string[2],
830                                          l2_data->l2_string[3], l2_data->l2_string[4],
831                                          l2_data->l2_string[5], l2_data->l2_string[6],
832                                          l2_data->l2_string[7], l2_data->l2_string[8],
833                                          l2_data->l2_string[9], l2_data->l2_string[10],
834                                          l2_data->l2_string[11], l2_data->phy_port);
835         }
836 }
837
838 void print_l3_stats(void)
839 {
840         printf("==============================================\n");
841         printf("\t\t L3 STATISTICS \t\n");
842         printf("==============================================\n");
843         printf(" Num of Received L3 Pkts     : %lu\n", stats.nb_rx_l3_pkt);
844         printf(" Num of Dropped L3 Pkts      : %lu\n", stats.nb_l3_drop_pkt);
845         printf(" Num of Transmitted L3 Pkts  : %lu\n", stats.nb_tx_l3_pkt);
846         printf(" Num of ICMP Pkts Rcvd at L3 : %lu\n", stats.nb_rx_l3_icmp_pkt);
847         printf(" Num of ICMP Pkts Tx to ICMP : %lu\n", stats.nb_tx_l3_icmp_pkt);
848         stats.total_nb_rx_l3_pkt = stats.nb_rx_l3_icmp_pkt + stats.nb_rx_l3_pkt;
849         stats.total_nb_tx_l3_pkt = stats.nb_tx_l3_icmp_pkt + stats.nb_tx_l3_pkt;
850         printf(" Total Num of Rcvd pkts at L3: %lu\n",
851                                  stats.total_nb_rx_l3_pkt);
852         printf(" Total Num of Sent pkts at L3: %lu\n",
853                                  stats.total_nb_tx_l3_pkt);
854 }
855
856 void
857 ip_local_packets_process(struct rte_mbuf **pkt_burst, uint16_t nb_rx,
858                          uint64_t icmp_pkt_mask, l2_phy_interface_t *port)
859 {
860         process_arpicmp_pkt_parse(pkt_burst, nb_rx, icmp_pkt_mask, port);
861 }
862
863 void
864 ip_forward_deliver(struct rte_mbuf **pkt_burst, uint16_t nb_pkts,
865                          uint64_t ipv4_forward_pkts_mask, l2_phy_interface_t *port)
866 {
867         if (L3FWD_DEBUG) {
868                 printf
869                                 ("ip_forward_deliver BEFORE DROP: nb_pkts: %u\n from in_port %u",
870                                  nb_pkts, port->pmdid);
871         }
872         uint64_t pkts_for_process = ipv4_forward_pkts_mask;
873
874         struct ipv4_hdr *ipv4_hdr;
875         l2_phy_interface_t *port_ptr[RTE_PORT_IN_BURST_SIZE_MAX];
876         uint64_t hit_mask = 0;
877
878         for (; pkts_for_process;) {
879 /**< process only valid packets.*/
880                 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_for_process);
881                 uint64_t pkt_mask = 1LLU << pos;   /**< bitmask representing only this packet */
882                 pkts_for_process &= ~pkt_mask;           /**< remove this packet from the mask */
883                 ipv4_hdr =
884                                 rte_pktmbuf_mtod_offset(pkt_burst[pos], struct ipv4_hdr *,
885                                                         sizeof(struct ether_hdr));
886                 /* Make sure the IPv4 packet is valid  */
887                 if (is_valid_ipv4_pkt(ipv4_hdr, pkt_burst[pos]->pkt_len) < 0) {
888                         rte_pktmbuf_free(pkt_burst[pos]);   /**< Drop the Unknown IPv4 Packet */
889                         pkt_burst[pos] = NULL;
890                         ipv4_forward_pkts_mask &= ~(1LLU << pos);  /**< That will clear bit of that position*/
891                         nb_pkts--;
892                         stats.nb_l3_drop_pkt++;
893                 }
894         }
895
896         if (L3FWD_DEBUG) {
897                 printf
898                                 ("\nl3fwd_rx_ipv4_packets_received AFTER DROP: nb_pkts: %u, valid_Pkts_mask :%lu\n",
899                                  nb_pkts, ipv4_forward_pkts_mask);
900         }
901
902         /* Lookup for IP destination in LPMv4 table */
903         lpm4_table_lookup(pkt_burst, nb_pkts, ipv4_forward_pkts_mask, port_ptr,
904                                 &hit_mask);
905
906         for (; hit_mask;) {
907 /**< process only valid packets.*/
908                 uint8_t pos = (uint8_t) __builtin_ctzll(hit_mask);
909                 uint64_t pkt_mask = 1LLU << pos;   /**< bitmask representing only this packet */
910                 hit_mask &= ~pkt_mask;           /**< remove this packet from the mask */
911
912                 port_ptr[pos]->transmit_single_pkt(port_ptr[pos],
913                                                          pkt_burst[pos]);
914         }
915
916 }
917
918 void
919 l3_protocol_type_add(uint8_t protocol_type,
920                                  void (*func) (struct rte_mbuf **, uint16_t, uint64_t,
921                                          l2_phy_interface_t *port))
922 {
923         switch (protocol_type) {
924         case IPPROTO_ICMP:
925                 proto_type[IP_LOCAL] =
926                                 rte_malloc(NULL, sizeof(struct ip_protocol_type),
927                                                  RTE_CACHE_LINE_SIZE);
928                 proto_type[IP_LOCAL]->protocol_type = protocol_type;
929                 proto_type[IP_LOCAL]->func = func;
930                 break;
931
932         case IPPROTO_TCP:       // Time being treared as Remote forwarding
933         case IPPROTO_UDP:
934                 proto_type[IP_REMOTE] =
935                                 rte_malloc(NULL, sizeof(struct ip_protocol_type),
936                                                  RTE_CACHE_LINE_SIZE);
937                 proto_type[IP_REMOTE]->protocol_type = protocol_type;
938                 proto_type[IP_REMOTE]->func = func;
939                 break;
940
941         }
942
943 }
944
945 void l3fwd_rx_ipv4_packets(struct rte_mbuf **m, uint16_t nb_pkts,
946                                  uint64_t valid_pkts_mask, l2_phy_interface_t *port)
947 {
948         if (L3FWD_DEBUG) {
949                 printf
950                                 ("l3fwd_rx_ipv4_packets_received BEFORE DROP: nb_pkts: %u\n from in_port %u",
951                                  nb_pkts, port->pmdid);
952         }
953         uint64_t pkts_for_process = valid_pkts_mask;
954
955         struct ipv4_hdr *ipv4_hdr;
956         uint32_t configure_port_ip = 0;
957         uint64_t icmp_pkts_mask = RTE_LEN2MASK(nb_pkts, uint64_t);
958         uint64_t ipv4_forward_pkts_mask = RTE_LEN2MASK(nb_pkts, uint64_t);
959         uint16_t nb_icmp_pkt = 0;
960         uint16_t nb_l3_pkt = 0;
961
962         if (port->ipv4_list != NULL)
963                 configure_port_ip =
964                                 (uint32_t) (((ipv4list_t *) (port->ipv4_list))->ipaddr);
965
966         for (; pkts_for_process;) {
967 /**< process only valid packets.*/
968                 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_for_process);
969                 uint64_t pkt_mask = 1LLU << pos;   /**< bitmask representing only this packet */
970                 pkts_for_process &= ~pkt_mask;           /**< remove this packet from the mask */
971                 ipv4_hdr =
972                                 rte_pktmbuf_mtod_offset(m[pos], struct ipv4_hdr *,
973                                                         sizeof(struct ether_hdr));
974
975                 if ((ipv4_hdr->next_proto_id == IPPROTO_ICMP)
976                                 && (ipv4_hdr->dst_addr == configure_port_ip)) {
977                         ipv4_forward_pkts_mask &= ~pkt_mask; /**< Its  ICMP, remove this packet from the ipv4_forward_pkts_mask*/
978                         stats.nb_rx_l3_icmp_pkt++;  /**< Increment stats for ICMP PKT */
979                         nb_icmp_pkt++;
980                 } else{         // Forward the packet
981                         icmp_pkts_mask &= ~pkt_mask;  /**< Not ICMP, remove this packet from the icmp_pkts_mask*/
982                         stats.nb_rx_l3_pkt++;
983                         nb_l3_pkt++;    /**< Increment stats for L3 PKT */
984                 }
985         }
986
987         if (icmp_pkts_mask) {
988                 if (L3FWD_DEBUG)
989                         printf
990                                         ("\n RECEiVED LOCAL ICMP PKT at L3...\n PROCESSING ICMP LOCAL PKT...\n");
991                 proto_type[IP_LOCAL]->func(m, nb_icmp_pkt, icmp_pkts_mask,
992                                                  port);
993         }
994
995         if (ipv4_forward_pkts_mask) {
996                 if (L3FWD_DEBUG)
997                         printf
998                                         ("\n RECEIVED L3 PKT, \n\n FORWARDING L3 PKT....\n");
999                 proto_type[IP_REMOTE]->func(m, nb_l3_pkt,
1000                                                         ipv4_forward_pkts_mask, port);
1001         }
1002 }
1003
1004 void
1005 resolve_l2_adj(uint32_t nexthop_ip, uint8_t out_port_id,
1006                                  const struct ether_addr *hw_addr)
1007 {
1008         struct l2_adj_key_ipv4 l2_adj_key = {
1009                 .Next_hop_ip = nexthop_ip,
1010                 .out_port_id = out_port_id,
1011         };
1012         //uint16_t ether_type = 0x0800;
1013
1014         struct l2_adj_entry *adj_data = retrieve_l2_adj_entry(l2_adj_key);
1015
1016         if (adj_data) {  /**< L2 Adj Entry Exists*/
1017
1018                 printf
1019                                 ("l2_adj_entry exists ip%x, port %d, Refcnt :%u Address :%p\n",
1020                                  l2_adj_key.Next_hop_ip, l2_adj_key.out_port_id,
1021                                  adj_data->refcount, adj_data);
1022
1023                 if (adj_data->flags == L2_ADJ_UNRESOLVED
1024                                 || memcmp(hw_addr, &adj_data->eth_addr,
1025                                                 sizeof(struct ether_addr))) {
1026                         memcpy(adj_data->l2_string, hw_addr, sizeof(struct ether_addr));        //** < Precompute the L2 String encap*/
1027                         memcpy(&adj_data->l2_string[6],
1028                                                  &adj_data->phy_port->macaddr,
1029                                                  sizeof(struct ether_addr));
1030                         //memcpy(&adj_data->l2_string[12], &ether_type, 2);
1031
1032                         ether_addr_copy(hw_addr, &adj_data->eth_addr);
1033                         adj_data->flags = L2_ADJ_RESOLVED;
1034                 }
1035
1036                 return;
1037         }
1038
1039         l2_phy_interface_t *port;
1040         port = ifm_get_port(out_port_id);
1041         if (port != NULL) {
1042
1043                 uint32_t size =
1044                                 RTE_CACHE_LINE_ROUNDUP(sizeof(struct l2_adj_entry));
1045                 adj_data = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1046                 if (adj_data == NULL) {
1047                         printf("L2 Adjacency memory allocation failed !\n");
1048                         return;
1049                 }
1050
1051                 adj_data->out_port_id = out_port_id;
1052                 adj_data->Next_hop_ip = nexthop_ip;
1053                 adj_data->phy_port = port;
1054
1055                 memcpy(adj_data->l2_string, hw_addr, sizeof(struct ether_addr));        //** < Precompute the L2 String encap*/
1056                 memcpy(&adj_data->l2_string[6], &adj_data->phy_port->macaddr,
1057                                          sizeof(struct ether_addr));
1058                 //memcpy(&adj_data->l2_string[12], &ether_type, 2);
1059
1060                 ether_addr_copy(hw_addr, &adj_data->eth_addr);
1061                 adj_data->flags = L2_ADJ_RESOLVED;
1062
1063                 rte_hash_add_key_data(l2_adj_hash_handle, &l2_adj_key,
1064                                                         adj_data);
1065                 printf
1066                                 ("L2 adj data stored in l2_adj_entry hash table,Addr:%p\n",
1067                                  adj_data);
1068         } else
1069                 printf("PORT:%u IS DOWN...\n", out_port_id);
1070
1071         return;
1072 }
1073
1074 uint8_t ip_hash_load_balance(struct rte_mbuf *mbuf)
1075 {
1076         uint32_t src_addr_offset =
1077                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
1078         uint32_t dst_addr_offset =
1079                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
1080         uint32_t *dst_addr = NULL;
1081         uint32_t *src_addr = NULL;
1082         src_addr =
1083                         (uint32_t *) RTE_MBUF_METADATA_UINT8_PTR(mbuf, src_addr_offset);
1084         dst_addr =
1085                         (uint32_t *) RTE_MBUF_METADATA_UINT8_PTR(mbuf, dst_addr_offset);
1086
1087         uint32_t hash_key1 = *src_addr; /* STORE SRC IP in key1 variable */
1088         uint32_t hash_key2 = *dst_addr; /* STORE DST IP in key variable */
1089
1090         hash_key1 = hash_key1 ^ hash_key2;      /* XOR With SRC and DST IP, Result is hask_key1 */
1091         hash_key2 = hash_key1;  /* MOVE The result to hask_key2 */
1092
1093         hash_key1 = rotr32(hash_key1, 16);      /* Circular Rotate to 16 bit */
1094         hash_key1 = hash_key1 ^ hash_key2;      /* XOR With Key1 with Key2 */
1095
1096         hash_key2 = hash_key1;  /* MOVE The result to hask_key2 */
1097
1098         hash_key1 = rotr32(hash_key1, 8);       /* Circular Rotate to 8 bit */
1099         hash_key1 = hash_key1 ^ hash_key2;      /* XOR With Key1 with Key2 */
1100
1101         hash_key1 = hash_key1 & (HASH_BUCKET_SIZE - 1); /* MASK the KEY with BUCKET SIZE */
1102         if (L3FWD_DEBUG)
1103                 printf("Hash Result_key: %d, \n", hash_key1);
1104         return hash_key1;
1105 }
1106
1107 uint32_t rotr32(uint32_t value, unsigned int count)
1108 {
1109         const unsigned int mask = (CHAR_BIT * sizeof(value) - 1);
1110         count &= mask;
1111         return (value >> count) | (value << ((-count) & mask));
1112 }
1113
1114 void
1115 ip_local_out_deliver(struct rte_mbuf **pkt_burst, uint16_t nb_rx,
1116                                  uint64_t ipv4_pkts_mask, l2_phy_interface_t *port)
1117 {
1118         ip_forward_deliver(pkt_burst, nb_rx, ipv4_pkts_mask, port);
1119 }