From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6C6A9A0553 for ; Mon, 17 Feb 2020 15:55:16 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 4F8081DA9F; Mon, 17 Feb 2020 15:55:16 +0100 (CET) Received: from EUR03-DB5-obe.outbound.protection.outlook.com (mail-oln040092071011.outbound.protection.outlook.com [40.92.71.11]) by dpdk.org (Postfix) with ESMTP id 375601D9C3 for ; Mon, 17 Feb 2020 15:55:15 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Sxc/mJDwCI2E27G7mJQaSnB5yf6q8UYCx21SQRcTaXGHZZ3JG/8o0qjGFuL9ZGymkewPTAOE7AAvqQ8QXCmo55dXZEAHGuxivOSxubC2GSEwvG2Nuq5XdkAESPzPDpHV1jSm4ZElv8/Z1PDtaRjFSKvYBC/muYiAoAFQ0Hto9D0pCZenHrYQIOkAu7V7/fpVcVUs6rzhZL6Q1kvMGP/h6tSAqbyOczrBSDAsv3Q4pWCNwvJwW3ZsbrIIr7FNVOVNTzbzH+MgYDfPiDgOpuoyW26lhrk+zSkzp/WnJqA5JVnQoZb/O5SbFXU7j76oVK4bTYUaYr2JIJ7aDwakfU2YQQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=rH+A9Ha0Xhu3XJJf0huJKyVFkSCO4icyxGid0i/HQOg=; b=XpJ0lgAP6vwg45KoRpvZ6apCglotJDOHSF5JSl8wKVU6xl0kY2xSN+HNySxy74uNThn/ZRPuZf4GTUnnvK3wW8eae9KDywwJHPUi1hI1yWJx1Ht2k3uh0A1i6Wpx1I+fS4hrSDXZTarU6y37LklXAZk/7fZSwwEkJV3YryCz0hz2VpyjYG2kn0S/33x2K/50nZUTU645x6e8Wuu0aK/xoP3s6xZN6iHKF+Uxn7z/TLXNIp8xSila5enYTrdNYjlFMHIvDqYcERyur5EqaonA31VNM/TNsmwpfg1BmBKNe6phxrUPSDn3XzhaSBwOgCgRl9mIaaduJMYJje0rHeTkBw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none Received: from AM5EUR03FT004.eop-EUR03.prod.protection.outlook.com (10.152.16.59) by AM5EUR03HT198.eop-EUR03.prod.protection.outlook.com (10.152.17.133) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2665.18; Mon, 17 Feb 2020 14:55:14 +0000 Received: from DB6PR10MB1736.EURPRD10.PROD.OUTLOOK.COM (10.152.16.56) by AM5EUR03FT004.mail.protection.outlook.com (10.152.16.163) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2665.18 via Frontend Transport; Mon, 17 Feb 2020 14:55:13 +0000 Received: from DB6PR10MB1736.EURPRD10.PROD.OUTLOOK.COM ([fe80::e4af:4e70:accb:b01e]) by DB6PR10MB1736.EURPRD10.PROD.OUTLOOK.COM ([fe80::e4af:4e70:accb:b01e%4]) with mapi id 15.20.2729.032; Mon, 17 Feb 2020 14:55:14 +0000 From: James Hymes To: "users@dpdk.org" Thread-Topic: Adding ESP packet filters to ACL table Thread-Index: AQHV5Z8WIXDTsDEJ/UmxQ7AMf2/eSA== Date: Mon, 17 Feb 2020 14:55:13 +0000 Message-ID: Accept-Language: en-GB, en-US Content-Language: en-GB X-MS-Has-Attach: X-MS-TNEF-Correlator: x-incomingtopheadermarker: OriginalChecksum:78A47A1628C209AA5F55F30829011FB2E83295B92A7FF05F7A7BADD6F1170996; UpperCasedChecksum:FF53EE4B9554C2361E8B10F3FC0D01CB63141C29C70F94533CDC387B23C7FC58; SizeAsReceived:6668; Count:42 x-tmn: [xhY6Lu4Uk3IORqu3AweZZRja2jcZ1Xms] x-ms-publictraffictype: Email x-incomingheadercount: 42 x-eopattributedmessage: 0 x-ms-office365-filtering-correlation-id: 9388dfee-a4e2-47a2-8849-08d7b3b964f1 x-ms-traffictypediagnostic: AM5EUR03HT198: x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: dOUtoimAuE2oHnBVqqWPUfp5akFavagxQ9n14YIT5nRmttjPlm+YAE2MjBsQpi+EI8yFKP94LVtpxKNpJg0/5skIXxVUb5SC7k9AcUUkm6Voq1OUg37tzOzPW5LZnyy+IlojLip9rwii2e9NjeoOXvSDsTC5/Ygh8+JEdDVKXm1FCMM/e7EGVwaC7cLfDdcC x-ms-exchange-antispam-messagedata: 5P9O5xrPhosqOIx+ppYXaaRpwEu77IczOFSZc/LvyRJiA+GAgcVSJvtrvNVWXSMONFghwbEvpJk6Wyp8sBvY8WhOTqVAkpakAEOxlw4R7/vM80Xs7PJEbhJ2v0/zwO7r2aI++Scb68QpFnTlxzVR7g== x-ms-exchange-transport-forked: True MIME-Version: 1.0 X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-CrossTenant-Network-Message-Id: 9388dfee-a4e2-47a2-8849-08d7b3b964f1 X-MS-Exchange-CrossTenant-rms-persistedconsumerorg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-CrossTenant-originalarrivaltime: 17 Feb 2020 14:55:13.9866 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Internet X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM5EUR03HT198 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable X-Content-Filtered-By: Mailman/MimeDel 2.1.15 Subject: [dpdk-users] Adding ESP packet filters to ACL table X-BeenThere: users@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK usage discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: users-bounces@dpdk.org Sender: "users" Hello, I am trying to make a flow classify based implementation able to filter pac= kets based on their esp spi values. I keep getting an error on line 405 whe= re the rule is validated returning an error -22: unsupported pattern. The c= ode I'm working off is a modified version of basicfwd with elements of flow= _classify. Am I missing something, or going about this the wrong way? Any l= ight shed on this would be greatly appreciated, after going through all the= relevant documentation I'm still stumped. The hardware I'm using is a FRWY-LS1046A and the following parameters are p= assed for running: "-l 0-1 -n 1 --proc-type auto --file-prefix c -b fm1-mac= 10 --" Here is the output I receive from running: EAL: Detected 4 lcore(s) EAL: Detected 1 NUMA nodes EAL: Auto-detected process type: PRIMARY EAL: Multi-process socket /var/run/dpdk/c/mp_socket EAL: Probing VFIO support... EAL: VFIO support initialized EAL: DPAA Bus Detected PMD: Using FMC script mode,Make sure to use DPDK supported FMC scripts only= . PMD: net: dpaa: fm1-mac5: 00:04:9f:06:2a:9b PMD: net: dpaa: fm1-mac6: 00:04:9f:06:2a:9c PMD: dpaa_sec-1 cryptodev init PMD: dpaa_sec-2 cryptodev init PMD: dpaa_sec-3 cryptodev init PMD: dpaa_sec-4 cryptodev init Port 0 MAC: 00 04 9f 06 2a 9b Port 1 MAC: 00 04 9f 06 2a 9c WARNING: Too many lcores enabled. Only 1 used. Core 0 forwarding packets. [Ctrl+C to quit] Classifier_app memory allocation successful Flow classifier create successful table create successful rule validate failed error -22: Unsupported pattern setup completed And here is the code that I am currently using #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RX_RING_SIZE 1024 #define TX_RING_SIZE 1024 #define NUM_MBUFS 8191 #define MBUF_CACHE_SIZE 250 #define BURST_SIZE 1 #define FLOW_CLASSIFY_MAX_RULE_NUM 91 char *convertToIP(uint32_t ip); void printPacketData(struct rte_mbuf *bufs, uint16_t nb_rx); struct flow_classifier *setupFlowClassify(void); static struct rte_flow_attr attr; static struct rte_flow_classify_rule *rules[10]; static const struct rte_eth_conf port_conf_default =3D { .rxmode =3D { .max_rx_pkt_len =3D ETHER_MAX_LEN, }, }; struct flow_classifier { struct rte_flow_classifier *classifier; }; struct flow_classifier_acl { struct flow_classifier classifier; }__rte_cache_aligned; static struct rte_flow_classify_stats classify_stats; //set up IPv4 5 tuple rule for table /* ACL field definitions for IPv4 5 tuple rule */ enum { PROTO_FIELD_IPV4, SRC_FIELD_IPV4, DST_FIELD_IPV4, SRCP_FIELD_IPV4, DSTP_FIELD_IPV4, NUM_FIELDS_IPV4 }; enum { PROTO_INPUT_IPV4, SRC_INPUT_IPV4, DST_INPUT_IPV4, SRCP_DESTP_INPUT_IPV4 }; static struct rte_acl_field_def ipv4_defs[6] =3D { /* first input field - always one byte long. */ { .type =3D RTE_ACL_FIELD_TYPE_BITMASK, .size =3D sizeof(uint8_t), .field_index =3D 0, .input_index =3D 0, .offset =3D sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, next_proto_id), }, /* next input field (IPv4 source address) - 4 consecutive bytes. */ { /* rte_flow uses a bit mask for IPv4 addresses */ .type =3D RTE_ACL_FIELD_TYPE_BITMASK, .size =3D sizeof(uint32_t), .field_index =3D 1, .input_index =3D 1, .offset =3D sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, src_addr), }, /* next input field (IPv4 destination address) - 4 consecutive bytes. *= / { // rte_flow uses a bit mask for IPv4 addresses .type =3D RTE_ACL_FIELD_TYPE_BITMASK, .size =3D sizeof(uint32_t), .field_index =3D 2, .input_index =3D 2, .offset =3D sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, dst_addr), }, //UDP part { // rte_flow uses a bit mask for protocol ports .type =3D RTE_ACL_FIELD_TYPE_BITMASK, .size =3D sizeof(uint16_t), .field_index =3D 3, .input_index =3D 3, .offset =3D sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + offsetof(struct udp_hdr, src_port), }, { // rte_flow uses a bit mask for protocol ports .type =3D RTE_ACL_FIELD_TYPE_BITMASK, .size =3D sizeof(uint16_t), .field_index =3D 4, .input_index =3D 4, .offset =3D sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + offsetof(struct udp_hdr, dst_port), }, /* * ESP Part. */ { .type =3D RTE_ACL_FIELD_TYPE_BITMASK, .size =3D sizeof(rte_be32_t), .field_index =3D 5, .input_index =3D 5, .offset =3D sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr) + offsetof(struct esp_hdr, spi), }, }; /* basicfwd.c: Basic DPDK skeleton forwarding example. */ struct rte_flow_query_count count =3D { .reset =3D 1, .hits_set =3D 1, .bytes_set =3D 1, .hits =3D 0, .bytes =3D 0, }; /* * Initializes a given port using global settings and with the RX buffers * coming from the mbuf_pool passed as a parameter. */ static inline int port_init(uint16_t port, struct rte_mempool *mbuf_pool) { struct rte_eth_conf port_conf =3D port_conf_default; const uint16_t rx_rings =3D 1, tx_rings =3D 1; uint16_t nb_rxd =3D RX_RING_SIZE; uint16_t nb_txd =3D TX_RING_SIZE; int retval; uint16_t q; struct rte_eth_dev_info dev_info; struct rte_eth_txconf txconf; if (!rte_eth_dev_is_valid_port(port)) return -1; rte_eth_dev_info_get(port, &dev_info); if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) port_conf.txmode.offloads |=3D DEV_TX_OFFLOAD_MBUF_FAST_FREE; /* Configure the Ethernet device. */ retval =3D rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval !=3D 0) return retval; retval =3D rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd); if (retval !=3D 0) return retval; /* Allocate and set up 1 RX queue per Ethernet port. */ for (q =3D 0; q < rx_rings; q++) { retval =3D rte_eth_rx_queue_setup(port, q, nb_rxd, rte_eth_dev_socket_id(port), NULL, mbuf_pool); if (retval < 0) return retval; } txconf =3D dev_info.default_txconf; txconf.offloads =3D port_conf.txmode.offloads; /* Allocate and set up 1 TX queue per Ethernet port. */ for (q =3D 0; q < tx_rings; q++) { retval =3D rte_eth_tx_queue_setup(port, q, nb_txd, rte_eth_dev_socket_id(port), &txconf); if (retval < 0) return retval; } /* Start the Ethernet port. */ retval =3D rte_eth_dev_start(port); if (retval < 0) return retval; /* Display the port MAC address. */ struct ether_addr addr; rte_eth_macaddr_get(port, &addr); printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n", port, addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]); /* Enable RX in promiscuous mode for the Ethernet device. */ rte_eth_promiscuous_enable(port); return 0; } //Recieves integer IPv4 ip address and converts to dot decimal format char *convertToIP(uint32_t ip){ char *address =3D malloc (sizeof (char) * 16); sprintf(address, "%d.%d.%d.%d", (ip>>24)& 0xFF, (ip>>16)& 0xFF,(ip>>8)&= 0xFF, ip& 0xFF); return address; } struct flow_classifier *setupFlowClassify(void){ //classifier structs struct flow_classifier *classifier_app; struct rte_flow_classifier_params classifier_params; //table structs struct rte_table_acl_params table_params; struct rte_flow_classify_table_params table_params_cls; //Flow Rule structs struct rte_flow_item packetTuple[5]; struct rte_flow_action actions[2]; struct rte_flow_classify_rule *rule; struct rte_flow_error error; //flow item structs struct rte_flow_item eth_part =3D {RTE_FLOW_ITEM_TYPE_ETH, 0, 0, 0 }; struct rte_flow_item end_part =3D {RTE_FLOW_ITEM_TYPE_END, 0, 0, 0 }; struct rte_flow_action count_action =3D { RTE_FLOW_ACTION_TYPE_COUNT, &= count}; struct rte_flow_action end_action =3D { RTE_FLOW_ACTION_TYPE_END, 0}; // ipv4 struct rte_flow_item ipv4_part; struct rte_flow_item_ipv4 ipv4_spec; struct rte_flow_item_ipv4 ipv4_mask; /* // UDP struct rte_flow_item udp_part; struct rte_flow_item_udp udp_spec; struct rte_flow_item_udp udp_mask; // ESP struct rte_flow_item esp_part; struct rte_flow_item_esp esp_spec; struct rte_flow_item_esp esp_mask; */ int ret =3D -1; int key_found; //setup classifier int size =3D RTE_CACHE_LINE_ROUNDUP(sizeof(struct flow_classifier_acl))= ; classifier_app =3D rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); if (classifier_app =3D=3D NULL) printf("Classifier_app memory allocation failed\n"); else printf("Classifier_app memory allocation successful\n"); classifier_params.name =3D "flow_classifier"; classifier_params.socket_id =3D rte_eth_dev_socket_id(0); classifier_app->classifier =3D rte_flow_classifier_create(&classifier_p= arams); if (classifier_app->classifier =3D=3D NULL) printf("Flow classifier create failed\n"); else printf("Flow classifier create successful\n"); //create table table_params.name =3D "table_acl"; table_params.n_rules =3D FLOW_CLASSIFY_MAX_RULE_NUM; table_params.n_rule_fields =3D RTE_DIM(ipv4_defs); memcpy(table_params.field_format, ipv4_defs, sizeof(ipv4_defs)); table_params_cls.ops =3D &rte_table_acl_ops; table_params_cls.arg_create =3D &table_params; table_params_cls.type =3D RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE; ret =3D rte_flow_classify_table_create(classifier_app->classifier, &tab= le_params_cls); if(ret){ printf("table create failed\n"); // if 1 then failed rte_flow_classifier_free(classifier_app->classifier); }else printf("table create successful\n"); //create packet profile 1 rules // set ether part packetTuple[0] =3D eth_part; //set IP header part //memory setup memset(&ipv4_spec, 0, sizeof(ipv4_spec)); memset(&ipv4_mask, 0, sizeof(ipv4_mask)); //create rules ipv4_spec.hdr.src_addr =3D (uint32_t)12345; ipv4_spec.hdr.dst_addr =3D (uint32_t)12345; ipv4_spec.hdr.next_proto_id =3D (uint8_t)50; ipv4_mask.hdr.src_addr =3D 0xFFFFFFFF; ipv4_mask.hdr.dst_addr =3D 0xFFFFFFFF; ipv4_mask.hdr.next_proto_id =3D 0xFF; //encapsulate ipv4_part.type =3D RTE_FLOW_ITEM_TYPE_IPV4; ipv4_part.spec =3D &ipv4_spec; ipv4_part.mask =3D &ipv4_mask; ipv4_part.last =3D NULL; packetTuple[1] =3D ipv4_part; //set UDP header part struct rte_flow_item udp_part; struct rte_flow_item_udp udp_spec; struct rte_flow_item_udp udp_mask; //memory setup memset(&udp_spec, 0, sizeof(udp_spec)); memset(&udp_mask, 0, sizeof(udp_mask)); //create rules udp_spec.hdr.src_port =3D (uint16_t)0; udp_spec.hdr.dst_port =3D (uint16_t)0; udp_spec.hdr.dgram_len =3D (uint16_t)0; udp_spec.hdr.dgram_cksum =3D (uint16_t)0; udp_mask.hdr.src_port =3D 0xFFFF; udp_mask.hdr.dst_port =3D 0xFFFF; udp_mask.hdr.dgram_len =3D (uint16_t)0; udp_mask.hdr.dgram_cksum =3D (uint16_t)0; //encapsulate udp_part.type =3D RTE_FLOW_ITEM_TYPE_UDP; udp_part.spec =3D &udp_spec; udp_part.mask =3D &udp_mask; udp_part.last =3D NULL; packetTuple[2] =3D udp_part; //set ESP header part struct rte_flow_item esp_part; struct rte_flow_item_esp esp_spec; struct rte_flow_item_esp esp_mask; //memory setup memset(&esp_spec, 0, sizeof(esp_spec)); memset(&esp_mask, 0, sizeof(esp_mask)); //create rules esp_spec.hdr.spi =3D 0x00000000; esp_spec.hdr.seq =3D 0x00000000; esp_mask.hdr.spi =3D 0xFFFFFFFF; esp_mask.hdr.seq =3D 0xFFFFFFFF; //encapsulate esp_part.type =3D RTE_FLOW_ITEM_TYPE_RAW; esp_part.spec =3D &esp_spec; esp_part.mask =3D &esp_mask; esp_part.last =3D NULL; packetTuple[3] =3D esp_part; //end profile packetTuple[4] =3D end_part; //final bits attr.priority =3D (uint32_t)0; attr.group =3D (uint32_t)0; attr.ingress =3D (uint32_t)1; //incoming packets actions[0] =3D count_action; actions[1] =3D end_action; //validate rule/ ret =3D rte_flow_classify_validate(classifier_app->classifier, &attr, p= acketTuple, actions, &error); if(ret){ printf("rule validate failed error %d: %s\n", ret, error.message); = // if 1 then failed rte_flow_classifier_free(classifier_app->classifier); }else printf("rule validate successful\n"); //create and store rule rule =3D rte_flow_classify_table_entry_add(classifier_app->classifier, = &attr, packetTuple, actions, &key_found, &error); rules[0] =3D rule; printf("setup completed\n"); return classifier_app; } /* * The lcore main. This is the main thread that does the work, reading from * an input port and writing to an output port. */ static __attribute__((noreturn)) void lcore_main(void) { uint16_t port; int ret; /* * Check that the port is on the same NUMA node as the polling thread * for best performance. */ RTE_ETH_FOREACH_DEV(port) if (rte_eth_dev_socket_id(port) > 0 && rte_eth_dev_socket_id(port) !=3D (int)rte_socket_id()) printf("WARNING, port %u is on remote NUMA node to " "polling thread.\n\tPerformance will " "not be optimal.\n", port); printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n", rte_lcore_id= ()); //printf("\nVersion: 0.20\n"); //setup flow classify struct flow_classifier *classifier_app =3D setupFlowClassify(); /* Run until the application is quit or killed. */ for (;;) { /* * Receive packets on a port and forward them on the paired * port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc. */ port =3D 1; /* Get burst of RX packets, from first port of pair. */ struct rte_mbuf *bufs[BURST_SIZE]; const uint16_t nb_rx =3D rte_eth_rx_burst(port, 0, bufs, BURST_SIZE); if (unlikely(nb_rx =3D=3D 0)) continue; // -------- Packets Recieved ---------- //printPacketData(*bufs, nb_rx); ret =3D rte_flow_classifier_query(classifier_app->classifier, bufs,= nb_rx, rules[1], &classify_stats); if (ret) printf("rule [%d] query failed ret [%d]\n\n", 0, ret); else printf("packet is profile 1?\n"); /* Send burst of TX packets, to second port of pair. */ const uint16_t nb_tx =3D rte_eth_tx_burst(port ^ 1, 0, bufs, nb_rx); /* Free any unsent packets. */ if (unlikely(nb_tx < nb_rx)) { uint16_t buf; for (buf =3D nb_tx; buf < nb_rx; buf++) rte_pktmbuf_free(bufs[buf]); } } rte_flow_classifier_free(classifier_app->classifier);//emptying it just= in case } /* * The main function, which does initialization and calls the per-lcore * functions. */ int main(int argc, char *argv[]) { struct rte_mempool *mbuf_pool; unsigned nb_ports; uint16_t portid; /* Initialize the Environment Abstraction Layer (EAL). */ int ret =3D rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); argc -=3D ret; argv +=3D ret; /* Check that there is an even number of ports to send/receive on. */ //nb_ports =3D rte_eth_dev_count_avail(); //if (nb_ports < 2 || (nb_ports & 1)) // rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n"); nb_ports =3D 2; /* Creates a new mempool in memory to hold the mbufs. */ mbuf_pool =3D rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports= , MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (mbuf_pool =3D=3D NULL) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* Initialize all ports. */ //for(portid =3D 0; portid < 2; portid++) RTE_ETH_FOREACH_DEV(portid) if (port_init(portid, mbuf_pool) !=3D 0) rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu16 "\n", portid); if (rte_lcore_count() > 1) printf("\nWARNING: Too many lcores enabled. Only 1 used.\n"); /* Call lcore_main on the master core only. */ lcore_main(); return 0; }