From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id B87E1A0509; Tue, 29 Mar 2022 12:33:58 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A0D4142815; Tue, 29 Mar 2022 12:33:58 +0200 (CEST) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by mails.dpdk.org (Postfix) with ESMTP id 6783440691 for ; Tue, 29 Mar 2022 12:33:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1648550036; x=1680086036; h=from:to:cc:subject:date:message-id:references: in-reply-to:content-transfer-encoding:mime-version; bh=XQe/XQcYwQZhdqxMJMERQbrj3v0BwzgrukiRRc6R1Vc=; b=ZjcaNKB655Pp/XJ5gfA1lGOd5mV/aKQxwVKZSJa7pBpIwuhzLZ9PXKcQ gw3Ji+piwfIRH/zhDORuUJT+ZVugwEDpAMCgenveL+KV4cbScirLUoMUb EFBmCp5+6q6z2fbAgMj2vE7XCxwXD9N0reSerm7J7+3L199CAzXGpjULd 0nDjyONlSg1L16xOpa1sVN7iRRWG6Blr+N/SC5llMbKshg4XEtRcCfbDb T8LYrThba6FWEJEyxLOxrKjFFmLh2GEooNz4coPxjehsYoUI20UlUmIcB OGzc5jqCln3pP5BwIt9Lrgbpxt4W4y0hAUhJAWSEdofcQ0pe6xuLJ3ugL A==; X-IronPort-AV: E=McAfee;i="6200,9189,10300"; a="256793421" X-IronPort-AV: E=Sophos;i="5.90,220,1643702400"; d="scan'208";a="256793421" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Mar 2022 03:33:55 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,220,1643702400"; d="scan'208";a="649398083" Received: from fmsmsx602.amr.corp.intel.com ([10.18.126.82]) by fmsmga002.fm.intel.com with ESMTP; 29 Mar 2022 03:33:55 -0700 Received: from fmsmsx602.amr.corp.intel.com (10.18.126.82) by fmsmsx602.amr.corp.intel.com (10.18.126.82) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.27; Tue, 29 Mar 2022 03:33:55 -0700 Received: from FMSEDG603.ED.cps.intel.com (10.1.192.133) by fmsmsx602.amr.corp.intel.com (10.18.126.82) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.27 via Frontend Transport; Tue, 29 Mar 2022 03:33:55 -0700 Received: from NAM10-BN7-obe.outbound.protection.outlook.com (104.47.70.103) by edgegateway.intel.com (192.55.55.68) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2308.21; Tue, 29 Mar 2022 03:33:54 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=mZV8rVQmQ0wZZrDma8HRK1Uj+kfAWitiFzRbNZUbDkztz4sM61CQkU7usPCZPqlFCXAgO6KzUXKmc6/E1ihksoHF2oE+H1nv9taGYTcoG1/za1s6Jhhs3z0UBO+LEeOdFvtvhPj7xVpCqLvPW7rpesyKupekDa2vZD54JPqAw0EnVPnLwl3DZXhr1jT0qIB4Cn8X6gU5iSs04R5V5n2BDcKW3rfBgxWnQSaIpNHG/CDgSvAkGz67YJToCyILG9NXIMs1/lNiw6XyTC0Jhtxa8zNw/nGo0IBmFGp5cqrp0naZvGysDvCC2e8ty4/XGlYW39ap+LgOPj3BIKQ2THXhuQ== 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-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=g+Vp3hf8FDmSA+WDKNF+MsaLfg7R1fU2g85mHF6VByk=; b=nyD6mxLKdNBab1Nxg1edwCyrCsY2qV07whYoW9WsD+oWDgqXYl2c68X3DBXp35zMMmPEa1wkgA4rJzeD/NJYlWJOI3RvQ/MJzQL7CJ9+UVClZYBPJFyPSBXFMGIohKGUu4CI/MZWLXSB9yT7PcziAnHAU9mJbxamMSmagNPvIAeDK634BlDadeND6qcZfm5cT2sd92HAWTznJAgk8ywxPYqK1EGCB0mzGlqNKQBA/m4ARrircmE7Eqt6f/KR4m9fSFKRrQTV/ux7G45/0s+q4MNnJ3EeneD9HwtqSICEvV53gOVEloVVztspdt2+DXIkHSQfQcNlp5sGLBushNLV8w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none Received: from DM6PR11MB4491.namprd11.prod.outlook.com (2603:10b6:5:204::19) by BN6PR1101MB2147.namprd11.prod.outlook.com (2603:10b6:405:57::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5102.17; Tue, 29 Mar 2022 10:33:51 +0000 Received: from DM6PR11MB4491.namprd11.prod.outlook.com ([fe80::ad2b:63fd:4cdd:130d]) by DM6PR11MB4491.namprd11.prod.outlook.com ([fe80::ad2b:63fd:4cdd:130d%4]) with mapi id 15.20.5102.023; Tue, 29 Mar 2022 10:33:51 +0000 From: "Ananyev, Konstantin" To: "Morrissey, Sean" CC: "dev@dpdk.org" Subject: RE: [PATCH v1] examples/l3fwd: merge l3fwd-acl into l3fwd Thread-Topic: [PATCH v1] examples/l3fwd: merge l3fwd-acl into l3fwd Thread-Index: AQHYQFsOxegft4AyA0eqqoAXVkLT3azVGfHg Date: Tue, 29 Mar 2022 10:33:51 +0000 Message-ID: References: <20220325151428.1037085-1-sean.morrissey@intel.com> In-Reply-To: <20220325151428.1037085-1-sean.morrissey@intel.com> Accept-Language: en-GB, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-reaction: no-action dlp-version: 11.6.401.20 authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=intel.com; x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 5ab7d366-2c90-4093-2915-08da116f9de5 x-ms-traffictypediagnostic: BN6PR1101MB2147:EE_ x-microsoft-antispam-prvs: x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: SdzKx4DXIHntIDmJYox/cA1OitDdDxcasb/FsvsdensV8KWoA1bPlH2AVMjYBULJ/Zt2bCY3gp74ux7aR9SX2S3snwn0H6FdggrkVkl/x1YB1+8SEK3p+g+WZIwb/cOMgoiRAYZOsY1Wq5nH/gSYkQghdeGnGIh4MN58k3lejLdjuLL5Vi5rjWeb2i/HJU4cpO0m5Zn+Ra/ZshScPpREP714g8qaFUPd5LOKA4I5lhGDmn4jSHmaTJfstBnxWfIu6LJIt3DPvRwx/wXf0AdkSArLVQeE1SX1p8pNZfEIDH3O1Wi5aQoEOAGyTWxlltGsyaB1KfUAttOuCG06qxmg09xSEqkHu2VHvwkzqLiR9tf++2CNSygNKW5iWgrxxwR4ZQJ0/lW5vBS67ZwocwZ1M/B7MiLHnHd3nhCCEgFOrtXr4emmKomywyjjrfZHUzgSAExrfuK/h24ZHQQ8uYfqVceJKLD2YZNx3cUA3NWj5mcOOeRzf0oRe3YH6LyizVoCUM2SZBk5a1titx9dngFtQkOJUB1TeXl6+HlnCYdJzBFPOeoIuJIBP7MiPkATiizML4O9GL1IKQcN/PTg2aogSfkgA8urBdY5cytzW+bSGQ3oaoZNVpE9KViL3u0lXzVhHx5Q0baoP/Pzy8WZlKfi5XyLpVKrTK2SxOcU2wtsd6u5GRoAYSI9vucrEmmbkSbfKo+n/vvV+GDzK6PYRKHfA+I3FEN6CIvyQ/iGivVpj/k= x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:DM6PR11MB4491.namprd11.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230001)(366004)(4326008)(76116006)(6862004)(66946007)(8676002)(66446008)(66556008)(66476007)(83380400001)(6506007)(7696005)(316002)(6636002)(71200400001)(64756008)(82960400001)(122000001)(33656002)(55016003)(5660300002)(26005)(30864003)(9686003)(2906002)(8936002)(52536014)(186003)(508600001)(38070700005)(38100700002)(86362001)(32563001)(579004)(559001); DIR:OUT; SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?wuXFrDTdDJRSzV9Qqb1ngLA3Bza81SSX6APn7da0yZH1mlje3UgLmeHXxA5S?= =?us-ascii?Q?Tk7mnUHREv0fFY8UoYpspzB1TWbnBfj7hL1UKjTJsMbtnZpG9bdFBY1ua5l3?= =?us-ascii?Q?KZgv5B6tTq0oyJ9SKoJqhnO8ctkVwgtyiG5v+mXYqv2f/xhzTNdvXHXCr2DD?= =?us-ascii?Q?hGNQM/+YnHcAmtpOTIzhKJmWaPwc0apcnA50L1rxthudUYtTQNza3O/7hRhd?= =?us-ascii?Q?N+ErqAIrD78QeRLiTK7pTgghiPA4bg9uG4XScIz8jhsx98TiuALa315Pws1t?= =?us-ascii?Q?1ngiPYwp5FgcyeHyF8oepv9p0IgmDdcnMFj5/sAEq5RWO0CRcFTRRQ6leFd3?= =?us-ascii?Q?hxXeOXKmCeHW9OfIlkbHvreduBhMrSO0tN6DsJ0KQqOIxunZdBPlCBrsT4NL?= =?us-ascii?Q?PWZaNjKREK6jfe3oZwake+gfVqmAHIB7kfXwjjodhCyQy6DAAp2bHyiL8uT0?= =?us-ascii?Q?11pqLMQUHdgbqwcXrFwCXGyoaLQSAnsIIbVvvXElFx3S88MRijx5bmkEZIMl?= =?us-ascii?Q?vihaGGZiBeGRu3SSLtAEEkYj1nc2zdwASAsrILwca7XEdQ2VOMsSP9Mea3Dk?= =?us-ascii?Q?JHlM+EWXI5oRA9W+OKE14GLBS4WWkfh6XFTAx0FPpeTBvoXRvFMH5XAULaC/?= =?us-ascii?Q?mErGgB0VPgaj7hTW73QCT4gpCYDYT4KbEPiyz1VlimXd1+eBDmnNS75lToyt?= =?us-ascii?Q?egjRPEpwyjTk4WfVtps07POIJyhy04A7YNzDmFj7suWiGlTIt2vfGQ2EfQMr?= =?us-ascii?Q?yjRBReu09OOLiObpMDJ56a4cbZ69DVuOL/qbkkgVkm7sBMw3OUPokoyy0NWG?= =?us-ascii?Q?W1zN/NZ2H3dUMjqKMVex4Zf+JiQ9pLQuabPiqofwGgsCQEmrqdmPFg86pUFV?= =?us-ascii?Q?agXGKtCRPsV783tQrJS104ZMHWY7T560o+K1cgTFyhNyFEJlWODlTEV1ADiv?= =?us-ascii?Q?gfS6JmFcc5vgdH024wye3/nnyfbyojQfg8WaFIsBeX1LwDjhGke0DvqfJdLs?= =?us-ascii?Q?rkVMXgciE2JRij97RoUJ8hYkO6xd4Ha4dCc7TwFCF0luzs2+6SDjbRqE1Wor?= =?us-ascii?Q?5kuPMsztrA57nO1TywIa1Bm4kBqf4AaOmtklo/wzI5LFsP9R7rCkVYGawy35?= =?us-ascii?Q?i4DqKsIHPJbr/iQTy0Y20UMMFzGMf6RUwKvHk0oHEJH5lVWFwBVKvpdLMC/3?= =?us-ascii?Q?1644XXQDqVCbkV3i8ONKaT9LgsaoRXHtpPdjjpf2ubunZGmTgCaL5RGmLVWV?= =?us-ascii?Q?7VS9WdMl4QS9FlRje9Im0fE3EJmip4XhJB57/WdMEmKAFflDYcewIB9sB8pY?= =?us-ascii?Q?HCkCkT2bU3uoJo7CNCKqDDriLrWCx3NnFTqJ50XuKK7XNERgZsOVmn8AoMUJ?= =?us-ascii?Q?Ro62TyEfqjxmX2rT6FiSjfFho+tWD+VIJAcVurybfI/Fo3Ji9GLimAOTMJi0?= =?us-ascii?Q?omBARMDPhhA/tnRr/FeOUGQBRcY8zV2JBQwhrnWpwvCm8QtNFxhAnkeYkXc+?= =?us-ascii?Q?pQM9BZmdS+cLDBIRTXRoeyYQMJvtCJ2/kv4A71XtirSrG2WXLrIXXbHQ4L+S?= =?us-ascii?Q?JePulqTSqSaE+f+CClXUfaPMFdvyHWv0nyBr+ZrL4V3vLeEBO/SIUc7EU+ZX?= =?us-ascii?Q?1p6CSFPzgymwcby1p1iCcyqMhwcV5LfMVC/aDv1Ne25+r30Rq3z0VHKBjPno?= =?us-ascii?Q?F7r8aqqZ0dZ3AimtZAezipwIYZSOjgItRA6L4tuwvACRwh/LN7dDAJprPAo4?= =?us-ascii?Q?8QD5Sa/HknEuWCu/v7RP3uFAus9KK/E=3D?= Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: DM6PR11MB4491.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 5ab7d366-2c90-4093-2915-08da116f9de5 X-MS-Exchange-CrossTenant-originalarrivaltime: 29 Mar 2022 10:33:51.3336 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: fgwlfBBjgAJxvINBnxjvLAReSjPVV5+n2/33UZYTe/Inztu9hclXPjO6nlAHltobIN7/oNXKLcgkba0CxKHRpMMx5Ke/oA7Jmws/aCfMp/g= X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN6PR1101MB2147 X-OriginatorOrg: intel.com X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Hi Sean, > l3fwd-acl contains duplicate functions to l3fwd. > For this reason we merge l3fwd-acl code into l3fwd > with '--lookup acl' cmdline option to run ACL. LGTM in general, some comments, mostly nits inline. As one generic comment - doc update seems missing.=20 Thanks Konstantin > Signed-off-by: Sean Morrissey > --- ... >=20 > diff --git a/examples/l3fwd/Makefile b/examples/l3fwd/Makefile > index 0badedb499..8efe6378e2 100644 > --- a/examples/l3fwd/Makefile > +++ b/examples/l3fwd/Makefile > @@ -5,7 +5,7 @@ > APP =3D l3fwd >=20 > # all source are stored in SRCS-y > -SRCS-y :=3D main.c l3fwd_lpm.c l3fwd_fib.c l3fwd_em.c l3fwd_event.c > +SRCS-y :=3D main.c l3fwd_acl.c l3fwd_lpm.c l3fwd_fib.c l3fwd_em.c l3fwd_= event.c > SRCS-y +=3D l3fwd_event_generic.c l3fwd_event_internal_port.c >=20 > PKGCONF ?=3D pkg-config > diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h > index ad39496e64..e93c695c2d 100644 > --- a/examples/l3fwd/l3fwd.h > +++ b/examples/l3fwd/l3fwd.h > @@ -7,6 +7,7 @@ >=20 > #include > #include > +#include >=20 > #define DO_RFC_1812_CHECKS >=20 > @@ -16,6 +17,12 @@ > #define NO_HASH_MULTI_LOOKUP 1 > #endif >=20 > +#if RTE_LOG_DP_LEVEL >=3D RTE_LOG_DEBUG > +#define L3FWDACL_DEBUG > +#endif > + > +#define NB_ALG 7 I don't think we do need these define any more. Probably we can safely remove it. > + > /* > * Configurable number of RX/TX ring descriptors > */ > @@ -61,6 +68,13 @@ > struct parm_cfg { > const char *rule_ipv4_name; > const char *rule_ipv6_name; > + enum rte_acl_classify_alg alg; > +}; > + > +struct acl_algorithms { > + const char *name; > + enum rte_acl_classify_alg alg; > + > }; >=20 > struct mbuf_table { > @@ -107,6 +121,8 @@ extern struct lcore_conf lcore_conf[RTE_MAX_LCORE]; >=20 > extern struct parm_cfg parm_config; >=20 > +extern struct acl_algorithms acl_alg[NB_ALG]; Probably just: extern struct acl_algorithms acl_alg[]; > + > /* Send burst of packets on an output interface */ > static inline int > send_burst(struct lcore_conf *qconf, uint16_t n, uint16_t port) > @@ -193,7 +209,10 @@ is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t= link_len) > int > init_mem(uint16_t portid, unsigned int nb_mbuf); >=20 > -/* Function pointers for LPM, EM or FIB functionality. */ > +/* Function pointers for ACL, LPM, EM or FIB functionality. */ > +void > +setup_acl(const int socketid); > + > void > setup_lpm(const int socketid); >=20 > @@ -203,12 +222,19 @@ setup_hash(const int socketid); > void > setup_fib(const int socketid); >=20 > +int > +acl_check_ptype(int portid); > + > int > em_check_ptype(int portid); >=20 > int > lpm_check_ptype(int portid); >=20 > +uint16_t > +acl_cb_parse_ptype(uint16_t port, uint16_t queue, struct rte_mbuf *pkts[= ], > + uint16_t nb_pkts, uint16_t max_pkts, void *user_param); > + > uint16_t > em_cb_parse_ptype(uint16_t port, uint16_t queue, struct rte_mbuf *pkts[]= , > uint16_t nb_pkts, uint16_t max_pkts, void *user_param); > @@ -217,6 +243,9 @@ uint16_t > lpm_cb_parse_ptype(uint16_t port, uint16_t queue, struct rte_mbuf *pkts[= ], > uint16_t nb_pkts, uint16_t max_pkts, void *user_param); >=20 > +int > +acl_main_loop(__rte_unused void *dummy); > + > int > em_main_loop(__rte_unused void *dummy); >=20 > @@ -278,7 +307,13 @@ int > fib_event_main_loop_tx_q_burst_vector(__rte_unused void *dummy); >=20 >=20 > -/* Return ipv4/ipv6 fwd lookup struct for LPM, EM or FIB. */ > +/* Return ipv4/ipv6 fwd lookup struct for ACL, LPM, EM or FIB. */ > +void * > +acl_get_ipv4_l3fwd_lookup_struct(const int socketid); > + > +void * > +acl_get_ipv6_l3fwd_lookup_struct(const int socketid); > + > void * > em_get_ipv4_l3fwd_lookup_struct(const int socketid); >=20 > diff --git a/examples/l3fwd/l3fwd_acl.c b/examples/l3fwd/l3fwd_acl.c > new file mode 100644 > index 0000000000..75e637d239 > --- /dev/null > +++ b/examples/l3fwd/l3fwd_acl.c > @@ -0,0 +1,1123 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2021 Intel Corporation > + */ > + > +#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 > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include Do we really need all these includes? Probably some of them could be safely removed? > +#include "l3fwd.h" > +#include "l3fwd_route.h" > + > +/* > + * Rule and trace formats definitions. > + */ > + > +enum { > + PROTO_FIELD_IPV4, > + SRC_FIELD_IPV4, > + DST_FIELD_IPV4, > + SRCP_FIELD_IPV4, > + DSTP_FIELD_IPV4, > + NUM_FIELDS_IPV4 > +}; > + > +/* > + * That effectively defines order of IPV4VLAN classifications: > + * - PROTO > + * - VLAN (TAG and DOMAIN) > + * - SRC IP ADDRESS > + * - DST IP ADDRESS > + * - PORTS (SRC and DST) > + */ > +enum { > + RTE_ACL_IPV4VLAN_PROTO, > + RTE_ACL_IPV4VLAN_VLAN, > + RTE_ACL_IPV4VLAN_SRC, > + RTE_ACL_IPV4VLAN_DST, > + RTE_ACL_IPV4VLAN_PORTS, > + RTE_ACL_IPV4VLAN_NUM > +}; > + > +struct acl_algorithms acl_alg[] =3D { > + { > + .name =3D "scalar", > + .alg =3D RTE_ACL_CLASSIFY_SCALAR, > + }, > + { > + .name =3D "sse", > + .alg =3D RTE_ACL_CLASSIFY_SSE, > + }, > + { > + .name =3D "avx2", > + .alg =3D RTE_ACL_CLASSIFY_AVX2, > + }, > + { > + .name =3D "neon", > + .alg =3D RTE_ACL_CLASSIFY_NEON, > + }, > + { > + .name =3D "altivec", > + .alg =3D RTE_ACL_CLASSIFY_ALTIVEC, > + }, > + { > + .name =3D "avx512x16", > + .alg =3D RTE_ACL_CLASSIFY_AVX512X16, > + }, > + { > + .name =3D "avx512x32", > + .alg =3D RTE_ACL_CLASSIFY_AVX512X32, > + }, > +}; > + > +struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] =3D { > + { > + .type =3D RTE_ACL_FIELD_TYPE_BITMASK, > + .size =3D sizeof(uint8_t), > + .field_index =3D PROTO_FIELD_IPV4, > + .input_index =3D RTE_ACL_IPV4VLAN_PROTO, > + .offset =3D 0, > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_MASK, > + .size =3D sizeof(uint32_t), > + .field_index =3D SRC_FIELD_IPV4, > + .input_index =3D RTE_ACL_IPV4VLAN_SRC, > + .offset =3D offsetof(struct rte_ipv4_hdr, src_addr) - > + offsetof(struct rte_ipv4_hdr, next_proto_id), > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_MASK, > + .size =3D sizeof(uint32_t), > + .field_index =3D DST_FIELD_IPV4, > + .input_index =3D RTE_ACL_IPV4VLAN_DST, > + .offset =3D offsetof(struct rte_ipv4_hdr, dst_addr) - > + offsetof(struct rte_ipv4_hdr, next_proto_id), > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_RANGE, > + .size =3D sizeof(uint16_t), > + .field_index =3D SRCP_FIELD_IPV4, > + .input_index =3D RTE_ACL_IPV4VLAN_PORTS, > + .offset =3D sizeof(struct rte_ipv4_hdr) - > + offsetof(struct rte_ipv4_hdr, next_proto_id), > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_RANGE, > + .size =3D sizeof(uint16_t), > + .field_index =3D DSTP_FIELD_IPV4, > + .input_index =3D RTE_ACL_IPV4VLAN_PORTS, > + .offset =3D sizeof(struct rte_ipv4_hdr) - > + offsetof(struct rte_ipv4_hdr, next_proto_id) + > + sizeof(uint16_t), > + }, > +}; > + > +enum { > + PROTO_FIELD_IPV6, > + SRC1_FIELD_IPV6, > + SRC2_FIELD_IPV6, > + SRC3_FIELD_IPV6, > + SRC4_FIELD_IPV6, > + DST1_FIELD_IPV6, > + DST2_FIELD_IPV6, > + DST3_FIELD_IPV6, > + DST4_FIELD_IPV6, > + SRCP_FIELD_IPV6, > + DSTP_FIELD_IPV6, > + NUM_FIELDS_IPV6 > +}; > + > +struct rte_acl_field_def ipv6_defs[NUM_FIELDS_IPV6] =3D { > + { > + .type =3D RTE_ACL_FIELD_TYPE_BITMASK, > + .size =3D sizeof(uint8_t), > + .field_index =3D PROTO_FIELD_IPV6, > + .input_index =3D PROTO_FIELD_IPV6, > + .offset =3D 0, > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_MASK, > + .size =3D sizeof(uint32_t), > + .field_index =3D SRC1_FIELD_IPV6, > + .input_index =3D SRC1_FIELD_IPV6, > + .offset =3D offsetof(struct rte_ipv6_hdr, src_addr) - > + offsetof(struct rte_ipv6_hdr, proto), > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_MASK, > + .size =3D sizeof(uint32_t), > + .field_index =3D SRC2_FIELD_IPV6, > + .input_index =3D SRC2_FIELD_IPV6, > + .offset =3D offsetof(struct rte_ipv6_hdr, src_addr) - > + offsetof(struct rte_ipv6_hdr, proto) + sizeof(uint32_t), > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_MASK, > + .size =3D sizeof(uint32_t), > + .field_index =3D SRC3_FIELD_IPV6, > + .input_index =3D SRC3_FIELD_IPV6, > + .offset =3D offsetof(struct rte_ipv6_hdr, src_addr) - > + offsetof(struct rte_ipv6_hdr, proto) + > + 2 * sizeof(uint32_t), > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_MASK, > + .size =3D sizeof(uint32_t), > + .field_index =3D SRC4_FIELD_IPV6, > + .input_index =3D SRC4_FIELD_IPV6, > + .offset =3D offsetof(struct rte_ipv6_hdr, src_addr) - > + offsetof(struct rte_ipv6_hdr, proto) + > + 3 * sizeof(uint32_t), > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_MASK, > + .size =3D sizeof(uint32_t), > + .field_index =3D DST1_FIELD_IPV6, > + .input_index =3D DST1_FIELD_IPV6, > + .offset =3D offsetof(struct rte_ipv6_hdr, dst_addr) > + - offsetof(struct rte_ipv6_hdr, proto), > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_MASK, > + .size =3D sizeof(uint32_t), > + .field_index =3D DST2_FIELD_IPV6, > + .input_index =3D DST2_FIELD_IPV6, > + .offset =3D offsetof(struct rte_ipv6_hdr, dst_addr) - > + offsetof(struct rte_ipv6_hdr, proto) + sizeof(uint32_t), > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_MASK, > + .size =3D sizeof(uint32_t), > + .field_index =3D DST3_FIELD_IPV6, > + .input_index =3D DST3_FIELD_IPV6, > + .offset =3D offsetof(struct rte_ipv6_hdr, dst_addr) - > + offsetof(struct rte_ipv6_hdr, proto) + > + 2 * sizeof(uint32_t), > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_MASK, > + .size =3D sizeof(uint32_t), > + .field_index =3D DST4_FIELD_IPV6, > + .input_index =3D DST4_FIELD_IPV6, > + .offset =3D offsetof(struct rte_ipv6_hdr, dst_addr) - > + offsetof(struct rte_ipv6_hdr, proto) + > + 3 * sizeof(uint32_t), > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_RANGE, > + .size =3D sizeof(uint16_t), > + .field_index =3D SRCP_FIELD_IPV6, > + .input_index =3D SRCP_FIELD_IPV6, > + .offset =3D sizeof(struct rte_ipv6_hdr) - > + offsetof(struct rte_ipv6_hdr, proto), > + }, > + { > + .type =3D RTE_ACL_FIELD_TYPE_RANGE, > + .size =3D sizeof(uint16_t), > + .field_index =3D DSTP_FIELD_IPV6, > + .input_index =3D SRCP_FIELD_IPV6, > + .offset =3D sizeof(struct rte_ipv6_hdr) - > + offsetof(struct rte_ipv6_hdr, proto) + sizeof(uint16_t), > + }, > +}; > + > +enum { > + CB_FLD_SRC_ADDR, > + CB_FLD_DST_ADDR, > + CB_FLD_SRC_PORT_LOW, > + CB_FLD_SRC_PORT_DLM, > + CB_FLD_SRC_PORT_HIGH, > + CB_FLD_DST_PORT_LOW, > + CB_FLD_DST_PORT_DLM, > + CB_FLD_DST_PORT_HIGH, > + CB_FLD_PROTO, > + CB_FLD_USERDATA, > + CB_FLD_NUM, > +}; > + > +RTE_ACL_RULE_DEF(acl4_rule, RTE_DIM(ipv4_defs)); > +RTE_ACL_RULE_DEF(acl6_rule, RTE_DIM(ipv6_defs)); > + > +struct acl_search_t { > + const uint8_t *data_ipv4[MAX_PKT_BURST]; > + struct rte_mbuf *m_ipv4[MAX_PKT_BURST]; > + uint32_t res_ipv4[MAX_PKT_BURST]; > + int num_ipv4; > + > + const uint8_t *data_ipv6[MAX_PKT_BURST]; > + struct rte_mbuf *m_ipv6[MAX_PKT_BURST]; > + uint32_t res_ipv6[MAX_PKT_BURST]; > + int num_ipv6; > +}; > + > +static struct { > + struct rte_acl_ctx *acx_ipv4[NB_SOCKETS]; > + struct rte_acl_ctx *acx_ipv6[NB_SOCKETS]; > +#ifdef L3FWDACL_DEBUG > + struct acl4_rule *rule_ipv4; > + struct acl6_rule *rule_ipv6; > +#endif > +} acl_config; > + > +static const char cb_port_delim[] =3D ":"; > + > +static struct rte_acl_rule *acl_base_ipv4, *route_base_ipv4, > + *acl_base_ipv6, *route_base_ipv6; > +static unsigned int acl_num_ipv4, route_num_ipv4, > + acl_num_ipv6, route_num_ipv6; > + > +#include "l3fwd_acl.h" > + > +#include "l3fwd_acl_scalar.h" > + > +/* > + * Parse IPV6 address, expects the following format: > + * XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X is a hexadecimal dig= it). > + */ > +static int > +parse_ipv6_addr(char *in, uint32_t v[IPV6_ADDR_U32], uint32_t *mask) > +{ > + char *sa, *sm, *sv; > + const char *dlm =3D "/"; > + > + sv =3D NULL; > + sa =3D strtok_r(in, dlm, &sv); > + if (sa =3D=3D NULL) > + return -EINVAL; > + sm =3D strtok_r(NULL, dlm, &sv); > + if (sm =3D=3D NULL) > + return -EINVAL; > + > + if (inet_pton(AF_INET6, sa, v) !=3D 1) > + return -EINVAL; > + > + GET_CB_FIELD(sm, *mask, 0, 128, 0); > + return 0; > +} > + > +static int > +parse_ipv6_net(char *in, struct rte_acl_field field[4]) > +{ > + int32_t rc; > + uint32_t i, v[4]; > + uint32_t m; > + const uint32_t nbu32 =3D sizeof(uint32_t) * CHAR_BIT; > + > + /* get address. */ > + rc =3D parse_ipv6_addr(in, v, &m); > + if (rc !=3D 0) > + return rc; > + > + /* put all together. */ > + for (i =3D 0; i !=3D RTE_DIM(v); i++) { > + if (m >=3D (i + 1) * nbu32) > + field[i].mask_range.u32 =3D nbu32; > + else > + field[i].mask_range.u32 =3D m > (i * nbu32) ? > + m - (i * 32) : 0; > + > + field[i].value.u32 =3D v[i]; > + } > + > + return 0; > +} > + > +static int > +parse_cb_ipv6_rule(char *str, struct rte_acl_rule *v, int has_userdata) > +{ > + int i, rc; > + char *s, *sp, *in[CB_FLD_NUM]; > + static const char *dlm =3D " \t\n"; > + int dim =3D has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA; > + s =3D str; > + > + for (i =3D 0; i !=3D dim; i++, s =3D NULL) { > + in[i] =3D strtok_r(s, dlm, &sp); > + if (in[i] =3D=3D NULL) > + return -EINVAL; > + } > + > + rc =3D parse_ipv6_net(in[CB_FLD_SRC_ADDR], v->field + SRC1_FIELD_IPV6); > + if (rc !=3D 0) { > + acl_log("failed to read source address/mask: %s\n", > + in[CB_FLD_SRC_ADDR]); > + return rc; > + } > + > + rc =3D parse_ipv6_net(in[CB_FLD_DST_ADDR], v->field + DST1_FIELD_IPV6); > + if (rc !=3D 0) { > + acl_log("failed to read destination address/mask: %s\n", > + in[CB_FLD_DST_ADDR]); > + return rc; > + } > + > + /* source port. */ > + GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW], > + v->field[SRCP_FIELD_IPV6].value.u16, > + 0, UINT16_MAX, 0); > + GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH], > + v->field[SRCP_FIELD_IPV6].mask_range.u16, > + 0, UINT16_MAX, 0); > + > + if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim, > + sizeof(cb_port_delim)) !=3D 0) > + return -EINVAL; > + > + /* destination port. */ > + GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW], > + v->field[DSTP_FIELD_IPV6].value.u16, > + 0, UINT16_MAX, 0); > + GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH], > + v->field[DSTP_FIELD_IPV6].mask_range.u16, > + 0, UINT16_MAX, 0); > + > + if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim, > + sizeof(cb_port_delim)) !=3D 0) > + return -EINVAL; > + > + if (v->field[SRCP_FIELD_IPV6].mask_range.u16 > + < v->field[SRCP_FIELD_IPV6].value.u16 > + || v->field[DSTP_FIELD_IPV6].mask_range.u16 > + < v->field[DSTP_FIELD_IPV6].value.u16) > + return -EINVAL; > + > + GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].value.u8, > + 0, UINT8_MAX, '/'); > + GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].mask_range.u8= , > + 0, UINT8_MAX, 0); > + > + if (has_userdata) > + GET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata, > + 0, UINT32_MAX, 0); > + > + return 0; > +} > + > +/* > + * Parse ClassBench rules file. > + * Expected format: > + * '@''/' \ > + * '/' \ > + * ":" \ > + * ":" \ > + * '/' > + */ > +static int > +parse_ipv4_net(char *in, uint32_t *addr, uint32_t *mask_len) > +{ > + char *sa, *sm, *sv; > + const char *dlm =3D "/"; > + > + sv =3D NULL; > + sa =3D strtok_r(in, dlm, &sv); > + if (sa =3D=3D NULL) > + return -EINVAL; > + sm =3D strtok_r(NULL, dlm, &sv); > + if (sm =3D=3D NULL) > + return -EINVAL; > + > + if (inet_pton(AF_INET, sa, addr) !=3D 1) > + return -EINVAL; > + > + GET_CB_FIELD(sm, *mask_len, 0, 32, 0); > + *addr =3D ntohl(*addr); > + return 0; > +} > + > +static int > +parse_cb_ipv4vlan_rule(char *str, struct rte_acl_rule *v, int has_userda= ta) > +{ > + int i, rc; > + char *s, *sp, *in[CB_FLD_NUM]; > + static const char *dlm =3D " \t\n"; > + int dim =3D has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA; > + s =3D str; > + > + for (i =3D 0; i !=3D dim; i++, s =3D NULL) { > + in[i] =3D strtok_r(s, dlm, &sp); > + if (in[i] =3D=3D NULL) > + return -EINVAL; > + } > + > + rc =3D parse_ipv4_net(in[CB_FLD_SRC_ADDR], > + &v->field[SRC_FIELD_IPV4].value.u32, > + &v->field[SRC_FIELD_IPV4].mask_range.u32); > + if (rc !=3D 0) { > + acl_log("failed to read source address/mask: %s\n", > + in[CB_FLD_SRC_ADDR]); > + return rc; > + } > + > + rc =3D parse_ipv4_net(in[CB_FLD_DST_ADDR], > + &v->field[DST_FIELD_IPV4].value.u32, > + &v->field[DST_FIELD_IPV4].mask_range.u32); > + if (rc !=3D 0) { > + acl_log("failed to read destination address/mask: %s\n", > + in[CB_FLD_DST_ADDR]); > + return rc; > + } > + > + GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW], > + v->field[SRCP_FIELD_IPV4].value.u16, > + 0, UINT16_MAX, 0); > + GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH], > + v->field[SRCP_FIELD_IPV4].mask_range.u16, > + 0, UINT16_MAX, 0); > + > + if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim, > + sizeof(cb_port_delim)) !=3D 0) { > + return -EINVAL; > + } > + > + GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW], > + v->field[DSTP_FIELD_IPV4].value.u16, > + 0, UINT16_MAX, 0); > + GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH], > + v->field[DSTP_FIELD_IPV4].mask_range.u16, > + 0, UINT16_MAX, 0); > + > + if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim, > + sizeof(cb_port_delim)) !=3D 0) { > + return -EINVAL; > + } > + > + if (v->field[SRCP_FIELD_IPV4].mask_range.u16 > + < v->field[SRCP_FIELD_IPV4].value.u16 > + || v->field[DSTP_FIELD_IPV4].mask_range.u16 > + < v->field[DSTP_FIELD_IPV4].value.u16) { > + return -EINVAL; > + } > + > + GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].value.u8, > + 0, UINT8_MAX, '/'); > + GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].mask_range.u8= , > + 0, UINT8_MAX, 0); > + > + if (has_userdata) > + GET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata, 0, > + UINT32_MAX, 0); > + > + return 0; > +} > + > +static int > +acl_add_rules(const char *rule_path, > + struct rte_acl_rule **proute_base, > + unsigned int *proute_num, > + struct rte_acl_rule **pacl_base, > + unsigned int *pacl_num, uint32_t rule_size, > + int (*parser)(char *, struct rte_acl_rule*, int)) > +{ > + uint8_t *acl_rules, *route_rules; > + struct rte_acl_rule *next; > + unsigned int acl_num =3D 0, route_num =3D 0, total_num =3D 0; > + unsigned int acl_cnt =3D 0, route_cnt =3D 0; > + char buff[LINE_MAX]; > + FILE *fh =3D fopen(rule_path, "rb"); > + unsigned int i =3D 0; > + int val; > + > + if (fh =3D=3D NULL) > + rte_exit(EXIT_FAILURE, "%s: Open %s failed\n", __func__, > + rule_path); > + > + while ((fgets(buff, LINE_MAX, fh) !=3D NULL)) { > + if (buff[0] =3D=3D ROUTE_LEAD_CHAR) > + route_num++; > + else if (buff[0] =3D=3D ACL_LEAD_CHAR) > + acl_num++; > + } > + > + if (route_num =3D=3D 0) > + rte_exit(EXIT_FAILURE, "Not find any route entries in %s!\n", > + rule_path); > + > + val =3D fseek(fh, 0, SEEK_SET); > + if (val < 0) { > + rte_exit(EXIT_FAILURE, "%s: File seek operation failed\n", > + __func__); > + } > + > + acl_rules =3D calloc(acl_num, rule_size); > + > + if (acl_rules =3D=3D NULL) > + rte_exit(EXIT_FAILURE, "%s: failed to malloc memory\n", > + __func__); > + > + route_rules =3D calloc(route_num, rule_size); > + > + if (route_rules =3D=3D NULL) > + rte_exit(EXIT_FAILURE, "%s: failed to malloc memory\n", > + __func__); > + > + i =3D 0; > + while (fgets(buff, LINE_MAX, fh) !=3D NULL) { > + i++; > + > + if (is_bypass_line(buff)) > + continue; > + > + char s =3D buff[0]; > + > + /* Route entry */ > + if (s =3D=3D ROUTE_LEAD_CHAR) > + next =3D (struct rte_acl_rule *)(route_rules + > + route_cnt * rule_size); > + > + /* ACL entry */ > + else if (s =3D=3D ACL_LEAD_CHAR) > + next =3D (struct rte_acl_rule *)(acl_rules + > + acl_cnt * rule_size); > + > + /* Illegal line */ > + else > + rte_exit(EXIT_FAILURE, > + "%s Line %u: should start with leading " > + "char %c or %c\n", > + rule_path, i, ROUTE_LEAD_CHAR, ACL_LEAD_CHAR); > + > + if (parser(buff + 1, next, s =3D=3D ROUTE_LEAD_CHAR) !=3D 0) > + rte_exit(EXIT_FAILURE, > + "%s Line %u: parse rules error\n", > + rule_path, i); > + > + if (s =3D=3D ROUTE_LEAD_CHAR) { > + /* Check the forwarding port number */ > + if ((enabled_port_mask & (1 << next->data.userdata)) =3D=3D > + 0) > + rte_exit(EXIT_FAILURE, > + "%s Line %u: fwd number illegal:%u\n", > + rule_path, i, next->data.userdata); > + next->data.userdata +=3D FWD_PORT_SHIFT; > + route_cnt++; > + } else { > + next->data.userdata =3D ACL_DENY_SIGNATURE + acl_cnt; > + acl_cnt++; > + } > + > + next->data.priority =3D RTE_ACL_MAX_PRIORITY - total_num; > + next->data.category_mask =3D -1; > + total_num++; > + } > + > + fclose(fh); > + > + *pacl_base =3D (struct rte_acl_rule *)acl_rules; > + *pacl_num =3D acl_num; > + *proute_base =3D (struct rte_acl_rule *)route_rules; > + *proute_num =3D route_cnt; > + > + return 0; > +} > + > +static const char * > +str_acl_alg(enum rte_acl_classify_alg alg) > +{ > + uint32_t i; > + > + for (i =3D 0; i !=3D RTE_DIM(acl_alg); i++) { > + if (alg =3D=3D acl_alg[i].alg) > + return acl_alg[i].name; > + } > + > + return "default"; > +} > + > +static void > +dump_acl_config(void) > +{ > + printf("ACL options are:\n"); > + printf("rule_ipv4: %s\n", parm_config.rule_ipv4_name); > + printf("rule_ipv6: %s\n", parm_config.rule_ipv6_name); > + printf("alg: %s\n", str_acl_alg(parm_config.alg)); > +} > + > +static int > +check_acl_config(void) > +{ > + if (parm_config.rule_ipv4_name =3D=3D NULL) { > + acl_log("ACL IPv4 rule file not specified\n"); > + return -1; > + } else if (parm_config.rule_ipv6_name =3D=3D NULL) { > + acl_log("ACL IPv6 rule file not specified\n"); > + return -1; > + } > + > + return 0; > +} > + > +static struct rte_acl_ctx* > +app_acl_init(struct rte_acl_rule *route_base, > + struct rte_acl_rule *acl_base, unsigned int route_num, > + unsigned int acl_num, int ipv6, int socketid) > +{ > + char name[PATH_MAX]; > + struct rte_acl_param acl_param; > + struct rte_acl_config acl_build_param; > + struct rte_acl_ctx *context; > + int dim =3D ipv6 ? RTE_DIM(ipv6_defs) : RTE_DIM(ipv4_defs); > + > + /* Create ACL contexts */ > + snprintf(name, sizeof(name), "%s%d", > + ipv6 ? L3FWD_ACL_IPV6_NAME : L3FWD_ACL_IPV4_NAME, > + socketid); > + > + acl_param.name =3D name; > + acl_param.socket_id =3D socketid; > + acl_param.rule_size =3D RTE_ACL_RULE_SZ(dim); > + acl_param.max_rule_num =3D MAX_ACL_RULE_NUM; > + > + context =3D rte_acl_create(&acl_param); > + if (context =3D=3D NULL) > + rte_exit(EXIT_FAILURE, "Failed to create ACL context\n"); > + > + if (parm_config.alg !=3D RTE_ACL_CLASSIFY_DEFAULT && > + rte_acl_set_ctx_classify(context, parm_config.alg) !=3D 0) > + rte_exit(EXIT_FAILURE, > + "Failed to setup classify method for ACL context\n"); > + > + if (rte_acl_add_rules(context, route_base, route_num) < 0) > + rte_exit(EXIT_FAILURE, "add rules failed\n"); > + > + if (rte_acl_add_rules(context, acl_base, acl_num) < 0) > + rte_exit(EXIT_FAILURE, "add rules failed\n"); > + > + /* Perform builds */ > + memset(&acl_build_param, 0, sizeof(acl_build_param)); > + > + acl_build_param.num_categories =3D DEFAULT_MAX_CATEGORIES; > + acl_build_param.num_fields =3D dim; > + memcpy(&acl_build_param.defs, ipv6 ? ipv6_defs : ipv4_defs, > + ipv6 ? sizeof(ipv6_defs) : sizeof(ipv4_defs)); > + > + if (rte_acl_build(context, &acl_build_param) !=3D 0) > + rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n"); > + > + rte_acl_dump(context); > + > + return context; > +} > + > +void > +acl_free_routes(void) > +{ > + free(route_base_ipv4); > + free(route_base_ipv6); > + route_base_ipv4 =3D NULL; > + route_base_ipv6 =3D NULL; > + route_num_ipv4 =3D 0; > + route_num_ipv6 =3D 0; > + free(acl_base_ipv4); > + free(acl_base_ipv6); > + acl_base_ipv4 =3D NULL; > + acl_base_ipv4 =3D NULL; acl_base_ipv6 =3D NULL; ? Also probably need to set acl_num_ipv(4|6) to zero. > +} > + > +/* Load rules from the input file */ > +void > +read_config_files_acl(void) > +{ > + /* ipv4 check */ > + if (parm_config.rule_ipv4_name !=3D NULL) { > + if (acl_add_rules(parm_config.rule_ipv4_name, &route_base_ipv4, > + &route_num_ipv4, &acl_base_ipv4, &acl_num_ipv4, > + sizeof(struct acl4_rule), &parse_cb_ipv4vlan_rule) < 0) { > + acl_free_routes(); > + rte_exit(EXIT_FAILURE, "Failed to add IPv4 rules\n"); > + } > + } else { > + RTE_LOG(ERR, L3FWD, "IPv4 rule file not specified\n"); > + rte_exit(EXIT_FAILURE, "Failed to get valid route options\n"); > + } > + > + /* ipv6 check */ > + if (parm_config.rule_ipv6_name !=3D NULL) { > + if (acl_add_rules(parm_config.rule_ipv6_name, &route_base_ipv6, > + &route_num_ipv6, > + &acl_base_ipv6, &acl_num_ipv6, > + sizeof(struct acl6_rule), &parse_cb_ipv6_rule) < 0) { > + acl_free_routes(); > + rte_exit(EXIT_FAILURE, "Failed to add IPv6 rules\n"); > + } > + } else { > + RTE_LOG(ERR, L3FWD, "IPv6 rule file not specified\n"); > + rte_exit(EXIT_FAILURE, "Failed to get valid route options\n"); > + } > +} > + > +#ifdef L3FWDACL_DEBUG > +static inline void > +dump_acl4_rule(struct rte_mbuf *m, uint32_t sig) > +{ > + char abuf[INET6_ADDRSTRLEN]; > + uint32_t offset =3D sig & ~ACL_DENY_SIGNATURE; > + struct rte_ipv4_hdr *ipv4_hdr =3D > + rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + > + printf("Packet Src:%s ", inet_ntop(AF_INET, ipv4_hdr->src_addr, > + abuf, sizeof(abuf))); > + printf("Dst:%s ", inet_ntop(AF_INET, ipv4_hdr->dst_addr, > + abuf, sizeof(abuf))); > + > + printf("Src port:%hu,Dst port:%hu ", > + rte_bswap16(*(uint16_t *)(ipv4_hdr + 1)), > + rte_bswap16(*((uint16_t *)(ipv4_hdr + 1) + 1))); > + printf("hit ACL %d - ", offset); > + > + print_one_ipv4_rule(acl_config.rule_ipv4 + offset, 1); > + > + printf("\n\n"); > +} > + > +static inline void > +dump_acl6_rule(struct rte_mbuf *m, uint32_t sig) > +{ > + char abuf[INET6_ADDRSTRLEN]; > + uint32_t offset =3D sig & ~ACL_DENY_SIGNATURE; > + struct rte_ipv6_hdr *ipv6_hdr =3D > + rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *, > + sizeof(struct rte_ether_hdr)); > + > + printf("Packet Src"); > + printf("%s", inet_ntop(AF_INET6, ipv6_hdr->src_addr, > + abuf, sizeof(abuf))); > + printf("\nDst"); > + printf("%s", inet_ntop(AF_INET6, ipv6_hdr->dst_addr, > + abuf, sizeof(abuf))); > + > + printf("\nSrc port:%hu,Dst port:%hu ", > + rte_bswap16(*(uint16_t *)(ipv6_hdr + 1)), > + rte_bswap16(*((uint16_t *)(ipv6_hdr + 1) + 1))); > + printf("hit ACL %d - ", offset); > + > + print_one_ipv6_rule(acl_config.rule_ipv6 + offset, 1); > + > + printf("\n\n"); > +} > +#endif /* L3FWDACL_DEBUG */ > + > +static inline void > +dump_ipv4_rules(struct acl4_rule *rule, int num, int extra) > +{ > + int i; > + > + for (i =3D 0; i < num; i++, rule++) { > + printf("\t%d:", i + 1); > + print_one_ipv4_rule(rule, extra); > + printf("\n"); > + } > +} > + > +static inline void > +dump_ipv6_rules(struct acl6_rule *rule, int num, int extra) > +{ > + int i; > + > + for (i =3D 0; i < num; i++, rule++) { > + printf("\t%d:", i + 1); > + print_one_ipv6_rule(rule, extra); > + printf("\n"); > + } > +} > + > +void > +setup_acl(const int socket_id) > +{ > + if (check_acl_config() !=3D 0) > + rte_exit(EXIT_FAILURE, "Failed to get valid ACL options\n"); > + > + dump_acl_config(); > + > + acl_log("IPv4 Route entries %u:\n", route_num_ipv4); > + dump_ipv4_rules((struct acl4_rule *)route_base_ipv4, route_num_ipv4, 1)= ; > + > + acl_log("IPv4 ACL entries %u:\n", acl_num_ipv4); > + dump_ipv4_rules((struct acl4_rule *)acl_base_ipv4, acl_num_ipv4, 1); > + > + acl_log("IPv6 Route entries %u:\n", route_num_ipv6); > + dump_ipv6_rules((struct acl6_rule *)route_base_ipv6, route_num_ipv6, 1)= ; > + > + acl_log("IPv6 ACL entries %u:\n", acl_num_ipv6); > + dump_ipv6_rules((struct acl6_rule *)acl_base_ipv6, acl_num_ipv6, 1); > + > + memset(&acl_config, 0, sizeof(acl_config)); > + > + /* Check sockets a context should be created on */ > + if (socket_id >=3D NB_SOCKETS) { > + acl_log("Socket %d is out " > + "of range %d\n", > + socket_id, NB_SOCKETS); > + acl_free_routes(); > + return; > + } > + > + acl_config.acx_ipv4[socket_id] =3D app_acl_init(route_base_ipv4, > + acl_base_ipv4, route_num_ipv4, acl_num_ipv4, > + 0, socket_id); > + > + acl_config.acx_ipv6[socket_id] =3D app_acl_init(route_base_ipv6, > + acl_base_ipv6, route_num_ipv6, acl_num_ipv6, > + 1, socket_id); > + > +#ifdef L3FWDACL_DEBUG > + acl_config.rule_ipv4 =3D (struct acl4_rule *)acl_base_ipv4; > + acl_config.rule_ipv6 =3D (struct acl6_rule *)acl_base_ipv6; > +#endif > + > +} > + > +/* main processing loop */ > +int > +acl_main_loop(__rte_unused void *dummy) > +{ > + struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; > + unsigned int lcore_id; > + uint64_t prev_tsc, diff_tsc, cur_tsc; > + int i, nb_rx; > + uint16_t portid; > + uint8_t queueid; > + struct lcore_conf *qconf; > + int socketid; > + const uint64_t drain_tsc =3D (rte_get_tsc_hz() + US_PER_S - 1) > + / US_PER_S * BURST_TX_DRAIN_US; > + > + prev_tsc =3D 0; > + lcore_id =3D rte_lcore_id(); > + qconf =3D &lcore_conf[lcore_id]; > + socketid =3D rte_lcore_to_socket_id(lcore_id); > + > + if (qconf->n_rx_queue =3D=3D 0) { > + RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id); > + return 0; > + } > + > + RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id); > + > + for (i =3D 0; i < qconf->n_rx_queue; i++) { > + > + portid =3D qconf->rx_queue_list[i].port_id; > + queueid =3D qconf->rx_queue_list[i].queue_id; > + RTE_LOG(INFO, L3FWD, > + " -- lcoreid=3D%u portid=3D%u rxqueueid=3D%hhu\n", > + lcore_id, portid, queueid); > + } > + > + while (!force_quit) { > + > + cur_tsc =3D rte_rdtsc(); > + > + /* > + * TX burst queue drain > + */ > + diff_tsc =3D cur_tsc - prev_tsc; > + if (unlikely(diff_tsc > drain_tsc)) { > + > + for (i =3D 0; i < qconf->n_tx_port; ++i) { > + portid =3D qconf->tx_port_id[i]; > + if (qconf->tx_mbufs[portid].len =3D=3D 0) > + continue; > + send_burst(qconf, > + qconf->tx_mbufs[portid].len, > + portid); > + qconf->tx_mbufs[portid].len =3D 0; > + } > + > + prev_tsc =3D cur_tsc; > + } > + > + /* > + * Read packet from RX queues > + */ > + for (i =3D 0; i < qconf->n_rx_queue; ++i) { > + > + portid =3D qconf->rx_queue_list[i].port_id; > + queueid =3D qconf->rx_queue_list[i].queue_id; > + nb_rx =3D rte_eth_rx_burst(portid, queueid, > + pkts_burst, MAX_PKT_BURST); > + > + if (nb_rx > 0) { > + struct acl_search_t acl_search; > + > + l3fwd_acl_prepare_acl_parameter(pkts_burst, &acl_search, > + nb_rx); > + > + if (acl_search.num_ipv4) { > + rte_acl_classify( > + acl_config.acx_ipv4[socketid], > + acl_search.data_ipv4, > + acl_search.res_ipv4, > + acl_search.num_ipv4, > + DEFAULT_MAX_CATEGORIES); > + > + l3fwd_acl_send_packets(qconf, > + acl_search.m_ipv4, > + acl_search.res_ipv4, > + acl_search.num_ipv4); > + } > + > + if (acl_search.num_ipv6) { > + rte_acl_classify( > + acl_config.acx_ipv6[socketid], > + acl_search.data_ipv6, > + acl_search.res_ipv6, > + acl_search.num_ipv6, > + DEFAULT_MAX_CATEGORIES); > + > + l3fwd_acl_send_packets(qconf, > + acl_search.m_ipv6, > + acl_search.res_ipv6, > + acl_search.num_ipv6); > + } > + } > + } > + } > + return 0; > +} > + > +static inline void > +acl_parse_ptype(struct rte_mbuf *m) > +{ > + struct rte_ether_hdr *eth_hdr; > + uint32_t packet_type =3D RTE_PTYPE_UNKNOWN; > + uint16_t ether_type; > + void *l3; > + int hdr_len; > + struct rte_ipv4_hdr *ipv4_hdr; > + struct rte_ipv6_hdr *ipv6_hdr; > + > + eth_hdr =3D rte_pktmbuf_mtod(m, struct rte_ether_hdr *); > + ether_type =3D eth_hdr->ether_type; > + l3 =3D (uint8_t *)eth_hdr + sizeof(struct rte_ether_hdr); > + if (ether_type =3D=3D rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) { > + ipv4_hdr =3D (struct rte_ipv4_hdr *)l3; > + hdr_len =3D rte_ipv4_hdr_len(ipv4_hdr); > + if (hdr_len =3D=3D sizeof(struct rte_ipv4_hdr)) { > + packet_type |=3D RTE_PTYPE_L3_IPV4; > + if (ipv4_hdr->next_proto_id =3D=3D IPPROTO_TCP) > + packet_type |=3D RTE_PTYPE_L4_TCP; > + else if (ipv4_hdr->next_proto_id =3D=3D IPPROTO_UDP) > + packet_type |=3D RTE_PTYPE_L4_UDP; > + } else > + packet_type |=3D RTE_PTYPE_L3_IPV4_EXT; > + } else if (ether_type =3D=3D rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) { > + ipv6_hdr =3D (struct rte_ipv6_hdr *)l3; > + if (ipv6_hdr->proto =3D=3D IPPROTO_TCP) > + packet_type |=3D RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; > + else if (ipv6_hdr->proto =3D=3D IPPROTO_UDP) > + packet_type |=3D RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; > + else > + packet_type |=3D RTE_PTYPE_L3_IPV6_EXT_UNKNOWN; > + } > + > + m->packet_type =3D packet_type; > +} > + > +uint16_t > +acl_cb_parse_ptype(uint16_t port __rte_unused, uint16_t queue __rte_unus= ed, struct rte_mbuf *pkts[], > + uint16_t nb_pkts, uint16_t max_pkts __rte_unused, void *user_param _= _rte_unused) > +{ > + unsigned int i; > + > + for (i =3D 0; i < nb_pkts; ++i) > + acl_parse_ptype(pkts[i]); > + > + return nb_pkts; > +} As I can see acl parse_ptype functions are identical to em conterparts. If so then we probably can remove dups and use the same functions for both = cases. > + > +int > +acl_check_ptype(int portid) > +{ > + int i, ret; > + int ptype_l3_ipv4_ext =3D 0; > + int ptype_l3_ipv6_ext =3D 0; > + int ptype_l4_tcp =3D 0; > + int ptype_l4_udp =3D 0; > + uint32_t ptype_mask =3D RTE_PTYPE_L3_MASK | RTE_PTYPE_L4_MASK; > + > + ret =3D rte_eth_dev_get_supported_ptypes(portid, ptype_mask, NULL, 0); > + if (ret <=3D 0) > + return 0; > + > + uint32_t ptypes[ret]; > + > + ret =3D rte_eth_dev_get_supported_ptypes(portid, ptype_mask, ptypes, re= t); > + for (i =3D 0; i < ret; ++i) { > + switch (ptypes[i]) { > + case RTE_PTYPE_L3_IPV4_EXT: > + ptype_l3_ipv4_ext =3D 1; > + break; > + case RTE_PTYPE_L3_IPV6_EXT: > + ptype_l3_ipv6_ext =3D 1; > + break; > + case RTE_PTYPE_L4_TCP: > + ptype_l4_tcp =3D 1; > + break; > + case RTE_PTYPE_L4_UDP: > + ptype_l4_udp =3D 1; > + break; > + } > + } > + > + if (ptype_l3_ipv4_ext =3D=3D 0) > + printf("port %d cannot parse RTE_PTYPE_L3_IPV4_EXT\n", portid); > + if (ptype_l3_ipv6_ext =3D=3D 0) > + printf("port %d cannot parse RTE_PTYPE_L3_IPV6_EXT\n", portid); > + if (!ptype_l3_ipv4_ext || !ptype_l3_ipv6_ext) > + return 0; > + > + if (ptype_l4_tcp =3D=3D 0) > + printf("port %d cannot parse RTE_PTYPE_L4_TCP\n", portid); > + if (ptype_l4_udp =3D=3D 0) > + printf("port %d cannot parse RTE_PTYPE_L4_UDP\n", portid); > + if (ptype_l4_tcp && ptype_l4_udp) > + return 1; > + > + return 0; > +} Same here, seems identical to em_check_ptype(). If so, can we possibly re-use existing one? > + > +/* Not used by L3fwd ACL. */ > +void * > +acl_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid) > +{ > + return NULL; > +} > + > +void * > +acl_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid) > +{ > + return NULL; > +} > diff --git a/examples/l3fwd/l3fwd_acl.h b/examples/l3fwd/l3fwd_acl.h > new file mode 100644 > index 0000000000..53df3343ee > --- /dev/null > +++ b/examples/l3fwd/l3fwd_acl.h > @@ -0,0 +1,120 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2021 Intel Corporation > + */ > + > +#ifndef __L3FWD_ACL_H__ > +#define __L3FWD_ACL_H__ > + > +#define MAX_ACL_RULE_NUM 100000 > +#define DEFAULT_MAX_CATEGORIES 1 > +#define L3FWD_ACL_IPV4_NAME "l3fwd-acl-ipv4" > +#define L3FWD_ACL_IPV6_NAME "l3fwd-acl-ipv6" > + > +#define ACL_DENY_SIGNATURE 0xf0000000 > +#define RTE_LOGTYPE_L3FWDACL RTE_LOGTYPE_USER3 > +#define acl_log(format, ...) RTE_LOG(ERR, L3FWDACL, format, ##__VA_ARGS_= _) > +#define uint32_t_to_char(ip, a, b, c, d) do {\ > + *a =3D (unsigned char)(ip >> 24 & 0xff);\ > + *b =3D (unsigned char)(ip >> 16 & 0xff);\ > + *c =3D (unsigned char)(ip >> 8 & 0xff);\ > + *d =3D (unsigned char)(ip & 0xff);\ > + } while (0) As I can see that macro is not used and can be safely removed. > +#define OFF_ETHHEAD (sizeof(struct rte_ether_hdr)) > +#define OFF_IPV42PROTO (offsetof(struct rte_ipv4_hdr, next_proto_id)) > +#define OFF_IPV62PROTO (offsetof(struct rte_ipv6_hdr, proto)) > +#define MBUF_IPV4_2PROTO(m) \ > + rte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV42PROTO) > +#define MBUF_IPV6_2PROTO(m) \ > + rte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV62PROTO) > + > +/* > + * ACL rules should have higher priorities than route ones to ensure ACL= rule > + * always be found when input packets have multi-matches in the database= . > + * A exception case is performance measure, which can define route rules= with > + * higher priority and route rules will always be returned in each looku= p. > + * Reserve range from ACL_RULE_PRIORITY_MAX + 1 to > + * RTE_ACL_MAX_PRIORITY for route entries in performance measure > + */ > +#define ACL_RULE_PRIORITY_MAX 0x10000000 > + > +/* > + * Forward port info save in ACL lib starts from 1 > + * since ACL assume 0 is invalid. > + * So, need add 1 when saving and minus 1 when forwarding packets. > + */ > +#define FWD_PORT_SHIFT 1 > + > +static inline void > +print_one_ipv4_rule(struct acl4_rule *rule, int extra) Probably no point to have print routines as 'static online'. They do not belong to fast-path. > +{ > + char abuf[INET6_ADDRSTRLEN]; > + uint32_t ipv4_addr; > + ipv4_addr =3D ntohl(rule->field[SRC_FIELD_IPV4].value.u32); > + printf("%s/%u ", inet_ntop(AF_INET, > + &(ipv4_addr), abuf, > + sizeof(abuf)), rule->field[SRC_FIELD_IPV4].mask_range.u32); > + ipv4_addr =3D ntohl(rule->field[DST_FIELD_IPV4].value.u32); > + printf("%s/%u ", inet_ntop(AF_INET, > + &(ipv4_addr), abuf, > + sizeof(abuf)), rule->field[DST_FIELD_IPV4].mask_range.u32); > + printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ", > + rule->field[SRCP_FIELD_IPV4].value.u16, > + rule->field[SRCP_FIELD_IPV4].mask_range.u16, > + rule->field[DSTP_FIELD_IPV4].value.u16, > + rule->field[DSTP_FIELD_IPV4].mask_range.u16, > + rule->field[PROTO_FIELD_IPV4].value.u8, > + rule->field[PROTO_FIELD_IPV4].mask_range.u8); > + if (extra) > + printf("0x%x-0x%x-0x%x ", > + rule->data.category_mask, > + rule->data.priority, > + rule->data.userdata); > +} > + > +static inline void > +print_one_ipv6_rule(struct acl6_rule *rule, int extra) > +{ > + char abuf[INET6_ADDRSTRLEN]; > + uint32_t ipv6_addr[4]; > + > + ipv6_addr[0] =3D rule->field[SRC1_FIELD_IPV6].value.u32; > + ipv6_addr[1] =3D rule->field[SRC2_FIELD_IPV6].value.u32; > + ipv6_addr[2] =3D rule->field[SRC3_FIELD_IPV6].value.u32; > + ipv6_addr[3] =3D rule->field[SRC4_FIELD_IPV6].value.u32; > + > + printf("%s", inet_ntop(AF_INET6, ipv6_addr, > + abuf, sizeof(abuf))); > + printf("/%u ", > + rule->field[SRC1_FIELD_IPV6].mask_range.u32 > + + rule->field[SRC2_FIELD_IPV6].mask_range.u32 > + + rule->field[SRC3_FIELD_IPV6].mask_range.u32 > + + rule->field[SRC4_FIELD_IPV6].mask_range.u32); > + > + ipv6_addr[0] =3D rule->field[DST1_FIELD_IPV6].value.u32; > + ipv6_addr[1] =3D rule->field[DST2_FIELD_IPV6].value.u32; > + ipv6_addr[2] =3D rule->field[DST3_FIELD_IPV6].value.u32; > + ipv6_addr[3] =3D rule->field[DST4_FIELD_IPV6].value.u32; > + > + printf("%s", inet_ntop(AF_INET6, ipv6_addr, > + abuf, sizeof(abuf))); > + printf("/%u ", > + rule->field[DST1_FIELD_IPV6].mask_range.u32 > + + rule->field[DST2_FIELD_IPV6].mask_range.u32 > + + rule->field[DST3_FIELD_IPV6].mask_range.u32 > + + rule->field[DST4_FIELD_IPV6].mask_range.u32); > + > + printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ", > + rule->field[SRCP_FIELD_IPV6].value.u16, > + rule->field[SRCP_FIELD_IPV6].mask_range.u16, > + rule->field[DSTP_FIELD_IPV6].value.u16, > + rule->field[DSTP_FIELD_IPV6].mask_range.u16, > + rule->field[PROTO_FIELD_IPV6].value.u8, > + rule->field[PROTO_FIELD_IPV6].mask_range.u8); > + if (extra) > + printf("0x%x-0x%x-0x%x ", > + rule->data.category_mask, > + rule->data.priority, > + rule->data.userdata); > +} > + > +#endif /* __L3FWD_ACL_H__ */ > diff --git a/examples/l3fwd/l3fwd_acl_scalar.h b/examples/l3fwd/l3fwd_acl= _scalar.h > new file mode 100644 > index 0000000000..1c8f9d3eb2 > --- /dev/null > +++ b/examples/l3fwd/l3fwd_acl_scalar.h > @@ -0,0 +1,160 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2021 Intel Corporation > + */ > + > +#ifndef __L3FWD_ACL_SCALAR_H__ > +#define __L3FWD_ACL_SCALAR_H__ > + > +#ifdef DO_RFC_1812_CHECKS > +static inline void > +l3fwd_acl_prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_searc= h_t *acl, > + int index) > +{ > + struct rte_ipv4_hdr *ipv4_hdr; > + struct rte_mbuf *pkt =3D pkts_in[index]; > + > + if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) { > + ipv4_hdr =3D rte_pktmbuf_mtod_offset(pkt, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + > + /* Check to make sure the packet is valid (RFC1812) */ > + if (is_valid_ipv4_pkt(ipv4_hdr, pkt->pkt_len) >=3D 0) { > + > + /* Update time to live and header checksum */ > + --(ipv4_hdr->time_to_live); > + ++(ipv4_hdr->hdr_checksum); > + > + /* Fill acl structure */ > + acl->data_ipv4[acl->num_ipv4] =3D MBUF_IPV4_2PROTO(pkt); > + acl->m_ipv4[(acl->num_ipv4)++] =3D pkt; > + > + } else { > + /* Not a valid IPv4 packet */ > + rte_pktmbuf_free(pkt); > + } > + } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) { > + /* Fill acl structure */ > + acl->data_ipv6[acl->num_ipv6] =3D MBUF_IPV6_2PROTO(pkt); > + acl->m_ipv6[(acl->num_ipv6)++] =3D pkt; > + > + } else { > + /* Unknown type, drop the packet */ > + rte_pktmbuf_free(pkt); > + } > +} > + > +#else > +static inline void > +l3fwd_acl_prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_searc= h_t *acl, > + int index) > +{ > + struct rte_mbuf *pkt =3D pkts_in[index]; > + > + if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) { > + /* Fill acl structure */ > + acl->data_ipv4[acl->num_ipv4] =3D MBUF_IPV4_2PROTO(pkt); > + acl->m_ipv4[(acl->num_ipv4)++] =3D pkt; > + > + } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) { > + /* Fill acl structure */ > + acl->data_ipv6[acl->num_ipv6] =3D MBUF_IPV6_2PROTO(pkt); > + acl->m_ipv6[(acl->num_ipv6)++] =3D pkt; > + } else { > + /* Unknown type, drop the packet */ > + rte_pktmbuf_free(pkt); > + } > +} > +#endif /* DO_RFC_1812_CHECKS */ > + > +/* Enqueue a single packet, and send burst if queue is filled */ > +static inline void > +l3fwd_acl_send_single_packet(struct lcore_conf *qconf, > + struct rte_mbuf *m, uint16_t port) > +{ Is that a dup of send_single_packet() fro l3fwd.h? If so, then better to use the original one and remove that one as a duplica= te. > + uint16_t len; > + > + len =3D qconf->tx_mbufs[port].len; > + qconf->tx_mbufs[port].m_table[len] =3D m; > + len++; > + > + /* enough pkts to be sent */ > + if (unlikely(len =3D=3D MAX_PKT_BURST)) { > + send_burst(qconf, MAX_PKT_BURST, port); > + len =3D 0; > + } > + > + qconf->tx_mbufs[port].len =3D len; > +} > + > +static inline void > +l3fwd_acl_prepare_acl_parameter(struct rte_mbuf **pkts_in, struct acl_se= arch_t *acl, > + int nb_rx) > +{ > + int i; > + > + acl->num_ipv4 =3D 0; > + acl->num_ipv6 =3D 0; > + > + /* Prefetch first packets */ > + for (i =3D 0; i < PREFETCH_OFFSET && i < nb_rx; i++) { > + rte_prefetch0(rte_pktmbuf_mtod( > + pkts_in[i], void *)); > + } > + > + for (i =3D 0; i < (nb_rx - PREFETCH_OFFSET); i++) { > + rte_prefetch0(rte_pktmbuf_mtod(pkts_in[ > + i + PREFETCH_OFFSET], void *)); > + l3fwd_acl_prepare_one_packet(pkts_in, acl, i); > + } > + > + /* Process left packets */ > + for (; i < nb_rx; i++) > + l3fwd_acl_prepare_one_packet(pkts_in, acl, i); > +} > + > +static inline void > +l3fwd_acl_send_one_packet(struct lcore_conf *qconf, struct rte_mbuf *m, > + uint32_t res) > +{ > + if (likely((res & ACL_DENY_SIGNATURE) =3D=3D 0 && res !=3D 0)) { > + /* forward packets */ > + l3fwd_acl_send_single_packet(qconf, m, > + (uint8_t)(res - FWD_PORT_SHIFT)); I don't see where we update mac addresses for outgoing packets... Is that part missing in updated acl code-path? If so, then we probably need to put it back. In fact, I wonder can we apply the same code as is done for fib: - in l3fwd_acl_prepare_one_packet() remove all packet modifications and ipv4 validity checks. So it will become something really simple like tha= t:=20 =20 static inline void l3fwd_acl_prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t= *acl, int index) { struct rte_mbuf *pkt =3D pkts_in[index]; if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) { /* Fill acl structure */ acl->data_ipv4[acl->num_ipv4] =3D MBUF_IPV4_2PROTO(pkt); } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) { /* Fill acl structure */ acl->data_ipv6[acl->num_ipv6] =3D MBUF_IPV6_2PROTO(pkt); } else { /* Unknown type, drop the packet */ rte_pktmbuf_free(pkt); } } - in l3fwd_acl_send_packets() do what fib (and other ) code paths do: #if defined SEND_MULTI send_packets_multi(...); #else l3fwd_acl_send_packets(...); #endif > + } else { > + /* in the ACL list, drop it */ > +#ifdef L3FWDACL_DEBUG > + if ((res & ACL_DENY_SIGNATURE) !=3D 0) { > + if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) > + dump_acl4_rule(m, res); > + else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) > + dump_acl6_rule(m, res); > + } > +#endif > + rte_pktmbuf_free(m); > + } > +} > + > +static inline void > +l3fwd_acl_send_packets(struct lcore_conf *qconf, struct rte_mbuf **m, > + uint32_t *res, int num) > +{ > + int i; > + > + /* Prefetch first packets */ > + for (i =3D 0; i < PREFETCH_OFFSET && i < num; i++) { > + rte_prefetch0(rte_pktmbuf_mtod( > + m[i], void *)); > + } > + > + for (i =3D 0; i < (num - PREFETCH_OFFSET); i++) { > + rte_prefetch0(rte_pktmbuf_mtod(m[ > + i + PREFETCH_OFFSET], void *)); > + l3fwd_acl_send_one_packet(qconf, m[i], res[i]); > + } > + > + /* Process left packets */ > + for (; i < num; i++) > + l3fwd_acl_send_one_packet(qconf, m[i], res[i]); > +} > + > +#endif /* __L3FWD_ACL_SCALAR_H__ */ > diff --git a/examples/l3fwd/l3fwd_route.h b/examples/l3fwd/l3fwd_route.h > index adf33dbf46..467c4d2859 100644 > --- a/examples/l3fwd/l3fwd_route.h > +++ b/examples/l3fwd/l3fwd_route.h > @@ -5,6 +5,7 @@ > /* Log file related character defs. */ > #define COMMENT_LEAD_CHAR ('#') > #define ROUTE_LEAD_CHAR ('R') > +#define ACL_LEAD_CHAR ('@') >=20 > #define IPV6_ADDR_LEN 16 > #define IPV6_ADDR_U16 (IPV6_ADDR_LEN / sizeof(uint16_t)) > @@ -96,11 +97,26 @@ read_config_files_lpm(void); > void > read_config_files_em(void); >=20 > +void > +read_config_files_acl(void); > + > void > em_free_routes(void); >=20 > void > lpm_free_routes(void); >=20 > +void > +acl_free_routes(void); > + > +void > +l3fwd_set_alg(const char *optarg); > + > +void > +l3fwd_set_rule_ipv6_name(const char *optarg); > + > +void > +l3fwd_set_rule_ipv4_name(const char *optarg); > + > int > is_bypass_line(const char *buff); > diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c > index a629198223..c259bfeaf2 100644 > --- a/examples/l3fwd/main.c > +++ b/examples/l3fwd/main.c > @@ -59,17 +59,17 @@ uint16_t nb_txd =3D RTE_TEST_TX_DESC_DEFAULT; > /**< Ports set in promiscuous mode off by default. */ > static int promiscuous_on; >=20 > -/* Select Longest-Prefix, Exact match or Forwarding Information Base. */ > +/* Select Longest-Prefix, Exact match, Forwarding Information Base or Ac= cess Control. */ > enum L3FWD_LOOKUP_MODE { > L3FWD_LOOKUP_DEFAULT, > L3FWD_LOOKUP_LPM, > L3FWD_LOOKUP_EM, > - L3FWD_LOOKUP_FIB > + L3FWD_LOOKUP_FIB, > + L3FWD_LOOKUP_ACL > }; > static enum L3FWD_LOOKUP_MODE lookup_mode; >=20 > /* Global variables. */ > - > static int numa_on =3D 1; /**< NUMA is enabled by default. */ > static int parse_ptype; /**< Parse packet type using rx callback, and */ > /**< disabled by default */ > @@ -187,6 +187,30 @@ static struct l3fwd_lkp_mode l3fwd_fib_lkp =3D { > .free_routes =3D lpm_free_routes, > }; >=20 > +static struct l3fwd_lkp_mode l3fwd_acl_lkp =3D { > + .read_config_files =3D read_config_files_acl, > + .setup =3D setup_acl, > + .check_ptype =3D acl_check_ptype, > + .cb_parse_ptype =3D acl_cb_parse_ptype, > + .main_loop =3D acl_main_loop, > + .get_ipv4_lookup_struct =3D acl_get_ipv4_l3fwd_lookup_struct, > + .get_ipv6_lookup_struct =3D acl_get_ipv6_l3fwd_lookup_struct, > + .free_routes =3D acl_free_routes, > +}; > + > +static enum rte_acl_classify_alg > +parse_acl_alg(const char *alg) > +{ > + uint32_t i; > + > + for (i =3D 0; i !=3D RTE_DIM(acl_alg); i++) { > + if (strcmp(alg, acl_alg[i].name) =3D=3D 0) > + return acl_alg[i].alg; > + } > + > + return RTE_ACL_CLASSIFY_DEFAULT; > +} > + > /* > * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735). > * 198.18.{0-15}.0/24 =3D Port {0-15} > @@ -236,18 +260,24 @@ const struct ipv6_l3fwd_route ipv6_l3fwd_route_arra= y[] =3D { > /* > * API's called during initialization to setup ACL/EM/LPM rules. > */ > -static void > +void > l3fwd_set_rule_ipv4_name(const char *optarg) > { > parm_config.rule_ipv4_name =3D optarg; > } >=20 > -static void > +void > l3fwd_set_rule_ipv6_name(const char *optarg) > { > parm_config.rule_ipv6_name =3D optarg; > } >=20 > +void > +l3fwd_set_alg(const char *optarg) > +{ > + parm_config.alg =3D parse_acl_alg(optarg); > +} > + > /* > * Setup lookup methods for forwarding. > * Currently exact-match, longest-prefix-match and forwarding informatio= n > @@ -262,6 +292,9 @@ setup_l3fwd_lookup_tables(void) > /* Setup FIB lookup functions. */ > else if (lookup_mode =3D=3D L3FWD_LOOKUP_FIB) > l3fwd_lkp =3D l3fwd_fib_lkp; > + /* Setup ACL lookup functions. */ > + else if (lookup_mode =3D=3D L3FWD_LOOKUP_ACL) > + l3fwd_lkp =3D l3fwd_acl_lkp; > /* Setup LPM lookup functions. */ > else > l3fwd_lkp =3D l3fwd_lpm_lkp; > @@ -357,10 +390,32 @@ init_lcore_rx_queues(void) > return 0; > } >=20 > +static int > +usage_acl_alg(char *buf, size_t sz) > +{ > + uint32_t i, n, rc, tn; > + > + n =3D 0; > + tn =3D 0; > + for (i =3D 0; i < RTE_DIM(acl_alg); i++) { > + rc =3D snprintf(buf + n, sz - n, > + i =3D=3D RTE_DIM(acl_alg) - 1 ? "%s" : "%s|", > + acl_alg[i].name); > + tn +=3D rc; > + if (rc < sz - n) > + n +=3D rc; > + } > + > + return tn; > +} > + > /* display usage */ > static void > print_usage(const char *prgname) > { > + char alg[PATH_MAX]; > + > + usage_acl_alg(alg, sizeof(alg)); > fprintf(stderr, "%s [EAL options] --" > " -p PORTMASK" > " --rule_ipv4=3DFILE" > @@ -387,7 +442,8 @@ print_usage(const char *prgname) > " -P : Enable promiscuous mode\n" > " --lookup: Select the lookup method\n" > " Default: lpm\n" > - " Accepted: em (Exact Match), lpm (Longest Prefix Match), f= ib (Forwarding Information Base)\n" > + " Accepted: em (Exact Match), lpm (Longest Prefix Match), f= ib (Forwarding Information Base),\n" > + " acl (Access Control List)\n" > " --config (port,queue,lcore): Rx queue configuration\n" > " --rx-queue-size NPKTS: Rx queue size in decimal\n" > " Default: %d\n" > @@ -416,8 +472,13 @@ print_usage(const char *prgname) > " -L : Enable longest prefix match, legacy flag please use --lookup= =3Dlpm instead\n" > " --rule_ipv4=3DFILE: Specify the ipv4 rules entries file.\n" > " Each rule occupies one line.\n" > - " --rule_ipv6=3DFILE: Specify the ipv6 rules entries file.\n\n", > - prgname, RTE_TEST_RX_DESC_DEFAULT, RTE_TEST_TX_DESC_DEFAULT); > + " 2 kinds of rules are supported.\n" > + " One is ACL entry at while line leads with charact= er '%c',\n" > + " another is route entry at while line leads with c= haracter '%c'.\n" > + " --rule_ipv6=3DFILE: Specify the ipv6 rules entries file.\n" > + " --alg: ACL classify method to use, one of: %s.\n\n", > + prgname, RTE_TEST_RX_DESC_DEFAULT, RTE_TEST_TX_DESC_DEFAULT, > + ACL_LEAD_CHAR, ROUTE_LEAD_CHAR, alg); > } >=20 > static int > @@ -632,8 +693,10 @@ parse_lookup(const char *optarg) > lookup_mode =3D L3FWD_LOOKUP_LPM; > else if (!strcmp(optarg, "fib")) > lookup_mode =3D L3FWD_LOOKUP_FIB; > + else if (!strcmp(optarg, "acl")) > + lookup_mode =3D L3FWD_LOOKUP_ACL; > else { > - fprintf(stderr, "Invalid lookup option! Accepted options: em, lpm, fib= \n"); > + fprintf(stderr, "Invalid lookup option! Accepted options: acl, em, lpm= , fib\n"); > return -1; > } > return 0; > @@ -667,6 +730,7 @@ static const char short_options[] =3D > #define CMD_LINE_OPT_VECTOR_TMO_NS "event-vector-tmo" > #define CMD_LINE_OPT_RULE_IPV4 "rule_ipv4" > #define CMD_LINE_OPT_RULE_IPV6 "rule_ipv6" > +#define CMD_LINE_OPT_ALG "alg" >=20 > enum { > /* long options mapped to a short option */ > @@ -685,6 +749,7 @@ enum { > CMD_LINE_OPT_PARSE_PTYPE_NUM, > CMD_LINE_OPT_RULE_IPV4_NUM, > CMD_LINE_OPT_RULE_IPV6_NUM, > + CMD_LINE_OPT_ALG_NUM, > CMD_LINE_OPT_PARSE_PER_PORT_POOL, > CMD_LINE_OPT_MODE_NUM, > CMD_LINE_OPT_EVENTQ_SYNC_NUM, > @@ -716,6 +781,7 @@ static const struct option lgopts[] =3D { > {CMD_LINE_OPT_VECTOR_TMO_NS, 1, 0, CMD_LINE_OPT_VECTOR_TMO_NS_NUM}, > {CMD_LINE_OPT_RULE_IPV4, 1, 0, CMD_LINE_OPT_RULE_IPV4_NUM}, > {CMD_LINE_OPT_RULE_IPV6, 1, 0, CMD_LINE_OPT_RULE_IPV6_NUM}, > + {CMD_LINE_OPT_ALG, 1, 0, CMD_LINE_OPT_ALG_NUM}, > {NULL, 0, 0, 0} > }; >=20 > @@ -884,6 +950,9 @@ parse_args(int argc, char **argv) > case CMD_LINE_OPT_RULE_IPV6_NUM: > l3fwd_set_rule_ipv6_name(optarg); > break; > + case CMD_LINE_OPT_ALG_NUM: > + l3fwd_set_alg(optarg); > + break; > default: > print_usage(prgname); > return -1; > @@ -923,7 +992,7 @@ parse_args(int argc, char **argv) > * as default match. > */ > if (lookup_mode =3D=3D L3FWD_LOOKUP_DEFAULT) { > - fprintf(stderr, "Neither LPM, EM, or FIB selected, defaulting to LPM\n= "); > + fprintf(stderr, "Neither ACL, LPM, EM, or FIB selected, defaulting to = LPM\n"); > lookup_mode =3D L3FWD_LOOKUP_LPM; > } >=20 > @@ -937,6 +1006,12 @@ parse_args(int argc, char **argv) > hash_entry_number =3D HASH_ENTRY_NUMBER_DEFAULT; > } >=20 > + /* For ACL, update port config rss hash filter */ > + if (lookup_mode =3D=3D L3FWD_LOOKUP_ACL) { > + port_conf.rx_adv_conf.rss_conf.rss_hf |=3D > + RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_SCTP; > + } > + > if (optind >=3D 0) > argv[optind-1] =3D prgname; >=20 > @@ -992,7 +1067,7 @@ init_mem(uint16_t portid, unsigned int nb_mbuf) > printf("Allocated mbuf pool on socket %d\n", > socketid); >=20 > - /* Setup LPM, EM(f.e Hash) or FIB. But, only once per > + /* Setup ACL, LPM, EM(f.e Hash) or FIB. But, only once per > * available socket. > */ > if (!lkp_per_socket[socketid]) { > diff --git a/examples/l3fwd/meson.build b/examples/l3fwd/meson.build > index 0830b3eb31..2fa00e5b74 100644 > --- a/examples/l3fwd/meson.build > +++ b/examples/l3fwd/meson.build > @@ -7,8 +7,9 @@ > # DPDK instance, use 'make' >=20 > allow_experimental_apis =3D true > -deps +=3D ['hash', 'lpm', 'fib', 'eventdev'] > +deps +=3D ['hash', 'lpm', 'fib', 'eventdev', 'acl'] > sources =3D files( > + 'l3fwd_acl.c', > 'l3fwd_em.c', > 'l3fwd_event.c', > 'l3fwd_event_internal_port.c', > diff --git a/examples/meson.build b/examples/meson.build > index 268422a257..78de0e1f37 100644 > --- a/examples/meson.build > +++ b/examples/meson.build > @@ -32,7 +32,6 @@ all_examples =3D [ > 'l2fwd-jobstats', > 'l2fwd-keepalive', > 'l3fwd', > - 'l3fwd-acl', > 'l3fwd-graph', > 'l3fwd-power', > 'link_status_interrupt', > -- > 2.25.1