16e9530b3b636dba5e08ba8962ea3a65a0b4fdc4
[dpdk.git] / examples / l3fwd-acl / main.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2016 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdint.h>
8 #include <inttypes.h>
9 #include <sys/types.h>
10 #include <string.h>
11 #include <sys/queue.h>
12 #include <stdarg.h>
13 #include <errno.h>
14 #include <getopt.h>
15
16 #include <rte_common.h>
17 #include <rte_byteorder.h>
18 #include <rte_log.h>
19 #include <rte_memory.h>
20 #include <rte_memcpy.h>
21 #include <rte_eal.h>
22 #include <rte_launch.h>
23 #include <rte_atomic.h>
24 #include <rte_cycles.h>
25 #include <rte_prefetch.h>
26 #include <rte_lcore.h>
27 #include <rte_per_lcore.h>
28 #include <rte_branch_prediction.h>
29 #include <rte_interrupts.h>
30 #include <rte_random.h>
31 #include <rte_debug.h>
32 #include <rte_ether.h>
33 #include <rte_ethdev.h>
34 #include <rte_mempool.h>
35 #include <rte_mbuf.h>
36 #include <rte_ip.h>
37 #include <rte_tcp.h>
38 #include <rte_udp.h>
39 #include <rte_string_fns.h>
40 #include <rte_acl.h>
41
42 #include <cmdline_parse.h>
43 #include <cmdline_parse_etheraddr.h>
44
45 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
46 #define L3FWDACL_DEBUG
47 #endif
48 #define DO_RFC_1812_CHECKS
49
50 #define RTE_LOGTYPE_L3FWD RTE_LOGTYPE_USER1
51
52 #define MAX_JUMBO_PKT_LEN  9600
53
54 #define MEMPOOL_CACHE_SIZE 256
55
56 /*
57  * This expression is used to calculate the number of mbufs needed
58  * depending on user input, taking into account memory for rx and tx hardware
59  * rings, cache per lcore and mtable per port per lcore.
60  * RTE_MAX is used to ensure that NB_MBUF never goes below a
61  * minimum value of 8192
62  */
63
64 #define NB_MBUF RTE_MAX(\
65         (nb_ports * nb_rx_queue * nb_rxd +      \
66         nb_ports * nb_lcores * MAX_PKT_BURST +  \
67         nb_ports * n_tx_queue * nb_txd +        \
68         nb_lcores * MEMPOOL_CACHE_SIZE),        \
69         (unsigned)8192)
70
71 #define MAX_PKT_BURST 32
72 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
73
74 #define NB_SOCKETS 8
75
76 /* Configure how many packets ahead to prefetch, when reading packets */
77 #define PREFETCH_OFFSET 3
78
79 /*
80  * Configurable number of RX/TX ring descriptors
81  */
82 #define RTE_TEST_RX_DESC_DEFAULT 1024
83 #define RTE_TEST_TX_DESC_DEFAULT 1024
84 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
85 static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
86
87 /* mask of enabled ports */
88 static uint32_t enabled_port_mask;
89 static int promiscuous_on; /**< Ports set in promiscuous mode off by default. */
90 static int numa_on = 1; /**< NUMA is enabled by default. */
91
92 struct lcore_rx_queue {
93         uint16_t port_id;
94         uint8_t queue_id;
95 } __rte_cache_aligned;
96
97 #define MAX_RX_QUEUE_PER_LCORE 16
98 #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS
99 #define MAX_RX_QUEUE_PER_PORT 128
100
101 #define MAX_LCORE_PARAMS 1024
102 struct lcore_params {
103         uint16_t port_id;
104         uint8_t queue_id;
105         uint8_t lcore_id;
106 } __rte_cache_aligned;
107
108 static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS];
109 static struct lcore_params lcore_params_array_default[] = {
110         {0, 0, 2},
111         {0, 1, 2},
112         {0, 2, 2},
113         {1, 0, 2},
114         {1, 1, 2},
115         {1, 2, 2},
116         {2, 0, 2},
117         {3, 0, 3},
118         {3, 1, 3},
119 };
120
121 static struct lcore_params *lcore_params = lcore_params_array_default;
122 static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) /
123                                 sizeof(lcore_params_array_default[0]);
124
125 static struct rte_eth_conf port_conf = {
126         .rxmode = {
127                 .mq_mode        = ETH_MQ_RX_RSS,
128                 .max_rx_pkt_len = RTE_ETHER_MAX_LEN,
129                 .split_hdr_size = 0,
130                 .offloads = DEV_RX_OFFLOAD_CHECKSUM,
131         },
132         .rx_adv_conf = {
133                 .rss_conf = {
134                         .rss_key = NULL,
135                         .rss_hf = ETH_RSS_IP | ETH_RSS_UDP |
136                                 ETH_RSS_TCP | ETH_RSS_SCTP,
137                 },
138         },
139         .txmode = {
140                 .mq_mode = ETH_MQ_TX_NONE,
141         },
142 };
143
144 static struct rte_mempool *pktmbuf_pool[NB_SOCKETS];
145
146 /* ethernet addresses of ports */
147 static struct rte_ether_hdr port_l2hdr[RTE_MAX_ETHPORTS];
148
149 /***********************start of ACL part******************************/
150 #ifdef DO_RFC_1812_CHECKS
151 static inline int
152 is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len);
153 #endif
154 static inline void
155 send_single_packet(struct rte_mbuf *m, uint16_t port);
156
157 #define MAX_ACL_RULE_NUM        100000
158 #define DEFAULT_MAX_CATEGORIES  1
159 #define L3FWD_ACL_IPV4_NAME     "l3fwd-acl-ipv4"
160 #define L3FWD_ACL_IPV6_NAME     "l3fwd-acl-ipv6"
161 #define ACL_LEAD_CHAR           ('@')
162 #define ROUTE_LEAD_CHAR         ('R')
163 #define COMMENT_LEAD_CHAR       ('#')
164 #define OPTION_CONFIG           "config"
165 #define OPTION_NONUMA           "no-numa"
166 #define OPTION_ENBJMO           "enable-jumbo"
167 #define OPTION_RULE_IPV4        "rule_ipv4"
168 #define OPTION_RULE_IPV6        "rule_ipv6"
169 #define OPTION_SCALAR           "scalar"
170 #define OPTION_ETH_DEST         "eth-dest"
171 #define ACL_DENY_SIGNATURE      0xf0000000
172 #define RTE_LOGTYPE_L3FWDACL    RTE_LOGTYPE_USER3
173 #define acl_log(format, ...)    RTE_LOG(ERR, L3FWDACL, format, ##__VA_ARGS__)
174 #define uint32_t_to_char(ip, a, b, c, d) do {\
175                 *a = (unsigned char)(ip >> 24 & 0xff);\
176                 *b = (unsigned char)(ip >> 16 & 0xff);\
177                 *c = (unsigned char)(ip >> 8 & 0xff);\
178                 *d = (unsigned char)(ip & 0xff);\
179         } while (0)
180 #define OFF_ETHHEAD     (sizeof(struct rte_ether_hdr))
181 #define OFF_IPV42PROTO (offsetof(struct rte_ipv4_hdr, next_proto_id))
182 #define OFF_IPV62PROTO (offsetof(struct rte_ipv6_hdr, proto))
183 #define MBUF_IPV4_2PROTO(m)     \
184         rte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV42PROTO)
185 #define MBUF_IPV6_2PROTO(m)     \
186         rte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV62PROTO)
187
188 #define GET_CB_FIELD(in, fd, base, lim, dlm)    do {            \
189         unsigned long val;                                      \
190         char *end;                                              \
191         errno = 0;                                              \
192         val = strtoul((in), &end, (base));                      \
193         if (errno != 0 || end[0] != (dlm) || val > (lim))       \
194                 return -EINVAL;                               \
195         (fd) = (typeof(fd))val;                                 \
196         (in) = end + 1;                                         \
197 } while (0)
198
199 /*
200   * ACL rules should have higher priorities than route ones to ensure ACL rule
201   * always be found when input packets have multi-matches in the database.
202   * A exception case is performance measure, which can define route rules with
203   * higher priority and route rules will always be returned in each lookup.
204   * Reserve range from ACL_RULE_PRIORITY_MAX + 1 to
205   * RTE_ACL_MAX_PRIORITY for route entries in performance measure
206   */
207 #define ACL_RULE_PRIORITY_MAX 0x10000000
208
209 /*
210   * Forward port info save in ACL lib starts from 1
211   * since ACL assume 0 is invalid.
212   * So, need add 1 when saving and minus 1 when forwarding packets.
213   */
214 #define FWD_PORT_SHIFT 1
215
216 /*
217  * Rule and trace formats definitions.
218  */
219
220 enum {
221         PROTO_FIELD_IPV4,
222         SRC_FIELD_IPV4,
223         DST_FIELD_IPV4,
224         SRCP_FIELD_IPV4,
225         DSTP_FIELD_IPV4,
226         NUM_FIELDS_IPV4
227 };
228
229 /*
230  * That effectively defines order of IPV4VLAN classifications:
231  *  - PROTO
232  *  - VLAN (TAG and DOMAIN)
233  *  - SRC IP ADDRESS
234  *  - DST IP ADDRESS
235  *  - PORTS (SRC and DST)
236  */
237 enum {
238         RTE_ACL_IPV4VLAN_PROTO,
239         RTE_ACL_IPV4VLAN_VLAN,
240         RTE_ACL_IPV4VLAN_SRC,
241         RTE_ACL_IPV4VLAN_DST,
242         RTE_ACL_IPV4VLAN_PORTS,
243         RTE_ACL_IPV4VLAN_NUM
244 };
245
246 struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
247         {
248                 .type = RTE_ACL_FIELD_TYPE_BITMASK,
249                 .size = sizeof(uint8_t),
250                 .field_index = PROTO_FIELD_IPV4,
251                 .input_index = RTE_ACL_IPV4VLAN_PROTO,
252                 .offset = 0,
253         },
254         {
255                 .type = RTE_ACL_FIELD_TYPE_MASK,
256                 .size = sizeof(uint32_t),
257                 .field_index = SRC_FIELD_IPV4,
258                 .input_index = RTE_ACL_IPV4VLAN_SRC,
259                 .offset = offsetof(struct rte_ipv4_hdr, src_addr) -
260                         offsetof(struct rte_ipv4_hdr, next_proto_id),
261         },
262         {
263                 .type = RTE_ACL_FIELD_TYPE_MASK,
264                 .size = sizeof(uint32_t),
265                 .field_index = DST_FIELD_IPV4,
266                 .input_index = RTE_ACL_IPV4VLAN_DST,
267                 .offset = offsetof(struct rte_ipv4_hdr, dst_addr) -
268                         offsetof(struct rte_ipv4_hdr, next_proto_id),
269         },
270         {
271                 .type = RTE_ACL_FIELD_TYPE_RANGE,
272                 .size = sizeof(uint16_t),
273                 .field_index = SRCP_FIELD_IPV4,
274                 .input_index = RTE_ACL_IPV4VLAN_PORTS,
275                 .offset = sizeof(struct rte_ipv4_hdr) -
276                         offsetof(struct rte_ipv4_hdr, next_proto_id),
277         },
278         {
279                 .type = RTE_ACL_FIELD_TYPE_RANGE,
280                 .size = sizeof(uint16_t),
281                 .field_index = DSTP_FIELD_IPV4,
282                 .input_index = RTE_ACL_IPV4VLAN_PORTS,
283                 .offset = sizeof(struct rte_ipv4_hdr) -
284                         offsetof(struct rte_ipv4_hdr, next_proto_id) +
285                         sizeof(uint16_t),
286         },
287 };
288
289 #define IPV6_ADDR_LEN   16
290 #define IPV6_ADDR_U16   (IPV6_ADDR_LEN / sizeof(uint16_t))
291 #define IPV6_ADDR_U32   (IPV6_ADDR_LEN / sizeof(uint32_t))
292
293 enum {
294         PROTO_FIELD_IPV6,
295         SRC1_FIELD_IPV6,
296         SRC2_FIELD_IPV6,
297         SRC3_FIELD_IPV6,
298         SRC4_FIELD_IPV6,
299         DST1_FIELD_IPV6,
300         DST2_FIELD_IPV6,
301         DST3_FIELD_IPV6,
302         DST4_FIELD_IPV6,
303         SRCP_FIELD_IPV6,
304         DSTP_FIELD_IPV6,
305         NUM_FIELDS_IPV6
306 };
307
308 struct rte_acl_field_def ipv6_defs[NUM_FIELDS_IPV6] = {
309         {
310                 .type = RTE_ACL_FIELD_TYPE_BITMASK,
311                 .size = sizeof(uint8_t),
312                 .field_index = PROTO_FIELD_IPV6,
313                 .input_index = PROTO_FIELD_IPV6,
314                 .offset = 0,
315         },
316         {
317                 .type = RTE_ACL_FIELD_TYPE_MASK,
318                 .size = sizeof(uint32_t),
319                 .field_index = SRC1_FIELD_IPV6,
320                 .input_index = SRC1_FIELD_IPV6,
321                 .offset = offsetof(struct rte_ipv6_hdr, src_addr) -
322                         offsetof(struct rte_ipv6_hdr, proto),
323         },
324         {
325                 .type = RTE_ACL_FIELD_TYPE_MASK,
326                 .size = sizeof(uint32_t),
327                 .field_index = SRC2_FIELD_IPV6,
328                 .input_index = SRC2_FIELD_IPV6,
329                 .offset = offsetof(struct rte_ipv6_hdr, src_addr) -
330                         offsetof(struct rte_ipv6_hdr, proto) + sizeof(uint32_t),
331         },
332         {
333                 .type = RTE_ACL_FIELD_TYPE_MASK,
334                 .size = sizeof(uint32_t),
335                 .field_index = SRC3_FIELD_IPV6,
336                 .input_index = SRC3_FIELD_IPV6,
337                 .offset = offsetof(struct rte_ipv6_hdr, src_addr) -
338                         offsetof(struct rte_ipv6_hdr, proto) +
339                         2 * sizeof(uint32_t),
340         },
341         {
342                 .type = RTE_ACL_FIELD_TYPE_MASK,
343                 .size = sizeof(uint32_t),
344                 .field_index = SRC4_FIELD_IPV6,
345                 .input_index = SRC4_FIELD_IPV6,
346                 .offset = offsetof(struct rte_ipv6_hdr, src_addr) -
347                         offsetof(struct rte_ipv6_hdr, proto) +
348                         3 * sizeof(uint32_t),
349         },
350         {
351                 .type = RTE_ACL_FIELD_TYPE_MASK,
352                 .size = sizeof(uint32_t),
353                 .field_index = DST1_FIELD_IPV6,
354                 .input_index = DST1_FIELD_IPV6,
355                 .offset = offsetof(struct rte_ipv6_hdr, dst_addr)
356                                 - offsetof(struct rte_ipv6_hdr, proto),
357         },
358         {
359                 .type = RTE_ACL_FIELD_TYPE_MASK,
360                 .size = sizeof(uint32_t),
361                 .field_index = DST2_FIELD_IPV6,
362                 .input_index = DST2_FIELD_IPV6,
363                 .offset = offsetof(struct rte_ipv6_hdr, dst_addr) -
364                         offsetof(struct rte_ipv6_hdr, proto) + sizeof(uint32_t),
365         },
366         {
367                 .type = RTE_ACL_FIELD_TYPE_MASK,
368                 .size = sizeof(uint32_t),
369                 .field_index = DST3_FIELD_IPV6,
370                 .input_index = DST3_FIELD_IPV6,
371                 .offset = offsetof(struct rte_ipv6_hdr, dst_addr) -
372                         offsetof(struct rte_ipv6_hdr, proto) +
373                         2 * sizeof(uint32_t),
374         },
375         {
376                 .type = RTE_ACL_FIELD_TYPE_MASK,
377                 .size = sizeof(uint32_t),
378                 .field_index = DST4_FIELD_IPV6,
379                 .input_index = DST4_FIELD_IPV6,
380                 .offset = offsetof(struct rte_ipv6_hdr, dst_addr) -
381                         offsetof(struct rte_ipv6_hdr, proto) +
382                         3 * sizeof(uint32_t),
383         },
384         {
385                 .type = RTE_ACL_FIELD_TYPE_RANGE,
386                 .size = sizeof(uint16_t),
387                 .field_index = SRCP_FIELD_IPV6,
388                 .input_index = SRCP_FIELD_IPV6,
389                 .offset = sizeof(struct rte_ipv6_hdr) -
390                         offsetof(struct rte_ipv6_hdr, proto),
391         },
392         {
393                 .type = RTE_ACL_FIELD_TYPE_RANGE,
394                 .size = sizeof(uint16_t),
395                 .field_index = DSTP_FIELD_IPV6,
396                 .input_index = SRCP_FIELD_IPV6,
397                 .offset = sizeof(struct rte_ipv6_hdr) -
398                         offsetof(struct rte_ipv6_hdr, proto) + sizeof(uint16_t),
399         },
400 };
401
402 enum {
403         CB_FLD_SRC_ADDR,
404         CB_FLD_DST_ADDR,
405         CB_FLD_SRC_PORT_LOW,
406         CB_FLD_SRC_PORT_DLM,
407         CB_FLD_SRC_PORT_HIGH,
408         CB_FLD_DST_PORT_LOW,
409         CB_FLD_DST_PORT_DLM,
410         CB_FLD_DST_PORT_HIGH,
411         CB_FLD_PROTO,
412         CB_FLD_USERDATA,
413         CB_FLD_NUM,
414 };
415
416 RTE_ACL_RULE_DEF(acl4_rule, RTE_DIM(ipv4_defs));
417 RTE_ACL_RULE_DEF(acl6_rule, RTE_DIM(ipv6_defs));
418
419 struct acl_search_t {
420         const uint8_t *data_ipv4[MAX_PKT_BURST];
421         struct rte_mbuf *m_ipv4[MAX_PKT_BURST];
422         uint32_t res_ipv4[MAX_PKT_BURST];
423         int num_ipv4;
424
425         const uint8_t *data_ipv6[MAX_PKT_BURST];
426         struct rte_mbuf *m_ipv6[MAX_PKT_BURST];
427         uint32_t res_ipv6[MAX_PKT_BURST];
428         int num_ipv6;
429 };
430
431 static struct {
432         char mapped[NB_SOCKETS];
433         struct rte_acl_ctx *acx_ipv4[NB_SOCKETS];
434         struct rte_acl_ctx *acx_ipv6[NB_SOCKETS];
435 #ifdef L3FWDACL_DEBUG
436         struct acl4_rule *rule_ipv4;
437         struct acl6_rule *rule_ipv6;
438 #endif
439 } acl_config;
440
441 static struct{
442         const char *rule_ipv4_name;
443         const char *rule_ipv6_name;
444         int scalar;
445 } parm_config;
446
447 const char cb_port_delim[] = ":";
448
449 static inline void
450 print_one_ipv4_rule(struct acl4_rule *rule, int extra)
451 {
452         unsigned char a, b, c, d;
453
454         uint32_t_to_char(rule->field[SRC_FIELD_IPV4].value.u32,
455                         &a, &b, &c, &d);
456         printf("%hhu.%hhu.%hhu.%hhu/%u ", a, b, c, d,
457                         rule->field[SRC_FIELD_IPV4].mask_range.u32);
458         uint32_t_to_char(rule->field[DST_FIELD_IPV4].value.u32,
459                         &a, &b, &c, &d);
460         printf("%hhu.%hhu.%hhu.%hhu/%u ", a, b, c, d,
461                         rule->field[DST_FIELD_IPV4].mask_range.u32);
462         printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ",
463                 rule->field[SRCP_FIELD_IPV4].value.u16,
464                 rule->field[SRCP_FIELD_IPV4].mask_range.u16,
465                 rule->field[DSTP_FIELD_IPV4].value.u16,
466                 rule->field[DSTP_FIELD_IPV4].mask_range.u16,
467                 rule->field[PROTO_FIELD_IPV4].value.u8,
468                 rule->field[PROTO_FIELD_IPV4].mask_range.u8);
469         if (extra)
470                 printf("0x%x-0x%x-0x%x ",
471                         rule->data.category_mask,
472                         rule->data.priority,
473                         rule->data.userdata);
474 }
475
476 static inline void
477 print_one_ipv6_rule(struct acl6_rule *rule, int extra)
478 {
479         unsigned char a, b, c, d;
480
481         uint32_t_to_char(rule->field[SRC1_FIELD_IPV6].value.u32,
482                 &a, &b, &c, &d);
483         printf("%.2x%.2x:%.2x%.2x", a, b, c, d);
484         uint32_t_to_char(rule->field[SRC2_FIELD_IPV6].value.u32,
485                 &a, &b, &c, &d);
486         printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
487         uint32_t_to_char(rule->field[SRC3_FIELD_IPV6].value.u32,
488                 &a, &b, &c, &d);
489         printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
490         uint32_t_to_char(rule->field[SRC4_FIELD_IPV6].value.u32,
491                 &a, &b, &c, &d);
492         printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d,
493                         rule->field[SRC1_FIELD_IPV6].mask_range.u32
494                         + rule->field[SRC2_FIELD_IPV6].mask_range.u32
495                         + rule->field[SRC3_FIELD_IPV6].mask_range.u32
496                         + rule->field[SRC4_FIELD_IPV6].mask_range.u32);
497
498         uint32_t_to_char(rule->field[DST1_FIELD_IPV6].value.u32,
499                 &a, &b, &c, &d);
500         printf("%.2x%.2x:%.2x%.2x", a, b, c, d);
501         uint32_t_to_char(rule->field[DST2_FIELD_IPV6].value.u32,
502                 &a, &b, &c, &d);
503         printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
504         uint32_t_to_char(rule->field[DST3_FIELD_IPV6].value.u32,
505                 &a, &b, &c, &d);
506         printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
507         uint32_t_to_char(rule->field[DST4_FIELD_IPV6].value.u32,
508                 &a, &b, &c, &d);
509         printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d,
510                         rule->field[DST1_FIELD_IPV6].mask_range.u32
511                         + rule->field[DST2_FIELD_IPV6].mask_range.u32
512                         + rule->field[DST3_FIELD_IPV6].mask_range.u32
513                         + rule->field[DST4_FIELD_IPV6].mask_range.u32);
514
515         printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ",
516                 rule->field[SRCP_FIELD_IPV6].value.u16,
517                 rule->field[SRCP_FIELD_IPV6].mask_range.u16,
518                 rule->field[DSTP_FIELD_IPV6].value.u16,
519                 rule->field[DSTP_FIELD_IPV6].mask_range.u16,
520                 rule->field[PROTO_FIELD_IPV6].value.u8,
521                 rule->field[PROTO_FIELD_IPV6].mask_range.u8);
522         if (extra)
523                 printf("0x%x-0x%x-0x%x ",
524                         rule->data.category_mask,
525                         rule->data.priority,
526                         rule->data.userdata);
527 }
528
529 /* Bypass comment and empty lines */
530 static inline int
531 is_bypass_line(char *buff)
532 {
533         int i = 0;
534
535         /* comment line */
536         if (buff[0] == COMMENT_LEAD_CHAR)
537                 return 1;
538         /* empty line */
539         while (buff[i] != '\0') {
540                 if (!isspace(buff[i]))
541                         return 0;
542                 i++;
543         }
544         return 1;
545 }
546
547 #ifdef L3FWDACL_DEBUG
548 static inline void
549 dump_acl4_rule(struct rte_mbuf *m, uint32_t sig)
550 {
551         uint32_t offset = sig & ~ACL_DENY_SIGNATURE;
552         unsigned char a, b, c, d;
553         struct rte_ipv4_hdr *ipv4_hdr =
554                 rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *,
555                                         sizeof(struct rte_ether_hdr));
556
557         uint32_t_to_char(rte_bswap32(ipv4_hdr->src_addr), &a, &b, &c, &d);
558         printf("Packet Src:%hhu.%hhu.%hhu.%hhu ", a, b, c, d);
559         uint32_t_to_char(rte_bswap32(ipv4_hdr->dst_addr), &a, &b, &c, &d);
560         printf("Dst:%hhu.%hhu.%hhu.%hhu ", a, b, c, d);
561
562         printf("Src port:%hu,Dst port:%hu ",
563                         rte_bswap16(*(uint16_t *)(ipv4_hdr + 1)),
564                         rte_bswap16(*((uint16_t *)(ipv4_hdr + 1) + 1)));
565         printf("hit ACL %d - ", offset);
566
567         print_one_ipv4_rule(acl_config.rule_ipv4 + offset, 1);
568
569         printf("\n\n");
570 }
571
572 static inline void
573 dump_acl6_rule(struct rte_mbuf *m, uint32_t sig)
574 {
575         unsigned i;
576         uint32_t offset = sig & ~ACL_DENY_SIGNATURE;
577         struct rte_ipv6_hdr *ipv6_hdr =
578                 rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *,
579                                         sizeof(struct rte_ether_hdr));
580
581         printf("Packet Src");
582         for (i = 0; i < RTE_DIM(ipv6_hdr->src_addr); i += sizeof(uint16_t))
583                 printf(":%.2x%.2x",
584                         ipv6_hdr->src_addr[i], ipv6_hdr->src_addr[i + 1]);
585
586         printf("\nDst");
587         for (i = 0; i < RTE_DIM(ipv6_hdr->dst_addr); i += sizeof(uint16_t))
588                 printf(":%.2x%.2x",
589                         ipv6_hdr->dst_addr[i], ipv6_hdr->dst_addr[i + 1]);
590
591         printf("\nSrc port:%hu,Dst port:%hu ",
592                         rte_bswap16(*(uint16_t *)(ipv6_hdr + 1)),
593                         rte_bswap16(*((uint16_t *)(ipv6_hdr + 1) + 1)));
594         printf("hit ACL %d - ", offset);
595
596         print_one_ipv6_rule(acl_config.rule_ipv6 + offset, 1);
597
598         printf("\n\n");
599 }
600 #endif /* L3FWDACL_DEBUG */
601
602 static inline void
603 dump_ipv4_rules(struct acl4_rule *rule, int num, int extra)
604 {
605         int i;
606
607         for (i = 0; i < num; i++, rule++) {
608                 printf("\t%d:", i + 1);
609                 print_one_ipv4_rule(rule, extra);
610                 printf("\n");
611         }
612 }
613
614 static inline void
615 dump_ipv6_rules(struct acl6_rule *rule, int num, int extra)
616 {
617         int i;
618
619         for (i = 0; i < num; i++, rule++) {
620                 printf("\t%d:", i + 1);
621                 print_one_ipv6_rule(rule, extra);
622                 printf("\n");
623         }
624 }
625
626 #ifdef DO_RFC_1812_CHECKS
627 static inline void
628 prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
629         int index)
630 {
631         struct rte_ipv4_hdr *ipv4_hdr;
632         struct rte_mbuf *pkt = pkts_in[index];
633
634         if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
635                 ipv4_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_ipv4_hdr *,
636                                                 sizeof(struct rte_ether_hdr));
637
638                 /* Check to make sure the packet is valid (RFC1812) */
639                 if (is_valid_ipv4_pkt(ipv4_hdr, pkt->pkt_len) >= 0) {
640
641                         /* Update time to live and header checksum */
642                         --(ipv4_hdr->time_to_live);
643                         ++(ipv4_hdr->hdr_checksum);
644
645                         /* Fill acl structure */
646                         acl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt);
647                         acl->m_ipv4[(acl->num_ipv4)++] = pkt;
648
649                 } else {
650                         /* Not a valid IPv4 packet */
651                         rte_pktmbuf_free(pkt);
652                 }
653         } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
654                 /* Fill acl structure */
655                 acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);
656                 acl->m_ipv6[(acl->num_ipv6)++] = pkt;
657
658         } else {
659                 /* Unknown type, drop the packet */
660                 rte_pktmbuf_free(pkt);
661         }
662 }
663
664 #else
665 static inline void
666 prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
667         int index)
668 {
669         struct rte_mbuf *pkt = pkts_in[index];
670
671         if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
672                 /* Fill acl structure */
673                 acl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt);
674                 acl->m_ipv4[(acl->num_ipv4)++] = pkt;
675
676         } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
677                 /* Fill acl structure */
678                 acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);
679                 acl->m_ipv6[(acl->num_ipv6)++] = pkt;
680         } else {
681                 /* Unknown type, drop the packet */
682                 rte_pktmbuf_free(pkt);
683         }
684 }
685 #endif /* DO_RFC_1812_CHECKS */
686
687 static inline void
688 prepare_acl_parameter(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
689         int nb_rx)
690 {
691         int i;
692
693         acl->num_ipv4 = 0;
694         acl->num_ipv6 = 0;
695
696         /* Prefetch first packets */
697         for (i = 0; i < PREFETCH_OFFSET && i < nb_rx; i++) {
698                 rte_prefetch0(rte_pktmbuf_mtod(
699                                 pkts_in[i], void *));
700         }
701
702         for (i = 0; i < (nb_rx - PREFETCH_OFFSET); i++) {
703                 rte_prefetch0(rte_pktmbuf_mtod(pkts_in[
704                                 i + PREFETCH_OFFSET], void *));
705                 prepare_one_packet(pkts_in, acl, i);
706         }
707
708         /* Process left packets */
709         for (; i < nb_rx; i++)
710                 prepare_one_packet(pkts_in, acl, i);
711 }
712
713 static inline void
714 send_one_packet(struct rte_mbuf *m, uint32_t res)
715 {
716         if (likely((res & ACL_DENY_SIGNATURE) == 0 && res != 0)) {
717                 /* forward packets */
718                 send_single_packet(m,
719                         (uint8_t)(res - FWD_PORT_SHIFT));
720         } else{
721                 /* in the ACL list, drop it */
722 #ifdef L3FWDACL_DEBUG
723                 if ((res & ACL_DENY_SIGNATURE) != 0) {
724                         if (RTE_ETH_IS_IPV4_HDR(m->packet_type))
725                                 dump_acl4_rule(m, res);
726                         else if (RTE_ETH_IS_IPV6_HDR(m->packet_type))
727                                 dump_acl6_rule(m, res);
728                 }
729 #endif
730                 rte_pktmbuf_free(m);
731         }
732 }
733
734
735
736 static inline void
737 send_packets(struct rte_mbuf **m, uint32_t *res, int num)
738 {
739         int i;
740
741         /* Prefetch first packets */
742         for (i = 0; i < PREFETCH_OFFSET && i < num; i++) {
743                 rte_prefetch0(rte_pktmbuf_mtod(
744                                 m[i], void *));
745         }
746
747         for (i = 0; i < (num - PREFETCH_OFFSET); i++) {
748                 rte_prefetch0(rte_pktmbuf_mtod(m[
749                                 i + PREFETCH_OFFSET], void *));
750                 send_one_packet(m[i], res[i]);
751         }
752
753         /* Process left packets */
754         for (; i < num; i++)
755                 send_one_packet(m[i], res[i]);
756 }
757
758 /*
759  * Parses IPV6 address, exepcts the following format:
760  * XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X - is a hexedecimal digit).
761  */
762 static int
763 parse_ipv6_addr(const char *in, const char **end, uint32_t v[IPV6_ADDR_U32],
764         char dlm)
765 {
766         uint32_t addr[IPV6_ADDR_U16];
767
768         GET_CB_FIELD(in, addr[0], 16, UINT16_MAX, ':');
769         GET_CB_FIELD(in, addr[1], 16, UINT16_MAX, ':');
770         GET_CB_FIELD(in, addr[2], 16, UINT16_MAX, ':');
771         GET_CB_FIELD(in, addr[3], 16, UINT16_MAX, ':');
772         GET_CB_FIELD(in, addr[4], 16, UINT16_MAX, ':');
773         GET_CB_FIELD(in, addr[5], 16, UINT16_MAX, ':');
774         GET_CB_FIELD(in, addr[6], 16, UINT16_MAX, ':');
775         GET_CB_FIELD(in, addr[7], 16, UINT16_MAX, dlm);
776
777         *end = in;
778
779         v[0] = (addr[0] << 16) + addr[1];
780         v[1] = (addr[2] << 16) + addr[3];
781         v[2] = (addr[4] << 16) + addr[5];
782         v[3] = (addr[6] << 16) + addr[7];
783
784         return 0;
785 }
786
787 static int
788 parse_ipv6_net(const char *in, struct rte_acl_field field[4])
789 {
790         int32_t rc;
791         const char *mp;
792         uint32_t i, m, v[4];
793         const uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT;
794
795         /* get address. */
796         rc = parse_ipv6_addr(in, &mp, v, '/');
797         if (rc != 0)
798                 return rc;
799
800         /* get mask. */
801         GET_CB_FIELD(mp, m, 0, CHAR_BIT * sizeof(v), 0);
802
803         /* put all together. */
804         for (i = 0; i != RTE_DIM(v); i++) {
805                 if (m >= (i + 1) * nbu32)
806                         field[i].mask_range.u32 = nbu32;
807                 else
808                         field[i].mask_range.u32 = m > (i * nbu32) ?
809                                 m - (i * 32) : 0;
810
811                 field[i].value.u32 = v[i];
812         }
813
814         return 0;
815 }
816
817 static int
818 parse_cb_ipv6_rule(char *str, struct rte_acl_rule *v, int has_userdata)
819 {
820         int i, rc;
821         char *s, *sp, *in[CB_FLD_NUM];
822         static const char *dlm = " \t\n";
823         int dim = has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA;
824         s = str;
825
826         for (i = 0; i != dim; i++, s = NULL) {
827                 in[i] = strtok_r(s, dlm, &sp);
828                 if (in[i] == NULL)
829                         return -EINVAL;
830         }
831
832         rc = parse_ipv6_net(in[CB_FLD_SRC_ADDR], v->field + SRC1_FIELD_IPV6);
833         if (rc != 0) {
834                 acl_log("failed to read source address/mask: %s\n",
835                         in[CB_FLD_SRC_ADDR]);
836                 return rc;
837         }
838
839         rc = parse_ipv6_net(in[CB_FLD_DST_ADDR], v->field + DST1_FIELD_IPV6);
840         if (rc != 0) {
841                 acl_log("failed to read destination address/mask: %s\n",
842                         in[CB_FLD_DST_ADDR]);
843                 return rc;
844         }
845
846         /* source port. */
847         GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW],
848                 v->field[SRCP_FIELD_IPV6].value.u16,
849                 0, UINT16_MAX, 0);
850         GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH],
851                 v->field[SRCP_FIELD_IPV6].mask_range.u16,
852                 0, UINT16_MAX, 0);
853
854         if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim,
855                         sizeof(cb_port_delim)) != 0)
856                 return -EINVAL;
857
858         /* destination port. */
859         GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW],
860                 v->field[DSTP_FIELD_IPV6].value.u16,
861                 0, UINT16_MAX, 0);
862         GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH],
863                 v->field[DSTP_FIELD_IPV6].mask_range.u16,
864                 0, UINT16_MAX, 0);
865
866         if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,
867                         sizeof(cb_port_delim)) != 0)
868                 return -EINVAL;
869
870         if (v->field[SRCP_FIELD_IPV6].mask_range.u16
871                         < v->field[SRCP_FIELD_IPV6].value.u16
872                         || v->field[DSTP_FIELD_IPV6].mask_range.u16
873                         < v->field[DSTP_FIELD_IPV6].value.u16)
874                 return -EINVAL;
875
876         GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].value.u8,
877                 0, UINT8_MAX, '/');
878         GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].mask_range.u8,
879                 0, UINT8_MAX, 0);
880
881         if (has_userdata)
882                 GET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata,
883                         0, UINT32_MAX, 0);
884
885         return 0;
886 }
887
888 /*
889  * Parse ClassBench rules file.
890  * Expected format:
891  * '@'<src_ipv4_addr>'/'<masklen> <space> \
892  * <dst_ipv4_addr>'/'<masklen> <space> \
893  * <src_port_low> <space> ":" <src_port_high> <space> \
894  * <dst_port_low> <space> ":" <dst_port_high> <space> \
895  * <proto>'/'<mask>
896  */
897 static int
898 parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len)
899 {
900         uint8_t a, b, c, d, m;
901
902         GET_CB_FIELD(in, a, 0, UINT8_MAX, '.');
903         GET_CB_FIELD(in, b, 0, UINT8_MAX, '.');
904         GET_CB_FIELD(in, c, 0, UINT8_MAX, '.');
905         GET_CB_FIELD(in, d, 0, UINT8_MAX, '/');
906         GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0);
907
908         addr[0] = RTE_IPV4(a, b, c, d);
909         mask_len[0] = m;
910
911         return 0;
912 }
913
914 static int
915 parse_cb_ipv4vlan_rule(char *str, struct rte_acl_rule *v, int has_userdata)
916 {
917         int i, rc;
918         char *s, *sp, *in[CB_FLD_NUM];
919         static const char *dlm = " \t\n";
920         int dim = has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA;
921         s = str;
922
923         for (i = 0; i != dim; i++, s = NULL) {
924                 in[i] = strtok_r(s, dlm, &sp);
925                 if (in[i] == NULL)
926                         return -EINVAL;
927         }
928
929         rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
930                         &v->field[SRC_FIELD_IPV4].value.u32,
931                         &v->field[SRC_FIELD_IPV4].mask_range.u32);
932         if (rc != 0) {
933                         acl_log("failed to read source address/mask: %s\n",
934                         in[CB_FLD_SRC_ADDR]);
935                 return rc;
936         }
937
938         rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
939                         &v->field[DST_FIELD_IPV4].value.u32,
940                         &v->field[DST_FIELD_IPV4].mask_range.u32);
941         if (rc != 0) {
942                 acl_log("failed to read destination address/mask: %s\n",
943                         in[CB_FLD_DST_ADDR]);
944                 return rc;
945         }
946
947         GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW],
948                 v->field[SRCP_FIELD_IPV4].value.u16,
949                 0, UINT16_MAX, 0);
950         GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH],
951                 v->field[SRCP_FIELD_IPV4].mask_range.u16,
952                 0, UINT16_MAX, 0);
953
954         if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim,
955                         sizeof(cb_port_delim)) != 0)
956                 return -EINVAL;
957
958         GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW],
959                 v->field[DSTP_FIELD_IPV4].value.u16,
960                 0, UINT16_MAX, 0);
961         GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH],
962                 v->field[DSTP_FIELD_IPV4].mask_range.u16,
963                 0, UINT16_MAX, 0);
964
965         if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,
966                         sizeof(cb_port_delim)) != 0)
967                 return -EINVAL;
968
969         if (v->field[SRCP_FIELD_IPV4].mask_range.u16
970                         < v->field[SRCP_FIELD_IPV4].value.u16
971                         || v->field[DSTP_FIELD_IPV4].mask_range.u16
972                         < v->field[DSTP_FIELD_IPV4].value.u16)
973                 return -EINVAL;
974
975         GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].value.u8,
976                 0, UINT8_MAX, '/');
977         GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].mask_range.u8,
978                 0, UINT8_MAX, 0);
979
980         if (has_userdata)
981                 GET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata, 0,
982                         UINT32_MAX, 0);
983
984         return 0;
985 }
986
987 static int
988 add_rules(const char *rule_path,
989                 struct rte_acl_rule **proute_base,
990                 unsigned int *proute_num,
991                 struct rte_acl_rule **pacl_base,
992                 unsigned int *pacl_num, uint32_t rule_size,
993                 int (*parser)(char *, struct rte_acl_rule*, int))
994 {
995         uint8_t *acl_rules, *route_rules;
996         struct rte_acl_rule *next;
997         unsigned int acl_num = 0, route_num = 0, total_num = 0;
998         unsigned int acl_cnt = 0, route_cnt = 0;
999         char buff[LINE_MAX];
1000         FILE *fh = fopen(rule_path, "rb");
1001         unsigned int i = 0;
1002         int val;
1003
1004         if (fh == NULL)
1005                 rte_exit(EXIT_FAILURE, "%s: Open %s failed\n", __func__,
1006                         rule_path);
1007
1008         while ((fgets(buff, LINE_MAX, fh) != NULL)) {
1009                 if (buff[0] == ROUTE_LEAD_CHAR)
1010                         route_num++;
1011                 else if (buff[0] == ACL_LEAD_CHAR)
1012                         acl_num++;
1013         }
1014
1015         if (0 == route_num)
1016                 rte_exit(EXIT_FAILURE, "Not find any route entries in %s!\n",
1017                                 rule_path);
1018
1019         val = fseek(fh, 0, SEEK_SET);
1020         if (val < 0) {
1021                 rte_exit(EXIT_FAILURE, "%s: File seek operation failed\n",
1022                         __func__);
1023         }
1024
1025         acl_rules = calloc(acl_num, rule_size);
1026
1027         if (NULL == acl_rules)
1028                 rte_exit(EXIT_FAILURE, "%s: failed to malloc memory\n",
1029                         __func__);
1030
1031         route_rules = calloc(route_num, rule_size);
1032
1033         if (NULL == route_rules)
1034                 rte_exit(EXIT_FAILURE, "%s: failed to malloc memory\n",
1035                         __func__);
1036
1037         i = 0;
1038         while (fgets(buff, LINE_MAX, fh) != NULL) {
1039                 i++;
1040
1041                 if (is_bypass_line(buff))
1042                         continue;
1043
1044                 char s = buff[0];
1045
1046                 /* Route entry */
1047                 if (s == ROUTE_LEAD_CHAR)
1048                         next = (struct rte_acl_rule *)(route_rules +
1049                                 route_cnt * rule_size);
1050
1051                 /* ACL entry */
1052                 else if (s == ACL_LEAD_CHAR)
1053                         next = (struct rte_acl_rule *)(acl_rules +
1054                                 acl_cnt * rule_size);
1055
1056                 /* Illegal line */
1057                 else
1058                         rte_exit(EXIT_FAILURE,
1059                                 "%s Line %u: should start with leading "
1060                                 "char %c or %c\n",
1061                                 rule_path, i, ROUTE_LEAD_CHAR, ACL_LEAD_CHAR);
1062
1063                 if (parser(buff + 1, next, s == ROUTE_LEAD_CHAR) != 0)
1064                         rte_exit(EXIT_FAILURE,
1065                                 "%s Line %u: parse rules error\n",
1066                                 rule_path, i);
1067
1068                 if (s == ROUTE_LEAD_CHAR) {
1069                         /* Check the forwarding port number */
1070                         if ((enabled_port_mask & (1 << next->data.userdata)) ==
1071                                         0)
1072                                 rte_exit(EXIT_FAILURE,
1073                                         "%s Line %u: fwd number illegal:%u\n",
1074                                         rule_path, i, next->data.userdata);
1075                         next->data.userdata += FWD_PORT_SHIFT;
1076                         route_cnt++;
1077                 } else {
1078                         next->data.userdata = ACL_DENY_SIGNATURE + acl_cnt;
1079                         acl_cnt++;
1080                 }
1081
1082                 next->data.priority = RTE_ACL_MAX_PRIORITY - total_num;
1083                 next->data.category_mask = -1;
1084                 total_num++;
1085         }
1086
1087         fclose(fh);
1088
1089         *pacl_base = (struct rte_acl_rule *)acl_rules;
1090         *pacl_num = acl_num;
1091         *proute_base = (struct rte_acl_rule *)route_rules;
1092         *proute_num = route_cnt;
1093
1094         return 0;
1095 }
1096
1097 static void
1098 dump_acl_config(void)
1099 {
1100         printf("ACL option are:\n");
1101         printf(OPTION_RULE_IPV4": %s\n", parm_config.rule_ipv4_name);
1102         printf(OPTION_RULE_IPV6": %s\n", parm_config.rule_ipv6_name);
1103         printf(OPTION_SCALAR": %d\n", parm_config.scalar);
1104 }
1105
1106 static int
1107 check_acl_config(void)
1108 {
1109         if (parm_config.rule_ipv4_name == NULL) {
1110                 acl_log("ACL IPv4 rule file not specified\n");
1111                 return -1;
1112         } else if (parm_config.rule_ipv6_name == NULL) {
1113                 acl_log("ACL IPv6 rule file not specified\n");
1114                 return -1;
1115         }
1116
1117         return 0;
1118 }
1119
1120 static struct rte_acl_ctx*
1121 setup_acl(struct rte_acl_rule *route_base,
1122                 struct rte_acl_rule *acl_base, unsigned int route_num,
1123                 unsigned int acl_num, int ipv6, int socketid)
1124 {
1125         char name[PATH_MAX];
1126         struct rte_acl_param acl_param;
1127         struct rte_acl_config acl_build_param;
1128         struct rte_acl_ctx *context;
1129         int dim = ipv6 ? RTE_DIM(ipv6_defs) : RTE_DIM(ipv4_defs);
1130
1131         /* Create ACL contexts */
1132         snprintf(name, sizeof(name), "%s%d",
1133                         ipv6 ? L3FWD_ACL_IPV6_NAME : L3FWD_ACL_IPV4_NAME,
1134                         socketid);
1135
1136         acl_param.name = name;
1137         acl_param.socket_id = socketid;
1138         acl_param.rule_size = RTE_ACL_RULE_SZ(dim);
1139         acl_param.max_rule_num = MAX_ACL_RULE_NUM;
1140
1141         if ((context = rte_acl_create(&acl_param)) == NULL)
1142                 rte_exit(EXIT_FAILURE, "Failed to create ACL context\n");
1143
1144         if (parm_config.scalar && rte_acl_set_ctx_classify(context,
1145                         RTE_ACL_CLASSIFY_SCALAR) != 0)
1146                 rte_exit(EXIT_FAILURE,
1147                         "Failed to setup classify method for  ACL context\n");
1148
1149         if (rte_acl_add_rules(context, route_base, route_num) < 0)
1150                         rte_exit(EXIT_FAILURE, "add rules failed\n");
1151
1152         if (rte_acl_add_rules(context, acl_base, acl_num) < 0)
1153                         rte_exit(EXIT_FAILURE, "add rules failed\n");
1154
1155         /* Perform builds */
1156         memset(&acl_build_param, 0, sizeof(acl_build_param));
1157
1158         acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES;
1159         acl_build_param.num_fields = dim;
1160         memcpy(&acl_build_param.defs, ipv6 ? ipv6_defs : ipv4_defs,
1161                 ipv6 ? sizeof(ipv6_defs) : sizeof(ipv4_defs));
1162
1163         if (rte_acl_build(context, &acl_build_param) != 0)
1164                 rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n");
1165
1166         rte_acl_dump(context);
1167
1168         return context;
1169 }
1170
1171 static int
1172 app_acl_init(void)
1173 {
1174         unsigned lcore_id;
1175         unsigned int i;
1176         int socketid;
1177         struct rte_acl_rule *acl_base_ipv4, *route_base_ipv4,
1178                 *acl_base_ipv6, *route_base_ipv6;
1179         unsigned int acl_num_ipv4 = 0, route_num_ipv4 = 0,
1180                 acl_num_ipv6 = 0, route_num_ipv6 = 0;
1181
1182         if (check_acl_config() != 0)
1183                 rte_exit(EXIT_FAILURE, "Failed to get valid ACL options\n");
1184
1185         dump_acl_config();
1186
1187         /* Load  rules from the input file */
1188         if (add_rules(parm_config.rule_ipv4_name, &route_base_ipv4,
1189                         &route_num_ipv4, &acl_base_ipv4, &acl_num_ipv4,
1190                         sizeof(struct acl4_rule), &parse_cb_ipv4vlan_rule) < 0)
1191                 rte_exit(EXIT_FAILURE, "Failed to add rules\n");
1192
1193         acl_log("IPv4 Route entries %u:\n", route_num_ipv4);
1194         dump_ipv4_rules((struct acl4_rule *)route_base_ipv4, route_num_ipv4, 1);
1195
1196         acl_log("IPv4 ACL entries %u:\n", acl_num_ipv4);
1197         dump_ipv4_rules((struct acl4_rule *)acl_base_ipv4, acl_num_ipv4, 1);
1198
1199         if (add_rules(parm_config.rule_ipv6_name, &route_base_ipv6,
1200                         &route_num_ipv6,
1201                         &acl_base_ipv6, &acl_num_ipv6,
1202                         sizeof(struct acl6_rule), &parse_cb_ipv6_rule) < 0)
1203                 rte_exit(EXIT_FAILURE, "Failed to add rules\n");
1204
1205         acl_log("IPv6 Route entries %u:\n", route_num_ipv6);
1206         dump_ipv6_rules((struct acl6_rule *)route_base_ipv6, route_num_ipv6, 1);
1207
1208         acl_log("IPv6 ACL entries %u:\n", acl_num_ipv6);
1209         dump_ipv6_rules((struct acl6_rule *)acl_base_ipv6, acl_num_ipv6, 1);
1210
1211         memset(&acl_config, 0, sizeof(acl_config));
1212
1213         /* Check sockets a context should be created on */
1214         if (!numa_on)
1215                 acl_config.mapped[0] = 1;
1216         else {
1217                 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1218                         if (rte_lcore_is_enabled(lcore_id) == 0)
1219                                 continue;
1220
1221                         socketid = rte_lcore_to_socket_id(lcore_id);
1222                         if (socketid >= NB_SOCKETS) {
1223                                 acl_log("Socket %d of lcore %u is out "
1224                                         "of range %d\n",
1225                                         socketid, lcore_id, NB_SOCKETS);
1226                                 free(route_base_ipv4);
1227                                 free(route_base_ipv6);
1228                                 free(acl_base_ipv4);
1229                                 free(acl_base_ipv6);
1230                                 return -1;
1231                         }
1232
1233                         acl_config.mapped[socketid] = 1;
1234                 }
1235         }
1236
1237         for (i = 0; i < NB_SOCKETS; i++) {
1238                 if (acl_config.mapped[i]) {
1239                         acl_config.acx_ipv4[i] = setup_acl(route_base_ipv4,
1240                                 acl_base_ipv4, route_num_ipv4, acl_num_ipv4,
1241                                 0, i);
1242
1243                         acl_config.acx_ipv6[i] = setup_acl(route_base_ipv6,
1244                                 acl_base_ipv6, route_num_ipv6, acl_num_ipv6,
1245                                 1, i);
1246                 }
1247         }
1248
1249         free(route_base_ipv4);
1250         free(route_base_ipv6);
1251
1252 #ifdef L3FWDACL_DEBUG
1253         acl_config.rule_ipv4 = (struct acl4_rule *)acl_base_ipv4;
1254         acl_config.rule_ipv6 = (struct acl6_rule *)acl_base_ipv6;
1255 #else
1256         free(acl_base_ipv4);
1257         free(acl_base_ipv6);
1258 #endif
1259
1260         return 0;
1261 }
1262
1263 /***********************end of ACL part******************************/
1264
1265 struct lcore_conf {
1266         uint16_t n_rx_queue;
1267         struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE];
1268         uint16_t n_tx_port;
1269         uint16_t tx_port_id[RTE_MAX_ETHPORTS];
1270         uint16_t tx_queue_id[RTE_MAX_ETHPORTS];
1271         struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS];
1272 } __rte_cache_aligned;
1273
1274 static struct lcore_conf lcore_conf[RTE_MAX_LCORE];
1275
1276 /* Enqueue a single packet, and send burst if queue is filled */
1277 static inline void
1278 send_single_packet(struct rte_mbuf *m, uint16_t port)
1279 {
1280         uint32_t lcore_id;
1281         struct lcore_conf *qconf;
1282         struct rte_ether_hdr *eh;
1283
1284         lcore_id = rte_lcore_id();
1285
1286         /* update src and dst mac*/
1287         eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
1288         memcpy(eh, &port_l2hdr[port], sizeof(eh->d_addr) + sizeof(eh->s_addr));
1289
1290         qconf = &lcore_conf[lcore_id];
1291         rte_eth_tx_buffer(port, qconf->tx_queue_id[port],
1292                         qconf->tx_buffer[port], m);
1293 }
1294
1295 #ifdef DO_RFC_1812_CHECKS
1296 static inline int
1297 is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
1298 {
1299         /* From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2 */
1300         /*
1301          * 1. The packet length reported by the Link Layer must be large
1302          * enough to hold the minimum length legal IP datagram (20 bytes).
1303          */
1304         if (link_len < sizeof(struct rte_ipv4_hdr))
1305                 return -1;
1306
1307         /* 2. The IP checksum must be correct. */
1308         /* this is checked in H/W */
1309
1310         /*
1311          * 3. The IP version number must be 4. If the version number is not 4
1312          * then the packet may be another version of IP, such as IPng or
1313          * ST-II.
1314          */
1315         if (((pkt->version_ihl) >> 4) != 4)
1316                 return -3;
1317         /*
1318          * 4. The IP header length field must be large enough to hold the
1319          * minimum length legal IP datagram (20 bytes = 5 words).
1320          */
1321         if ((pkt->version_ihl & 0xf) < 5)
1322                 return -4;
1323
1324         /*
1325          * 5. The IP total length field must be large enough to hold the IP
1326          * datagram header, whose length is specified in the IP header length
1327          * field.
1328          */
1329         if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct rte_ipv4_hdr))
1330                 return -5;
1331
1332         return 0;
1333 }
1334 #endif
1335
1336 /* main processing loop */
1337 static int
1338 main_loop(__rte_unused void *dummy)
1339 {
1340         struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
1341         unsigned lcore_id;
1342         uint64_t prev_tsc, diff_tsc, cur_tsc;
1343         int i, nb_rx;
1344         uint16_t portid;
1345         uint8_t queueid;
1346         struct lcore_conf *qconf;
1347         int socketid;
1348         const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1)
1349                         / US_PER_S * BURST_TX_DRAIN_US;
1350
1351         prev_tsc = 0;
1352         lcore_id = rte_lcore_id();
1353         qconf = &lcore_conf[lcore_id];
1354         socketid = rte_lcore_to_socket_id(lcore_id);
1355
1356         if (qconf->n_rx_queue == 0) {
1357                 RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id);
1358                 return 0;
1359         }
1360
1361         RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id);
1362
1363         for (i = 0; i < qconf->n_rx_queue; i++) {
1364
1365                 portid = qconf->rx_queue_list[i].port_id;
1366                 queueid = qconf->rx_queue_list[i].queue_id;
1367                 RTE_LOG(INFO, L3FWD,
1368                         " -- lcoreid=%u portid=%u rxqueueid=%hhu\n",
1369                         lcore_id, portid, queueid);
1370         }
1371
1372         while (1) {
1373
1374                 cur_tsc = rte_rdtsc();
1375
1376                 /*
1377                  * TX burst queue drain
1378                  */
1379                 diff_tsc = cur_tsc - prev_tsc;
1380                 if (unlikely(diff_tsc > drain_tsc)) {
1381                         for (i = 0; i < qconf->n_tx_port; ++i) {
1382                                 portid = qconf->tx_port_id[i];
1383                                 rte_eth_tx_buffer_flush(portid,
1384                                                 qconf->tx_queue_id[portid],
1385                                                 qconf->tx_buffer[portid]);
1386                         }
1387                         prev_tsc = cur_tsc;
1388                 }
1389
1390                 /*
1391                  * Read packet from RX queues
1392                  */
1393                 for (i = 0; i < qconf->n_rx_queue; ++i) {
1394
1395                         portid = qconf->rx_queue_list[i].port_id;
1396                         queueid = qconf->rx_queue_list[i].queue_id;
1397                         nb_rx = rte_eth_rx_burst(portid, queueid,
1398                                 pkts_burst, MAX_PKT_BURST);
1399
1400                         if (nb_rx > 0) {
1401                                 struct acl_search_t acl_search;
1402
1403                                 prepare_acl_parameter(pkts_burst, &acl_search,
1404                                         nb_rx);
1405
1406                                 if (acl_search.num_ipv4) {
1407                                         rte_acl_classify(
1408                                                 acl_config.acx_ipv4[socketid],
1409                                                 acl_search.data_ipv4,
1410                                                 acl_search.res_ipv4,
1411                                                 acl_search.num_ipv4,
1412                                                 DEFAULT_MAX_CATEGORIES);
1413
1414                                         send_packets(acl_search.m_ipv4,
1415                                                 acl_search.res_ipv4,
1416                                                 acl_search.num_ipv4);
1417                                 }
1418
1419                                 if (acl_search.num_ipv6) {
1420                                         rte_acl_classify(
1421                                                 acl_config.acx_ipv6[socketid],
1422                                                 acl_search.data_ipv6,
1423                                                 acl_search.res_ipv6,
1424                                                 acl_search.num_ipv6,
1425                                                 DEFAULT_MAX_CATEGORIES);
1426
1427                                         send_packets(acl_search.m_ipv6,
1428                                                 acl_search.res_ipv6,
1429                                                 acl_search.num_ipv6);
1430                                 }
1431                         }
1432                 }
1433         }
1434 }
1435
1436 static int
1437 check_lcore_params(void)
1438 {
1439         uint8_t queue, lcore;
1440         uint16_t i;
1441         int socketid;
1442
1443         for (i = 0; i < nb_lcore_params; ++i) {
1444                 queue = lcore_params[i].queue_id;
1445                 if (queue >= MAX_RX_QUEUE_PER_PORT) {
1446                         printf("invalid queue number: %hhu\n", queue);
1447                         return -1;
1448                 }
1449                 lcore = lcore_params[i].lcore_id;
1450                 if (!rte_lcore_is_enabled(lcore)) {
1451                         printf("error: lcore %hhu is not enabled in "
1452                                 "lcore mask\n", lcore);
1453                         return -1;
1454                 }
1455                 socketid = rte_lcore_to_socket_id(lcore);
1456                 if (socketid != 0 && numa_on == 0) {
1457                         printf("warning: lcore %hhu is on socket %d "
1458                                 "with numa off\n",
1459                                 lcore, socketid);
1460                 }
1461         }
1462         return 0;
1463 }
1464
1465 static int
1466 check_port_config(void)
1467 {
1468         unsigned portid;
1469         uint16_t i;
1470
1471         for (i = 0; i < nb_lcore_params; ++i) {
1472                 portid = lcore_params[i].port_id;
1473
1474                 if ((enabled_port_mask & (1 << portid)) == 0) {
1475                         printf("port %u is not enabled in port mask\n", portid);
1476                         return -1;
1477                 }
1478                 if (!rte_eth_dev_is_valid_port(portid)) {
1479                         printf("port %u is not present on the board\n", portid);
1480                         return -1;
1481                 }
1482         }
1483         return 0;
1484 }
1485
1486 static uint8_t
1487 get_port_n_rx_queues(const uint16_t port)
1488 {
1489         int queue = -1;
1490         uint16_t i;
1491
1492         for (i = 0; i < nb_lcore_params; ++i) {
1493                 if (lcore_params[i].port_id == port &&
1494                                 lcore_params[i].queue_id > queue)
1495                         queue = lcore_params[i].queue_id;
1496         }
1497         return (uint8_t)(++queue);
1498 }
1499
1500 static int
1501 init_lcore_rx_queues(void)
1502 {
1503         uint16_t i, nb_rx_queue;
1504         uint8_t lcore;
1505
1506         for (i = 0; i < nb_lcore_params; ++i) {
1507                 lcore = lcore_params[i].lcore_id;
1508                 nb_rx_queue = lcore_conf[lcore].n_rx_queue;
1509                 if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) {
1510                         printf("error: too many queues (%u) for lcore: %u\n",
1511                                 (unsigned)nb_rx_queue + 1, (unsigned)lcore);
1512                         return -1;
1513                 } else {
1514                         lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id =
1515                                 lcore_params[i].port_id;
1516                         lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id =
1517                                 lcore_params[i].queue_id;
1518                         lcore_conf[lcore].n_rx_queue++;
1519                 }
1520         }
1521         return 0;
1522 }
1523
1524 /* display usage */
1525 static void
1526 print_usage(const char *prgname)
1527 {
1528         printf("%s [EAL options] -- -p PORTMASK -P"
1529                 "--"OPTION_RULE_IPV4"=FILE"
1530                 "--"OPTION_RULE_IPV6"=FILE"
1531                 "  [--"OPTION_CONFIG" (port,queue,lcore)[,(port,queue,lcore]]"
1532                 "  [--"OPTION_ENBJMO" [--max-pkt-len PKTLEN]]\n"
1533                 "  -p PORTMASK: hexadecimal bitmask of ports to configure\n"
1534                 "  -P : enable promiscuous mode\n"
1535                 "  --"OPTION_CONFIG": (port,queue,lcore): "
1536                 "rx queues configuration\n"
1537                 "  --"OPTION_NONUMA": optional, disable numa awareness\n"
1538                 "  --"OPTION_ENBJMO": enable jumbo frame"
1539                 " which max packet len is PKTLEN in decimal (64-9600)\n"
1540                 "  --"OPTION_RULE_IPV4"=FILE: specify the ipv4 rules entries "
1541                 "file. "
1542                 "Each rule occupy one line. "
1543                 "2 kinds of rules are supported. "
1544                 "One is ACL entry at while line leads with character '%c', "
1545                 "another is route entry at while line leads with "
1546                 "character '%c'.\n"
1547                 "  --"OPTION_RULE_IPV6"=FILE: specify the ipv6 rules "
1548                 "entries file.\n"
1549                 "  --"OPTION_SCALAR": Use scalar function to do lookup\n",
1550                 prgname, ACL_LEAD_CHAR, ROUTE_LEAD_CHAR);
1551 }
1552
1553 static int
1554 parse_max_pkt_len(const char *pktlen)
1555 {
1556         char *end = NULL;
1557         unsigned long len;
1558
1559         /* parse decimal string */
1560         len = strtoul(pktlen, &end, 10);
1561         if ((pktlen[0] == '\0') || (end == NULL) || (*end != '\0'))
1562                 return -1;
1563
1564         if (len == 0)
1565                 return -1;
1566
1567         return len;
1568 }
1569
1570 static int
1571 parse_portmask(const char *portmask)
1572 {
1573         char *end = NULL;
1574         unsigned long pm;
1575
1576         /* parse hexadecimal string */
1577         pm = strtoul(portmask, &end, 16);
1578         if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
1579                 return 0;
1580
1581         return pm;
1582 }
1583
1584 static int
1585 parse_config(const char *q_arg)
1586 {
1587         char s[256];
1588         const char *p, *p0 = q_arg;
1589         char *end;
1590         enum fieldnames {
1591                 FLD_PORT = 0,
1592                 FLD_QUEUE,
1593                 FLD_LCORE,
1594                 _NUM_FLD
1595         };
1596         unsigned long int_fld[_NUM_FLD];
1597         char *str_fld[_NUM_FLD];
1598         int i;
1599         unsigned size;
1600
1601         nb_lcore_params = 0;
1602
1603         while ((p = strchr(p0, '(')) != NULL) {
1604                 ++p;
1605                 if ((p0 = strchr(p, ')')) == NULL)
1606                         return -1;
1607
1608                 size = p0 - p;
1609                 if (size >= sizeof(s))
1610                         return -1;
1611
1612                 snprintf(s, sizeof(s), "%.*s", size, p);
1613                 if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') !=
1614                                 _NUM_FLD)
1615                         return -1;
1616                 for (i = 0; i < _NUM_FLD; i++) {
1617                         errno = 0;
1618                         int_fld[i] = strtoul(str_fld[i], &end, 0);
1619                         if (errno != 0 || end == str_fld[i] || int_fld[i] > 255)
1620                                 return -1;
1621                 }
1622                 if (nb_lcore_params >= MAX_LCORE_PARAMS) {
1623                         printf("exceeded max number of lcore params: %hu\n",
1624                                 nb_lcore_params);
1625                         return -1;
1626                 }
1627                 lcore_params_array[nb_lcore_params].port_id =
1628                         (uint8_t)int_fld[FLD_PORT];
1629                 lcore_params_array[nb_lcore_params].queue_id =
1630                         (uint8_t)int_fld[FLD_QUEUE];
1631                 lcore_params_array[nb_lcore_params].lcore_id =
1632                         (uint8_t)int_fld[FLD_LCORE];
1633                 ++nb_lcore_params;
1634         }
1635         lcore_params = lcore_params_array;
1636         return 0;
1637 }
1638
1639 static const char *
1640 parse_eth_dest(const char *optarg)
1641 {
1642         unsigned long portid;
1643         char *port_end;
1644
1645         errno = 0;
1646         portid = strtoul(optarg, &port_end, 0);
1647         if (errno != 0 || port_end == optarg || *port_end++ != ',')
1648                 return "Invalid format";
1649         else if (portid >= RTE_MAX_ETHPORTS)
1650                 return "port value exceeds RTE_MAX_ETHPORTS("
1651                         RTE_STR(RTE_MAX_ETHPORTS) ")";
1652
1653         if (cmdline_parse_etheraddr(NULL, port_end, &port_l2hdr[portid].d_addr,
1654                         sizeof(port_l2hdr[portid].d_addr)) < 0)
1655                 return "Invalid ethernet address";
1656         return NULL;
1657 }
1658
1659 /* Parse the argument given in the command line of the application */
1660 static int
1661 parse_args(int argc, char **argv)
1662 {
1663         int opt, ret;
1664         char **argvopt;
1665         int option_index;
1666         char *prgname = argv[0];
1667         static struct option lgopts[] = {
1668                 {OPTION_CONFIG, 1, 0, 0},
1669                 {OPTION_NONUMA, 0, 0, 0},
1670                 {OPTION_ENBJMO, 0, 0, 0},
1671                 {OPTION_RULE_IPV4, 1, 0, 0},
1672                 {OPTION_RULE_IPV6, 1, 0, 0},
1673                 {OPTION_SCALAR, 0, 0, 0},
1674                 {OPTION_ETH_DEST, 1, 0, 0},
1675                 {NULL, 0, 0, 0}
1676         };
1677
1678         argvopt = argv;
1679
1680         while ((opt = getopt_long(argc, argvopt, "p:P",
1681                                 lgopts, &option_index)) != EOF) {
1682
1683                 switch (opt) {
1684                 /* portmask */
1685                 case 'p':
1686                         enabled_port_mask = parse_portmask(optarg);
1687                         if (enabled_port_mask == 0) {
1688                                 printf("invalid portmask\n");
1689                                 print_usage(prgname);
1690                                 return -1;
1691                         }
1692                         break;
1693                 case 'P':
1694                         printf("Promiscuous mode selected\n");
1695                         promiscuous_on = 1;
1696                         break;
1697
1698                 /* long options */
1699                 case 0:
1700                         if (!strncmp(lgopts[option_index].name,
1701                                         OPTION_CONFIG,
1702                                         sizeof(OPTION_CONFIG))) {
1703                                 ret = parse_config(optarg);
1704                                 if (ret) {
1705                                         printf("invalid config\n");
1706                                         print_usage(prgname);
1707                                         return -1;
1708                                 }
1709                         }
1710
1711                         if (!strncmp(lgopts[option_index].name,
1712                                         OPTION_NONUMA,
1713                                         sizeof(OPTION_NONUMA))) {
1714                                 printf("numa is disabled\n");
1715                                 numa_on = 0;
1716                         }
1717
1718                         if (!strncmp(lgopts[option_index].name,
1719                                         OPTION_ENBJMO, sizeof(OPTION_ENBJMO))) {
1720                                 struct option lenopts = {
1721                                         "max-pkt-len",
1722                                         required_argument,
1723                                         0,
1724                                         0
1725                                 };
1726
1727                                 printf("jumbo frame is enabled\n");
1728                                 port_conf.rxmode.offloads |=
1729                                                 DEV_RX_OFFLOAD_JUMBO_FRAME;
1730                                 port_conf.txmode.offloads |=
1731                                                 DEV_TX_OFFLOAD_MULTI_SEGS;
1732
1733                                 /*
1734                                  * if no max-pkt-len set, then use the
1735                                  * default value RTE_ETHER_MAX_LEN
1736                                  */
1737                                 if (0 == getopt_long(argc, argvopt, "",
1738                                                 &lenopts, &option_index)) {
1739                                         ret = parse_max_pkt_len(optarg);
1740                                         if ((ret < 64) ||
1741                                                 (ret > MAX_JUMBO_PKT_LEN)) {
1742                                                 printf("invalid packet "
1743                                                         "length\n");
1744                                                 print_usage(prgname);
1745                                                 return -1;
1746                                         }
1747                                         port_conf.rxmode.max_rx_pkt_len = ret;
1748                                 }
1749                                 printf("set jumbo frame max packet length "
1750                                         "to %u\n",
1751                                         (unsigned int)
1752                                         port_conf.rxmode.max_rx_pkt_len);
1753                         }
1754
1755                         if (!strncmp(lgopts[option_index].name,
1756                                         OPTION_RULE_IPV4,
1757                                         sizeof(OPTION_RULE_IPV4)))
1758                                 parm_config.rule_ipv4_name = optarg;
1759
1760                         if (!strncmp(lgopts[option_index].name,
1761                                         OPTION_RULE_IPV6,
1762                                         sizeof(OPTION_RULE_IPV6))) {
1763                                 parm_config.rule_ipv6_name = optarg;
1764                         }
1765
1766                         if (!strncmp(lgopts[option_index].name,
1767                                         OPTION_SCALAR, sizeof(OPTION_SCALAR)))
1768                                 parm_config.scalar = 1;
1769
1770                         if (!strncmp(lgopts[option_index].name, OPTION_ETH_DEST,
1771                                         sizeof(OPTION_ETH_DEST))) {
1772                                 const char *serr = parse_eth_dest(optarg);
1773                                 if (serr != NULL) {
1774                                         printf("invalid %s value:\"%s\": %s\n",
1775                                                 OPTION_ETH_DEST, optarg, serr);
1776                                         print_usage(prgname);
1777                                         return -1;
1778                                 }
1779                         }
1780
1781                         break;
1782
1783                 default:
1784                         print_usage(prgname);
1785                         return -1;
1786                 }
1787         }
1788
1789         if (optind >= 0)
1790                 argv[optind-1] = prgname;
1791
1792         ret = optind-1;
1793         optind = 1; /* reset getopt lib */
1794         return ret;
1795 }
1796
1797 static void
1798 print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr)
1799 {
1800         char buf[RTE_ETHER_ADDR_FMT_SIZE];
1801         rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
1802         printf("%s%s", name, buf);
1803 }
1804
1805 static int
1806 init_mem(unsigned nb_mbuf)
1807 {
1808         int socketid;
1809         unsigned lcore_id;
1810         char s[64];
1811
1812         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1813                 if (rte_lcore_is_enabled(lcore_id) == 0)
1814                         continue;
1815
1816                 if (numa_on)
1817                         socketid = rte_lcore_to_socket_id(lcore_id);
1818                 else
1819                         socketid = 0;
1820
1821                 if (socketid >= NB_SOCKETS) {
1822                         rte_exit(EXIT_FAILURE,
1823                                 "Socket %d of lcore %u is out of range %d\n",
1824                                 socketid, lcore_id, NB_SOCKETS);
1825                 }
1826                 if (pktmbuf_pool[socketid] == NULL) {
1827                         snprintf(s, sizeof(s), "mbuf_pool_%d", socketid);
1828                         pktmbuf_pool[socketid] =
1829                                 rte_pktmbuf_pool_create(s, nb_mbuf,
1830                                         MEMPOOL_CACHE_SIZE, 0,
1831                                         RTE_MBUF_DEFAULT_BUF_SIZE,
1832                                         socketid);
1833                         if (pktmbuf_pool[socketid] == NULL)
1834                                 rte_exit(EXIT_FAILURE,
1835                                         "Cannot init mbuf pool on socket %d\n",
1836                                         socketid);
1837                         else
1838                                 printf("Allocated mbuf pool on socket %d\n",
1839                                         socketid);
1840                 }
1841         }
1842         return 0;
1843 }
1844
1845 /* Check the link status of all ports in up to 9s, and print them finally */
1846 static void
1847 check_all_ports_link_status(uint32_t port_mask)
1848 {
1849 #define CHECK_INTERVAL 100 /* 100ms */
1850 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
1851         uint16_t portid;
1852         uint8_t count, all_ports_up, print_flag = 0;
1853         struct rte_eth_link link;
1854         int ret;
1855         char link_status_text[RTE_ETH_LINK_MAX_STR_LEN];
1856
1857         printf("\nChecking link status");
1858         fflush(stdout);
1859         for (count = 0; count <= MAX_CHECK_TIME; count++) {
1860                 all_ports_up = 1;
1861                 RTE_ETH_FOREACH_DEV(portid) {
1862                         if ((port_mask & (1 << portid)) == 0)
1863                                 continue;
1864                         memset(&link, 0, sizeof(link));
1865                         ret = rte_eth_link_get_nowait(portid, &link);
1866                         if (ret < 0) {
1867                                 all_ports_up = 0;
1868                                 if (print_flag == 1)
1869                                         printf("Port %u link get failed: %s\n",
1870                                                 portid, rte_strerror(-ret));
1871                                 continue;
1872                         }
1873                         /* print link status if flag set */
1874                         if (print_flag == 1) {
1875                                 rte_eth_link_to_str(link_status_text,
1876                                         sizeof(link_status_text), &link);
1877                                 printf("Port %d %s\n", portid,
1878                                        link_status_text);
1879                                 continue;
1880                         }
1881                         /* clear all_ports_up flag if any link down */
1882                         if (link.link_status == ETH_LINK_DOWN) {
1883                                 all_ports_up = 0;
1884                                 break;
1885                         }
1886                 }
1887                 /* after finally printing all link status, get out */
1888                 if (print_flag == 1)
1889                         break;
1890
1891                 if (all_ports_up == 0) {
1892                         printf(".");
1893                         fflush(stdout);
1894                         rte_delay_ms(CHECK_INTERVAL);
1895                 }
1896
1897                 /* set the print_flag if all ports up or timeout */
1898                 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
1899                         print_flag = 1;
1900                         printf("done\n");
1901                 }
1902         }
1903 }
1904
1905 /*
1906  * build-up default vaues for dest MACs.
1907  */
1908 static void
1909 set_default_dest_mac(void)
1910 {
1911         uint32_t i;
1912
1913         for (i = 0; i != RTE_DIM(port_l2hdr); i++) {
1914                 port_l2hdr[i].d_addr.addr_bytes[0] = RTE_ETHER_LOCAL_ADMIN_ADDR;
1915                 port_l2hdr[i].d_addr.addr_bytes[5] = i;
1916         }
1917 }
1918
1919 int
1920 main(int argc, char **argv)
1921 {
1922         struct lcore_conf *qconf;
1923         struct rte_eth_dev_info dev_info;
1924         struct rte_eth_txconf *txconf;
1925         int ret;
1926         unsigned nb_ports;
1927         uint16_t queueid;
1928         unsigned lcore_id;
1929         uint32_t n_tx_queue, nb_lcores;
1930         uint16_t portid;
1931         uint8_t nb_rx_queue, queue, socketid;
1932
1933         /* init EAL */
1934         ret = rte_eal_init(argc, argv);
1935         if (ret < 0)
1936                 rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n");
1937         argc -= ret;
1938         argv += ret;
1939
1940         set_default_dest_mac();
1941
1942         /* parse application arguments (after the EAL ones) */
1943         ret = parse_args(argc, argv);
1944         if (ret < 0)
1945                 rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n");
1946
1947         if (check_lcore_params() < 0)
1948                 rte_exit(EXIT_FAILURE, "check_lcore_params failed\n");
1949
1950         ret = init_lcore_rx_queues();
1951         if (ret < 0)
1952                 rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n");
1953
1954         nb_ports = rte_eth_dev_count_avail();
1955
1956         if (check_port_config() < 0)
1957                 rte_exit(EXIT_FAILURE, "check_port_config failed\n");
1958
1959         /* Add ACL rules and route entries, build trie */
1960         if (app_acl_init() < 0)
1961                 rte_exit(EXIT_FAILURE, "app_acl_init failed\n");
1962
1963         nb_lcores = rte_lcore_count();
1964
1965         /* initialize all ports */
1966         RTE_ETH_FOREACH_DEV(portid) {
1967                 struct rte_eth_conf local_port_conf = port_conf;
1968
1969                 /* skip ports that are not enabled */
1970                 if ((enabled_port_mask & (1 << portid)) == 0) {
1971                         printf("\nSkipping disabled port %d\n", portid);
1972                         continue;
1973                 }
1974
1975                 /* init port */
1976                 printf("Initializing port %d ... ", portid);
1977                 fflush(stdout);
1978
1979                 nb_rx_queue = get_port_n_rx_queues(portid);
1980                 n_tx_queue = nb_lcores;
1981                 if (n_tx_queue > MAX_TX_QUEUE_PER_PORT)
1982                         n_tx_queue = MAX_TX_QUEUE_PER_PORT;
1983                 printf("Creating queues: nb_rxq=%d nb_txq=%u... ",
1984                         nb_rx_queue, (unsigned)n_tx_queue);
1985
1986                 ret = rte_eth_dev_info_get(portid, &dev_info);
1987                 if (ret != 0)
1988                         rte_exit(EXIT_FAILURE,
1989                                 "Error during getting device (port %u) info: %s\n",
1990                                 portid, strerror(-ret));
1991
1992                 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
1993                         local_port_conf.txmode.offloads |=
1994                                 DEV_TX_OFFLOAD_MBUF_FAST_FREE;
1995
1996                 local_port_conf.rx_adv_conf.rss_conf.rss_hf &=
1997                         dev_info.flow_type_rss_offloads;
1998                 if (local_port_conf.rx_adv_conf.rss_conf.rss_hf !=
1999                                 port_conf.rx_adv_conf.rss_conf.rss_hf) {
2000                         printf("Port %u modified RSS hash function based on hardware support,"
2001                                 "requested:%#"PRIx64" configured:%#"PRIx64"\n",
2002                                 portid,
2003                                 port_conf.rx_adv_conf.rss_conf.rss_hf,
2004                                 local_port_conf.rx_adv_conf.rss_conf.rss_hf);
2005                 }
2006
2007                 ret = rte_eth_dev_configure(portid, nb_rx_queue,
2008                                         (uint16_t)n_tx_queue, &local_port_conf);
2009                 if (ret < 0)
2010                         rte_exit(EXIT_FAILURE,
2011                                 "Cannot configure device: err=%d, port=%d\n",
2012                                 ret, portid);
2013
2014                 ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd,
2015                                                        &nb_txd);
2016                 if (ret < 0)
2017                         rte_exit(EXIT_FAILURE,
2018                                 "rte_eth_dev_adjust_nb_rx_tx_desc: err=%d, port=%d\n",
2019                                 ret, portid);
2020
2021                 ret = rte_eth_macaddr_get(portid, &port_l2hdr[portid].s_addr);
2022                 if (ret < 0)
2023                         rte_exit(EXIT_FAILURE,
2024                                 "rte_eth_macaddr_get: err=%d, port=%d\n",
2025                                 ret, portid);
2026
2027                 print_ethaddr("Dst MAC:", &port_l2hdr[portid].d_addr);
2028                 print_ethaddr(", Src MAC:", &port_l2hdr[portid].s_addr);
2029                 printf(", ");
2030
2031                 /* init memory */
2032                 ret = init_mem(NB_MBUF);
2033                 if (ret < 0)
2034                         rte_exit(EXIT_FAILURE, "init_mem failed\n");
2035
2036                 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
2037                         if (rte_lcore_is_enabled(lcore_id) == 0)
2038                                 continue;
2039
2040                         /* Initialize TX buffers */
2041                         qconf = &lcore_conf[lcore_id];
2042                         qconf->tx_buffer[portid] = rte_zmalloc_socket("tx_buffer",
2043                                         RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0,
2044                                         rte_eth_dev_socket_id(portid));
2045                         if (qconf->tx_buffer[portid] == NULL)
2046                                 rte_exit(EXIT_FAILURE, "Can't allocate tx buffer for port %u\n",
2047                                                 (unsigned) portid);
2048
2049                         rte_eth_tx_buffer_init(qconf->tx_buffer[portid], MAX_PKT_BURST);
2050                 }
2051
2052                 /* init one TX queue per couple (lcore,port) */
2053                 queueid = 0;
2054                 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
2055                         if (rte_lcore_is_enabled(lcore_id) == 0)
2056                                 continue;
2057
2058                         if (numa_on)
2059                                 socketid = (uint8_t)
2060                                         rte_lcore_to_socket_id(lcore_id);
2061                         else
2062                                 socketid = 0;
2063
2064                         printf("txq=%u,%d,%d ", lcore_id, queueid, socketid);
2065                         fflush(stdout);
2066
2067                         ret = rte_eth_dev_info_get(portid, &dev_info);
2068                         if (ret != 0)
2069                                 rte_exit(EXIT_FAILURE,
2070                                         "Error during getting device (port %u) info: %s\n",
2071                                         portid, strerror(-ret));
2072
2073                         txconf = &dev_info.default_txconf;
2074                         txconf->offloads = local_port_conf.txmode.offloads;
2075                         ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,
2076                                                      socketid, txconf);
2077                         if (ret < 0)
2078                                 rte_exit(EXIT_FAILURE,
2079                                         "rte_eth_tx_queue_setup: err=%d, "
2080                                         "port=%d\n", ret, portid);
2081
2082                         qconf = &lcore_conf[lcore_id];
2083                         qconf->tx_queue_id[portid] = queueid;
2084                         queueid++;
2085
2086                         qconf->tx_port_id[qconf->n_tx_port] = portid;
2087                         qconf->n_tx_port++;
2088                 }
2089                 printf("\n");
2090         }
2091
2092         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
2093                 if (rte_lcore_is_enabled(lcore_id) == 0)
2094                         continue;
2095                 qconf = &lcore_conf[lcore_id];
2096                 printf("\nInitializing rx queues on lcore %u ... ", lcore_id);
2097                 fflush(stdout);
2098                 /* init RX queues */
2099                 for (queue = 0; queue < qconf->n_rx_queue; ++queue) {
2100                         struct rte_eth_rxconf rxq_conf;
2101
2102                         portid = qconf->rx_queue_list[queue].port_id;
2103                         queueid = qconf->rx_queue_list[queue].queue_id;
2104
2105                         if (numa_on)
2106                                 socketid = (uint8_t)
2107                                         rte_lcore_to_socket_id(lcore_id);
2108                         else
2109                                 socketid = 0;
2110
2111                         printf("rxq=%d,%d,%d ", portid, queueid, socketid);
2112                         fflush(stdout);
2113
2114                         ret = rte_eth_dev_info_get(portid, &dev_info);
2115                         if (ret != 0)
2116                                 rte_exit(EXIT_FAILURE,
2117                                         "Error during getting device (port %u) info: %s\n",
2118                                         portid, strerror(-ret));
2119
2120                         rxq_conf = dev_info.default_rxconf;
2121                         rxq_conf.offloads = port_conf.rxmode.offloads;
2122                         ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd,
2123                                         socketid, &rxq_conf,
2124                                         pktmbuf_pool[socketid]);
2125                         if (ret < 0)
2126                                 rte_exit(EXIT_FAILURE,
2127                                         "rte_eth_rx_queue_setup: err=%d,"
2128                                         "port=%d\n", ret, portid);
2129                 }
2130         }
2131
2132         printf("\n");
2133
2134         /* start ports */
2135         RTE_ETH_FOREACH_DEV(portid) {
2136                 if ((enabled_port_mask & (1 << portid)) == 0)
2137                         continue;
2138
2139                 /* Start device */
2140                 ret = rte_eth_dev_start(portid);
2141                 if (ret < 0)
2142                         rte_exit(EXIT_FAILURE,
2143                                 "rte_eth_dev_start: err=%d, port=%d\n",
2144                                 ret, portid);
2145
2146                 /*
2147                  * If enabled, put device in promiscuous mode.
2148                  * This allows IO forwarding mode to forward packets
2149                  * to itself through 2 cross-connected  ports of the
2150                  * target machine.
2151                  */
2152                 if (promiscuous_on) {
2153                         ret = rte_eth_promiscuous_enable(portid);
2154                         if (ret != 0)
2155                                 rte_exit(EXIT_FAILURE,
2156                                         "rte_eth_promiscuous_enable: err=%s, port=%u\n",
2157                                         rte_strerror(-ret), portid);
2158                 }
2159         }
2160
2161         check_all_ports_link_status(enabled_port_mask);
2162
2163         /* launch per-lcore init on every lcore */
2164         rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER);
2165         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
2166                 if (rte_eal_wait_lcore(lcore_id) < 0)
2167                         return -1;
2168         }
2169
2170         return 0;
2171 }