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.
23 #include <rte_common.h>
24 #include <rte_malloc.h>
26 #include <rte_byteorder.h>
28 #include <rte_table_lpm.h>
29 #include <rte_table_hash.h>
30 #include <rte_pipeline.h>
34 #include <rte_jhash.h>
35 #include <rte_cycles.h>
36 #include <rte_timer.h>
37 #include "interface.h"
40 #include "l3fwd_lpm4.h"
41 #include "vnf_common.h"
43 #if (RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN)
44 #define CHECK_ENDIAN_16(x) rte_be_to_cpu_16(x)
45 #define CHECK_ENDIAN_32(x) rte_be_to_cpu_32(x)
47 #define CHECK_ENDIAN_16(x) (x)
48 #define CHECK_ENDIAN_32(x) (x)
51 #define NB_ARPICMP_MBUF 64
52 #define NB_NDICMP_MBUF 64
53 #define IP_VERSION_4 0x40
54 #define IP_HDRLEN 0x05 /**< default IP header length == five 32-bits words. */
55 #define IP_VHL_DEF (IP_VERSION_4 | IP_HDRLEN)
57 #define is_multicast_ipv4_addr(ipv4_addr) \
58 (((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)
60 extern uint8_t prv_in_port_a[PIPELINE_MAX_PORT_IN];
61 extern uint32_t timer_lcore;
62 uint32_t arp_timeout = ARP_TIMER_EXPIRY;
67 static int my_inet_pton_ipv6(int af, const char *src, void *dst);
68 static int inet_pton_ipv6(const char *src, unsigned char *dst);
69 static int inet_pton_ipv4(const char *src, unsigned char *dst);
70 extern void convert_prefixlen_to_netmask_ipv6(uint32_t depth,
71 uint8_t netmask_ipv6[]);
73 uint8_t vnf_common_arp_lib_init;
74 uint8_t vnf_common_nd_lib_init;
75 uint8_t loadb_pipeline_count;
77 uint32_t ARPICMP_DEBUG;
78 uint32_t NDIPV6_DEBUG;
80 uint32_t arp_route_tbl_index;
81 uint32_t nd_route_tbl_index;
82 uint32_t link_hw_addr_array_idx;
84 uint32_t lib_arp_get_mac_req;
85 uint32_t lib_arp_nh_found;
86 uint32_t lib_arp_no_nh_found;
87 uint32_t lib_arp_arp_entry_found;
88 uint32_t lib_arp_no_arp_entry_found;
89 uint32_t lib_arp_populate_called;
90 uint32_t lib_arp_delete_called;
91 uint32_t lib_arp_duplicate_found;
93 uint32_t lib_nd_get_mac_req;
94 uint32_t lib_nd_nh_found;
95 uint32_t lib_nd_no_nh_found;
96 uint32_t lib_nd_nd_entry_found;
97 uint32_t lib_nd_no_arp_entry_found;
98 uint32_t lib_nd_populate_called;
99 uint32_t lib_nd_delete_called;
100 uint32_t lib_nd_duplicate_found;
101 struct rte_mempool *lib_arp_pktmbuf_tx_pool;
102 struct rte_mempool *lib_nd_pktmbuf_tx_pool;
104 struct rte_mbuf *lib_arp_pkt;
105 struct rte_mbuf *lib_nd_pkt;
107 uint8_t default_ether_addr[6] = { 0, 0, 0, 0, 1, 1 };
108 uint8_t default_ip[4] = { 0, 0, 1, 1 };
110 static struct rte_hash_parameters arp_hash_params = {
114 .key_len = sizeof(struct arp_key_ipv4),
115 .hash_func = rte_jhash,
116 .hash_func_init_val = 0,
119 static struct rte_hash_parameters nd_hash_params = {
123 .key_len = sizeof(struct nd_key_ipv6),
124 .hash_func = rte_jhash,
125 .hash_func_init_val = 0,
128 struct rte_hash *arp_hash_handle;
129 struct rte_hash *nd_hash_handle;
131 void print_pkt1(struct rte_mbuf *pkt);
133 struct app_params *myApp;
134 struct rte_pipeline *myP;
135 uint8_t num_vnf_threads;
138 * A structure for Arp port address
140 struct arp_port_address {
141 uint32_t ip; /**< Ip address */
142 uint8_t mac_addr[6]; /**< Mac address */
145 struct arp_port_address arp_port_addresses[RTE_MAX_ETHPORTS];
146 struct rte_mempool *timer_mempool_arp;
148 int timer_objs_mempool_count = 70000;
150 #define MAX_NUM_ARP_ENTRIES 64
151 #define MAX_NUM_ND_ENTRIES 64
153 uint32_t get_nh(uint32_t, uint32_t *);
154 void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[]);
156 #define MAX_ARP_DATA_ENTRY_TABLE 7
158 struct table_arp_entry_data arp_entry_data_table[MAX_ARP_DATA_ENTRY_TABLE] = {
159 {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(192, 168, 0, 2)},
160 {{0, 0, 0, 0, 0, 2}, 0, INCOMPLETE, IPv4(192, 168, 0, 3)},
161 {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(30, 40, 50, 60)},
162 {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(120, 0, 0, 2)},
163 {{0, 0, 0, 0, 0, 4}, 3, INCOMPLETE, IPv4(1, 1, 1, 4)},
164 {{0, 0, 0, 0, 0, 5}, 4, INCOMPLETE, IPv4(1, 1, 1, 5)},
165 {{0, 0, 0, 0, 0, 6}, 1, INCOMPLETE, IPv4(1, 1, 1, 7)},
168 #define MAX_ND_DATA_ENTRY_TABLE 7
169 struct table_nd_entry_data nd_entry_data_table[MAX_ND_DATA_ENTRY_TABLE] = {
170 {{0, 0, 0, 0, 0, 8}, 1, INCOMPLETE,
171 {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, 0},
173 {{0, 0, 0, 0, 0, 9}, 1, INCOMPLETE,
174 {20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20}, 0},
175 {{0, 0, 0, 0, 0, 10}, 2, INCOMPLETE,
176 {3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
177 {{0, 0, 0, 0, 0, 11}, 3, INCOMPLETE,
178 {4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
179 {{0, 0, 0, 0, 0, 12}, 4, INCOMPLETE,
180 {5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
181 {{0, 0, 0, 0, 0, 13}, 5, INCOMPLETE,
182 {6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
183 {{0, 0, 0, 0, 0, 14}, 6, INCOMPLETE,
184 {7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
187 struct lib_nd_route_table_entry lib_nd_route_table[MAX_ND_RT_ENTRY] = {
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} },
234 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
235 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
236 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
237 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
238 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
239 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
240 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
241 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
242 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
243 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
244 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
245 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
246 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
247 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
248 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
249 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
250 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
251 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }
254 struct lib_arp_route_table_entry lib_arp_route_table[MAX_ARP_RT_ENTRY] = {
289 void print_trace(void);
291 /* Obtain a backtrace and print it to stdout. */
292 void print_trace(void)
299 size = backtrace(array, 10);
300 strings = backtrace_symbols(array, size);
302 RTE_LOG(INFO, LIBARP, "Obtained %zd stack frames.\n", size);
304 for (i = 0; i < size; i++)
305 RTE_LOG(INFO, LIBARP, "%s\n", strings[i]);
310 uint32_t get_nh(uint32_t ip, uint32_t *port)
313 for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
314 if (((lib_arp_route_table[i].
315 ip & lib_arp_route_table[i].mask) ==
316 (ip & lib_arp_route_table[i].mask))) {
318 *port = lib_arp_route_table[i].port;
320 return lib_arp_route_table[i].nh;
323 printf("No nh match ip 0x%x, port %u, t_ip "
324 "0x%x, t_port %u, mask 0x%x, r1 %x, r2 %x\n",
325 ip, *port, lib_arp_route_table[i].ip,
326 lib_arp_route_table[i].port,
327 lib_arp_route_table[i].mask,
328 (lib_arp_route_table[i].ip &
329 lib_arp_route_table[i].mask),
330 (ip & lib_arp_route_table[i].mask));
333 printf("No NH - ip 0x%x, port %u\n", ip, *port);
334 lib_arp_no_nh_found++;
339 void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[])
342 uint8_t netmask_ipv6[16], netip_nd[16], netip_in[16];
343 uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
344 memset(netmask_ipv6, 0, sizeof(netmask_ipv6));
345 memset(netip_nd, 0, sizeof(netip_nd));
346 memset(netip_in, 0, sizeof(netip_in));
349 for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
351 convert_prefixlen_to_netmask_ipv6(lib_nd_route_table[i].depth,
354 for (k = 0; k < 16; k++) {
355 if (lib_nd_route_table[i].ipv6[k] & netmask_ipv6[k]) {
357 netip_nd[k] = lib_nd_route_table[i].ipv6[k];
361 for (l = 0; l < 16; l++) {
362 if (ipv6[l] & netmask_ipv6[l]) {
364 netip_in[l] = ipv6[l];
368 if ((depthflags == depthflags1)
369 && (memcmp(netip_nd, netip_in, sizeof(netip_nd)) == 0)) {
370 //&& (lib_nd_route_table[i].port == port))
371 *port = lib_nd_route_table[i].port;
374 for (j = 0; j < 16; j++)
375 nhipv6[j] = lib_nd_route_table[i].nhipv6[j];
381 printf("No nh match\n");
386 printf("No NH - ip 0x%x, port %u\n", ipv6[0], *port);
387 lib_nd_no_nh_found++;
390 /* Added for Multiport changes*/
391 int get_dest_mac_addr_port(const uint32_t ipaddr,
392 uint32_t *phy_port, struct ether_addr *hw_addr)
394 lib_arp_get_mac_req++;
397 nhip = get_nh(ipaddr, phy_port);
400 printf("ARPICMP no nh found for ip %x, port %d\n",
406 struct arp_entry_data *ret_arp_data = NULL;
407 struct arp_key_ipv4 tmp_arp_key;
408 tmp_arp_key.port_id = *phy_port; /* Changed for Multi Port */
409 tmp_arp_key.ip = nhip;
412 printf("%s: nhip: %x, phyport: %d\n", __FUNCTION__, nhip,
415 ret_arp_data = retrieve_arp_entry(tmp_arp_key);
416 if (ret_arp_data == NULL) {
419 ("ARPICMP no arp entry found for ip %x, port %d\n",
425 printf("CG-NAPT requesting ARP for ip %x, "
426 "port %d\n", nhip, *phy_port);
427 request_arp(*phy_port, nhip); //Changed for Multiport
430 lib_arp_no_arp_entry_found++;
431 return ARP_NOT_FOUND;
433 ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
434 lib_arp_arp_entry_found++;
436 printf("%s: ARPICMP hwaddr found\n", __FUNCTION__);
440 int get_dest_mac_address(const uint32_t ipaddr, uint32_t *phy_port,
441 struct ether_addr *hw_addr, uint32_t *nhip)
443 lib_arp_get_mac_req++;
445 *nhip = get_nh(ipaddr, phy_port);
447 if (ARPICMP_DEBUG && ipaddr)
448 RTE_LOG(INFO, LIBARP,
449 "ARPICMP no nh found for ip %x, port %d\n",
454 struct arp_entry_data *ret_arp_data = NULL;
455 struct arp_key_ipv4 tmp_arp_key;
456 tmp_arp_key.port_id = *phy_port;
457 tmp_arp_key.ip = *nhip;
459 ret_arp_data = retrieve_arp_entry(tmp_arp_key);
460 if (ret_arp_data == NULL) {
461 if (ARPICMP_DEBUG && ipaddr) {
462 RTE_LOG(INFO, LIBARP,
463 "ARPICMP no arp entry found for ip %x, port %d\n",
467 lib_arp_no_arp_entry_found++;
470 ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
471 lib_arp_arp_entry_found++;
476 int get_dest_mac_addr(const uint32_t ipaddr,
477 uint32_t *phy_port, struct ether_addr *hw_addr)
479 lib_arp_get_mac_req++;
482 nhip = get_nh(ipaddr, phy_port);
484 if (ARPICMP_DEBUG && ipaddr)
485 RTE_LOG(INFO, LIBARP,
486 "ARPICMP no nh found for ip %x, port %d\n",
491 struct arp_entry_data *ret_arp_data = NULL;
492 struct arp_key_ipv4 tmp_arp_key;
493 tmp_arp_key.port_id = *phy_port;
494 tmp_arp_key.ip = nhip;
496 ret_arp_data = retrieve_arp_entry(tmp_arp_key);
497 if (ret_arp_data == NULL) {
498 if (ARPICMP_DEBUG && ipaddr) {
500 ("ARPICMP no arp entry found for ip %x, port %d\n",
506 if (ARPICMP_DEBUG > 4)
508 ("CG-NAPT requesting ARP for ip %x, port %d\n",
510 if (ifm_chk_port_ipv4_enabled(*phy_port)) {
511 request_arp(*phy_port, nhip);
514 RTE_LOG(INFO, LIBARP,
515 "%s: IP is not enabled on port %u, not sending ARP REQ\n\r",
516 __FUNCTION__, *phy_port);
520 lib_arp_no_arp_entry_found++;
523 ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
524 lib_arp_arp_entry_found++;
528 int get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], uint32_t *phy_port,
529 struct ether_addr *hw_addr, uint8_t nhipv6[])
531 int i = 0, j = 0, flag = 0;
532 lib_nd_get_mac_req++;
534 get_nh_ipv6(ipv6addr, phy_port, nhipv6);
535 for (j = 0; j < 16; j++) {
541 printf("NDIPV6 no nh found for ipv6 "
542 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
543 "%02x%02x%02x%02x%02x%02x, port %d\n",
544 ipv6addr[0], ipv6addr[1], ipv6addr[2],
545 ipv6addr[3], ipv6addr[4], ipv6addr[5],
546 ipv6addr[6], ipv6addr[7], ipv6addr[8],
547 ipv6addr[9], ipv6addr[10], ipv6addr[11],
548 ipv6addr[12], ipv6addr[13], ipv6addr[14],
549 ipv6addr[15], *phy_port);
553 struct nd_entry_data *ret_nd_data = NULL;
554 struct nd_key_ipv6 tmp_nd_key;
555 tmp_nd_key.port_id = *phy_port;
557 for (i = 0; i < 16; i++)
558 tmp_nd_key.ipv6[i] = nhipv6[i];
560 ret_nd_data = retrieve_nd_entry(tmp_nd_key);
561 if (ret_nd_data == NULL) {
563 printf("NDIPV6 no nd entry found for ip %x, port %d\n",
564 ipv6addr[0], *phy_port);
566 lib_nd_no_arp_entry_found++;
569 ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
570 lib_nd_nd_entry_found++;
574 int get_dest_mac_address_ipv6(uint8_t ipv6addr[], uint32_t *phy_port,
575 struct ether_addr *hw_addr, uint8_t nhipv6[])
577 int i = 0, j = 0, flag = 0;
578 lib_nd_get_mac_req++;
580 get_nh_ipv6(ipv6addr, phy_port, nhipv6);
581 for (j = 0; j < 16; j++) {
587 if (NDIPV6_DEBUG && ipv6addr)
588 RTE_LOG(INFO, LIBARP,
589 "NDIPV6 no nh found for ipv6 %x, port %d\n",
590 ipv6addr[0], *phy_port);
594 struct nd_entry_data *ret_nd_data = NULL;
595 struct nd_key_ipv6 tmp_nd_key;
596 tmp_nd_key.port_id = *phy_port;
598 for (i = 0; i < 16; i++) {
599 tmp_nd_key.ipv6[i] = nhipv6[i];
602 ret_nd_data = retrieve_nd_entry(tmp_nd_key);
603 if (ret_nd_data == NULL) {
604 if (NDIPV6_DEBUG && ipv6addr) {
605 RTE_LOG(INFO, LIBARP,
606 "NDIPV6 no nd entry found for ip %x, port %d\n",
607 ipv6addr[0], *phy_port);
610 if (ARPICMP_DEBUG > 4)
612 ("Requesting ARP for ipv6 addr and port %d\n",
614 request_nd(&nhipv6[0], ifm_get_port(*phy_port));
618 lib_nd_no_arp_entry_found++;
621 ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
622 lib_nd_nd_entry_found++;
627 * A structure for arp entries in Arp table
630 struct lib_arp_arp_table_entry {
631 struct rte_pipeline_table_entry head;
632 uint64_t macaddr; /**< Mac address */
635 static const char *arp_op_name(uint16_t arp_op)
637 switch (CHECK_ENDIAN_16(arp_op)) {
638 case (ARP_OP_REQUEST):
639 return "ARP Request";
642 case (ARP_OP_REVREQUEST):
643 return "Reverse ARP Request";
644 case (ARP_OP_REVREPLY):
645 return "Reverse ARP Reply";
646 case (ARP_OP_INVREQUEST):
647 return "Peer Identify Request";
648 case (ARP_OP_INVREPLY):
649 return "Peer Identify Reply";
653 return "Unkwown ARP op";
656 static void print_icmp_packet(struct icmp_hdr *icmp_h)
658 RTE_LOG(INFO, LIBARP, " ICMP: type=%d (%s) code=%d id=%d seqnum=%d\n",
660 (icmp_h->icmp_type == IP_ICMP_ECHO_REPLY ? "Reply" :
661 (icmp_h->icmp_type ==
662 IP_ICMP_ECHO_REQUEST ? "Reqest" : "Undef")),
663 icmp_h->icmp_code, CHECK_ENDIAN_16(icmp_h->icmp_ident),
664 CHECK_ENDIAN_16(icmp_h->icmp_seq_nb));
667 static void print_ipv4_h(struct ipv4_hdr *ip_h)
669 struct icmp_hdr *icmp_h =
670 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
671 RTE_LOG(INFO, LIBARP, " IPv4: Version=%d HLEN=%d Type=%d Length=%d\n",
672 (ip_h->version_ihl & 0xf0) >> 4, (ip_h->version_ihl & 0x0f),
673 ip_h->type_of_service, rte_cpu_to_be_16(ip_h->total_length));
674 if (ip_h->next_proto_id == IPPROTO_ICMP) {
675 print_icmp_packet(icmp_h);
679 static void print_arp_packet(struct arp_hdr *arp_h)
681 RTE_LOG(INFO, LIBARP, " ARP: hrd=%d proto=0x%04x hln=%d "
682 "pln=%d op=%u (%s)\n",
683 CHECK_ENDIAN_16(arp_h->arp_hrd),
684 CHECK_ENDIAN_16(arp_h->arp_pro), arp_h->arp_hln,
685 arp_h->arp_pln, CHECK_ENDIAN_16(arp_h->arp_op),
686 arp_op_name(arp_h->arp_op));
688 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER) {
689 RTE_LOG(INFO, LIBARP,
690 "incorrect arp_hrd format for IPv4 ARP (%d)\n",
692 } else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4) {
693 RTE_LOG(INFO, LIBARP,
694 "incorrect arp_pro format for IPv4 ARP (%d)\n",
696 } else if (arp_h->arp_hln != 6) {
697 RTE_LOG(INFO, LIBARP,
698 "incorrect arp_hln format for IPv4 ARP (%d)\n",
700 } else if (arp_h->arp_pln != 4) {
701 RTE_LOG(INFO, LIBARP,
702 "incorrect arp_pln format for IPv4 ARP (%d)\n",
705 RTE_LOG(INFO, LIBARP,
706 " sha=%02X:%02X:%02X:%02X:%02X:%02X",
707 arp_h->arp_data.arp_sha.addr_bytes[0],
708 arp_h->arp_data.arp_sha.addr_bytes[1],
709 arp_h->arp_data.arp_sha.addr_bytes[2],
710 arp_h->arp_data.arp_sha.addr_bytes[3],
711 arp_h->arp_data.arp_sha.addr_bytes[4],
712 arp_h->arp_data.arp_sha.addr_bytes[5]);
713 RTE_LOG(INFO, LIBARP, " sip=%d.%d.%d.%d\n",
714 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 24) & 0xFF,
715 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 16) & 0xFF,
716 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 8) & 0xFF,
717 CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) & 0xFF);
718 RTE_LOG(INFO, LIBARP,
719 " tha=%02X:%02X:%02X:%02X:%02X:%02X",
720 arp_h->arp_data.arp_tha.addr_bytes[0],
721 arp_h->arp_data.arp_tha.addr_bytes[1],
722 arp_h->arp_data.arp_tha.addr_bytes[2],
723 arp_h->arp_data.arp_tha.addr_bytes[3],
724 arp_h->arp_data.arp_tha.addr_bytes[4],
725 arp_h->arp_data.arp_tha.addr_bytes[5]);
726 RTE_LOG(INFO, LIBARP, " tip=%d.%d.%d.%d\n",
727 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 24) & 0xFF,
728 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 16) & 0xFF,
729 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 8) & 0xFF,
730 CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) & 0xFF);
734 static void print_eth(struct ether_hdr *eth_h)
736 RTE_LOG(INFO, LIBARP, " ETH: src=%02X:%02X:%02X:%02X:%02X:%02X",
737 eth_h->s_addr.addr_bytes[0],
738 eth_h->s_addr.addr_bytes[1],
739 eth_h->s_addr.addr_bytes[2],
740 eth_h->s_addr.addr_bytes[3],
741 eth_h->s_addr.addr_bytes[4], eth_h->s_addr.addr_bytes[5]);
742 RTE_LOG(INFO, LIBARP, " dst=%02X:%02X:%02X:%02X:%02X:%02X\n",
743 eth_h->d_addr.addr_bytes[0],
744 eth_h->d_addr.addr_bytes[1],
745 eth_h->d_addr.addr_bytes[2],
746 eth_h->d_addr.addr_bytes[3],
747 eth_h->d_addr.addr_bytes[4], eth_h->d_addr.addr_bytes[5]);
752 print_mbuf(const char *rx_tx, uint8_t portid, struct rte_mbuf *mbuf,
755 struct ether_hdr *eth_h = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
756 struct arp_hdr *arp_h =
757 (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
758 struct ipv4_hdr *ipv4_h =
759 (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
761 RTE_LOG(INFO, LIBARP, "%s(%d): on port %d pkt-len=%u nb-segs=%u\n",
762 rx_tx, line, portid, mbuf->pkt_len, mbuf->nb_segs);
764 switch (rte_cpu_to_be_16(eth_h->ether_type)) {
765 case ETHER_TYPE_IPv4:
766 print_ipv4_h(ipv4_h);
769 print_arp_packet(arp_h);
772 RTE_LOG(INFO, LIBARP, " unknown packet type\n");
778 struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key)
780 struct arp_entry_data *ret_arp_data = NULL;
785 int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
786 (void **)&ret_arp_data);
788 // RTE_LOG(INFO, LIBARP,"arp-hash lookup failed ret %d, EINVAL %d, ENOENT %d\n", ret, EINVAL, ENOENT);
791 if (ret_arp_data->mode == DYNAMIC_ARP) {
792 struct arp_timer_key callback_key;
793 callback_key.port_id = ret_arp_data->port;
794 callback_key.ip = ret_arp_data->ip;
795 /*lcore need to check which parameter need to be put */
796 if (rte_timer_reset(ret_arp_data->timer,
797 (arp_timeout * rte_get_tsc_hz()),
802 RTE_LOG(INFO, LIBARP,
803 "Err : Timer already running\n");
812 struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key)
814 struct nd_entry_data *ret_nd_data = NULL;
820 /*Find a nd IPv6 key-data pair in the hash table for ND IPv6 */
821 int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
822 (void **)&ret_nd_data);
824 /* RTE_LOG(INFO, LIBARP,"nd-hash: no lookup Entry Found - ret %d, EINVAL %d, ENOENT %d\n",
825 ret, EINVAL, ENOENT);*/
827 if (ret_nd_data->mode == DYNAMIC_ND) {
828 struct nd_timer_key callback_key;
829 callback_key.port_id = ret_nd_data->port;
831 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
832 callback_key.ipv6[i] = ret_nd_data->ipv6[i];
838 (arp_timeout * rte_get_tsc_hz()), SINGLE,
839 timer_lcore, nd_timer_callback, &callback_key) < 0)
841 RTE_LOG(INFO, LIBARP,
842 "Err : Timer already running\n");
850 void print_arp_table(void)
852 const void *next_key;
857 ("------------------------ ARP CACHE -----------------------------------------\n");
859 ("----------------------------------------------------------------------------\n");
860 printf("\tport hw addr status ip addr\n");
862 ("----------------------------------------------------------------------------\n");
864 while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
867 struct arp_entry_data *tmp_arp_data =
868 (struct arp_entry_data *)next_data;
869 struct arp_key_ipv4 tmp_arp_key;
870 memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4));
872 ("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s %d.%d.%d.%d\n",
873 tmp_arp_data->port, tmp_arp_data->eth_addr.addr_bytes[0],
874 tmp_arp_data->eth_addr.addr_bytes[1],
875 tmp_arp_data->eth_addr.addr_bytes[2],
876 tmp_arp_data->eth_addr.addr_bytes[3],
877 tmp_arp_data->eth_addr.addr_bytes[4],
878 tmp_arp_data->eth_addr.addr_bytes[5],
879 tmp_arp_data->status ==
880 COMPLETE ? "COMPLETE" : "INCOMPLETE",
881 (tmp_arp_data->ip >> 24),
882 ((tmp_arp_data->ip & 0x00ff0000) >> 16),
883 ((tmp_arp_data->ip & 0x0000ff00) >> 8),
884 ((tmp_arp_data->ip & 0x000000ff)));
888 printf("\nARP routing table has %d entries\n", arp_route_tbl_index);
889 printf("\nIP_Address Mask Port NH_IP_Address\n");
890 for (i = 0; i < arp_route_tbl_index; i++) {
891 printf("0x%x 0x%x %d 0x%x\n",
892 lib_arp_route_table[i].ip,
893 lib_arp_route_table[i].mask,
894 lib_arp_route_table[i].port, lib_arp_route_table[i].nh);
898 ("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
899 lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found,
900 lib_arp_arp_entry_found, lib_arp_no_arp_entry_found,
901 lib_arp_populate_called, lib_arp_delete_called,
902 lib_arp_duplicate_found);
904 printf("ARP table key len is %lu\n", sizeof(struct arp_key_ipv4));
908 void print_nd_table(void)
910 const void *next_key;
913 uint8_t ii = 0, j = 0, k = 0;
915 ("------------------------------------------------------------------------------------------------------\n");
916 printf("\tport hw addr status ip addr\n");
919 ("------------------------------------------------------------------------------------------------------\n");
920 while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
923 struct nd_entry_data *tmp_nd_data =
924 (struct nd_entry_data *)next_data;
925 struct nd_key_ipv6 tmp_nd_key;
926 memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6));
927 printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s\n",
929 tmp_nd_data->eth_addr.addr_bytes[0],
930 tmp_nd_data->eth_addr.addr_bytes[1],
931 tmp_nd_data->eth_addr.addr_bytes[2],
932 tmp_nd_data->eth_addr.addr_bytes[3],
933 tmp_nd_data->eth_addr.addr_bytes[4],
934 tmp_nd_data->eth_addr.addr_bytes[5],
935 tmp_nd_data->status ==
936 COMPLETE ? "COMPLETE" : "INCOMPLETE");
937 printf("\t\t\t\t\t\t");
938 for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) {
939 printf("%02X%02X ", tmp_nd_data->ipv6[ii],
940 tmp_nd_data->ipv6[ii + 1]);
946 printf("\n\nND IPV6 routing table has %d entries\n",
949 ("\nIP_Address Depth Port NH_IP_Address\n");
950 for (i = 0; i < nd_route_tbl_index; i++) {
953 for (j = 0; j < ND_IPV6_ADDR_SIZE; j += 2) {
954 RTE_LOG(INFO, LIBARP, "%02X%02X ",
955 lib_nd_route_table[i].ipv6[j],
956 lib_nd_route_table[i].ipv6[j + 1]);
960 ("\n\t\t\t %d %d \n",
961 lib_nd_route_table[i].depth, lib_nd_route_table[i].port);
962 printf("\t\t\t\t\t\t\t\t\t");
963 for (k = 0; k < ND_IPV6_ADDR_SIZE; k += 2) {
964 printf("%02X%02X ", lib_nd_route_table[i].nhipv6[k],
965 lib_nd_route_table[i].ipv6[k + 1]);
969 ("\nND IPV6 Stats: \nTotal Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
970 lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found,
971 lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
972 lib_nd_populate_called, lib_nd_delete_called,
973 lib_nd_duplicate_found);
974 printf("ND table key len is %lu\n\n", sizeof(struct nd_key_ipv6));
977 void remove_arp_entry(uint32_t ipaddr, uint8_t portid, void *arg)
980 struct arp_key_ipv4 arp_key;
981 arp_key.port_id = portid;
987 lib_arp_delete_called++;
989 struct arp_entry_data *ret_arp_data = NULL;
991 int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
992 (void **)&ret_arp_data);
994 // RTE_LOG(INFO, LIBARP,"arp-hash lookup failed ret %d, EINVAL %d, ENOENT %d\n", ret, EINVAL, ENOENT);
997 if (ret_arp_data->mode == DYNAMIC_ARP) {
998 if (ret_arp_data->retry_count == 3) {
999 rte_timer_stop(ret_arp_data->timer);
1000 rte_free(ret_arp_data->timer_key);
1001 if (ARPICMP_DEBUG) {
1002 RTE_LOG(INFO, LIBARP,
1003 "ARP Entry Deleted for IP :%d.%d.%d.%d , port %d\n",
1005 ((arp_key.ip & 0x00ff0000) >>
1007 ((arp_key.ip & 0x0000ff00) >>
1009 ((arp_key.ip & 0x000000ff)),
1012 rte_hash_del_key(arp_hash_handle, &arp_key);
1013 //print_arp_table();
1015 ret_arp_data->retry_count++;
1017 RTE_LOG(INFO, LIBARP,
1018 "RETRY ARP..retry count : %u\n",
1019 ret_arp_data->retry_count);
1020 //print_arp_table();
1022 RTE_LOG(INFO, LIBARP,
1023 "TIMER STARTED FOR %u seconds\n",
1025 if (ifm_chk_port_ipv4_enabled
1026 (ret_arp_data->port)) {
1027 request_arp(ret_arp_data->port,
1031 RTE_LOG(INFO, LIBARP,
1032 "%s: IP is not enabled on port %u, not sending GARP\n\r",
1034 ret_arp_data->port);
1036 if (rte_timer_reset(ret_arp_data->timer,
1038 rte_get_tsc_hz()), SINGLE,
1043 RTE_LOG(INFO, LIBARP,
1044 "Err : Timer already running\n");
1048 rte_hash_del_key(arp_hash_handle, &arp_key);
1054 void remove_nd_entry_ipv6(uint8_t ipv6addr[], uint8_t portid)
1057 struct nd_entry_data *ret_nd_data = NULL;
1058 struct nd_key_ipv6 nd_key;
1059 nd_key.port_id = portid;
1061 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1062 nd_key.ipv6[i] = ipv6addr[i];
1069 lib_nd_delete_called++;
1072 RTE_LOG(INFO, LIBARP,
1073 "Deletes rte hash table nd entry for port %d ipv6=",
1075 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1076 RTE_LOG(INFO, LIBARP, "%02X%02X ", nd_key.ipv6[i],
1077 nd_key.ipv6[i + 1]);
1080 struct nd_timer_key callback_key;
1081 callback_key.port_id = portid;
1083 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1084 callback_key.ipv6[i] = ipv6addr[i];
1087 int ret = rte_hash_lookup_data(arp_hash_handle, &callback_key,
1088 (void **)&ret_nd_data);
1090 // RTE_LOG(INFO, LIBARP,"arp-hash lookup failed ret %d, EINVAL %d, ENOENT %d\n", ret, EINVAL, ENOENT);
1092 if (ret_nd_data->mode == DYNAMIC_ND) {
1093 rte_timer_stop(ret_nd_data->timer);
1094 rte_free(ret_nd_data->timer);
1097 rte_hash_del_key(nd_hash_handle, &nd_key);
1101 populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
1102 uint8_t portid, uint8_t mode)
1104 struct arp_key_ipv4 arp_key;
1105 arp_key.port_id = portid;
1106 arp_key.ip = ipaddr;
1107 arp_key.filler1 = 0;
1108 arp_key.filler2 = 0;
1109 arp_key.filler3 = 0;
1111 lib_arp_populate_called++;
1114 RTE_LOG(INFO, LIBARP, "populate_arp_entry ip %x, port %d\n",
1115 arp_key.ip, arp_key.port_id);
1117 struct arp_entry_data *new_arp_data = retrieve_arp_entry(arp_key);
1118 if (new_arp_data && ((new_arp_data->mode == STATIC_ARP
1119 && mode == DYNAMIC_ARP) || (new_arp_data->mode == DYNAMIC_ARP
1120 && mode == STATIC_ARP))) {
1122 RTE_LOG(INFO, LIBARP,"populate_arp_entry: ARP entry already exists(%d %d)\n",
1123 new_arp_data->mode, mode);
1128 if (mode == DYNAMIC_ARP) {
1130 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1131 if (ARPICMP_DEBUG) {
1132 RTE_LOG(INFO, LIBARP,
1133 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1135 ((arp_key.ip & 0x00ff0000) >> 16),
1136 ((arp_key.ip & 0x0000ff00) >> 8),
1137 ((arp_key.ip & 0x000000ff)),
1140 lib_arp_duplicate_found++;
1141 new_arp_data->retry_count = 0; // Reset
1142 if (rte_timer_reset(new_arp_data->timer,
1143 (arp_timeout * rte_get_tsc_hz()),
1144 SINGLE, timer_lcore,
1146 new_arp_data->timer_key) < 0)
1148 RTE_LOG(INFO, LIBARP,
1149 "Err : Timer already running\n");
1154 RTE_CACHE_LINE_ROUNDUP(sizeof(struct arp_entry_data));
1155 new_arp_data = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1156 new_arp_data->eth_addr = *hw_addr;
1157 new_arp_data->status = COMPLETE;
1158 new_arp_data->port = portid;
1159 new_arp_data->ip = ipaddr;
1160 new_arp_data->mode = mode;
1162 (timer_mempool_arp, (void **)&(new_arp_data->timer)) < 0) {
1163 RTE_LOG(INFO, LIBARP,
1164 "TIMER - Error in getting timer alloc buffer\n");
1168 rte_hash_add_key_data(arp_hash_handle, &arp_key, new_arp_data);
1169 if (ARPICMP_DEBUG) {
1170 RTE_LOG(INFO, LIBARP,
1171 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1173 ((arp_key.ip & 0x00ff0000) >> 16),
1174 ((arp_key.ip & 0x0000ff00) >> 8),
1175 ((arp_key.ip & 0x000000ff)), arp_key.port_id);
1177 // Call l3fwd module for resolving 2_adj structure.
1178 resolve_l2_adj(ipaddr, portid, hw_addr);
1180 rte_timer_init(new_arp_data->timer);
1181 struct arp_timer_key *callback_key =
1182 (struct arp_timer_key *)rte_malloc(NULL,
1185 RTE_CACHE_LINE_SIZE);
1186 callback_key->port_id = portid;
1187 callback_key->ip = ipaddr;
1190 RTE_LOG(INFO, LIBARP, "TIMER STARTED FOR %u seconds\n",
1193 (new_arp_data->timer, (arp_timeout * rte_get_tsc_hz()),
1194 SINGLE, timer_lcore, arp_timer_callback, callback_key) < 0)
1196 RTE_LOG(INFO, LIBARP,
1197 "Err : Timer already running\n");
1199 new_arp_data->timer_key = callback_key;
1202 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1203 if (ARPICMP_DEBUG) {
1204 RTE_LOG(INFO, LIBARP,
1205 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1207 ((arp_key.ip & 0x00ff0000) >> 16),
1208 ((arp_key.ip & 0x0000ff00) >> 8),
1209 ((arp_key.ip & 0x000000ff)),
1212 lib_arp_duplicate_found++;
1215 RTE_CACHE_LINE_ROUNDUP(sizeof
1216 (struct arp_entry_data));
1218 rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1219 new_arp_data->eth_addr = *hw_addr;
1220 new_arp_data->status = COMPLETE;
1221 new_arp_data->port = portid;
1222 new_arp_data->ip = ipaddr;
1223 new_arp_data->mode = mode;
1225 rte_hash_add_key_data(arp_hash_handle, &arp_key,
1227 if (ARPICMP_DEBUG) {
1228 RTE_LOG(INFO, LIBARP,
1229 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1231 ((arp_key.ip & 0x00ff0000) >> 16),
1232 ((arp_key.ip & 0x0000ff00) >> 8),
1233 ((arp_key.ip & 0x000000ff)),
1236 // Call l3fwd module for resolving 2_adj structure.
1237 resolve_l2_adj(ipaddr, portid, hw_addr);
1240 if (ARPICMP_DEBUG) {
1241 /* print entire hash table */
1242 RTE_LOG(INFO, LIBARP,
1243 "\tARP: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x ip=%d.%d.%d.%d on port=%d\n",
1244 new_arp_data->eth_addr.addr_bytes[0],
1245 new_arp_data->eth_addr.addr_bytes[1],
1246 new_arp_data->eth_addr.addr_bytes[2],
1247 new_arp_data->eth_addr.addr_bytes[3],
1248 new_arp_data->eth_addr.addr_bytes[4],
1249 new_arp_data->eth_addr.addr_bytes[5],
1250 (arp_key.ip >> 24), ((arp_key.ip & 0x00ff0000) >> 16),
1251 ((arp_key.ip & 0x0000ff00) >> 8),
1252 ((arp_key.ip & 0x000000ff)), portid);
1260 * Install key - data pair in Hash table - From Pipeline Configuration
1264 void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
1265 uint8_t portid, uint8_t mode)
1268 /* need to lock here if multi-threaded */
1269 /* rte_hash_add_key_data is not thread safe */
1271 struct nd_key_ipv6 nd_key;
1272 nd_key.port_id = portid;
1274 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
1275 nd_key.ipv6[i] = ipv6[i];
1277 // RTE_LOG(INFO, LIBARP,"\n");
1282 lib_nd_populate_called++;
1284 /* Validate if key-value pair already exists in the hash table for ND IPv6 */
1285 struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key);
1287 if (mode == DYNAMIC_ND) {
1289 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1292 RTE_LOG(INFO, LIBARP,
1293 "nd_entry exists port %d ipv6 = ",
1295 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1297 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1299 nd_key.ipv6[i + 1]);
1303 lib_nd_duplicate_found++;
1304 RTE_LOG(INFO, LIBARP, "nd_entry exists\n");
1308 RTE_CACHE_LINE_ROUNDUP(sizeof(struct nd_entry_data));
1309 new_nd_data = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1311 //new_nd_data = (struct nd_entry_data *)rte_malloc(NULL, sizeof(struct nd_entry_data *),RTE_CACHE_LINE_SIZE);
1312 new_nd_data->eth_addr = *hw_addr;
1313 new_nd_data->status = COMPLETE;
1314 new_nd_data->port = portid;
1315 new_nd_data->mode = mode;
1317 (timer_mempool_arp, (void **)&(new_nd_data->timer)) < 0) {
1318 RTE_LOG(INFO, LIBARP,
1319 "TIMER - Error in getting timer alloc buffer\n");
1324 RTE_LOG(INFO, LIBARP, "populate_nd_entry ipv6=");
1326 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1327 new_nd_data->ipv6[i] = ipv6[i];
1331 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1333 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1334 new_nd_data->ipv6[i],
1335 new_nd_data->ipv6[i + 1]);
1339 /*Add a key-data pair at hash table for ND IPv6 static routing */
1340 rte_hash_add_key_data(nd_hash_handle, &nd_key, new_nd_data);
1341 /* need to check the return value of the hash add */
1343 /* after the hash is created then time is started */
1344 rte_timer_init(new_nd_data->timer);
1345 struct nd_timer_key *callback_key =
1346 (struct nd_timer_key *)rte_malloc(NULL,
1347 sizeof(struct nd_timer_key
1349 RTE_CACHE_LINE_SIZE);
1350 callback_key->port_id = portid;
1352 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1353 callback_key->ipv6[i] = ipv6[i];
1356 (new_nd_data->timer, (arp_timeout * rte_get_tsc_hz()),
1357 SINGLE, timer_lcore, nd_timer_callback, callback_key) < 0)
1358 RTE_LOG(INFO, LIBARP, "Err : Timer already running\n");
1361 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1363 RTE_LOG(INFO, LIBARP,
1364 "nd_entry exists port %d ipv6 = ",
1366 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1368 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1370 nd_key.ipv6[i + 1]);
1374 lib_nd_duplicate_found++;
1377 RTE_CACHE_LINE_ROUNDUP(sizeof
1378 (struct nd_entry_data));
1380 rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1382 //new_nd_data = (struct nd_entry_data *)rte_malloc(NULL, sizeof(struct nd_entry_data *),RTE_CACHE_LINE_SIZE);
1383 new_nd_data->eth_addr = *hw_addr;
1384 new_nd_data->status = COMPLETE;
1385 new_nd_data->port = portid;
1386 new_nd_data->mode = mode;
1387 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1388 new_nd_data->ipv6[i] = ipv6[i];
1391 /*Add a key-data pair at hash table for ND IPv6 static routing */
1392 rte_hash_add_key_data(nd_hash_handle, &nd_key,
1394 /* need to check the return value of the hash add */
1399 ("\n....Added a key-data pair at rte hash table for ND IPv6 static routing\n");
1402 /* print entire hash table */
1404 ("\tND: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x on port=%d\n",
1405 new_nd_data->eth_addr.addr_bytes[0],
1406 new_nd_data->eth_addr.addr_bytes[1],
1407 new_nd_data->eth_addr.addr_bytes[2],
1408 new_nd_data->eth_addr.addr_bytes[3],
1409 new_nd_data->eth_addr.addr_bytes[4],
1410 new_nd_data->eth_addr.addr_bytes[5], portid);
1411 RTE_LOG(INFO, LIBARP, "\tipv6=");
1412 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1413 new_nd_data->ipv6[i] = ipv6[i];
1414 RTE_LOG(INFO, LIBARP, "%02X%02X ", new_nd_data->ipv6[i],
1415 new_nd_data->ipv6[i + 1]);
1418 RTE_LOG(INFO, LIBARP, "\n");
1424 void print_pkt1(struct rte_mbuf *pkt)
1426 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
1428 RTE_LOG(INFO, LIBARP, "\nPacket Contents...\n");
1429 for (i = 0; i < 20; i++) {
1430 for (j = 0; j < 20; j++)
1431 RTE_LOG(INFO, LIBARP, "%02x ", rd[(20 * i) + j]);
1432 RTE_LOG(INFO, LIBARP, "\n");
1436 struct ether_addr broadcast_ether_addr = {
1437 .addr_bytes[0] = 0xFF,
1438 .addr_bytes[1] = 0xFF,
1439 .addr_bytes[2] = 0xFF,
1440 .addr_bytes[3] = 0xFF,
1441 .addr_bytes[4] = 0xFF,
1442 .addr_bytes[5] = 0xFF,
1445 static const struct ether_addr null_ether_addr = {
1446 .addr_bytes[0] = 0x00,
1447 .addr_bytes[1] = 0x00,
1448 .addr_bytes[2] = 0x00,
1449 .addr_bytes[3] = 0x00,
1450 .addr_bytes[4] = 0x00,
1451 .addr_bytes[5] = 0x00,
1454 #define MAX_NUM_MAC_ADDRESS 16
1455 struct ether_addr link_hw_addr[MAX_NUM_MAC_ADDRESS] = {
1456 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc8} },
1457 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1458 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1459 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1460 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1461 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1462 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1463 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1464 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1465 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1466 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1467 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1468 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1469 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1470 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1471 {.addr_bytes = {0x18, 0x19, 0x1a, 0x1b, 0xcd, 0xef} }
1474 struct ether_addr *get_link_hw_addr(uint8_t out_port)
1476 return &link_hw_addr[out_port];
1479 void request_arp(uint8_t port_id, uint32_t ip)
1482 struct ether_hdr *eth_h;
1483 struct arp_hdr *arp_h;
1485 l2_phy_interface_t *link;
1486 link = ifm_get_port(port_id);
1487 struct rte_mbuf *arp_pkt = lib_arp_pkt;
1489 if (arp_pkt == NULL) {
1491 RTE_LOG(INFO, LIBARP,
1492 "Error allocating arp_pkt rte_mbuf\n");
1496 eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
1498 ether_addr_copy(&broadcast_ether_addr, ð_h->d_addr);
1499 ether_addr_copy((struct ether_addr *)
1500 &link->macaddr[0], ð_h->s_addr);
1501 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
1503 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1504 arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
1505 arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
1506 arp_h->arp_hln = ETHER_ADDR_LEN;
1507 arp_h->arp_pln = sizeof(uint32_t);
1508 arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
1510 ether_addr_copy((struct ether_addr *)
1511 &link->macaddr[0], &arp_h->arp_data.arp_sha);
1512 if (link && link->ipv4_list) {
1513 arp_h->arp_data.arp_sip =
1514 (((ipv4list_t *) (link->ipv4_list))->ipaddr);
1516 ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
1517 arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
1519 RTE_LOG(INFO, LIBARP, "arp tip:%x arp sip :%x\n",
1520 arp_h->arp_data.arp_tip, arp_h->arp_data.arp_sip);
1521 // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
1522 arp_pkt->pkt_len = 42;
1523 arp_pkt->data_len = 42;
1525 if (ARPICMP_DEBUG) {
1526 RTE_LOG(INFO, LIBARP, "Sending arp request\n");
1527 print_mbuf("TX", port_id, arp_pkt, __LINE__);
1530 link->transmit_single_pkt(link, arp_pkt);
1533 struct rte_mbuf *request_echo(uint32_t port_id, uint32_t ip)
1535 struct ether_hdr *eth_h;
1536 struct ipv4_hdr *ip_h;
1537 struct icmp_hdr *icmp_h;
1538 l2_phy_interface_t *port = ifm_get_port(port_id);
1540 struct rte_mbuf *icmp_pkt = lib_arp_pkt;
1541 if (icmp_pkt == NULL) {
1543 RTE_LOG(INFO, LIBARP,
1544 "Error allocating icmp_pkt rte_mbuf\n");
1548 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
1550 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1551 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1553 ip_h->version_ihl = IP_VHL_DEF;
1554 ip_h->type_of_service = 0;
1555 ip_h->total_length =
1556 rte_cpu_to_be_16(sizeof(struct ipv4_hdr) + sizeof(struct icmp_hdr));
1557 ip_h->packet_id = 0xaabb;
1558 ip_h->fragment_offset = 0x0000;
1559 ip_h->time_to_live = 64;
1560 ip_h->next_proto_id = IPPROTO_ICMP;
1561 if (port && port->ipv4_list)
1563 rte_cpu_to_be_32(((ipv4list_t *) port->ipv4_list)->ipaddr);
1564 ip_h->dst_addr = rte_cpu_to_be_32(ip);
1566 ip_h->hdr_checksum = 0;
1567 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
1569 icmp_h->icmp_type = IP_ICMP_ECHO_REQUEST;
1570 icmp_h->icmp_code = 0;
1571 icmp_h->icmp_ident = 0xdead;
1572 icmp_h->icmp_seq_nb = 0xbeef;
1574 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
1577 sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
1578 sizeof(struct icmp_hdr);
1579 icmp_pkt->data_len = icmp_pkt->pkt_len;
1581 print_mbuf("TX", 0, icmp_pkt, __LINE__);
1588 * Function to send ICMP dest unreachable msg
1591 struct rte_mbuf *send_icmp_dest_unreachable_msg(uint32_t src_ip,
1594 struct ether_hdr *eth_h;
1595 struct ipv4_hdr *ip_h;
1596 struct icmp_hdr *icmp_h;
1597 struct rte_mbuf *icmp_pkt = lib_arp_pkt;
1599 if (icmp_pkt == NULL) {
1601 RTE_LOG(INFO, LIBARP,
1602 "Error allocating icmp_pkt rte_mbuf\n");
1606 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
1607 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1608 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1610 ip_h->version_ihl = IP_VHL_DEF;
1611 ip_h->type_of_service = 0;
1612 ip_h->total_length =
1613 rte_cpu_to_be_16(sizeof(struct ipv4_hdr) + sizeof(struct icmp_hdr));
1614 ip_h->packet_id = 0xaabb;
1615 ip_h->fragment_offset = 0x0000;
1616 ip_h->time_to_live = 64;
1617 ip_h->next_proto_id = 1;
1619 ip_h->dst_addr = rte_bswap32(dest_ip);
1620 ip_h->src_addr = rte_bswap32(src_ip);
1622 ip_h->hdr_checksum = 0;
1623 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
1625 icmp_h->icmp_type = 3; /* Destination Unreachable */
1626 icmp_h->icmp_code = 13; /* Communication administratively prohibited */
1628 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
1630 icmp_pkt->pkt_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
1631 sizeof(struct icmp_hdr);
1632 icmp_pkt->data_len = icmp_pkt->pkt_len;
1638 process_arpicmp_pkt_parse(struct rte_mbuf **pkt, uint16_t pkt_num,
1639 uint64_t pkt_mask, l2_phy_interface_t *port)
1641 RTE_SET_USED(pkt_num);
1643 RTE_LOG(INFO, LIBARP,
1644 "============ARP ENTRY================\n");
1647 RTE_LOG(INFO, LIBARP,
1648 "============ARP PROCESS================\n");
1651 uint64_t pkts_for_process = pkt_mask;
1652 for (; pkts_for_process;) {
1653 /**< process only valid packets. */
1654 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_for_process);
1655 uint64_t pkts_mask = 1LLU << pos; /** <bitmask representing only this packet. */
1656 pkts_for_process &= ~pkts_mask; /** <remove this packet from the mask. */
1657 process_arpicmp_pkt(pkt[pos], port);
1662 void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
1664 uint8_t in_port_id = pkt->port;
1665 struct ether_hdr *eth_h;
1666 struct arp_hdr *arp_h;
1667 struct ipv4_hdr *ip_h;
1668 struct icmp_hdr *icmp_h;
1675 eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
1677 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) {
1679 RTE_LOG(INFO, LIBARP, "%s, portid %u. Line %d\n\r",
1680 __FUNCTION__, port->pmdid, __LINE__);
1682 (struct arp_hdr *)((char *)eth_h +
1683 sizeof(struct ether_hdr));
1684 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER)
1685 RTE_LOG(INFO, LIBARP,
1686 "Invalid hardware format of hardware address - not processing ARP req\n");
1687 else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4)
1688 RTE_LOG(INFO, LIBARP,
1689 "Invalid protocol address format - not processing ARP req\n");
1690 else if (arp_h->arp_hln != 6)
1691 RTE_LOG(INFO, LIBARP,
1692 "Invalid hardware address length - not processing ARP req\n");
1693 else if (arp_h->arp_pln != 4)
1694 RTE_LOG(INFO, LIBARP,
1695 "Invalid protocol address length - not processing ARP req\n");
1697 if (port->ipv4_list == NULL) {
1698 RTE_LOG(INFO, LIBARP,
1699 "Ports IPV4 List is NULL.. Unable to Process\n");
1703 if (arp_h->arp_data.arp_tip !=
1704 ((ipv4list_t *) (port->ipv4_list))->ipaddr) {
1705 if (arp_h->arp_data.arp_tip == arp_h->arp_data.arp_sip) {
1707 (struct ether_addr *)&arp_h->arp_data.arp_sha,
1708 rte_cpu_to_be_32(arp_h->arp_data.arp_sip),
1713 RTE_LOG(INFO, LIBARP,"ARP requested IP address mismatches interface IP - discarding\n");
1716 /// revise conditionals to allow processing of requests with target ip = this ip and
1717 // processing of replies to destination ip = this ip
1718 else if (arp_h->arp_op ==
1719 rte_cpu_to_be_16(ARP_OP_REQUEST)) {
1720 if (ARPICMP_DEBUG) {
1721 RTE_LOG(INFO, LIBARP,
1722 "%s, portid %u. Line %d\n\r",
1723 __FUNCTION__, port->pmdid,
1726 RTE_LOG(INFO, LIBARP,
1727 "arp_op %d, ARP_OP_REQUEST %d\n",
1731 print_mbuf("RX", in_port_id, pkt,
1735 populate_arp_entry((struct ether_addr *)
1736 &arp_h->arp_data.arp_sha,
1738 (arp_h->arp_data.arp_sip),
1739 in_port_id, DYNAMIC_ARP);
1742 req_tip = arp_h->arp_data.arp_tip;
1743 ether_addr_copy(ð_h->s_addr, ð_h->d_addr);
1744 ether_addr_copy((struct ether_addr *)&port->macaddr[0], ð_h->s_addr); /**< set sender mac address*/
1745 arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
1746 ether_addr_copy(ð_h->s_addr,
1747 &arp_h->arp_data.arp_sha);
1748 arp_h->arp_data.arp_tip =
1749 arp_h->arp_data.arp_sip;
1750 arp_h->arp_data.arp_sip = req_tip;
1751 ether_addr_copy(ð_h->d_addr,
1752 &arp_h->arp_data.arp_tha);
1755 print_mbuf("TX ARP REPLY PKT",
1756 port->pmdid, pkt, __LINE__);
1757 port->transmit_bulk_pkts(port, &pkt, 1);
1759 print_mbuf("TX", port->pmdid, pkt,
1763 } else if (arp_h->arp_op ==
1764 rte_cpu_to_be_16(ARP_OP_REPLY)) {
1765 if (ARPICMP_DEBUG) {
1766 RTE_LOG(INFO, LIBARP,
1767 "ARP_OP_REPLY received");
1768 print_mbuf("RX", port->pmdid, pkt,
1771 populate_arp_entry((struct ether_addr *)
1772 &arp_h->arp_data.arp_sha,
1775 in_port_id, DYNAMIC_ARP);
1780 RTE_LOG(INFO, LIBARP,
1781 "Invalid ARP opcode - not processing ARP req %x\n",
1786 rte_pktmbuf_free(pkt);
1789 (struct ipv4_hdr *)((char *)eth_h +
1790 sizeof(struct ether_hdr));
1792 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1794 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
1796 if (ip_h->next_proto_id != IPPROTO_ICMP) {
1797 if (ARPICMP_DEBUG) {
1798 RTE_LOG(INFO, LIBARP,
1799 "IP protocol ID is not set to ICMP - discarding\n");
1801 } else if ((ip_h->version_ihl & 0xf0) != IP_VERSION_4) {
1802 if (ARPICMP_DEBUG) {
1803 RTE_LOG(INFO, LIBARP,
1804 "IP version other than 4 - discarding\n");
1806 } else if ((ip_h->version_ihl & 0x0f) != IP_HDRLEN) {
1807 if (ARPICMP_DEBUG) {
1808 RTE_LOG(INFO, LIBARP,
1809 "Unknown IHL - discarding\n");
1812 if (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST
1813 && icmp_h->icmp_code == 0) {
1815 print_mbuf("RX", in_port_id,
1818 ip_addr = ip_h->src_addr;
1819 ether_addr_copy(ð_h->s_addr,
1821 ether_addr_copy((struct ether_addr *)
1825 RTE_LOG(INFO, LIBARP,
1826 "%s, portid %u. Line %d\n\r",
1828 port->pmdid, __LINE__);
1830 if (is_multicast_ipv4_addr
1835 rte_be_to_cpu_32(ip_addr);
1836 if ((ip_src & 0x00000003) == 1)
1847 rte_cpu_to_be_32(ip_src);
1848 ip_h->dst_addr = ip_addr;
1850 ip_h->hdr_checksum = 0;
1851 ip_h->hdr_checksum =
1852 ~rte_raw_cksum(ip_h,
1857 RTE_LOG(INFO, LIBARP,
1858 "%s, portid %u. Line %d\n\r",
1862 ip_h->src_addr = ip_h->dst_addr;
1863 ip_h->dst_addr = ip_addr;
1866 icmp_h->icmp_type = IP_ICMP_ECHO_REPLY;
1867 cksum = ~icmp_h->icmp_cksum & 0xffff;
1869 ~htons(IP_ICMP_ECHO_REQUEST << 8) &
1871 cksum += htons(IP_ICMP_ECHO_REPLY << 8);
1873 (cksum & 0xffff) + (cksum >> 16);
1875 (cksum & 0xffff) + (cksum >> 16);
1876 icmp_h->icmp_cksum = ~cksum;
1880 ("TX ICMP ECHO REPLY PKT",
1881 in_port_id, pkt, __LINE__);
1882 port->transmit_bulk_pkts(port, &pkt, 1);
1884 print_mbuf("TX", port->pmdid,
1888 } else if (icmp_h->icmp_type ==
1890 && icmp_h->icmp_code == 0) {
1892 print_mbuf("RX", in_port_id,
1895 struct arp_key_ipv4 arp_key;
1896 arp_key.port_id = in_port_id;
1898 rte_bswap32(ip_h->src_addr);
1899 arp_key.filler1 = 0;
1900 arp_key.filler2 = 0;
1901 arp_key.filler3 = 0;
1903 struct arp_entry_data *arp_entry =
1904 retrieve_arp_entry(arp_key);
1905 if (arp_entry == NULL) {
1907 RTE_LOG(INFO, LIBARP,
1908 "Received unsolicited ICMP echo reply from ip%x, port %d\n",
1913 arp_entry->status = COMPLETE;
1918 rte_pktmbuf_free(pkt);
1923 * inet_pton(af, src, dst)
1924 * convert from presentation format (which usually means ASCII printable)
1925 * to network format (which is usually some kind of binary format).
1927 * 1 if the address was valid for the specified address family
1928 * 0 if the address wasn't valid (`dst' is untouched in this case)
1929 * -1 if some other error occurred (`dst' is untouched in this case, too)
1933 static int my_inet_pton_ipv6(int af, const char *src, void *dst)
1937 return inet_pton_ipv4(src, dst);
1939 return inet_pton_ipv6(src, dst);
1941 errno = EAFNOSUPPORT;
1948 * inet_pton_ipv4(src, dst)
1949 * like inet_aton() but without all the hexadecimal and shorthand.
1951 * 1 if `src' is a valid dotted quad, else 0.
1953 * does not touch `dst' unless it's returning 1.
1957 static int inet_pton_ipv4(const char *src, unsigned char *dst)
1959 static const char digits[] = "0123456789";
1960 int saw_digit, octets, ch;
1961 unsigned char tmp[INADDRSZ], *tp;
1966 while ((ch = *src++) != '\0') {
1969 pch = strchr(digits, ch);
1971 unsigned int new = *tp * 10 + (pch - digits);
1980 *tp = (unsigned char)new;
1981 } else if (ch == '.' && saw_digit) {
1992 memcpy(dst, tmp, INADDRSZ);
1997 * inet_pton_ipv6(src, dst)
1998 * convert presentation level address to network order binary form.
2000 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
2002 * (1) does not touch `dst' unless it's returning 1.
2003 * (2) :: in a full address is silently ignored.
2005 * inspired by Mark Andrews.
2009 static int inet_pton_ipv6(const char *src, unsigned char *dst)
2011 static const char xdigits_l[] = "0123456789abcdef",
2012 xdigits_u[] = "0123456789ABCDEF";
2013 unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
2014 const char *xdigits = 0, *curtok = 0;
2015 int ch = 0, saw_xdigit = 0, count_xdigit = 0;
2016 unsigned int val = 0;
2017 unsigned int dbloct_count = 0;
2019 memset((tp = tmp), '\0', IN6ADDRSZ);
2020 endp = tp + IN6ADDRSZ;
2022 /* Leading :: requires some special handling. */
2027 saw_xdigit = count_xdigit = 0;
2030 while ((ch = *src++) != '\0') {
2033 pch = strchr((xdigits = xdigits_l), ch);
2035 pch = strchr((xdigits = xdigits_u), ch);
2037 if (count_xdigit >= 4)
2040 val |= (pch - xdigits);
2054 } else if (*src == '\0') {
2057 if (tp + sizeof(int16_t) > endp)
2059 *tp++ = (unsigned char)((val >> 8) & 0xff);
2060 *tp++ = (unsigned char)(val & 0xff);
2067 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
2068 inet_pton_ipv4(curtok, tp) > 0) {
2072 break; /* '\0' was seen by inet_pton4(). */
2077 if (tp + sizeof(int16_t) > endp)
2079 *tp++ = (unsigned char)((val >> 8) & 0xff);
2080 *tp++ = (unsigned char)(val & 0xff);
2083 if (colonp != NULL) {
2084 /* if we already have 8 double octets, having a colon means error */
2085 if (dbloct_count == 8)
2089 * Since some memmove()'s erroneously fail to handle
2090 * overlapping regions, we'll do the shift by hand.
2092 const int n = tp - colonp;
2095 for (i = 1; i <= n; i++) {
2096 endp[-i] = colonp[n - i];
2103 memcpy(dst, tmp, IN6ADDRSZ);
2107 static int arp_parse_args(struct pipeline_params *params)
2109 uint32_t arp_route_tbl_present = 0;
2110 uint32_t nd_route_tbl_present = 0;
2111 uint32_t ports_mac_list_present = 0;
2113 uint32_t n_vnf_threads_present = 0;
2115 uint32_t pktq_in_prv_present = 0;
2116 uint32_t prv_to_pub_map_present = 0;
2118 uint8_t n_prv_in_port = 0;
2120 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
2121 in_port_dir_a[i] = 0; //make all RX ports ingress initially
2122 prv_to_pub_map[i] = 0xff;
2123 pub_to_prv_map[i] = 0xff;
2126 RTE_SET_USED(ports_mac_list_present);
2127 RTE_SET_USED(nd_route_tbl_present);
2128 RTE_SET_USED(arp_route_tbl_present);
2129 for (numArg = 0; numArg < params->n_args; numArg++) {
2130 char *arg_name = params->args_name[numArg];
2131 char *arg_value = params->args_value[numArg];
2133 /* arp timer expiry */
2134 if (strcmp(arg_name, "arp_timer_expiry") == 0) {
2135 arp_timeout = atoi(arg_value);
2139 if (strcmp(arg_name, "pktq_in_prv") == 0) {
2140 if (pktq_in_prv_present) {
2142 ("Duplicate pktq_in_prv ... parse failed..\n\n");
2145 pktq_in_prv_present = 1;
2147 int rxport = 0, j = 0;
2148 char phy_port_num[5];
2149 char *token = strtok(arg_value, "RXQ");
2152 while ((j < 4) && (token[j] != '.')) {
2153 phy_port_num[j] = token[j];
2156 phy_port_num[j] = '\0';
2157 rxport = atoi(phy_port_num);
2158 prv_in_port_a[n_prv_in_port++] = rxport;
2162 ("token: %s, phy_port_str: %s, phy_port_num %d\n",
2163 token, phy_port_num, rxport);
2164 prv_in_port_a[n_prv_in_port++] = rxport;
2165 if(rxport < PIPELINE_MAX_PORT_IN)
2166 in_port_dir_a[rxport] = 1; // set rxport egress
2167 token = strtok(NULL, "RXQ");
2170 if (n_prv_in_port == 0) {
2172 ("VNF common parse error - no prv RX phy port\n");
2178 /* prv_to_pub_map */
2179 if (strcmp(arg_name, "prv_to_pub_map") == 0) {
2180 if (prv_to_pub_map_present) {
2182 ("Duplicated prv_to_pub_map ... parse failed ...\n");
2185 prv_to_pub_map_present = 1;
2187 int rxport = 0, txport = 0, j = 0, k = 0;
2188 char rx_phy_port_num[5];
2189 char tx_phy_port_num[5];
2190 char *token = strtok(arg_value, "(");
2193 while ((j < 4) && (token[j] != ',')) {
2194 rx_phy_port_num[j] = token[j];
2197 rx_phy_port_num[j] = '\0';
2198 rxport = atoi(rx_phy_port_num);
2204 while ((k < 4) && (token[j + k] != ')')) {
2205 tx_phy_port_num[k] = token[j + k];
2208 tx_phy_port_num[k] = '\0';
2209 txport = atoi(tx_phy_port_num);
2213 RTE_LOG(INFO, LIBARP, "token: %s,"
2214 "rx_phy_port_str: %s, phy_port_num %d,"
2215 "tx_phy_port_str: %s, tx_phy_port_num %d\n",
2216 token, rx_phy_port_num, rxport,
2217 tx_phy_port_num, txport);
2219 if ((rxport >= PIPELINE_MAX_PORT_IN) ||
2220 (txport >= PIPELINE_MAX_PORT_IN) ||
2221 (in_port_dir_a[rxport] != 1)) {
2223 ("CG-NAPT parse error - incorrect prv-pub translation. Rx %d, Tx %d, Rx Dir %d\n",
2225 in_port_dir_a[rxport]);
2229 prv_to_pub_map[rxport] = txport;
2230 pub_to_prv_map[txport] = rxport;
2231 token = strtok(NULL, "(");
2237 if (strcmp(arg_name, "n_vnf_threads") == 0) {
2238 if (n_vnf_threads_present)
2240 n_vnf_threads_present = 1;
2242 num_vnf_threads = atoi(arg_value);
2243 if (num_vnf_threads <= 0) {
2244 RTE_LOG(INFO, LIBARP,
2245 "n_vnf_threads is invalid\n");
2248 RTE_LOG(INFO, LIBARP, "n_vnf_threads: 0x%x\n",
2253 if (strcmp(arg_name, "lib_arp_debug") == 0) {
2254 ARPICMP_DEBUG = atoi(arg_value);
2259 /* ports_mac_list */
2260 if (strcmp(arg_name, "ports_mac_list") == 0) {
2261 ports_mac_list_present = 1;
2263 uint32_t i = 0, j = 0, k = 0, MAC_NUM_BYTES = 6;
2265 char byteStr[MAC_NUM_BYTES][3];
2266 uint32_t byte[MAC_NUM_BYTES];
2268 char *token = strtok(arg_value, " ");
2271 for (i = 0; i < MAC_NUM_BYTES; i++) {
2272 for (j = 0; j < 2; j++) {
2273 byteStr[i][j] = token[k++];
2275 byteStr[i][j] = '\0';
2279 for (i = 0; i < MAC_NUM_BYTES; i++) {
2280 byte[i] = strtoul(byteStr[i], NULL, 16);
2283 if (ARPICMP_DEBUG) {
2284 RTE_LOG(INFO, LIBARP, "token: %s",
2286 for (i = 0; i < MAC_NUM_BYTES; i++)
2287 RTE_LOG(INFO, LIBARP,
2290 RTE_LOG(INFO, LIBARP, "\n");
2292 //Populate the static arp_route_table
2293 for (i = 0; i < MAC_NUM_BYTES; i++)
2295 [link_hw_addr_array_idx].addr_bytes
2298 link_hw_addr_array_idx++;
2299 token = strtok(NULL, " ");
2306 if (strcmp(arg_name, "arp_route_tbl") == 0) {
2307 arp_route_tbl_present = 1;
2309 uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip =
2310 0, i = 0, j = 0, k = 0, l = 0;
2311 uint32_t arp_route_tbl_str_max_len = 10;
2312 char dest_ip_str[arp_route_tbl_str_max_len];
2313 char mask_str[arp_route_tbl_str_max_len];
2314 char tx_port_str[arp_route_tbl_str_max_len];
2315 char nh_ip_str[arp_route_tbl_str_max_len];
2316 char *token = strtok(arg_value, "(");
2319 while ((i < (arp_route_tbl_str_max_len - 1))
2320 && (token[i] != ',')) {
2321 dest_ip_str[i] = token[i];
2324 dest_ip_str[i] = '\0';
2325 dest_ip = strtoul(dest_ip_str, NULL, 16);
2329 while ((j < (arp_route_tbl_str_max_len - 1))
2330 && (token[i + j] != ',')) {
2331 mask_str[j] = token[i + j];
2335 mask = strtoul(mask_str, NULL, 16);
2339 while ((k < (arp_route_tbl_str_max_len - 1))
2340 && (token[i + j + k] != ',')) {
2341 tx_port_str[k] = token[i + j + k];
2344 tx_port_str[k] = '\0';
2345 tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str);
2349 while ((l < (arp_route_tbl_str_max_len - 1))
2350 && (token[i + j + k + l] != ')')) {
2351 nh_ip_str[l] = token[i + j + k + l];
2354 nh_ip_str[l] = '\0';
2355 nh_ip = strtoul(nh_ip_str, NULL, 16); //atoi(nh_ip_str);
2358 RTE_LOG(INFO, LIBARP, "token: %s, "
2359 "dest_ip_str: %s, dest_ip %u, "
2360 "mask_str: %s, mask %u, "
2361 "tx_port_str: %s, tx_port %u, "
2362 "nh_ip_str: %s, nh_ip %u\n",
2363 token, dest_ip_str, dest_ip,
2364 mask_str, mask, tx_port_str,
2365 tx_port, nh_ip_str, nh_ip);
2368 /* if (tx_port >= params->n_ports_out)
2370 RTE_LOG(INFO, LIBARP,"ARP-ICMP parse error - incorrect tx_port %d, max %d\n",
2371 tx_port, params->n_ports_out);
2375 //Populate the static arp_route_table
2376 lib_arp_route_table[arp_route_tbl_index].ip =
2378 lib_arp_route_table[arp_route_tbl_index].mask =
2380 lib_arp_route_table[arp_route_tbl_index].port =
2382 lib_arp_route_table[arp_route_tbl_index].nh =
2384 arp_route_tbl_index++;
2385 token = strtok(NULL, "(");
2392 if (strcmp(arg_name, "nd_route_tbl") == 0) {
2393 nd_route_tbl_present = 1;
2395 uint8_t dest_ipv6[16], depth = 0, tx_port =
2396 0, nh_ipv6[16], i = 0, j = 0, k = 0, l = 0;
2397 uint8_t nd_route_tbl_str_max_len = 128; //64;
2398 char dest_ipv6_str[nd_route_tbl_str_max_len];
2399 char depth_str[nd_route_tbl_str_max_len];
2400 char tx_port_str[nd_route_tbl_str_max_len];
2401 char nh_ipv6_str[nd_route_tbl_str_max_len];
2402 char *token = strtok(arg_value, "(");
2405 while ((i < (nd_route_tbl_str_max_len - 1))
2406 && (token[i] != ',')) {
2407 dest_ipv6_str[i] = token[i];
2410 dest_ipv6_str[i] = '\0';
2411 my_inet_pton_ipv6(AF_INET6, dest_ipv6_str,
2416 while ((j < (nd_route_tbl_str_max_len - 1))
2417 && (token[i + j] != ',')) {
2418 depth_str[j] = token[i + j];
2421 depth_str[j] = '\0';
2422 //converting string char to integer
2424 for (s = 0; depth_str[s] != '\0'; ++s)
2425 depth = depth * 10 + depth_str[s] - '0';
2429 while ((k < (nd_route_tbl_str_max_len - 1))
2430 && (token[i + j + k] != ',')) {
2431 tx_port_str[k] = token[i + j + k];
2434 tx_port_str[k] = '\0';
2435 tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str);
2439 while ((l < (nd_route_tbl_str_max_len - 1))
2440 && (token[i + j + k + l] != ')')) {
2441 nh_ipv6_str[l] = token[i + j + k + l];
2444 nh_ipv6_str[l] = '\0';
2445 my_inet_pton_ipv6(AF_INET6, nh_ipv6_str,
2448 //Populate the static arp_route_table
2449 for (i = 0; i < 16; i++) {
2451 [nd_route_tbl_index].ipv6[i] =
2454 [nd_route_tbl_index].nhipv6[i] =
2457 lib_nd_route_table[nd_route_tbl_index].depth =
2459 lib_nd_route_table[nd_route_tbl_index].port =
2462 nd_route_tbl_index++;
2463 token = strtok(NULL, "(");
2471 /* Check that mandatory arguments are present */
2473 if ((arp_route_tbl_present == 0) || (ports_mac_list_present == 0)) {
2474 RTE_LOG(INFO, LIBARP,"VNF common not all mandatory arguments are present\n");
2475 RTE_LOG(INFO, LIBARP,"%d, %d \n",
2476 arp_route_tbl_present, ports_mac_list_present);
2484 void lib_arp_init(struct pipeline_params *params,
2485 __rte_unused struct app_params *app)
2488 RTE_LOG(INFO, LIBARP, "ARP initialization ...\n");
2490 /* Parse arguments */
2491 if (arp_parse_args(params)) {
2492 RTE_LOG(INFO, LIBARP, "arp_parse_args failed ...\n");
2496 /* create the arp_icmp mbuf rx pool */
2497 lib_arp_pktmbuf_tx_pool =
2498 rte_pktmbuf_pool_create("lib_arp_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2499 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2502 if (lib_arp_pktmbuf_tx_pool == NULL) {
2503 RTE_LOG(INFO, LIBARP, "ARP mbuf pool create failed.\n");
2507 lib_arp_pkt = rte_pktmbuf_alloc(lib_arp_pktmbuf_tx_pool);
2508 if (lib_arp_pkt == NULL) {
2509 RTE_LOG(INFO, LIBARP, "ARP lib_arp_pkt alloc failed.\n");
2513 arp_hash_params.socket_id = rte_socket_id();
2514 arp_hash_params.entries = MAX_NUM_ARP_ENTRIES;
2515 arp_hash_params.key_len = sizeof(struct arp_key_ipv4);
2516 arp_hash_handle = rte_hash_create(&arp_hash_params);
2518 if (arp_hash_handle == NULL) {
2519 RTE_LOG(INFO, LIBARP,
2520 "ARP rte_hash_create failed. socket %d ... \n",
2521 arp_hash_params.socket_id);
2523 RTE_LOG(INFO, LIBARP, "arp_hash_handle %p\n\n",
2524 (void *)arp_hash_handle);
2527 /* Create port alloc buffer */
2529 timer_mempool_arp = rte_mempool_create("timer_mempool_arp",
2530 timer_objs_mempool_count,
2531 sizeof(struct rte_timer),
2534 NULL, NULL, rte_socket_id(), 0);
2535 if (timer_mempool_arp == NULL) {
2536 rte_panic("timer_mempool create error\n");
2538 rte_timer_subsystem_init();
2539 list_add_type(ETHER_TYPE_ARP, process_arpicmp_pkt_parse);
2542 nd_hash_params.socket_id = rte_socket_id();
2543 nd_hash_params.entries = MAX_NUM_ND_ENTRIES;
2544 nd_hash_params.key_len = sizeof(struct nd_key_ipv6);
2545 nd_hash_handle = rte_hash_create(&nd_hash_params);
2546 if (nd_hash_handle == NULL) {
2547 RTE_LOG(INFO, LIBARP,
2548 "ND rte_hash_create failed. socket %d ... \n",
2549 nd_hash_params.socket_id);
2551 RTE_LOG(INFO, LIBARP, "nd_hash_handle %p\n\n",
2552 (void *)nd_hash_handle);
2558 void arp_timer_callback(struct rte_timer *timer, void *arg)
2560 struct arp_timer_key *remove_key = (struct arp_timer_key *)arg;
2562 RTE_LOG(INFO, LIBARP, "ARP TIMER callback : expire :%d\n",
2563 (int)timer->expire);
2565 RTE_LOG(INFO, LIBARP,
2566 "Remove ARP Entry for IP :%d.%d.%d.%d , port %d\n",
2567 (remove_key->ip >> 24),
2568 ((remove_key->ip & 0x00ff0000) >> 16),
2569 ((remove_key->ip & 0x0000ff00) >> 8),
2570 ((remove_key->ip & 0x000000ff)), remove_key->port_id);
2571 remove_arp_entry((uint32_t) remove_key->ip,
2572 (uint8_t) remove_key->port_id, arg);
2576 void nd_timer_callback(struct rte_timer *timer, void *arg)
2578 struct nd_timer_key *remove_key = (struct nd_timer_key *)arg;
2580 RTE_LOG(INFO, LIBARP, "nd time callback : expire :%d\n",
2581 (int)timer->expire);
2582 remove_nd_entry_ipv6(remove_key->ipv6, remove_key->port_id);
2586 void create_arp_table(void)
2590 for (i = 0; i < MAX_ARP_DATA_ENTRY_TABLE; i++) {
2591 populate_arp_entry((const struct ether_addr *)
2592 &arp_entry_data_table[i].eth_addr,
2593 arp_entry_data_table[i].ip,
2594 (uint8_t) arp_entry_data_table[i].port,
2601 void create_nd_table(void)
2605 for (i = 0; i < MAX_ND_DATA_ENTRY_TABLE; i++) {
2606 populate_nd_entry((const struct ether_addr *)
2607 nd_entry_data_table[i].eth_addr,
2608 nd_entry_data_table[i].ipv6,
2609 (uint8_t) nd_entry_data_table[i].port,
2616 void send_gratuitous_arp(l2_phy_interface_t *port)
2618 struct ether_hdr *eth_h;
2619 struct arp_hdr *arp_h;
2621 struct rte_mbuf *arp_pkt = lib_arp_pkt;
2624 RTE_LOG(INFO, LIBARP, "PORT ID DOWN.. %s\n", __FUNCTION__);
2629 if (arp_pkt == NULL) {
2631 RTE_LOG(INFO, LIBARP,
2632 "Error allocating arp_pkt rte_mbuf\n");
2636 eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
2638 ether_addr_copy(&broadcast_ether_addr, ð_h->d_addr);
2639 ether_addr_copy((struct ether_addr *)
2640 &port->macaddr[0], ð_h->s_addr);
2641 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
2643 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
2644 arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
2645 arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
2646 arp_h->arp_hln = ETHER_ADDR_LEN;
2647 arp_h->arp_pln = sizeof(uint32_t);
2648 arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
2650 ether_addr_copy((struct ether_addr *)
2651 &port->macaddr[0], &arp_h->arp_data.arp_sha);
2652 if (port->ipv4_list == NULL) {
2654 RTE_LOG(INFO, LIBARP, "port->ipv4_list is NULL.. %s\n",
2658 arp_h->arp_data.arp_sip = (((ipv4list_t *) (port->ipv4_list))->ipaddr);
2659 ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
2660 //arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
2661 arp_h->arp_data.arp_tip = 0; //(((ipv4list_t *) (port->ipv4_list))->ipaddr);
2662 // RTE_LOG(INFO, LIBARP,"arp tip:%x arp sip :%x\n", arp_h->arp_data.arp_tip,
2663 //arp_h->arp_data.arp_sip);
2664 // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
2665 arp_pkt->pkt_len = 42;
2666 arp_pkt->data_len = 42;
2668 if (ARPICMP_DEBUG) {
2669 RTE_LOG(INFO, LIBARP, "SENDING GRATUITOUS ARP REQUEST\n");
2670 print_mbuf("TX", port->pmdid, arp_pkt, __LINE__);
2672 port->transmit_single_pkt(port, arp_pkt);
2675 void set_arpdebug(int flag)
2678 RTE_LOG(INFO, LIBARP, "Debugs turned on\n\r");
2683 RTE_LOG(INFO, LIBARP, "Debugs turned off\n\r");
2689 void set_arptimeout(uint32_t timeout_val)
2691 if (timeout_val == 0) {
2692 RTE_LOG(INFO, LIBARP, "Cannot be zero...\n\r");
2696 RTE_LOG(INFO, LIBARP,
2697 "set_arptimeout: arp_timeout %u, timeout_val %u\n\r",
2698 arp_timeout, timeout_val);
2699 arp_timeout = timeout_val;
2701 RTE_LOG(INFO, LIBARP, "set_arptimeout: arp_timeout %u\n\r",