2 // Copyright (c) 2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
26 #include <rte_common.h>
27 #include <rte_malloc.h>
29 #include <rte_byteorder.h>
30 #include <rte_table_stub.h>
31 #include <rte_table_hash.h>
32 #include <rte_pipeline.h>
36 #include <rte_jhash.h>
37 #include <rte_cycles.h>
38 #include <rte_hexdump.h>
39 #include "pipeline_actions_common.h"
40 #include "hash_func.h"
41 #include "vnf_common.h"
42 #include "pipeline_common_be.h"
43 #include "pipeline_arpicmp_be.h"
45 #include "hash_func.h"
46 #include "vnf_common.h"
49 #include"pipeline_common_fe.h"
52 #include "lib_icmpv6.h"
53 #include "interface.h"
58 #define NB_ARPICMP_MBUF 64
59 #define NB_NDICMP_MBUF 64
60 #define IP_VERSION_4 0x40
61 /* default IP header length == five 32-bits words. */
62 #define IP_HDRLEN 0x05
63 #define IP_VHL_DEF (IP_VERSION_4 | IP_HDRLEN)
65 #define is_multicast_ipv4_addr(ipv4_addr) \
66 (((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)
72 static int my_inet_pton_ipv6(int af, const char *src, void *dst);
73 static int inet_pton_ipv6(const char *src, unsigned char *dst);
74 static int inet_pton_ipv4(const char *src, unsigned char *dst);
76 uint8_t vnf_common_arp_lib_init;
77 uint8_t vnf_common_nd_lib_init;
78 uint8_t loadb_pipeline_count;
80 uint32_t ARPICMP_DEBUG;
81 uint32_t NDIPV6_DEBUG;
83 uint32_t arp_route_tbl_index;
84 uint32_t nd_route_tbl_index;
85 uint32_t link_hw_addr_array_idx;
87 uint32_t lib_arp_get_mac_req;
88 uint32_t lib_arp_nh_found;
89 uint32_t lib_arp_no_nh_found;
90 uint32_t lib_arp_arp_entry_found;
91 uint32_t lib_arp_no_arp_entry_found;
92 uint32_t lib_arp_populate_called;
93 uint32_t lib_arp_delete_called;
94 uint32_t lib_arp_duplicate_found;
96 uint32_t lib_nd_get_mac_req;
97 uint32_t lib_nd_nh_found;
98 uint32_t lib_nd_no_nh_found;
99 uint32_t lib_nd_nd_entry_found;
100 uint32_t lib_nd_no_arp_entry_found;
101 uint32_t lib_nd_populate_called;
102 uint32_t lib_nd_delete_called;
103 uint32_t lib_nd_duplicate_found;
105 struct rte_mempool *lib_arp_pktmbuf_tx_pool;
106 struct rte_mempool *lib_nd_pktmbuf_tx_pool;
108 struct rte_mbuf *lib_arp_pkt;
109 struct rte_mbuf *lib_nd_pkt;
111 static struct rte_hash_parameters arp_hash_params = {
115 .key_len = sizeof(struct arp_key_ipv4),
116 .hash_func = rte_jhash,
117 .hash_func_init_val = 0,
120 static struct rte_hash_parameters nd_hash_params = {
124 .key_len = sizeof(struct nd_key_ipv6),
125 .hash_func = rte_jhash,
126 .hash_func_init_val = 0,
129 struct rte_hash *arp_hash_handle;
130 struct rte_hash *nd_hash_handle;
133 /* Shared among all VNFs including LB */
134 struct app_params *myApp;
135 struct rte_pipeline *myP;
136 struct pipeline_arpicmp *gp_arp;
137 uint8_t num_vnf_threads;
141 struct arp_port_address {
146 struct arp_port_address arp_port_addresses[RTE_MAX_ETHPORTS];
148 uint16_t arp_meta_offset;
151 struct pipeline_arpicmp {
153 pipeline_msg_req_handler
154 custom_handlers[PIPELINE_ARPICMP_MSG_REQS];
155 uint64_t receivedPktCount;
156 uint64_t droppedPktCount;
157 uint64_t sentPktCount;
158 uint8_t links_map[PIPELINE_MAX_PORT_IN];
159 uint8_t outport_id[PIPELINE_MAX_PORT_IN];
160 uint8_t pipeline_num;
161 } __rte_cache_aligned;
165 #define MAX_NUM_ARP_ENTRIES 64
166 #define MAX_NUM_ND_ENTRIES 64
169 struct lib_nd_route_table_entry lib_nd_route_table[MAX_ND_RT_ENTRY] = {
170 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
171 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
172 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
173 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
174 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
175 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
176 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
177 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
178 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
179 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
180 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
181 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
182 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
183 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
184 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
185 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
186 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
187 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
188 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
189 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
190 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
191 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
192 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
193 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
194 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
195 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
196 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
197 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
198 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
199 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
200 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
201 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
202 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
203 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
204 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
205 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
206 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
207 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
208 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
209 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
210 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
211 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
212 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
213 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
214 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
215 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
216 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
217 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
218 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
219 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
220 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
221 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
222 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
223 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
224 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
225 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
226 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
227 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
228 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
229 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
230 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
231 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
232 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
233 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }
236 struct lib_arp_route_table_entry lib_arp_route_table[MAX_ARP_RT_ENTRY] = {
237 // {0xac102814, 1, 0xac102814},
238 // {0xac106414, 0, 0xac106414},
275 void pipelines_port_info(void)
277 struct app_params *app = myApp;
279 for (pipeline = 0; pipeline < app->n_pipelines; pipeline++) {
280 printf("*** PIPELINE %d ***\n\n", pipeline);
282 printf("*** OUTPORTs ***\n");
283 for (i = 1; i < app->pipeline_params[pipeline].n_pktq_out;
285 switch (app->pipeline_params[pipeline].pktq_out[i].
287 case APP_PKTQ_OUT_SWQ:
288 printf("pktq_out[%d]:%s\n", i,
289 app->swq_params[app->pipeline_params
291 pktq_out[i].id].name);
293 case APP_PKTQ_OUT_HWQ:
294 printf("pktq_out[%d]:%s\n", i,
295 app->hwq_out_params[app->pipeline_params
300 printf("Not OUT SWQ or HWQ\n");
303 printf("*** INPORTs ***\n");
304 for (i = 0; i < app->pipeline_params[pipeline].n_pktq_in; i++) {
305 switch (app->pipeline_params[pipeline].pktq_in[i]
307 case APP_PKTQ_IN_SWQ:
308 printf("pktq_in[%d]:%s\n", i,
309 app->swq_params[app->pipeline_params
311 pktq_in[i].id].name);
313 case APP_PKTQ_IN_HWQ:
314 printf("pktq_in[%d]:%s\n", i,
315 app->hwq_in_params[app->pipeline_params
317 pktq_in[i].id].name);
320 printf("Not IN SWQ or HWQ\n");
326 void pipelines_map_info(void)
330 printf("PIPELINE_MAX_PORT_IN %d\n", PIPELINE_MAX_PORT_IN);
331 printf("lb_outport_id[%d", lb_outport_id[0]);
332 for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
333 printf(",%d", lb_outport_id[i]);
336 printf("vnf_to_loadb_map[%d", vnf_to_loadb_map[0]);
337 for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
338 printf(",%d", vnf_to_loadb_map[i]);
341 printf("port_to_loadb_map[%d", port_to_loadb_map[0]);
342 for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
343 printf(",%d", port_to_loadb_map[i]);
346 printf("loadb_pipeline_nums[%d", loadb_pipeline_nums[0]);
347 for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
348 printf(",%d", loadb_pipeline_nums[i]);
351 printf("loadb_pipeline[%p", loadb_pipeline[0]);
352 for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
353 printf(",%p", loadb_pipeline[i]);
357 void register_pipeline_Qs(uint8_t pipeline_num, struct pipeline *p)
359 struct rte_port_ethdev_reader *hwq;
360 struct rte_port_ring_writer *out_swq;
361 struct rte_port_ring_reader *in_swq;
362 struct rte_pipeline *rte = p->p;
363 uint8_t port_count = 0;
364 int queue_out = 0xff, queue_in = 0xff;
366 printf("Calling register_pipeline_Qs in PIPELINE%d\n", pipeline_num);
367 for (port_count = 0; port_count < rte->num_ports_out; port_count++) {
369 switch (myApp->pipeline_params[pipeline_num].
370 pktq_out[port_count].type){
372 case APP_PKTQ_OUT_SWQ:
374 if (port_count >= rte->num_ports_in) {
376 /* Dont register ARP output Q */
377 if (rte->num_ports_out % rte->num_ports_in)
378 if (port_count == rte->num_ports_out - 1)
381 temp = ((port_count) % rte->num_ports_in);
383 in_swq = rte->ports_in[temp].h_port;
384 out_swq = rte->ports_out[port_count].h_port;
385 printf("in_swq : %s\n",
388 sscanf(in_swq->ring->name, "SWQ%d",
391 printf("Unable to read SWQ number\n");
394 printf("out_swq: %s\n",
395 out_swq->ring->name);
397 sscanf(out_swq->ring->name, "SWQ%d",
400 printf("Unable to read SWQ number\n");
403 if (queue_in < 128 && queue_out < 128) {
404 SWQ_to_Port_map[queue_out] =
405 SWQ_to_Port_map[queue_in];
406 printf("SWQ_to_Port_map[%d]%d\n", queue_out,
407 SWQ_to_Port_map[queue_out]);
412 switch (myApp->pipeline_params[pipeline_num].
413 pktq_in[port_count].type){
415 case APP_PKTQ_OUT_HWQ:
416 hwq = rte->ports_in[port_count].h_port;
417 out_swq = rte->ports_out[port_count].h_port;
418 printf("out_swq: %s\n",
419 out_swq->ring->name);
421 sscanf(out_swq->ring->name, "SWQ%d",
425 printf("Unable to read SWQ number\n");
428 if (queue_out < 128) {
429 SWQ_to_Port_map[queue_out] = hwq->port_id;
430 printf("SWQ_to_Port_map[%d]%d\n", queue_out,
431 SWQ_to_Port_map[queue_out]);
435 case APP_PKTQ_OUT_SWQ:
436 in_swq = rte->ports_in[port_count].h_port;
437 out_swq = rte->ports_out[port_count].h_port;
438 printf("in_swq : %s\n",
441 sscanf(in_swq->ring->name, "SWQ%d",
444 printf("Unable to read SWQ number\n");
447 printf("out_swq: %s\n",
448 out_swq->ring->name);
450 sscanf(out_swq->ring->name, "SWQ%d",
453 printf("Unable to read SWQ number\n");
456 if (queue_in < 128 && queue_out < 128){
457 SWQ_to_Port_map[queue_out] =
458 SWQ_to_Port_map[queue_in];
459 printf("SWQ_to_Port_map[%d]%d\n", queue_out,
460 SWQ_to_Port_map[queue_out]);
465 printf("This never hits\n");
470 case APP_PKTQ_OUT_HWQ:
471 printf("This is HWQ\n");
475 printf("set_phy_outport_map: This never hits\n");
480 void set_link_map(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
482 struct rte_port_ethdev_writer *hwq;
483 struct rte_port_ring_writer *out_swq;
484 struct rte_pipeline *rte = p->p;
486 uint8_t port_count = 0;
487 int index = 0, queue_out = 0xff;
489 printf("Calling set_link_map in PIPELINE%d\n", pipeline_num);
490 for (port_count = 0; port_count < rte->num_ports_out; port_count++) {
492 switch (myApp->pipeline_params[pipeline_num].
493 pktq_out[port_count].type){
495 case APP_PKTQ_OUT_HWQ:
496 hwq = rte->ports_out[port_count].h_port;
497 map[index++] = hwq->port_id;
498 printf("links_map[%d]:%d\n", index - 1, map[index - 1]);
501 case APP_PKTQ_OUT_SWQ:
502 out_swq = rte->ports_out[port_count].h_port;
503 printf("set_link_map out_swq: %s\n",
504 out_swq->ring->name);
505 int status = sscanf(out_swq->ring->name, "SWQ%d",
508 printf("Unable to read SWQ number\n");
512 if (queue_out < 128) {
513 map[index++] = SWQ_to_Port_map[queue_out];
514 printf("links_map[%s]:%d\n", out_swq->ring->name,
520 printf("set_phy_outport_map: This never hits\n");
525 void set_outport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
527 uint8_t port_count = 0;
528 int queue_out = 0xff, index = 0;
530 struct rte_port_ethdev_writer *hwq;
531 struct rte_port_ring_writer *out_swq;
532 struct rte_pipeline *rte = p->p;
534 printf("\n**** set_outport_id() with pipeline_num:%d ****\n\n",
537 port_count < rte->num_ports_out;
540 switch (myApp->pipeline_params[pipeline_num].
541 pktq_out[port_count].type) {
543 case APP_PKTQ_OUT_HWQ:
544 hwq = rte->ports_out[port_count].h_port;
547 map[hwq->port_id] = index;
548 printf("hwq port_id:%d index:%d\n",
549 hwq->port_id, index);
550 map[hwq->port_id] = index++;
551 printf("hwq port_id:%d index:%d\n",
552 hwq->port_id, index-1);
553 printf("outport_id[%d]:%d\n", index - 1,
558 case APP_PKTQ_OUT_SWQ:
560 /* Dont register ARP output Q */
561 if (port_count >= rte->num_ports_in)
562 if (rte->num_ports_out % rte->num_ports_in)
563 if (port_count == rte->num_ports_out - 1)
565 out_swq = rte->ports_out[port_count].h_port;
566 printf("set_outport_id out_swq: %s\n",
567 out_swq->ring->name);
568 int temp = sscanf(out_swq->ring->name, "SWQ%d",
571 printf("Unable to read SWQ number\n");
575 if (queue_out < 128 && index >= 0) {
576 map[SWQ_to_Port_map[queue_out]] = index++;
577 printf("outport_id[%s]:%d\n", out_swq->ring->name,
578 map[SWQ_to_Port_map[queue_out]]);
589 void set_phy_outport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
591 uint8_t port_count = 0;
594 struct rte_port_ethdev_writer *hwq;
595 struct rte_pipeline *rte = p->p;
597 printf("\n**** set_phy_outport_id() with pipeline_num:%d ****\n\n",
600 port_count < myApp->pipeline_params[pipeline_num].n_pktq_out;
603 switch (myApp->pipeline_params[pipeline_num].
604 pktq_out[port_count].type) {
606 case APP_PKTQ_OUT_HWQ:
607 hwq = rte->ports_out[port_count].h_port;
608 map[hwq->port_id] = index++;
609 printf("outport_id[%d]:%d\n", index - 1,
620 void set_phy_inport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
622 uint8_t port_count = 0;
625 struct rte_port_ethdev_reader *hwq;
626 struct rte_pipeline *rte = p->p;
628 printf("\n**** set_phy_inport_id() with pipeline_num:%d ****\n\n",
631 port_count < myApp->pipeline_params[pipeline_num].n_pktq_in;
634 switch (myApp->pipeline_params[pipeline_num].
635 pktq_in[port_count].type) {
637 case APP_PKTQ_OUT_HWQ:
638 hwq = rte->ports_in[port_count].h_port;
639 map[hwq->port_id] = index++;
640 printf("outport_id[%d]:%d\n", index - 1,
653 uint32_t get_nh(uint32_t ip, uint32_t *port)
656 for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
657 if (((lib_arp_route_table[i].
658 ip & lib_arp_route_table[i].mask) ==
659 (ip & lib_arp_route_table[i].mask))) {
661 *port = lib_arp_route_table[i].port;
663 return lib_arp_route_table[i].nh;
665 if (ARPICMP_DEBUG > 1)
666 printf("No nh match ip 0x%x, port %u, t_ip "
667 "0x%x, t_port %u, mask 0x%x, r1 %x, r2 %x\n",
668 ip, *port, lib_arp_route_table[i].ip,
669 lib_arp_route_table[i].port,
670 lib_arp_route_table[i].mask,
671 (lib_arp_route_table[i].ip &
672 lib_arp_route_table[i].mask),
673 (ip & lib_arp_route_table[i].mask));
675 if (ARPICMP_DEBUG && ip)
676 printf("No NH - ip 0x%x, port %u\n", ip, *port);
677 lib_arp_no_nh_found++;
682 void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[])
685 uint8_t netmask_ipv6[16], netip_nd[16], netip_in[16];
686 uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
687 memset(netmask_ipv6, 0, sizeof(netmask_ipv6));
688 memset(netip_nd, 0, sizeof(netip_nd));
689 memset(netip_in, 0, sizeof(netip_in));
692 for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
694 convert_prefixlen_to_netmask_ipv6(
695 lib_nd_route_table[i].depth,
698 for (k = 0; k < 16; k++) {
699 if (lib_nd_route_table[i].ipv6[k] & netmask_ipv6[k]) {
701 netip_nd[k] = lib_nd_route_table[i].ipv6[k];
705 for (l = 0; l < 16; l++) {
706 if (ipv6[l] & netmask_ipv6[l]) {
708 netip_in[l] = ipv6[l];
712 if ((depthflags == depthflags1)
713 && (memcmp(netip_nd, netip_in,
714 sizeof(netip_nd)) == 0)) {
715 //&& (lib_nd_route_table[i].port == port))
716 *port = lib_nd_route_table[i].port;
719 for (j = 0; j < 16; j++)
720 nhipv6[j] = lib_nd_route_table[i].nhipv6[j];
725 if (NDIPV6_DEBUG > 1)
726 printf("No nh match\n");
730 if (NDIPV6_DEBUG && ipv6)
731 printf("No NH - ip 0x%x, port %u\n", ipv6[0], *port);
732 lib_nd_no_nh_found++;
735 /* Added for Multiport changes*/
736 int get_dest_mac_addr_port(const uint32_t ipaddr,
737 uint32_t *phy_port, struct ether_addr *hw_addr)
739 lib_arp_get_mac_req++;
742 nhip = get_nh(ipaddr, phy_port);
744 if (ARPICMP_DEBUG && ipaddr)
745 printf("ARPICMP no nh found for ip %x, port %d\n",
751 struct arp_entry_data *ret_arp_data = NULL;
752 struct arp_key_ipv4 tmp_arp_key;
753 tmp_arp_key.port_id = *phy_port;/* Changed for Multi Port*/
754 tmp_arp_key.ip = nhip;
756 ret_arp_data = retrieve_arp_entry(tmp_arp_key);
757 if (ret_arp_data == NULL) {
758 if (ARPICMP_DEBUG && ipaddr) {
760 ("ARPICMP no arp entry found for ip %x, port %d\n",
764 lib_arp_no_arp_entry_found++;
765 return ARP_NOT_FOUND;
767 ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
768 lib_arp_arp_entry_found++;
773 int get_dest_mac_address_ipv6(uint8_t ipv6addr[], uint32_t phy_port,
774 struct ether_addr *hw_addr, uint8_t nhipv6[])
776 int i = 0, j = 0, flag = 0;
777 lib_nd_get_mac_req++;
780 get_nh_ipv6(ipv6addr, &phy_port, nhipv6);
781 for (j = 0; j < 16; j++) {
787 if (NDIPV6_DEBUG && ipv6addr)
788 printf("NDIPV6 no nh found for ipv6 "
789 "%02x%02x%02x%02x%02x%02x%02x%02x%02x"
790 "%02x%02x%02x%02x%02x%02x%02x, port %d\n",
791 ipv6addr[0], ipv6addr[1], ipv6addr[2], ipv6addr[3],
792 ipv6addr[4], ipv6addr[5], ipv6addr[6], ipv6addr[7],
793 ipv6addr[8], ipv6addr[9], ipv6addr[10],
794 ipv6addr[11], ipv6addr[12], ipv6addr[13],
795 ipv6addr[14], ipv6addr[15], phy_port);
800 struct nd_entry_data *ret_nd_data = NULL;
801 struct nd_key_ipv6 tmp_nd_key;
802 tmp_nd_key.port_id = phy_port;
804 for (i = 0; i < 16; i++)
805 tmp_nd_key.ipv6[i] = nhipv6[i];
807 ret_nd_data = retrieve_nd_entry(tmp_nd_key);
808 if (ret_nd_data == NULL) {
809 if (NDIPV6_DEBUG && ipv6addr) {
810 printf("NDIPV6 no nd entry found for ip %x, port %d\n",
811 ipv6addr[0], phy_port);
813 lib_nd_no_arp_entry_found++;
816 ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
817 lib_nd_nd_entry_found++;
823 int get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], uint32_t *phy_port,
824 struct ether_addr *hw_addr, uint8_t nhipv6[])
826 int i = 0, j = 0, flag = 0;
827 lib_nd_get_mac_req++;
829 get_nh_ipv6(ipv6addr, phy_port, nhipv6);
830 for (j = 0; j < 16; j++) {
835 if (NDIPV6_DEBUG && ipv6addr)
836 printf("NDIPV6 no nh found for ipv6 "
837 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
838 "%02x%02x%02x%02x%02x%02x, port %d\n",
839 ipv6addr[0], ipv6addr[1], ipv6addr[2], ipv6addr[3],
840 ipv6addr[4], ipv6addr[5], ipv6addr[6], ipv6addr[7],
841 ipv6addr[8], ipv6addr[9], ipv6addr[10],
842 ipv6addr[11], ipv6addr[12], ipv6addr[13],
843 ipv6addr[14], ipv6addr[15], *phy_port);
847 struct nd_entry_data *ret_nd_data = NULL;
848 struct nd_key_ipv6 tmp_nd_key;
849 tmp_nd_key.port_id = *phy_port;
851 for (i = 0; i < 16; i++)
852 tmp_nd_key.ipv6[i] = nhipv6[i];
854 ret_nd_data = retrieve_nd_entry(tmp_nd_key);
855 if (ret_nd_data == NULL) {
856 if (NDIPV6_DEBUG && ipv6addr) {
857 printf("NDIPV6 no nd entry found for ip %x, port %d\n",
858 ipv6addr[0], *phy_port);
860 lib_nd_no_arp_entry_found++;
863 ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
864 lib_nd_nd_entry_found++;
872 struct lib_arp_arp_table_entry {
873 struct rte_pipeline_table_entry head;
877 static const char *arp_op_name(uint16_t arp_op)
879 switch (CHECK_ENDIAN_16(arp_op)) {
880 case (ARP_OP_REQUEST):
881 return "ARP Request";
884 case (ARP_OP_REVREQUEST):
885 return "Reverse ARP Request";
886 case (ARP_OP_REVREPLY):
887 return "Reverse ARP Reply";
888 case (ARP_OP_INVREQUEST):
889 return "Peer Identify Request";
890 case (ARP_OP_INVREPLY):
891 return "Peer Identify Reply";
895 return "Unkwown ARP op";
898 static void print_icmp_packet(struct icmp_hdr *icmp_h)
900 printf(" ICMP: type=%d (%s) code=%d id=%d seqnum=%d\n",
902 (icmp_h->icmp_type == IP_ICMP_ECHO_REPLY ? "Reply" :
903 (icmp_h->icmp_type ==
904 IP_ICMP_ECHO_REQUEST ? "Reqest" : "Undef")), icmp_h->icmp_code,
905 CHECK_ENDIAN_16(icmp_h->icmp_ident),
906 CHECK_ENDIAN_16(icmp_h->icmp_seq_nb));
909 static void print_ipv4_h(struct ipv4_hdr *ip_h)
911 struct icmp_hdr *icmp_h =
912 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
913 printf(" IPv4: Version=%d HLEN=%d Type=%d Length=%d\n",
914 (ip_h->version_ihl & 0xf0) >> 4, (ip_h->version_ihl & 0x0f),
915 ip_h->type_of_service, rte_cpu_to_be_16(ip_h->total_length));
916 if (ip_h->next_proto_id == IPPROTO_ICMP)
917 print_icmp_packet(icmp_h);
920 static void print_arp_packet(struct arp_hdr *arp_h)
922 printf(" ARP: hrd=%d proto=0x%04x hln=%d "
923 "pln=%d op=%u (%s)\n",
924 CHECK_ENDIAN_16(arp_h->arp_hrd),
925 CHECK_ENDIAN_16(arp_h->arp_pro), arp_h->arp_hln,
926 arp_h->arp_pln, CHECK_ENDIAN_16(arp_h->arp_op),
927 arp_op_name(arp_h->arp_op));
929 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER) {
930 printf("incorrect arp_hrd format for IPv4 ARP (%d)\n",
932 } else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4) {
933 printf("incorrect arp_pro format for IPv4 ARP (%d)\n",
935 } else if (arp_h->arp_hln != 6) {
936 printf("incorrect arp_hln format for IPv4 ARP (%d)\n",
938 } else if (arp_h->arp_pln != 4) {
939 printf("incorrect arp_pln format for IPv4 ARP (%d)\n",
942 // print remainder of ARP request
943 printf(" sha=%02X:%02X:%02X:%02X:%02X:%02X",
944 arp_h->arp_data.arp_sha.addr_bytes[0],
945 arp_h->arp_data.arp_sha.addr_bytes[1],
946 arp_h->arp_data.arp_sha.addr_bytes[2],
947 arp_h->arp_data.arp_sha.addr_bytes[3],
948 arp_h->arp_data.arp_sha.addr_bytes[4],
949 arp_h->arp_data.arp_sha.addr_bytes[5]);
950 printf(" sip=%d.%d.%d.%d\n",
951 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 24) & 0xFF,
952 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 16) & 0xFF,
953 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 8) & 0xFF,
954 CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) & 0xFF);
955 printf(" tha=%02X:%02X:%02X:%02X:%02X:%02X",
956 arp_h->arp_data.arp_tha.addr_bytes[0],
957 arp_h->arp_data.arp_tha.addr_bytes[1],
958 arp_h->arp_data.arp_tha.addr_bytes[2],
959 arp_h->arp_data.arp_tha.addr_bytes[3],
960 arp_h->arp_data.arp_tha.addr_bytes[4],
961 arp_h->arp_data.arp_tha.addr_bytes[5]);
962 printf(" tip=%d.%d.%d.%d\n",
963 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 24) & 0xFF,
964 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 16) & 0xFF,
965 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 8) & 0xFF,
966 CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) & 0xFF);
970 static void print_eth(struct ether_hdr *eth_h)
972 printf(" ETH: src=%02X:%02X:%02X:%02X:%02X:%02X",
973 eth_h->s_addr.addr_bytes[0],
974 eth_h->s_addr.addr_bytes[1],
975 eth_h->s_addr.addr_bytes[2],
976 eth_h->s_addr.addr_bytes[3],
977 eth_h->s_addr.addr_bytes[4], eth_h->s_addr.addr_bytes[5]);
978 printf(" dst=%02X:%02X:%02X:%02X:%02X:%02X\n",
979 eth_h->d_addr.addr_bytes[0],
980 eth_h->d_addr.addr_bytes[1],
981 eth_h->d_addr.addr_bytes[2],
982 eth_h->d_addr.addr_bytes[3],
983 eth_h->d_addr.addr_bytes[4], eth_h->d_addr.addr_bytes[5]);
988 print_mbuf(const char *rx_tx, unsigned int portid, struct rte_mbuf *mbuf,
991 struct ether_hdr *eth_h = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
992 struct arp_hdr *arp_h =
993 (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
994 struct ipv4_hdr *ipv4_h =
995 (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
997 printf("%s(%d): on port %d pkt-len=%u nb-segs=%u\n",
998 rx_tx, line, portid, mbuf->pkt_len, mbuf->nb_segs);
1000 switch (rte_cpu_to_be_16(eth_h->ether_type)) {
1001 case ETHER_TYPE_IPv4:
1002 print_ipv4_h(ipv4_h);
1004 case ETHER_TYPE_ARP:
1005 print_arp_packet(arp_h);
1008 printf(" unknown packet type\n");
1014 struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key)
1016 struct arp_entry_data *ret_arp_data = NULL;
1017 arp_key.filler1 = 0;
1018 arp_key.filler2 = 0;
1019 arp_key.filler3 = 0;
1021 int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
1022 (void **)&ret_arp_data);
1025 printf("arp-hash lookup failed ret %d, "
1026 "EINVAL %d, ENOENT %d\n",
1027 ret, EINVAL, ENOENT);
1029 return ret_arp_data;
1037 * Validate if key-value pair already exists in the hash table
1038 * for given key - ND IPv6
1041 struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key)
1043 struct nd_entry_data *ret_nd_data = NULL;
1048 /*Find a nd IPv6 key-data pair in the hash table for ND IPv6 */
1049 int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
1050 (void **)&ret_nd_data);
1053 printf("nd-hash: no lookup Entry Found - "
1054 "ret %d, EINVAL %d, ENOENT %d\n",
1055 ret, EINVAL, ENOENT);
1063 void print_arp_table(void)
1065 const void *next_key;
1069 printf("\tport hw addr status ip addr\n");
1071 while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
1074 struct arp_entry_data *tmp_arp_data =
1075 (struct arp_entry_data *)next_data;
1076 struct arp_key_ipv4 tmp_arp_key;
1077 memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4));
1079 ("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s %d.%d.%d.%d\n",
1080 tmp_arp_data->port, tmp_arp_data->eth_addr.addr_bytes[0],
1081 tmp_arp_data->eth_addr.addr_bytes[1],
1082 tmp_arp_data->eth_addr.addr_bytes[2],
1083 tmp_arp_data->eth_addr.addr_bytes[3],
1084 tmp_arp_data->eth_addr.addr_bytes[4],
1085 tmp_arp_data->eth_addr.addr_bytes[5],
1086 tmp_arp_data->status ==
1087 COMPLETE ? "COMPLETE" : "INCOMPLETE",
1088 (tmp_arp_data->ip >> 24),
1089 ((tmp_arp_data->ip & 0x00ff0000) >> 16),
1090 ((tmp_arp_data->ip & 0x0000ff00) >> 8),
1091 ((tmp_arp_data->ip & 0x000000ff)));
1095 printf("\nARP routing table has %d entries\n", arp_route_tbl_index);
1096 printf("\nIP_Address Mask Port NH_IP_Address\n");
1097 for (i = 0; i < arp_route_tbl_index; i++) {
1098 printf("0x%x 0x%x %d 0x%x\n",
1099 lib_arp_route_table[i].ip,
1100 lib_arp_route_table[i].mask,
1101 lib_arp_route_table[i].port, lib_arp_route_table[i].nh);
1104 printf("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, "
1105 "ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
1106 lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found,
1107 lib_arp_arp_entry_found, lib_arp_no_arp_entry_found,
1108 lib_arp_populate_called, lib_arp_delete_called,
1109 lib_arp_duplicate_found);
1111 printf("ARP table key len is %lu\n", sizeof(struct arp_key_ipv4));
1115 void print_nd_table(void)
1117 const void *next_key;
1120 uint8_t ii = 0, j = 0, k = 0;
1122 printf("\tport hw addr status ip addr\n");
1124 while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
1127 struct nd_entry_data *tmp_nd_data =
1128 (struct nd_entry_data *)next_data;
1129 struct nd_key_ipv6 tmp_nd_key;
1130 memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6));
1131 printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s\n",
1133 tmp_nd_data->eth_addr.addr_bytes[0],
1134 tmp_nd_data->eth_addr.addr_bytes[1],
1135 tmp_nd_data->eth_addr.addr_bytes[2],
1136 tmp_nd_data->eth_addr.addr_bytes[3],
1137 tmp_nd_data->eth_addr.addr_bytes[4],
1138 tmp_nd_data->eth_addr.addr_bytes[5],
1139 tmp_nd_data->status ==
1140 COMPLETE ? "COMPLETE" : "INCOMPLETE");
1141 printf("\t\t\t\t\t\t");
1142 for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) {
1143 printf("%02X%02X ", tmp_nd_data->ipv6[ii],
1144 tmp_nd_data->ipv6[ii + 1]);
1150 printf("\n\nND IPV6 routing table has %d entries\n",
1151 nd_route_tbl_index);
1152 printf("\nIP_Address Depth Port NH_IP_Address\n");
1153 for (i = 0; i < nd_route_tbl_index; i++) {
1156 for (j = 0; j < ND_IPV6_ADDR_SIZE; j += 2) {
1157 printf("%02X%02X ", lib_nd_route_table[i].ipv6[j],
1158 lib_nd_route_table[i].ipv6[j + 1]);
1162 ("\n\t\t\t %d %d\n",
1163 lib_nd_route_table[i].depth, lib_nd_route_table[i].port);
1164 printf("\t\t\t\t\t\t\t\t\t");
1165 for (k = 0; k < ND_IPV6_ADDR_SIZE; k += 2) {
1166 printf("%02X%02X ", lib_nd_route_table[i].nhipv6[k],
1167 lib_nd_route_table[i].ipv6[k + 1]);
1170 printf("\nND IPV6 Stats:\nTotal Queries %u, ok_NH %u, no_NH %u,"
1171 "ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
1172 lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found,
1173 lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
1174 lib_nd_populate_called, lib_nd_delete_called,
1175 lib_nd_duplicate_found);
1176 printf("ND table key len is %lu\n\n", sizeof(struct nd_key_ipv6));
1179 void remove_arp_entry(uint32_t ipaddr, uint8_t portid)
1182 /* need to lock here if multi-threaded... */
1183 /* rte_hash_del_key is not thread safe */
1184 struct arp_key_ipv4 arp_key;
1185 arp_key.port_id = portid;
1186 arp_key.ip = ipaddr;
1187 arp_key.filler1 = 0;
1188 arp_key.filler2 = 0;
1189 arp_key.filler3 = 0;
1191 lib_arp_delete_called++;
1194 printf("remove_arp_entry ip %x, port %d\n", arp_key.ip,
1196 rte_hash_del_key(arp_hash_handle, &arp_key);
1200 void remove_nd_entry_ipv6(uint8_t ipv6addr[], uint8_t portid)
1202 /* need to lock here if multi-threaded */
1203 /* rte_hash_del_key is not thread safe */
1205 struct nd_key_ipv6 nd_key;
1206 nd_key.port_id = portid;
1207 /* arp_key.ip = rte_bswap32(ipaddr); */
1209 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
1210 nd_key.ipv6[i] = ipv6addr[i];
1216 lib_nd_delete_called++;
1219 printf("Deletes rte hash table nd entry for port %d ipv6=",
1221 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2)
1222 printf("%02X%02X ", nd_key.ipv6[i], nd_key.ipv6[i + 1]);
1224 rte_hash_del_key(nd_hash_handle, &nd_key);
1228 populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
1231 /* need to lock here if multi-threaded */
1232 /* rte_hash_add_key_data is not thread safe */
1233 struct arp_key_ipv4 arp_key;
1234 arp_key.port_id = portid;
1235 arp_key.ip = ipaddr;
1236 arp_key.filler1 = 0;
1237 arp_key.filler2 = 0;
1238 arp_key.filler3 = 0;
1240 lib_arp_populate_called++;
1243 printf("populate_arp_entry ip %x, port %d\n", arp_key.ip,
1245 struct arp_entry_data *new_arp_data = retrieve_arp_entry(arp_key);
1247 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1249 printf("arp_entry exists ip%x, port %d\n", arp_key.ip,
1251 lib_arp_duplicate_found++;
1254 new_arp_data = (struct arp_entry_data *)
1255 malloc(sizeof(struct arp_entry_data));
1256 if (new_arp_data == NULL) {
1257 printf("populate_arp_entry:new_arp_data is NULL\n");
1260 new_arp_data->eth_addr = *hw_addr;
1261 new_arp_data->status = INCOMPLETE;
1262 new_arp_data->port = portid;
1263 new_arp_data->ip = ipaddr;
1264 rte_hash_add_key_data(arp_hash_handle, &arp_key, new_arp_data);
1266 if (ARPICMP_DEBUG) {
1267 // print entire hash table
1268 printf("\tARP: table update - hwaddr= "
1269 "%02x:%02x:%02x:%02x:%02x:%02x ip=%d.%d.%d.%d "
1271 new_arp_data->eth_addr.addr_bytes[0],
1272 new_arp_data->eth_addr.addr_bytes[1],
1273 new_arp_data->eth_addr.addr_bytes[2],
1274 new_arp_data->eth_addr.addr_bytes[3],
1275 new_arp_data->eth_addr.addr_bytes[4],
1276 new_arp_data->eth_addr.addr_bytes[5],
1278 ((arp_key.ip & 0x00ff0000) >> 16),
1279 ((arp_key.ip & 0x0000ff00) >> 8),
1280 ((arp_key.ip & 0x000000ff)), portid);
1281 /* print_arp_table(); */
1289 * Install key - data pair in Hash table - From Pipeline Configuration
1293 populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
1297 /* need to lock here if multi-threaded */
1298 /* rte_hash_add_key_data is not thread safe */
1300 struct nd_key_ipv6 nd_key;
1301 nd_key.port_id = portid;
1303 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++ /*i+=2 */)
1304 nd_key.ipv6[i] = ipv6[i];
1311 lib_nd_populate_called++;
1313 /*Validate if key-value pair already
1314 * exists in the hash table for ND IPv6
1316 struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key);
1318 if (new_nd_data && is_same_ether_addr(&new_nd_data->eth_addr,
1322 printf("nd_entry exists port %d ipv6 = ",
1324 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1326 printf("%02X%02X ", nd_key.ipv6[i],
1327 nd_key.ipv6[i + 1]);
1331 lib_nd_duplicate_found++;
1333 printf("nd_entry exists\n");
1337 new_nd_data = (struct nd_entry_data *)
1338 malloc(sizeof(struct nd_entry_data));
1339 if (new_nd_data == NULL) {
1340 printf("populate_nd_entry: new_nd_data is NULL\n");
1343 new_nd_data->eth_addr = *hw_addr;
1344 new_nd_data->status = COMPLETE;
1345 new_nd_data->port = portid;
1348 printf("populate_nd_entry ipv6=");
1350 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++ /*i+=2 */)
1351 new_nd_data->ipv6[i] = ipv6[i];
1354 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1356 printf("%02X%02X ", new_nd_data->ipv6[i],
1357 new_nd_data->ipv6[i + 1]);
1361 /*Add a key-data pair at hash table for ND IPv6 static routing */
1362 rte_hash_add_key_data(nd_hash_handle, &nd_key, new_nd_data);
1365 printf("\n....Added a key-data pair at rte hash table "
1366 "for ND IPv6 static routing\n");
1369 /* print entire hash table */
1370 printf("\tND: table update - hwaddr= "
1371 "%02x:%02x:%02x:%02x:%02x:%02x on port=%d\n",
1372 new_nd_data->eth_addr.addr_bytes[0],
1373 new_nd_data->eth_addr.addr_bytes[1],
1374 new_nd_data->eth_addr.addr_bytes[2],
1375 new_nd_data->eth_addr.addr_bytes[3],
1376 new_nd_data->eth_addr.addr_bytes[4],
1377 new_nd_data->eth_addr.addr_bytes[5], portid);
1379 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1380 new_nd_data->ipv6[i] = ipv6[i];
1381 printf("%02X%02X ", new_nd_data->ipv6[i],
1382 new_nd_data->ipv6[i + 1]);
1392 void print_pkt1(struct rte_mbuf *pkt)
1394 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
1396 printf("\nPacket Contents...\n");
1397 for (i = 0; i < 20; i++) {
1398 for (j = 0; j < 20; j++)
1399 printf("%02x ", rd[(20 * i) + j]);
1404 struct ether_addr broadcast_ether_addr = {
1405 .addr_bytes[0] = 0xFF,
1406 .addr_bytes[1] = 0xFF,
1407 .addr_bytes[2] = 0xFF,
1408 .addr_bytes[3] = 0xFF,
1409 .addr_bytes[4] = 0xFF,
1410 .addr_bytes[5] = 0xFF,
1413 static const struct ether_addr null_ether_addr = {
1414 .addr_bytes[0] = 0x00,
1415 .addr_bytes[1] = 0x00,
1416 .addr_bytes[2] = 0x00,
1417 .addr_bytes[3] = 0x00,
1418 .addr_bytes[4] = 0x00,
1419 .addr_bytes[5] = 0x00,
1422 #define MAX_NUM_MAC_ADDRESS 16
1423 struct ether_addr link_hw_addr[MAX_NUM_MAC_ADDRESS] = {
1424 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc8} },
1425 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1426 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1427 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1428 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1429 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1430 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1431 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1432 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1433 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1434 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1435 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1436 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1437 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1438 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1439 {.addr_bytes = {0x18, 0x19, 0x1a, 0x1b, 0xcd, 0xef} }
1442 struct ether_addr *get_link_hw_addr(uint8_t out_port)
1444 return &link_hw_addr[out_port];
1448 request_icmp_echo(unsigned int port_id, uint32_t ip, struct ether_addr *gw_addr)
1450 struct ether_hdr *eth_h;
1451 struct ipv4_hdr *ip_h;
1452 struct icmp_hdr *icmp_h;
1454 struct app_link_params *link;
1455 link = &myApp->link_params[port_id];
1456 arp_port_addresses[port_id].ip = link->ip;
1457 arp_port_addresses[port_id].mac_addr = link->mac_addr;
1459 struct rte_mbuf *icmp_pkt = lib_arp_pkt;
1460 if (icmp_pkt == NULL) {
1462 printf("Error allocating icmp_pkt rte_mbuf\n");
1466 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
1467 ether_addr_copy(gw_addr, ð_h->d_addr);
1468 ether_addr_copy((struct ether_addr *)
1469 &arp_port_addresses[port_id].mac_addr, ð_h->s_addr);
1470 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
1472 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1473 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1475 ip_h->version_ihl = IP_VHL_DEF;
1476 ip_h->type_of_service = 0;
1477 ip_h->total_length =
1478 rte_cpu_to_be_16(sizeof(struct ipv4_hdr) + sizeof(struct icmp_hdr));
1479 ip_h->packet_id = 0xaabb;
1480 ip_h->fragment_offset = 0x0000;
1481 ip_h->time_to_live = 64;
1482 ip_h->next_proto_id = IPPROTO_ICMP;
1483 ip_h->src_addr = rte_bswap32(arp_port_addresses[port_id].ip);
1484 ip_h->dst_addr = ip;
1486 ip_h->hdr_checksum = 0;
1487 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
1489 icmp_h->icmp_type = IP_ICMP_ECHO_REQUEST;
1490 icmp_h->icmp_code = 0;
1491 icmp_h->icmp_ident = 0xdead;
1492 icmp_h->icmp_seq_nb = 0xbeef;
1494 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
1497 sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
1498 sizeof(struct icmp_hdr);
1499 icmp_pkt->data_len = icmp_pkt->pkt_len;
1501 if (ARPICMP_DEBUG) {
1502 printf("Sending echo request\n");
1503 print_mbuf("TX", port_id, icmp_pkt, __LINE__);
1506 rte_pipeline_port_out_packet_insert(gp_arp->p.p,
1507 gp_arp->outport_id[port_id], icmp_pkt);
1508 gp_arp->sentPktCount++;
1511 void request_echo(unsigned int port_id, uint32_t ip)
1516 struct ether_addr gw_addr;
1517 uint32_t dest_ip = rte_bswap32(ip);
1520 if (get_dest_mac_addr_port(dest_ip, &phy_port, &gw_addr) == ARP_FOUND) {
1521 request_icmp_echo(phy_port, ip, &gw_addr);
1526 printf("Sending echo request ... get mac failed.\n");
1529 void request_arp(uint8_t port_id, uint32_t ip, struct rte_pipeline *rte_p)
1534 struct ether_hdr *eth_h;
1535 struct arp_hdr *arp_h;
1537 struct app_link_params *link;
1538 link = &myApp->link_params[port_id];
1539 arp_port_addresses[port_id].ip = link->ip;
1540 arp_port_addresses[port_id].mac_addr = link->mac_addr;
1542 struct rte_mbuf *arp_pkt = lib_arp_pkt;
1544 if (arp_pkt == NULL) {
1546 printf("Error allocating arp_pkt rte_mbuf\n");
1550 eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
1552 ether_addr_copy(&broadcast_ether_addr, ð_h->d_addr);
1553 ether_addr_copy((struct ether_addr *)
1554 &arp_port_addresses[port_id].mac_addr, ð_h->s_addr);
1555 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
1557 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1558 arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
1559 arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
1560 arp_h->arp_hln = ETHER_ADDR_LEN;
1561 arp_h->arp_pln = sizeof(uint32_t);
1562 arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
1564 ether_addr_copy((struct ether_addr *)
1565 &arp_port_addresses[port_id].mac_addr,
1566 &arp_h->arp_data.arp_sha);
1567 arp_h->arp_data.arp_sip =
1568 rte_cpu_to_be_32(arp_port_addresses[port_id].ip);
1569 ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
1570 arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
1571 printf("arp tip:%x arp sip :%x\n", arp_h->arp_data.arp_tip,
1572 arp_h->arp_data.arp_sip);
1573 /* mmcd changed length from 60 to 42 -
1574 * real length of arp request, no padding on ethernet needed -
1575 * looks now like linux arp
1578 arp_pkt->pkt_len = 42;
1579 arp_pkt->data_len = 42;
1581 if (ARPICMP_DEBUG) {
1582 printf("Sending arp request\n");
1583 print_mbuf("TX", port_id, arp_pkt, __LINE__);
1586 rte_pipeline_port_out_packet_insert(rte_p, port_id, arp_pkt);
1587 gp_arp->sentPktCount++;
1591 void request_arp_wrap(uint8_t port_id, uint32_t ip)
1593 request_arp(port_id, ip, gp_arp->p.p);
1596 void process_arpicmp_pkt(
1597 struct rte_mbuf *pkt,
1601 uint8_t in_port_id = pkt->port;
1602 struct app_link_params *link;
1603 struct ether_hdr *eth_h;
1604 struct arp_hdr *arp_h;
1605 struct ipv4_hdr *ip_h;
1606 struct icmp_hdr *icmp_h;
1612 eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
1614 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) {
1616 (struct arp_hdr *)((char *)eth_h +
1617 sizeof(struct ether_hdr));
1618 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER)
1620 ("Invalid hardware format of hardware address - "
1621 "not processing ARP req\n");
1622 else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4)
1624 ("Invalid protocol address format - "
1625 "not processing ARP req\n");
1626 else if (arp_h->arp_hln != 6)
1628 ("Invalid hardware address length - "
1629 "not processing ARP req\n");
1630 else if (arp_h->arp_pln != 4)
1632 ("Invalid protocol address length - "
1633 "not processing ARP req\n");
1635 link = &myApp->link_params[in_port_id];
1636 arp_port_addresses[in_port_id].ip = link->ip;
1637 arp_port_addresses[in_port_id].mac_addr =
1640 if (arp_h->arp_data.arp_tip !=
1641 rte_bswap32(arp_port_addresses[in_port_id].ip)) {
1643 ("ARP requested IP address mismatches "
1644 "interface IP - discarding\n");
1645 printf("arp_tip = %x\n",
1646 arp_h->arp_data.arp_tip);
1647 printf("arp_port_addresses = %x\n",
1648 arp_port_addresses[in_port_id].ip);
1649 printf("in_port_id = %x\n", in_port_id);
1650 printf("arp_port_addresses[0] = %x\n",
1651 arp_port_addresses[0].ip);
1653 rte_pipeline_ah_packet_drop(gp_arp->p.p,
1655 gp_arp->droppedPktCount++;
1658 /* revise conditionals to allow processing of
1659 * requests with target ip = this ip and
1660 * processing of replies to destination ip = this ip
1662 else if (arp_h->arp_op ==
1663 rte_cpu_to_be_16(ARP_OP_REQUEST)) {
1665 if (ARPICMP_DEBUG) {
1666 printf("arp_op %d, ARP_OP_REQUEST %d\n",
1668 rte_cpu_to_be_16(ARP_OP_REQUEST));
1669 print_mbuf("RX", in_port_id, pkt, __LINE__);
1672 populate_arp_entry((struct ether_addr *)
1673 &arp_h->arp_data.arp_sha,
1675 (arp_h->arp_data.arp_sip),
1679 req_tip = arp_h->arp_data.arp_tip;
1680 ether_addr_copy(ð_h->s_addr, ð_h->d_addr);
1682 // set sender mac address -
1683 ether_addr_copy((struct ether_addr *)&
1684 arp_port_addresses[in_port_id].mac_addr,
1687 arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
1688 ether_addr_copy(ð_h->s_addr,
1689 &arp_h->arp_data.arp_sha);
1690 arp_h->arp_data.arp_tip =
1691 arp_h->arp_data.arp_sip;
1692 arp_h->arp_data.arp_sip = req_tip;
1693 ether_addr_copy(ð_h->d_addr,
1694 &arp_h->arp_data.arp_tha);
1696 rte_pipeline_port_out_packet_insert(gp_arp->p.p,
1698 gp_arp->sentPktCount++;
1700 } else if (arp_h->arp_op ==
1701 rte_cpu_to_be_16(ARP_OP_REPLY)) {
1702 // TODO: be sure that ARP request
1703 //was actually sent!!!
1704 if (ARPICMP_DEBUG) {
1705 printf("ARP_OP_REPLY received");
1706 print_mbuf("RX", in_port_id, pkt,
1709 populate_arp_entry((struct ether_addr *)
1710 &arp_h->arp_data.arp_sha,
1715 /* To drop the packet from LB */
1716 rte_pipeline_ah_packet_drop(gp_arp->p.p,
1718 gp_arp->droppedPktCount++;
1722 printf("Invalid ARP opcode - not "
1723 "processing ARP req %x\n",
1729 (struct ipv4_hdr *)((char *)eth_h +
1730 sizeof(struct ether_hdr));
1732 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1734 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
1736 link = &myApp->link_params[in_port_id];
1737 arp_port_addresses[in_port_id].ip = link->ip;
1738 arp_port_addresses[in_port_id].mac_addr =
1741 if (!is_same_ether_addr((struct ether_addr *)
1742 &arp_port_addresses[in_port_id].
1743 mac_addr, ð_h->d_addr)) {
1746 printf("Ethernet frame not destined "
1747 "for MAC address of received network "
1748 "interface - discarding\n");
1750 } else if (ip_h->next_proto_id != IPPROTO_ICMP) {
1752 printf("IP protocol ID is not set to "
1753 "ICMP - discarding\n");
1755 } else if ((ip_h->version_ihl & 0xf0) != IP_VERSION_4) {
1757 printf("IP version other than 4 - "
1760 } else if ((ip_h->version_ihl & 0x0f) != IP_HDRLEN) {
1762 printf("Unknown IHL - discarding\n");
1765 if (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST
1766 && icmp_h->icmp_code == 0) {
1768 print_mbuf("RX", in_port_id,
1771 ip_addr = ip_h->src_addr;
1772 ether_addr_copy(ð_h->s_addr,
1774 ether_addr_copy((struct ether_addr *)
1776 [in_port_id].mac_addr,
1779 if (ip_h->dst_addr !=
1780 rte_bswap32(arp_port_addresses
1782 if (ARPICMP_DEBUG) {
1783 printf("IPv4 packet not destined for "
1784 "configured IP on RX port - "
1786 printf("ip_h->dst_addr = %u, "
1788 "arp_port_addresses.ip = %u\n",
1789 ip_h->dst_addr, in_port_id,
1790 arp_port_addresses[in_port_id].ip);
1794 if (is_multicast_ipv4_addr
1798 ip_src = rte_be_to_cpu_32
1800 if ((ip_src & 0x00000003) == 1)
1810 rte_cpu_to_be_32(ip_src);
1811 ip_h->dst_addr = ip_addr;
1813 ip_h->hdr_checksum = 0;
1814 ip_h->hdr_checksum = ~rte_raw_cksum(
1818 ip_h->src_addr = ip_h->dst_addr;
1819 ip_h->dst_addr = ip_addr;
1824 cksum = ~icmp_h->icmp_cksum & 0xffff;
1825 cksum += ~htons(IP_ICMP_ECHO_REQUEST << 8) & 0xffff;
1826 cksum += htons(IP_ICMP_ECHO_REPLY << 8);
1827 cksum = (cksum & 0xffff) + (cksum >> 16);
1828 cksum = (cksum & 0xffff) + (cksum >> 16);
1829 icmp_h->icmp_cksum = ~cksum;
1832 print_mbuf("TX", in_port_id, pkt, __LINE__);
1834 rte_pipeline_port_out_packet_insert(gp_arp->p.p,
1836 gp_arp->sentPktCount++;
1840 else if (icmp_h->icmp_type == IP_ICMP_ECHO_REPLY
1841 && icmp_h->icmp_code == 0) {
1843 print_mbuf("RX", in_port_id,
1846 struct arp_key_ipv4 arp_key;
1847 arp_key.port_id = in_port_id;
1849 rte_bswap32(ip_h->src_addr);
1850 arp_key.filler1 = 0;
1851 arp_key.filler2 = 0;
1852 arp_key.filler3 = 0;
1854 struct arp_entry_data *arp_entry =
1855 retrieve_arp_entry(arp_key);
1856 if (arp_entry == NULL) {
1857 printf("Received unsolicited "
1858 "ICMP echo reply from ip%x, "
1865 arp_entry->status = COMPLETE;
1866 /* To drop the packet from LB */
1867 rte_pipeline_ah_packet_drop(gp_arp->p.p,
1869 gp_arp->droppedPktCount++;
1879 * inet_pton(af, src, dst)
1880 * convert from presentation format (which usually means ASCII printable)
1881 * to network format (which is usually some kind of binary format).
1883 * 1 if the address was valid for the specified address family
1884 * 0 if the address wasn't valid (`dst' is untouched in this case)
1885 * -1 if some other error occurred (`dst' is untouched in this case, too)
1889 static int my_inet_pton_ipv6(int af, const char *src, void *dst)
1893 return inet_pton_ipv4(src, dst);
1895 return inet_pton_ipv6(src, dst);
1897 errno = EAFNOSUPPORT;
1904 * inet_pton_ipv4(src, dst)
1905 * like inet_aton() but without all the hexadecimal and shorthand.
1907 * 1 if `src' is a valid dotted quad, else 0.
1909 * does not touch `dst' unless it's returning 1.
1913 static int inet_pton_ipv4(const char *src, unsigned char *dst)
1915 static const char digits[] = "0123456789";
1916 int saw_digit, octets, ch;
1917 unsigned char tmp[INADDRSZ], *tp;
1922 while ((ch = *src++) != '\0') {
1925 pch = strchr(digits, ch);
1927 unsigned int new = *tp * 10 + (pch - digits);
1936 *tp = (unsigned char)new;
1937 } else if (ch == '.' && saw_digit) {
1948 memcpy(dst, tmp, INADDRSZ);
1953 * inet_pton_ipv6(src, dst)
1954 * convert presentation level address to network order binary form.
1956 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1958 * (1) does not touch `dst' unless it's returning 1.
1959 * (2) :: in a full address is silently ignored.
1961 * inspired by Mark Andrews.
1965 static int inet_pton_ipv6(const char *src, unsigned char *dst)
1967 static const char xdigits_l[] = "0123456789abcdef",
1968 xdigits_u[] = "0123456789ABCDEF";
1969 unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
1970 const char *xdigits = 0, *curtok = 0;
1971 int ch = 0, saw_xdigit = 0, count_xdigit = 0;
1972 unsigned int val = 0;
1973 unsigned int dbloct_count = 0;
1975 memset((tp = tmp), '\0', IN6ADDRSZ);
1976 endp = tp + IN6ADDRSZ;
1978 /* Leading :: requires some special handling. */
1983 saw_xdigit = count_xdigit = 0;
1986 while ((ch = *src++) != '\0') {
1989 pch = strchr((xdigits = xdigits_l), ch);
1991 pch = strchr((xdigits = xdigits_u), ch);
1993 if (count_xdigit >= 4)
1996 val |= (pch - xdigits);
2010 } else if (*src == '\0') {
2013 if (tp + sizeof(int16_t) > endp)
2015 *tp++ = (unsigned char)((val >> 8) & 0xff);
2016 *tp++ = (unsigned char)(val & 0xff);
2023 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
2024 inet_pton_ipv4(curtok, tp) > 0) {
2028 break; /* '\0' was seen by inet_pton4(). */
2033 if (tp + sizeof(int16_t) > endp)
2035 *tp++ = (unsigned char)((val >> 8) & 0xff);
2036 *tp++ = (unsigned char)(val & 0xff);
2039 if (colonp != NULL) {
2040 /* if we already have 8 double octets,
2041 * having a colon means error
2043 if (dbloct_count == 8)
2047 * Since some memmove()'s erroneously fail to handle
2048 * overlapping regions, we'll do the shift by hand.
2050 const int n = tp - colonp;
2053 for (i = 1; i <= n; i++) {
2054 endp[-i] = colonp[n - i];
2061 memcpy(dst, tmp, IN6ADDRSZ);
2066 * Function to classify ICMPv6 Packets based on NextHeader field in IPv6 Header.
2067 * Updates ND Cache table with link layer addresses as received from Neighbor.
2068 * Processes ICMPv6 Echo destined to local port and replys.
2071 * A pointer to the packet received from Loadbalancer pipeline
2073 * A pointer to the output port action
2083 struct rte_mbuf *pkt,
2085 __rte_unused uint32_t pkt_num)
2088 uint8_t in_port_id = pkt->port;
2089 struct app_link_params *link;
2090 struct ether_hdr *eth_h;
2091 struct ipv6_hdr *ipv6_h;
2092 struct icmpv6_hdr *icmpv6_h;
2093 struct icmpv6_nd_hdr *icmpv6_nd_h;
2094 uint8_t ipv6_addr[16];
2095 uint8_t i = 0, flag = 1;
2096 uint8_t req_tipv6[16];
2098 eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
2099 ipv6_h = (struct ipv6_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
2101 (struct icmpv6_hdr *)((char *)ipv6_h + sizeof(struct ipv6_hdr));
2102 struct rte_mbuf *icmpv6_pkt = pkt;
2104 link = &myApp->link_params[in_port_id];
2105 icmpv6_port_addresses[in_port_id].mac_addr = link->mac_addr;
2107 if (!is_same_ether_addr
2108 ((struct ether_addr *)&icmpv6_port_addresses[in_port_id].mac_addr,
2110 if (ARPICMP_DEBUG) {
2111 printf("Ethernet frame not destined for MAC address "
2112 "of received network interface - discarding\n");
2115 if ((icmpv6_h->icmpv6_type == ICMPV6_ECHO_REQUEST)
2116 && (icmpv6_h->icmpv6_code == 0)) {
2117 for (i = 0; i < 16; i++)
2118 ipv6_addr[i] = ipv6_h->src_addr[i];
2120 for (i = 0; i < 16; i++) {
2121 if (ipv6_h->dst_addr[i] !=
2122 icmpv6_port_addresses[in_port_id].ipv6[i]) {
2127 printf("IPv6 packet not destined for "
2128 "configured IP on RX port - discarding\n");
2132 ether_addr_copy(ð_h->s_addr,
2134 ether_addr_copy((struct ether_addr *)
2135 &icmpv6_port_addresses
2136 [in_port_id].mac_addr,
2139 for (i = 0; i < 16; i++)
2140 ipv6_h->src_addr[i] =
2141 ipv6_h->dst_addr[i];
2142 for (i = 0; i < 16; i++)
2143 ipv6_h->dst_addr[i] =
2146 icmpv6_h->icmpv6_type =
2149 rte_pipeline_port_out_packet_insert
2150 (gp_arp->p.p, out_port, icmpv6_pkt);
2151 gp_arp->sentPktCount++;
2155 } else if ((icmpv6_h->icmpv6_type == ICMPV6_ECHO_REPLY)
2156 && (icmpv6_h->icmpv6_code == 0)) {
2157 struct nd_key_ipv6 nd_key;
2158 nd_key.port_id = in_port_id;
2160 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2161 nd_key.ipv6[i] = ipv6_h->src_addr[i];
2167 /* Validate if key-value pair already
2168 * exists in the hash table for ND IPv6
2170 struct nd_entry_data *new_nd_data =
2171 retrieve_nd_entry(nd_key);
2173 if (new_nd_data == NULL) {
2174 printf("Received unsolicited ICMPv6 echo "
2175 "reply on port %d\n",
2177 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
2178 printf("%02X%02X ", nd_key.ipv6[i],
2179 nd_key.ipv6[i + 1]);
2184 new_nd_data->status = COMPLETE;
2187 if ((icmpv6_h->icmpv6_type == ICMPV6_NEIGHBOR_SOLICITATION)
2188 && (icmpv6_h->icmpv6_code == 0)) {
2191 (struct icmpv6_nd_hdr *)((char *)icmpv6_h +
2192 sizeof(struct icmpv6_hdr));
2193 struct ether_addr *src_hw_addr = ð_h->s_addr;
2194 uint8_t src_ipv6[16], dst_ipv6[16];
2196 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2197 src_ipv6[i] = ipv6_h->src_addr[i];
2198 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2199 dst_ipv6[i] = ipv6_h->dst_addr[i];
2201 // Check for Multicast Address
2203 && ((dst_ipv6[0] << 8) | dst_ipv6[1]))) {
2204 if (populate_nd_entry
2205 (src_hw_addr, src_ipv6, in_port_id)) {
2207 //build a Neighbor Advertisement message
2208 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2210 icmpv6_nd_h->target_ipv6[i];
2212 ether_addr_copy(ð_h->s_addr,
2214 ether_addr_copy((struct ether_addr *)
2215 &icmpv6_port_addresses
2216 [in_port_id].mac_addr,
2219 // set sender mac address
2220 ether_addr_copy(ð_h->s_addr,
2222 link_layer_address);
2223 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2224 ipv6_h->dst_addr[i] =
2225 ipv6_h->src_addr[i];
2226 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2227 ipv6_h->src_addr[i] =
2229 icmpv6_h->icmpv6_type =
2230 ICMPV6_NEIGHBOR_ADVERTISEMENT;
2232 e_Target_Link_Layer_Address;
2233 icmpv6_nd_h->icmpv6_reserved |=
2235 (NEIGHBOR_SOLICITATION_SET);
2237 rte_pipeline_port_out_packet_insert
2238 (gp_arp->p.p, out_port, icmpv6_pkt);
2239 gp_arp->sentPktCount++;
2242 if (ARPICMP_DEBUG) {
2243 printf("Non-Multicasted Neighbor "
2244 "Solicitation Message Received, "
2245 "can't do Address Resolution\n");
2246 printf("............Some one else "
2247 "is the target host here !!!\n");
2252 if ((icmpv6_h->icmpv6_type == ICMPV6_NEIGHBOR_ADVERTISEMENT)
2253 && (icmpv6_h->icmpv6_code == 0)) {
2254 struct ether_addr *src_hw_addr = ð_h->s_addr;
2256 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2257 ipv6[i] = ipv6_h->src_addr[i];
2259 if (populate_nd_entry(src_hw_addr, ipv6, in_port_id))
2261 printf("Now on, unicast IPv6 traffic "
2263 // Now on, unicast IPv6 traffic is possible
2265 if (ARPICMP_DEBUG) {
2266 printf("ICMPv6 Type %d Not Supported yet !!!\n",
2267 icmpv6_h->icmpv6_type);
2275 void request_icmpv6_echo(uint32_t port_id, uint8_t ipv6[])
2281 struct ether_addr gw_addr;
2283 uint8_t dest_ipv6[16];
2286 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2287 dest_ipv6[i] = ipv6[i];
2289 if (get_dest_mac_address_ipv6_port(dest_ipv6, &phy_port,
2290 &gw_addr, nhipv6)) {
2291 request_icmpv6_echo_message(phy_port, ipv6, &gw_addr);
2296 printf("Sending icmpv6 echo request ... get mac failed.\n");
2300 request_icmpv6_echo_message(uint16_t port_id, uint8_t ipv6[],
2301 struct ether_addr *gw_addr)
2303 struct ether_hdr *eth_h;
2304 struct ipv6_hdr *ipv6_h;
2305 struct icmpv6_hdr *icmpv6_h;
2306 struct icmpv6_info_hdr *icmpv6_info_h;
2308 struct app_link_params *link;
2309 link = &mylink[port_id];
2311 for (i = 0; i < 16; i++)
2312 icmpv6_port_addresses[port_id].ipv6[i] = link->ipv6[i];
2314 icmpv6_port_addresses[port_id].mac_addr = link->mac_addr;
2316 struct rte_mbuf *icmpv6_pkt = lib_icmpv6_pkt;
2317 if (icmpv6_pkt == NULL) {
2319 printf("Error allocating icmpv6_pkt rte_mbuf\n");
2323 eth_h = rte_pktmbuf_mtod(icmpv6_pkt, struct ether_hdr *);
2324 ether_addr_copy(gw_addr, ð_h->d_addr);
2325 ether_addr_copy((struct ether_addr *)&icmpv6_port_addresses[port_id].
2326 mac_addr, ð_h->s_addr);
2327 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv6);
2329 ipv6_h = (struct ipv6_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
2331 (struct icmpv6_hdr *)((char *)ipv6_h + sizeof(struct ipv6_hdr));
2333 (struct icmpv6_info_hdr *)((char *)icmpv6_h +
2334 sizeof(struct icmpv6_hdr));
2336 ipv6_h->vtc_flow = 0x60000000;
2337 ipv6_h->payload_len = 64;
2339 ipv6_h->hop_limits = 64;
2341 for (i = 0; i < 16; i++) {
2342 ipv6_h->src_addr[i] = icmpv6_port_addresses[port_id].ipv6[i];
2343 ipv6_h->dst_addr[i] = ipv6[i];
2346 icmpv6_h->icmpv6_type = ICMPV6_ECHO_REQUEST;
2347 icmpv6_h->icmpv6_code = 0;
2348 icmpv6_info_h->icmpv6_ident = 0x5151;
2349 icmpv6_info_h->icmpv6_seq_nb = 0x1;
2351 icmpv6_h->icmpv6_cksum =
2352 ~rte_raw_cksum(icmpv6_h, sizeof(struct icmpv6_hdr));
2354 icmpv6_pkt->pkt_len =
2355 sizeof(struct ether_hdr) + sizeof(struct ipv6_hdr) +
2356 sizeof(struct icmpv6_hdr);
2357 icmpv6_pkt->data_len = icmpv6_pkt->pkt_len;
2360 printf("Sending icmpv6 echo request\n");
2362 rte_pipeline_port_out_packet_insert(gp_arp->p.p,
2363 gp_arp->outport_id[port_id],
2366 gp_arp->sentPktCount++;
2372 static void *pipeline_arpicmp_msg_req_custom_handler(struct pipeline *p,
2375 static pipeline_msg_req_handler handlers[] = {
2376 [PIPELINE_MSG_REQ_PING] =
2377 pipeline_msg_req_ping_handler,
2378 [PIPELINE_MSG_REQ_STATS_PORT_IN] =
2379 pipeline_msg_req_stats_port_in_handler,
2380 [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
2381 pipeline_msg_req_stats_port_out_handler,
2382 [PIPELINE_MSG_REQ_STATS_TABLE] =
2383 pipeline_msg_req_stats_table_handler,
2384 [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
2385 pipeline_msg_req_port_in_enable_handler,
2386 [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
2387 pipeline_msg_req_port_in_disable_handler,
2388 [PIPELINE_MSG_REQ_CUSTOM] =
2389 pipeline_arpicmp_msg_req_custom_handler,
2393 static void *pipeline_arpicmp_msg_req_entry_dbg_handler(struct pipeline *p,
2395 static void *pipeline_arpicmp_msg_req_entry_dbg_handler(
2396 __rte_unused struct pipeline *p,
2397 __rte_unused void *msg)
2399 /*have to handle dbg commands*/
2403 static __rte_unused pipeline_msg_req_handler custom_handlers[] = {
2404 [PIPELINE_ARPICMP_MSG_REQ_ENTRY_DBG] =
2405 pipeline_arpicmp_msg_req_entry_dbg_handler,
2409 * Function for pipeline custom handlers
2412 * A void pointer to pipeline
2414 * void pointer for incoming data
2417 * void pointer of response
2419 void *pipeline_arpicmp_msg_req_custom_handler(struct pipeline *p, void *msg)
2421 struct pipeline_arpicmp *p_arp = (struct pipeline_arpicmp *)p;
2422 struct pipeline_custom_msg_req *req = msg;
2423 pipeline_msg_req_handler f_handle;
2425 f_handle = (req->subtype < PIPELINE_ARPICMP_MSG_REQS) ?
2426 p_arp->custom_handlers[req->subtype] :
2427 pipeline_msg_req_invalid_handler;
2429 if (f_handle == NULL)
2430 f_handle = pipeline_msg_req_invalid_handler;
2432 return f_handle(p, req);
2437 /* Not needed as no arguments are needed for TxRX
2438 * ARP arguments are handled in ARP module
2441 pipeline_arpicmp_parse_args(struct pipeline_arpicmp *p,
2442 struct pipeline_params *params);
2444 pipeline_arpicmp_parse_args(
2445 __rte_unused struct pipeline_arpicmp *p,
2446 struct pipeline_params *params)
2450 uint32_t arp_meta_offset_present = 0;
2452 uint32_t arp_route_tbl_present = 0;
2453 uint32_t nd_route_tbl_present = 0;
2454 uint32_t ports_mac_list_present = 0;
2455 uint32_t pktq_in_prv_present = 0;
2456 uint32_t prv_to_pub_map_present = 0;
2458 uint8_t n_prv_in_port = 0;
2459 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
2460 in_port_dir_a[i] = 0; //make all RX ports ingress initially
2461 prv_to_pub_map[i] = 0xff;
2462 pub_to_prv_map[i] = 0xff;
2465 for (i = 0; i < params->n_args; i++) {
2466 char *arg_name = params->args_name[i];
2467 char *arg_value = params->args_value[i];
2469 if (ARPICMP_DEBUG > 2) {
2470 printf("ARP args[%d]: %s %d, %s\n", i, arg_name,
2471 atoi(arg_value), arg_value);
2473 if (strcmp(arg_name, "arp_meta_offset") == 0) {
2474 if (arp_meta_offset_present) {
2475 printf("arp_meta_offset "
2476 "initialized already\n");
2479 arp_meta_offset_present = 1;
2480 arp_meta_offset = atoi(arg_value);
2484 if (strcmp(arg_name, "pktq_in_prv") == 0) {
2485 if (pktq_in_prv_present) {
2486 printf("Duplicate pktq_in_prv ... "
2487 "parse failed..\n\n");
2490 pktq_in_prv_present = 1;
2492 int rxport = 0, j = 0;
2493 char phy_port_num[5];
2494 char *token = strtok(arg_value, "RXQ");
2497 while ((j < 4) && (token[j] != '.')) {
2498 phy_port_num[j] = token[j];
2501 phy_port_num[j] = '\0';
2502 rxport = atoi(phy_port_num);
2503 printf("token: %s, phy_port_str: %s, "
2504 "phy_port_num %d\n",
2505 token, phy_port_num, rxport);
2507 prv_in_port_a[n_prv_in_port++] = rxport;
2508 // set rxport egress
2509 if(rxport < PIPELINE_MAX_PORT_IN)
2510 in_port_dir_a[rxport] = 1;
2511 token = strtok(NULL, "RXQ");
2514 if (n_prv_in_port == 0) {
2516 ("VNF common parse error - "
2517 "no prv RX phy port\n");
2523 /* prv_to_pub_map */
2524 if (strcmp(arg_name, "prv_to_pub_map") == 0) {
2525 if (prv_to_pub_map_present) {
2527 ("Duplicated prv_to_pub_map ... "
2528 "parse failed ...\n");
2531 prv_to_pub_map_present = 1;
2533 int rxport = 0, txport = 0, j = 0, k = 0;
2534 char rx_phy_port_num[5];
2535 char tx_phy_port_num[5];
2536 char *token = strtok(arg_value, "(");
2539 while ((j < 4) && (token[j] != ',')) {
2540 rx_phy_port_num[j] = token[j];
2543 rx_phy_port_num[j] = '\0';
2544 rxport = atoi(rx_phy_port_num);
2548 while ((k < 4) && (token[j + k] != ')')) {
2549 tx_phy_port_num[k] = token[j + k];
2552 tx_phy_port_num[k] = '\0';
2553 txport = atoi(tx_phy_port_num);
2554 if (rxport < PIPELINE_MAX_PORT_IN && txport < PIPELINE_MAX_PORT_IN){
2556 "rx_phy_port_str: %s, phy_port_num %d,"
2557 "tx_phy_port_str: %s, tx_phy_port_num %d\n",
2558 token, rx_phy_port_num, rxport,
2559 tx_phy_port_num, txport);
2563 if ((rxport >= PIPELINE_MAX_PORT_IN) ||
2564 (txport >= PIPELINE_MAX_PORT_IN) ||
2565 (in_port_dir_a[rxport] != 1)) {
2566 printf("CG-NAPT parse error - "
2567 "incorrect prv-pub translation. "
2568 "Rx %d, Tx %d, Rx Dir %d\n",
2569 rxport, txport, in_port_dir_a[rxport]);
2573 prv_to_pub_map[rxport] = txport;
2574 pub_to_prv_map[txport] = rxport;
2575 token = strtok(NULL, "(");
2582 if (strcmp(arg_name, "lib_arp_debug") == 0) {
2583 ARPICMP_DEBUG = atoi(arg_value);
2588 /* ports_mac_list */
2589 if (strcmp(arg_name, "ports_mac_list") == 0) {
2590 ports_mac_list_present = 1;
2592 uint32_t i = 0, j = 0, k = 0, MAC_NUM_BYTES = 6;
2594 char byteStr[MAC_NUM_BYTES][3];
2595 uint32_t byte[MAC_NUM_BYTES];
2597 char *token = strtok(arg_value, " ");
2600 for (i = 0; i < MAC_NUM_BYTES; i++) {
2601 for (j = 0; j < 2; j++)
2602 byteStr[i][j] = token[k++];
2603 byteStr[i][j] = '\0';
2607 for (i = 0; i < MAC_NUM_BYTES; i++)
2608 byte[i] = strtoul(byteStr[i], NULL, 16);
2610 if (ARPICMP_DEBUG) {
2611 printf("token: %s", token);
2612 for (i = 0; i < MAC_NUM_BYTES; i++)
2613 printf(", byte[%u] %u", i,
2617 //Populate the static arp_route_table
2618 for (i = 0; i < MAC_NUM_BYTES; i++)
2620 [link_hw_addr_array_idx].addr_bytes
2623 link_hw_addr_array_idx++;
2624 token = strtok(NULL, " ");
2631 if (strcmp(arg_name, "arp_route_tbl") == 0) {
2632 arp_route_tbl_present = 1;
2634 uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip =
2635 0, i = 0, j = 0, k = 0, l = 0;
2636 uint32_t arp_route_tbl_str_max_len = 10;
2637 char dest_ip_str[arp_route_tbl_str_max_len];
2638 char mask_str[arp_route_tbl_str_max_len];
2639 char tx_port_str[arp_route_tbl_str_max_len];
2640 char nh_ip_str[arp_route_tbl_str_max_len];
2641 char *token = strtok(arg_value, "(");
2644 while ((i < (arp_route_tbl_str_max_len - 1))
2645 && (token[i] != ',')) {
2646 dest_ip_str[i] = token[i];
2649 dest_ip_str[i] = '\0';
2650 dest_ip = strtoul(dest_ip_str, NULL, 16);
2654 while ((j < (arp_route_tbl_str_max_len - 1))
2655 && (token[i + j] != ',')) {
2656 mask_str[j] = token[i + j];
2660 mask = strtoul(mask_str, NULL, 16);
2664 while ((k < (arp_route_tbl_str_max_len - 1))
2665 && (token[i + j + k] != ',')) {
2666 tx_port_str[k] = token[i + j + k];
2669 tx_port_str[k] = '\0';
2670 //atoi(tx_port_str);
2671 tx_port = strtoul(tx_port_str, NULL, 16);
2675 while ((l < (arp_route_tbl_str_max_len - 1))
2676 && (token[i + j + k + l] != ')')) {
2677 nh_ip_str[l] = token[i + j + k + l];
2680 nh_ip_str[l] = '\0';
2682 nh_ip = strtoul(nh_ip_str, NULL, 16);
2684 if (ARPICMP_DEBUG) {
2685 printf("token: %s, "
2686 "dest_ip_str: %s, dest_ip %u, "
2687 "mask_str: %s, mask %u, "
2688 "tx_port_str: %s, tx_port %u, "
2689 "nh_ip_str: %s, nh_ip %u\n",
2690 token, dest_ip_str, dest_ip,
2691 mask_str, mask, tx_port_str,
2692 tx_port, nh_ip_str, nh_ip);
2695 if (tx_port >= params->n_ports_out) {
2696 printf("ARP-ICMP parse error - "
2697 "incorrect tx_port %d, max %d\n",
2698 tx_port, params->n_ports_out);
2703 //Populate the static arp_route_table
2704 lib_arp_route_table[arp_route_tbl_index].ip =
2706 lib_arp_route_table[arp_route_tbl_index].mask =
2708 lib_arp_route_table[arp_route_tbl_index].port =
2710 lib_arp_route_table[arp_route_tbl_index].nh =
2712 arp_route_tbl_index++;
2713 token = strtok(NULL, "(");
2720 if (strcmp(arg_name, "nd_route_tbl") == 0) {
2721 nd_route_tbl_present = 1;
2723 uint8_t dest_ipv6[16], depth = 0, tx_port =
2724 0, nh_ipv6[16], i = 0, j = 0, k = 0, l = 0;
2725 uint8_t nd_route_tbl_str_max_len = 128; //64;
2726 char dest_ipv6_str[nd_route_tbl_str_max_len];
2727 char depth_str[nd_route_tbl_str_max_len];
2728 char tx_port_str[nd_route_tbl_str_max_len];
2729 char nh_ipv6_str[nd_route_tbl_str_max_len];
2730 char *token = strtok(arg_value, "(");
2733 while ((i < (nd_route_tbl_str_max_len - 1))
2734 && (token[i] != ',')) {
2735 dest_ipv6_str[i] = token[i];
2738 dest_ipv6_str[i] = '\0';
2739 my_inet_pton_ipv6(AF_INET6, dest_ipv6_str,
2744 while ((j < (nd_route_tbl_str_max_len - 1))
2745 && (token[i + j] != ',')) {
2746 depth_str[j] = token[i + j];
2749 depth_str[j] = '\0';
2750 //converting string char to integer
2752 for (s = 0; depth_str[s] != '\0'; ++s)
2753 depth = depth * 10 + depth_str[s] - '0';
2757 while ((k < (nd_route_tbl_str_max_len - 1))
2758 && (token[i + j + k] != ',')) {
2759 tx_port_str[k] = token[i + j + k];
2762 tx_port_str[k] = '\0';
2763 //atoi(tx_port_str);
2764 tx_port = strtoul(tx_port_str, NULL, 16);
2768 while ((l < (nd_route_tbl_str_max_len - 1))
2769 && (token[i + j + k + l] != ')')) {
2770 nh_ipv6_str[l] = token[i + j + k + l];
2773 nh_ipv6_str[l] = '\0';
2774 my_inet_pton_ipv6(AF_INET6, nh_ipv6_str,
2777 //Populate the static arp_route_table
2778 for (i = 0; i < 16; i++) {
2780 [nd_route_tbl_index].ipv6[i] =
2783 [nd_route_tbl_index].nhipv6[i] =
2786 lib_nd_route_table[nd_route_tbl_index].depth =
2788 lib_nd_route_table[nd_route_tbl_index].port =
2791 nd_route_tbl_index++;
2792 token = strtok(NULL, "(");
2802 if (!arp_meta_offset_present) {
2803 printf("ARPICMP: arp_meta_offset not initialized\n");
2808 if (!arp_route_tbl_present && !nd_route_tbl_present) {
2809 printf("Neither arp_route_tbl_present nor "
2810 "nd_route_tbl_present declared\n");
2814 if (!pktq_in_prv_present) {
2815 printf("pktq_in_prv not declared\n");
2819 if (!ports_mac_list_present) {
2820 printf("ports_mac_list not declared\n");
2829 uint32_t arpicmp_pkt_print_count;
2831 pkt_key_arpicmp(struct rte_mbuf *pkt, uint32_t pkt_num, void *arg)
2834 struct pipeline_arpicmp_in_port_h_arg *ap = arg;
2835 struct pipeline_arpicmp *p_arp = (struct pipeline_arpicmp *)ap->p;
2837 p_arp->receivedPktCount++;
2839 uint8_t in_port_id = pkt->port;
2841 struct app_link_params *link;
2844 uint32_t pkt_mask = 1 << pkt_num;
2845 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
2847 uint32_t prot_offset =
2848 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
2854 uint16_t *eth_proto =
2855 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
2857 /* header room + eth hdr size + src_aadr offset in ip header */
2859 uint32_t dst_addr_offset =
2860 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
2861 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset);
2865 uint32_t prot_offset_ipv6 =
2866 MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
2868 if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6)
2869 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset_ipv6);
2871 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset);
2873 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset);
2877 if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
2879 arpicmp_pkt_print_count++;
2880 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
2881 "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
2882 rte_be_to_cpu_16(*eth_proto), *protocol, ETH_TYPE_ARP,
2883 ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
2887 link = &myApp->link_params[in_port_id];
2890 /* Classifier for ICMP pass-through*/
2891 if ((rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_ARP) ||
2892 ((rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_IPV4)
2893 && (*protocol == IP_PROTOCOL_ICMP)
2895 && (link->ip == rte_be_to_cpu_32(*dst_addr))
2900 out_port = p_arp->outport_id[in_port_id];
2901 process_arpicmp_pkt(pkt, out_port, pkt_mask);
2903 process_arpicmp_pkt(pkt, ifm_get_port(in_port_id));
2908 else if ((rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_IPV6)
2909 && (*protocol == ICMPV6_PROTOCOL_ID)) {
2911 out_port = p_arp->outport_id[in_port_id];
2912 process_icmpv6_pkt(pkt, out_port, pkt_mask);
2914 process_icmpv6_pkt(pkt, ifm_get_port(in_port_id));
2921 /* Drop the pkt if not ARP/ICMP */
2922 rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask);
2923 p_arp->droppedPktCount++;
2928 pkt4_key_arpicmp(struct rte_mbuf **pkt, uint32_t pkt_num, void *arg)
2931 struct pipeline_arpicmp_in_port_h_arg *ap = arg;
2932 struct pipeline_arpicmp *p_arp = (struct pipeline_arpicmp *)ap->p;
2934 p_arp->receivedPktCount += 4;
2936 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
2937 uint8_t in_port_id = pkt[0]->port;
2939 uint32_t prot_offset =
2940 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
2942 /* header room + eth hdr size + src_aadr offset in ip header */
2944 uint32_t dst_addr_offset =
2945 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
2948 uint32_t pkt_mask0 = 1 << pkt_num;
2949 uint32_t pkt_mask1 = 1 << (pkt_num + 1);
2950 uint32_t pkt_mask2 = 1 << (pkt_num + 2);
2951 uint32_t pkt_mask3 = 1 << (pkt_num + 3);
2960 uint16_t *eth_proto0 =
2961 RTE_MBUF_METADATA_UINT16_PTR(pkt[0], eth_proto_offset);
2962 uint16_t *eth_proto1 =
2963 RTE_MBUF_METADATA_UINT16_PTR(pkt[1], eth_proto_offset);
2964 uint16_t *eth_proto2 =
2965 RTE_MBUF_METADATA_UINT16_PTR(pkt[2], eth_proto_offset);
2966 uint16_t *eth_proto3 =
2967 RTE_MBUF_METADATA_UINT16_PTR(pkt[3], eth_proto_offset);
2975 uint32_t *dst_addr0 =
2976 RTE_MBUF_METADATA_UINT32_PTR(pkt[0], dst_addr_offset);
2977 uint32_t *dst_addr1 =
2978 RTE_MBUF_METADATA_UINT32_PTR(pkt[1], dst_addr_offset);
2979 uint32_t *dst_addr2 =
2980 RTE_MBUF_METADATA_UINT32_PTR(pkt[2], dst_addr_offset);
2981 uint32_t *dst_addr3 =
2982 RTE_MBUF_METADATA_UINT32_PTR(pkt[3], dst_addr_offset);
2984 struct app_link_params *link0;
2985 struct app_link_params *link1;
2986 struct app_link_params *link2;
2987 struct app_link_params *link3;
2989 link0 = &myApp->link_params[pkt[0]->port];
2990 link1 = &myApp->link_params[pkt[1]->port];
2991 link2 = &myApp->link_params[pkt[2]->port];
2992 link3 = &myApp->link_params[pkt[3]->port];
2996 uint32_t prot_offset_ipv6 =
2997 MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
3003 if (rte_be_to_cpu_16(*eth_proto0) == ETHER_TYPE_IPv6)
3005 RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset_ipv6);
3007 protocol0 = RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset);
3010 if (rte_be_to_cpu_16(*eth_proto1) == ETHER_TYPE_IPv6)
3012 RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset_ipv6);
3014 protocol1 = RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset);
3017 if (rte_be_to_cpu_16(*eth_proto2) == ETHER_TYPE_IPv6)
3019 RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset_ipv6);
3021 protocol2 = RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset);
3024 if (rte_be_to_cpu_16(*eth_proto3) == ETHER_TYPE_IPv6)
3026 RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset_ipv6);
3028 protocol3 = RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset);
3030 protocol0 = RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset);
3031 protocol1 = RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset);
3032 protocol2 = RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset);
3033 protocol3 = RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset);
3036 if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
3038 arpicmp_pkt_print_count++;
3039 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
3040 "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
3041 rte_be_to_cpu_16(*eth_proto0), *protocol0, ETH_TYPE_ARP,
3042 ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
3046 if ((rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_ARP) ||
3047 ((rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_IPV4)
3048 && (*protocol0 == IP_PROTOCOL_ICMP)
3050 && (link0->ip == rte_be_to_cpu_32(*dst_addr0))
3055 out_port0 = p_arp->outport_id[pkt[0]->port];
3056 process_arpicmp_pkt(pkt[0], out_port0, pkt_mask0);
3058 process_arpicmp_pkt(pkt[0], ifm_get_port(in_port_id));
3064 else if ((rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_IPV6)
3065 && (*protocol0 == ICMPV6_PROTOCOL_ID)) {
3068 out_port0 = p_arp->outport_id[pkt[0]->port];
3069 process_icmpv6_pkt(pkt[0], out_port0, pkt_mask0);
3071 process_icmpv6_pkt(pkt[0], ifm_get_port(in_port_id));
3078 /* Drop the pkt if not ARP/ICMP */
3079 rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask0);
3080 p_arp->droppedPktCount++;
3083 if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
3085 arpicmp_pkt_print_count++;
3086 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
3087 "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
3088 rte_be_to_cpu_16(*eth_proto1), *protocol1, ETH_TYPE_ARP,
3089 ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
3092 if ((rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_ARP) ||
3093 ((rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_IPV4)
3094 && (*protocol1 == IP_PROTOCOL_ICMP)
3096 && (link1->ip == rte_be_to_cpu_32(*dst_addr1))
3101 out_port1 = p_arp->outport_id[pkt[1]->port];
3102 process_arpicmp_pkt(pkt[1], out_port1, pkt_mask1);
3104 process_arpicmp_pkt(pkt[1], ifm_get_port(in_port_id));
3109 else if ((rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_IPV6)
3110 && (*protocol1 == ICMPV6_PROTOCOL_ID)) {
3113 out_port1 = p_arp->outport_id[pkt[1]->port];
3114 process_icmpv6_pkt(pkt[1], out_port1, pkt_mask1);
3116 process_icmpv6_pkt(pkt[1], ifm_get_port(in_port_id));
3123 /* Drop the pkt if not ARP/ICMP */
3124 rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask1);
3125 p_arp->droppedPktCount++;
3128 if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
3130 arpicmp_pkt_print_count++;
3131 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
3132 "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
3133 rte_be_to_cpu_16(*eth_proto2), *protocol2, ETH_TYPE_ARP,
3134 ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
3137 if ((rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_ARP) ||
3138 ((rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_IPV4)
3139 && (*protocol2 == IP_PROTOCOL_ICMP)
3141 && (link2->ip == rte_be_to_cpu_32(*dst_addr2))
3146 out_port2 = p_arp->outport_id[pkt[2]->port];
3147 process_arpicmp_pkt(pkt[2], out_port2, pkt_mask2);
3149 process_arpicmp_pkt(pkt[2], ifm_get_port(in_port_id));
3155 else if ((rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_IPV6)
3156 && (*protocol2 == ICMPV6_PROTOCOL_ID)) {
3159 out_port2 = p_arp->outport_id[pkt[2]->port];
3160 process_icmpv6_pkt(pkt[2], out_port2, pkt_mask2);
3162 process_icmpv6_pkt(pkt[2], ifm_get_port(in_port_id));
3169 /* Drop the pkt if not ARP/ICMP */
3170 rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask2);
3171 p_arp->droppedPktCount++;
3174 if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
3176 arpicmp_pkt_print_count++;
3177 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
3178 "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
3179 rte_be_to_cpu_16(*eth_proto3), *protocol3, ETH_TYPE_ARP,
3180 ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
3183 if ((rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_ARP) ||
3184 ((rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_IPV4)
3185 && (*protocol3 == IP_PROTOCOL_ICMP)
3188 && (link3->ip == rte_be_to_cpu_32(*dst_addr3))
3193 out_port3 = p_arp->outport_id[pkt[3]->port];
3194 process_arpicmp_pkt(pkt[3], out_port3, pkt_mask3);
3196 process_arpicmp_pkt(pkt[3], ifm_get_port(in_port_id));
3202 else if ((rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_IPV6)
3203 && (*protocol3 == ICMPV6_PROTOCOL_ID)) {
3206 out_port3 = p_arp->outport_id[pkt[3]->port];
3207 process_icmpv6_pkt(pkt[3], out_port3, pkt_mask3);
3209 process_icmpv6_pkt(pkt[3], ifm_get_port(in_port_id));
3215 /* Drop the pkt if not ARP/ICMP */
3216 rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask3);
3217 p_arp->droppedPktCount++;
3222 PIPELINE_ARPICMP_KEY_PORT_IN_AH(
3227 static void *pipeline_arpicmp_init(struct pipeline_params *params,
3228 __rte_unused void *arg)
3231 struct pipeline_arpicmp *p_arp;
3232 uint32_t size, i, in_ports_arg_size;
3234 printf("Start pipeline_arpicmp_init\n");
3236 /* Check input arguments */
3237 if ((params == NULL) ||
3238 (params->n_ports_in == 0) ||
3239 (params->n_ports_out == 0))
3242 /* Memory allocation */
3243 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_arpicmp));
3244 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
3245 p_arp = (struct pipeline_arpicmp *)p;
3250 struct app_params *app = (struct app_params *)arg;
3253 PLOG(p, HIGH, "ARPICMP");
3254 strcpy(p->name, params->name);
3255 p->log_level = params->log_level;
3257 p_arp->receivedPktCount = 0;
3258 p_arp->droppedPktCount = 0;
3261 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++)
3262 p_arp->links_map[i] = 0xff;
3264 p_arp->pipeline_num = 0;
3266 /* Parse arguments */
3267 if (pipeline_arpicmp_parse_args(p_arp, params))
3271 lib_arp_init(params, app);
3276 struct rte_pipeline_params pipeline_params = {
3278 .socket_id = params->socket_id,
3279 .offset_port_id = 0,
3280 //.offset_port_id = arp_meta_offset,
3283 p->p = rte_pipeline_create(&pipeline_params);
3290 p->n_ports_in = params->n_ports_in;
3291 p->n_ports_out = params->n_ports_out;
3294 /* Memory allocation for in_port_h_arg */
3295 in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
3296 (sizeof(struct pipeline_arpicmp_in_port_h_arg)) *
3297 (params->n_ports_in));
3298 struct pipeline_arpicmp_in_port_h_arg *ap =
3299 (struct pipeline_arpicmp_in_port_h_arg *)rte_zmalloc(NULL,
3301 RTE_CACHE_LINE_SIZE);
3306 for (i = 0; i < p->n_ports_in; i++) {
3307 /* passing our txrx pipeline in call back arg */
3309 (ap[i]).in_port_id = i;
3310 struct rte_pipeline_port_in_params port_params = {
3312 pipeline_port_in_params_get_ops(¶ms->
3315 pipeline_port_in_params_convert(¶ms->
3319 .burst_size = params->port_in[i].burst_size,
3322 port_params.f_action = port_in_ah_arpicmp;
3324 int status = rte_pipeline_port_in_create(p->p,
3329 rte_pipeline_free(p->p);
3336 for (i = 0; i < p->n_ports_out; i++) {
3337 struct rte_pipeline_port_out_params port_params = {
3339 pipeline_port_out_params_get_ops(¶ms->
3342 pipeline_port_out_params_convert(¶ms->
3348 int status = rte_pipeline_port_out_create(p->p,
3350 &p->port_out_id[i]);
3353 rte_pipeline_free(p->p);
3358 int pipeline_num = 0;
3360 int status = sscanf(params->name, "PIPELINE%d", &pipeline_num);
3364 printf("Unable to read pipeline number\n");
3367 p_arp->pipeline_num = (uint8_t) pipeline_num;
3369 register_pipeline_Qs(p_arp->pipeline_num, p);
3370 set_phy_outport_id(p_arp->pipeline_num, p, p_arp->outport_id);
3374 struct rte_pipeline_table_params table_params = {
3375 .ops = &rte_table_stub_ops,
3377 .f_action_hit = NULL,
3378 .f_action_miss = NULL,
3380 .action_data_size = 0,
3383 int status = rte_pipeline_table_create(p->p,
3388 rte_pipeline_free(p->p);
3394 /* Connecting input ports to tables */
3395 for (i = 0; i < p->n_ports_in; i++) {
3397 int status = rte_pipeline_port_in_connect_to_table(p->p,
3405 rte_pipeline_free(p->p);
3412 /* Enable input ports */
3413 for (i = 0; i < p->n_ports_in; i++) {
3414 int status = rte_pipeline_port_in_enable(p->p,
3418 rte_pipeline_free(p->p);
3424 /* Check pipeline consistency */
3425 if (rte_pipeline_check(p->p) < 0) {
3426 rte_pipeline_free(p->p);
3431 /* Message queues */
3432 p->n_msgq = params->n_msgq;
3433 for (i = 0; i < p->n_msgq; i++)
3434 p->msgq_in[i] = params->msgq_in[i];
3435 for (i = 0; i < p->n_msgq; i++)
3436 p->msgq_out[i] = params->msgq_out[i];
3438 /* Message handlers */
3439 memcpy(p->handlers, handlers, sizeof(p->handlers));
3443 /* create the arpicmp mbuf rx pool */
3444 lib_arp_pktmbuf_tx_pool = rte_pktmbuf_pool_create(
3445 "lib_arp_mbuf_tx_pool",
3446 NB_ARPICMP_MBUF, 32,
3447 0, RTE_MBUF_DEFAULT_BUF_SIZE,
3450 if (lib_arp_pktmbuf_tx_pool == NULL) {
3451 printf("ARP mbuf pool create failed.\n");
3455 lib_arp_pkt = rte_pktmbuf_alloc(lib_arp_pktmbuf_tx_pool);
3456 if (lib_arp_pkt == NULL) {
3457 printf("ARP lib_arp_pkt alloc failed.\n");
3462 arp_hash_params.socket_id = rte_socket_id();
3463 arp_hash_params.entries = MAX_NUM_ARP_ENTRIES;
3464 arp_hash_handle = rte_hash_create(&arp_hash_params);
3466 if (arp_hash_handle == NULL) {
3467 printf("ARP rte_hash_create failed. socket %d ...\n",
3468 arp_hash_params.socket_id);
3471 printf("arp_hash_handle %p\n\n", (void *)arp_hash_handle);
3474 nd_hash_params.socket_id = rte_socket_id();
3475 nd_hash_params.entries = MAX_NUM_ND_ENTRIES;
3476 nd_hash_handle = rte_hash_create(&nd_hash_params);
3478 if (nd_hash_handle == NULL) {
3479 printf("ND rte_hash_create failed. socket %d ...\n",
3480 nd_hash_params.socket_id);
3484 printf("nd_hash_handle %p\n\n", (void *)nd_hash_handle);
3489 static int pipeline_arpicmp_free(void *pipeline)
3491 struct pipeline *p = (struct pipeline *)pipeline;
3493 /* Check input arguments */
3497 /* Free resources */
3498 rte_pipeline_free(p->p);
3503 static int pipeline_arpicmp_timer(void *pipeline)
3505 struct pipeline *p = (struct pipeline *)pipeline;
3507 pipeline_msg_req_handle(p);
3508 rte_pipeline_flush(p->p);
3514 pipeline_arpicmp_track(void *pipeline, uint32_t port_in, uint32_t *port_out)
3516 struct pipeline *p = (struct pipeline *)pipeline;
3518 /* Check input arguments */
3519 if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
3522 *port_out = port_in / p->n_ports_in;
3526 struct pipeline_be_ops pipeline_arpicmp_be_ops = {
3527 .f_init = pipeline_arpicmp_init,
3528 .f_free = pipeline_arpicmp_free,
3530 .f_timer = pipeline_arpicmp_timer,
3531 .f_track = pipeline_arpicmp_track,