From patchwork Thu Apr 7 21:47:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Owen Hilyard X-Patchwork-Id: 109440 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 12D91A050C; Thu, 7 Apr 2022 23:47:42 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id D734341145; Thu, 7 Apr 2022 23:47:30 +0200 (CEST) Received: from mail-pl1-f226.google.com (mail-pl1-f226.google.com [209.85.214.226]) by mails.dpdk.org (Postfix) with ESMTP id D27A740689 for ; Thu, 7 Apr 2022 23:47:28 +0200 (CEST) Received: by mail-pl1-f226.google.com with SMTP id o10so6216318ple.7 for ; Thu, 07 Apr 2022 14:47:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iol.unh.edu; s=unh-iol; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=O8r1cZRzCIdnsQSIBJtzWEqrHdQBq1DtnMFodCK3R88=; b=AdeQ+0VBOw/wfLt75y6bjTk82sImQLbEtEw+cTh04ittQAGmiMLbeXcgQZqNxI2Y8O OWEv8jXP1Xwb5GL5u63k83SW7U5Ug5akSJfv9ETgLCKj+SNzZqaDXsJoHVeKGuWWu+G9 Fae6O1c/t2DFVVdnlBl5Ik7bTwGP6wAmeuuhM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=O8r1cZRzCIdnsQSIBJtzWEqrHdQBq1DtnMFodCK3R88=; b=attRHIzsrcgIca5eN5hLmCYMrfUXMEGMwQn+QrrQgnP2748MXv9gpMIVOBXB1fHHLY gHti7v4UbjUBNlVbEa90HlHu9WFjwT87gLZOB4ge/yp7EIHpxYtcQGSbvhA5XjTbniIg o97y7tT1yCU0tdyqP1w34mVjjGuorrkLjJS+Uu8n/tISV4WWrQWxeWnIdy1+uV/yPwp0 I/8kM1gEZJ+Gp00ch4HyPR6SPtaBSlTChZ3HJ+8JUfX0JkofrUXs/UGTI1XlkzZicAnK s1T9wqVvPpC5ly2p5lSwxGCvDLzFF4BB0jbEtdWJG2MkiZ0JwKXH+TUXmev44HoIC2wF JoBQ== X-Gm-Message-State: AOAM530CP5a7WUl2pxzVceEx2pqoKlORkQMfOJgBoyytX6EoKbiMsyMk opEfmFiRbtJfwEpzSIQ2eJ1v1QttrDfGZUAjYxLt+J1+q/l7GxdR9G+6WZ3oD+CJ0g== X-Google-Smtp-Source: ABdhPJzAeRIiQo86w7hZDNv9a/o5o1nlzchTqiS1UsxNh4/Pl0htbF7mq40jkuv6CaF4N5r+hdyLtOl8mzPq X-Received: by 2002:a17:903:244d:b0:154:3772:6b32 with SMTP id l13-20020a170903244d00b0015437726b32mr15896593pls.70.1649368048037; Thu, 07 Apr 2022 14:47:28 -0700 (PDT) Received: from postal.iol.unh.edu (postal.iol.unh.edu. [2606:4100:3880:1234::84]) by smtp-relay.gmail.com with ESMTPS id e3-20020a170903240300b0014faa5e5fd1sm841866plo.63.2022.04.07.14.47.27 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 Apr 2022 14:47:28 -0700 (PDT) X-Relaying-Domain: iol.unh.edu Received: from iol.unh.edu (unknown [IPv6:2606:4100:3880:1257::105d]) by postal.iol.unh.edu (Postfix) with ESMTP id 36DB16051839; Thu, 7 Apr 2022 17:47:27 -0400 (EDT) From: ohilyard@iol.unh.edu To: dev@dpdk.org Cc: Honnappa.Nagarahalli@arm.com, thomas@monjalon.net, Owen Hilyard Subject: [PATCH v1 1/4] app/test-pmd-api: Add C++ Compiler Date: Thu, 7 Apr 2022 17:47:05 -0400 Message-Id: <20220407214707.29730-2-ohilyard@iol.unh.edu> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220407214707.29730-1-ohilyard@iol.unh.edu> References: <20220407214707.29730-1-ohilyard@iol.unh.edu> MIME-Version: 1.0 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 From: Owen Hilyard Adds a C++ compiler to the project, which is currently enabled by default for ease of testing. Meson currently lacks a way to try to get a compiler, and failing to find a compiler for a language always causes a hard error, so this is the only workable approach. Signed-off-by: Owen Hilyard --- meson.build | 3 +++ meson_options.txt | 2 ++ 2 files changed, 5 insertions(+) diff --git a/meson.build b/meson.build index 937f6110c0..01d47100f2 100644 --- a/meson.build +++ b/meson.build @@ -31,6 +31,9 @@ endif # set up some global vars for compiler, platform, configuration, etc. cc = meson.get_compiler('c') +if get_option('use_cpp') + cxx = meson.get_compiler('cpp') +endif dpdk_source_root = meson.current_source_dir() dpdk_build_root = meson.current_build_dir() dpdk_conf = configuration_data() diff --git a/meson_options.txt b/meson_options.txt index 7c220ad68d..9461d194a1 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -48,3 +48,5 @@ option('tests', type: 'boolean', value: true, description: 'build unit tests') option('use_hpet', type: 'boolean', value: false, description: 'use HPET timer in EAL') +option('use_cpp', type: 'boolean', value: true, description: + 'enable components requiring a C++ compiler.') \ No newline at end of file From patchwork Thu Apr 7 21:47:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Owen Hilyard X-Patchwork-Id: 109441 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 08260A050C; Thu, 7 Apr 2022 23:47:48 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C9371427EF; Thu, 7 Apr 2022 23:47:31 +0200 (CEST) Received: from mail-pl1-f227.google.com (mail-pl1-f227.google.com [209.85.214.227]) by mails.dpdk.org (Postfix) with ESMTP id D7F864068F for ; Thu, 7 Apr 2022 23:47:28 +0200 (CEST) Received: by mail-pl1-f227.google.com with SMTP id o10so6216320ple.7 for ; Thu, 07 Apr 2022 14:47:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iol.unh.edu; s=unh-iol; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=33WPSoOL7NpA5oJqa7hh4jbxcUXvO2rZYX6zYEQsxBY=; b=PvGlkhx+mZsbf0tnGJYt6SKfeXIFpcN1WhJLYRfYIHRsPFuJTXnp/gDNY+1kr1XkpY JeIN8FmB2uniCQ2v7EiwvtxjlzunDLfnECoOqRkd6S80NAIaWNvxheif9K4thZJcY6lg KhRfzStKmdCCqh+qsK1ZwxmGMaUGcUOuUrV8M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=33WPSoOL7NpA5oJqa7hh4jbxcUXvO2rZYX6zYEQsxBY=; b=INQVU/6s7rsDtIGte87jDYAVvyeFwfhBOVgAUBewKBbhFUMEFqDgEaTGV8ZDTmjsNC gkFAE1AQ/6Gt1aEzBS6iJpAY6Ev9/f6iiNp7kyjD1nEaACMNfxOj//jfk1eMYhMFUBJI 5smWkR0eXZYbIyDfod+khKiZ3xQI+6+B1DghPZKuBDK7NqX5CTgL4OOzBnLcL4CsAAV+ 5nablFnKlJG/S+HoRcD1pHBDNzCfEpvaG6YmM5ixia0v3kVnF6bqMdoYkH1cOs8LmMEY XUrFXtDgaWY/PWQz/6MyOo6TzeoQqK9bd/3X5RN8C+gGkYMRSbHqMJJ9EFyqE4Et/p6X Vqrw== X-Gm-Message-State: AOAM533zaiJ1Ye5Beok0u+FJ4i4ZYyt9czCfyzl+dzKQC8AERzM7SdLl b2WQTyIgMxdnAnuKffRD52fISLY9R6ose/ilAddCuXg50/JdYDGPnyiw1Kv/d3zCRQ== X-Google-Smtp-Source: ABdhPJzUhplZIU8hBE4JfZJM8cWOvl9G2/n7hv2nFWDcAvprLhMfm49e8j3L1t9NB906C3udULBJhvfYIAFd X-Received: by 2002:a17:90a:cb94:b0:1ca:7c56:dd4d with SMTP id a20-20020a17090acb9400b001ca7c56dd4dmr18150836pju.133.1649368048117; Thu, 07 Apr 2022 14:47:28 -0700 (PDT) Received: from postal.iol.unh.edu (postal.iol.unh.edu. [2606:4100:3880:1234::84]) by smtp-relay.gmail.com with ESMTPS id x5-20020a17090a46c500b001ca7a173c3asm986010pjg.17.2022.04.07.14.47.27 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 Apr 2022 14:47:28 -0700 (PDT) X-Relaying-Domain: iol.unh.edu Received: from iol.unh.edu (unknown [IPv6:2606:4100:3880:1257::105d]) by postal.iol.unh.edu (Postfix) with ESMTP id 3CAAD605183A; Thu, 7 Apr 2022 17:47:27 -0400 (EDT) From: ohilyard@iol.unh.edu To: dev@dpdk.org Cc: Honnappa.Nagarahalli@arm.com, thomas@monjalon.net, Owen Hilyard Subject: [PATCH v1 2/4] app/test-pmd-api: Add POC with gRPC deps Date: Thu, 7 Apr 2022 17:47:06 -0400 Message-Id: <20220407214707.29730-3-ohilyard@iol.unh.edu> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220407214707.29730-1-ohilyard@iol.unh.edu> References: <20220407214707.29730-1-ohilyard@iol.unh.edu> MIME-Version: 1.0 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 From: Owen Hilyard The new app is disabled if the dependencies are not present, in order to avoid breaking the build on any system that does not have gRPC installed. The meson file for the app is heavily derived from the testpmd. Signed-off-by: Owen Hilyard --- app/meson.build | 17 +++++++ app/test-pmd-api/meson.build | 96 ++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 app/test-pmd-api/meson.build diff --git a/app/meson.build b/app/meson.build index 93d8c15032..3dfd5c003e 100644 --- a/app/meson.build +++ b/app/meson.build @@ -20,6 +20,23 @@ apps = [ 'test-sad', ] +if get_option('use_cpp') + protoc = find_program('protoc', required : false) + protobuf_dep = dependency('protobuf', required : false) + grpc_cpp_plugin = find_program('grpc_cpp_plugin', required: false) + grpc_python_plugin = find_program('grpc_python_plugin', required: false) + grpc_dep = dependency('grpc', required: false) + grpcpp_dep = dependency('grpc++', required: false) + + if protoc.found() and dep.found() and grpc_cpp_plugin.found() and grpc_python_plugin.found() and grpc_dep.found() and grpcpp_dep.found() + apps += [ + 'test-pmd-api' + ] + endif + +endif + + default_cflags = machine_args + ['-DALLOW_EXPERIMENTAL_API'] default_ldflags = [] if get_option('default_library') == 'static' and not is_windows diff --git a/app/test-pmd-api/meson.build b/app/test-pmd-api/meson.build new file mode 100644 index 0000000000..7438098e9d --- /dev/null +++ b/app/test-pmd-api/meson.build @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2017 Intel Corporation + +# override default name to drop the hyphen +name = 'testpmd-api' +cflags += [ + '-Wno-deprecated-declarations' +] +sources += files( + 'main.c', + 'api_impl.cc' +) + +ldflags += [ + '-ldl', + '-lgrpc++_reflection', +] + +ext_deps += [protobuf_dep, grpc_dep, grpcpp_dep, dependency('threads')] + +if dpdk_conf.has('RTE_HAS_JANSSON') + ext_deps += jansson_dep +endif + +deps += ['ethdev', 'cmdline', 'bus_pci'] +if dpdk_conf.has('RTE_CRYPTO_SCHEDULER') + deps += 'crypto_scheduler' +endif +if dpdk_conf.has('RTE_LIB_BITRATESTATS') + deps += 'bitratestats' +endif +if dpdk_conf.has('RTE_LIB_BPF') + deps += 'bpf' +endif +if dpdk_conf.has('RTE_LIB_GRO') + deps += 'gro' +endif +if dpdk_conf.has('RTE_LIB_GSO') + deps += 'gso' +endif +if dpdk_conf.has('RTE_LIB_LATENCYSTATS') + deps += 'latencystats' +endif +if dpdk_conf.has('RTE_LIB_METRICS') + deps += 'metrics' +endif +if dpdk_conf.has('RTE_LIB_PDUMP') + deps += 'pdump' +endif +if dpdk_conf.has('RTE_NET_BOND') + deps += 'net_bond' +endif +if dpdk_conf.has('RTE_NET_BNXT') + deps += 'net_bnxt' +endif +if dpdk_conf.has('RTE_NET_I40E') + deps += 'net_i40e' +endif +if dpdk_conf.has('RTE_NET_IXGBE') + deps += 'net_ixgbe' +endif +if dpdk_conf.has('RTE_NET_DPAA') + deps += ['bus_dpaa', 'mempool_dpaa', 'net_dpaa'] +endif + +if meson.version().version_compare('>=0.55') + grpc_cpp_plugin_path = grpc_cpp_plugin.full_path() + grpc_python_plugin_path = grpc_python_plugin.full_path() +else + grpc_cpp_plugin_path = grpc_cpp_plugin.path() + grpc_python_plugin_path = grpc_python_plugin.path() +endif + + +cpp_generator = generator(protoc, + output : ['@BASENAME@.pb.cc', '@BASENAME@.pb.h', '@BASENAME@.grpc.pb.cc', '@BASENAME@.grpc.pb.h'], + arguments : [ + '--proto_path=@CURRENT_SOURCE_DIR@', + '--plugin=protoc-gen-grpc=@0@'.format(grpc_cpp_plugin_path), + '--cpp_out=@BUILD_DIR@', + '--grpc_out=@BUILD_DIR@', + '@INPUT@' + ]) + +python_generator = generator(protoc, + output : ['@BASENAME@_pb2.py', '@BASENAME@_pb2_grpc.py'], + arguments : [ + '--proto_path=@CURRENT_SOURCE_DIR@', + '--plugin=protoc-gen-grpc=@0@'.format(grpc_python_plugin_path), + '--python_out=@BUILD_DIR@', + '--grpc_out=@BUILD_DIR@', + '@INPUT@' + ]) + +sources += cpp_generator.process('api.proto') +sources += python_generator.process('api.proto') \ No newline at end of file From patchwork Thu Apr 7 21:47:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Owen Hilyard X-Patchwork-Id: 109442 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 325C3A050C; Thu, 7 Apr 2022 23:47:55 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 000534285E; Thu, 7 Apr 2022 23:47:32 +0200 (CEST) Received: from mail-pg1-f225.google.com (mail-pg1-f225.google.com [209.85.215.225]) by mails.dpdk.org (Postfix) with ESMTP id F11BF4068B for ; Thu, 7 Apr 2022 23:47:28 +0200 (CEST) Received: by mail-pg1-f225.google.com with SMTP id t13so6104143pgn.8 for ; Thu, 07 Apr 2022 14:47:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iol.unh.edu; s=unh-iol; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=iWD5Sba03+eoCy5qnnT2+gm7irC/WZv2m93QM8nYajM=; b=ifqetHtCiWkBjxJJtdoVVEETUKPw3AkanpZBSkkdf9QzkxLmwP3G8E4J/rv6GLNkA+ SqB1fCcOt0CmWBN72SV+GZexXVg41ABrxURekv4yucRVg3VVgytkvzCUZvNhpG+1ooz2 Q9mdfbEujAzFL1RGCb3qoQzGr+EShAhZzvslY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=iWD5Sba03+eoCy5qnnT2+gm7irC/WZv2m93QM8nYajM=; b=21KfZEe/ep2GchWP1cvouno83w5k2X8KAeeDin07bzy8JczWTjBf7MwqS7doEjJuIU rmy18Wkpycc/1fUDklHMuxJO5SyR2HWLU3UqJHUE/7MGIafr7kK2xAtpmKewVg/V5aXK qpSwQurd85L4QS5qoUhmKuGtEAcx186UAHTxVY7uJx90uPgdCKqYZDiqmlw58eJ+LbAk m8flGb3F+BpsGR9rRAEpnhhXDuZuia/qIB6RyO3ZewUcORX5Pv2dpwr+YRVO2YWFcGJD EndOauWu0+Nw3MhPmQ2CM/lOA42DFYUwhp0RlMdjR31DXvjUEa2fhapb7FI1pgnOLCvv CJHw== X-Gm-Message-State: AOAM531MJiG6sJY3G2JmkmhskNX2RwliB8zuprfr8co7ocK28I5O00n0 /RZWZEFQMPwTrtifgVc90N4A4q9KlCrnRqdxartpYhoEoMV1hA== X-Google-Smtp-Source: ABdhPJzoT9FtYch9kMGEY9v1plBgfc7FB5F1mvGOlDJNrBPf+Tz2ezvfBGHw76w4YjY6W/47VvLSxlrg955e X-Received: by 2002:a63:8c2:0:b0:380:bfd8:9e10 with SMTP id 185-20020a6308c2000000b00380bfd89e10mr12806275pgi.422.1649368048265; Thu, 07 Apr 2022 14:47:28 -0700 (PDT) Received: from postal.iol.unh.edu (postal.iol.unh.edu. [132.177.123.84]) by smtp-relay.gmail.com with ESMTPS id k1-20020a170902ce0100b00156bb39fd25sm420789plg.142.2022.04.07.14.47.28 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 Apr 2022 14:47:28 -0700 (PDT) X-Relaying-Domain: iol.unh.edu Received: from iol.unh.edu (unknown [IPv6:2606:4100:3880:1257::105d]) by postal.iol.unh.edu (Postfix) with ESMTP id 4EB3B605183B; Thu, 7 Apr 2022 17:47:27 -0400 (EDT) From: ohilyard@iol.unh.edu To: dev@dpdk.org Cc: Honnappa.Nagarahalli@arm.com, thomas@monjalon.net, Owen Hilyard Subject: [PATCH v1 3/4] app/test-pmd-api: Add protobuf file Date: Thu, 7 Apr 2022 17:47:07 -0400 Message-Id: <20220407214707.29730-4-ohilyard@iol.unh.edu> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220407214707.29730-1-ohilyard@iol.unh.edu> References: <20220407214707.29730-1-ohilyard@iol.unh.edu> MIME-Version: 1.0 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 From: Owen Hilyard This file contains the gRPC definitions for the api as it currently stands. Signed-off-by: Owen Hilyard --- app/test-pmd-api/api.proto | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 app/test-pmd-api/api.proto diff --git a/app/test-pmd-api/api.proto b/app/test-pmd-api/api.proto new file mode 100644 index 0000000000..ba52e379e9 --- /dev/null +++ b/app/test-pmd-api/api.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; +import "google/protobuf/empty.proto"; + +message AclSetupArgs { + repeated string args = 1; +} + +service TestpmdAPI { + rpc acl_setup (AclSetupArgs) returns (google.protobuf.Empty); + rpc acl_search (google.protobuf.Empty) returns (google.protobuf.Empty); + rpc acl_cleanup_config (google.protobuf.Empty) returns (google.protobuf.Empty); +} \ No newline at end of file From patchwork Thu Apr 7 21:47:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Owen Hilyard X-Patchwork-Id: 109439 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 99917A050C; Thu, 7 Apr 2022 23:47:35 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0CCEE410FB; Thu, 7 Apr 2022 23:47:30 +0200 (CEST) Received: from mail-io1-f99.google.com (mail-io1-f99.google.com [209.85.166.99]) by mails.dpdk.org (Postfix) with ESMTP id 9B4004068B for ; Thu, 7 Apr 2022 23:47:28 +0200 (CEST) Received: by mail-io1-f99.google.com with SMTP id h63so8449968iof.12 for ; Thu, 07 Apr 2022 14:47:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iol.unh.edu; s=unh-iol; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ohOZdEi3bvjh7FwaerKTqpsrLkao+rn30c16jL/WQ00=; b=P7kz3Atl24xRUhPba2Ci11K5lxrW6TBhcFahGIjgVSNXHJDNQm/xaSF3V9Zpf4yd/n s3fp+Lusw8immQnxq2cjF26emMgj3ahYTo5rKPt9n7pgVgnmxekexaQPOwdgF64BTEvY iO4lapT1WL5KpZ7wfOQWduZJwrzuKCH3xKFFw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ohOZdEi3bvjh7FwaerKTqpsrLkao+rn30c16jL/WQ00=; b=FeZRRC4ue0t/YWW24oSHzTKZbkN5BnVRzzTDxQX0XE2gVbm5YNiudbQ0X8RGZCgUu4 q4z8A7aQijswKsoGm5CFmyDKi1ynFiGmdI6kwdLyK+GBOkHWVmYJbYXVpya3dX1yyYrf 3dAD0iPG+JmfiPHsZHe8Yku4yNCVvwouv3AnP9wNJNJwhUTugm0Dk17IS9UXz80jx7Pi 3tCwNxQ82e5FOlv6cIWVRPE4jeNvch0zhmrMXrLDjR0Ed4ZcWv6nET/nfZ9t06euTi0H 92vs/73+6914ctvfmf55yYUh5DVEKPSpv0mfsgvalRCFfCSZ4FII6xT3+5XHZ7MODQCW uA9Q== X-Gm-Message-State: AOAM531j5BWEC9pM8uDngrl7IpXDDButnIfeM2PVu2SC8is2a5ggHVak /HXuxw6X1JomjbPSoDUbkdV5NlbpvDoBbI1WxR854PZ2bbLn5gR+Pry7JvsmupprhQ== X-Google-Smtp-Source: ABdhPJy3J0D+ejhre3d1/TXqxYW9YZNtBKx/VJuQ0oSOwpokv0BOYL7OGIb7ComQECxh33qoS67EmGf91Q6s X-Received: by 2002:a05:6638:d88:b0:322:e0cf:cf8e with SMTP id l8-20020a0566380d8800b00322e0cfcf8emr8153882jaj.171.1649368047953; Thu, 07 Apr 2022 14:47:27 -0700 (PDT) Received: from postal.iol.unh.edu (postal.iol.unh.edu. [2606:4100:3880:1234::84]) by smtp-relay.gmail.com with ESMTPS id i11-20020a02a0cb000000b003233fb0f448sm1396095jah.67.2022.04.07.14.47.27 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 Apr 2022 14:47:27 -0700 (PDT) X-Relaying-Domain: iol.unh.edu Received: from iol.unh.edu (unknown [IPv6:2606:4100:3880:1257::105d]) by postal.iol.unh.edu (Postfix) with ESMTP id 64440605183C; Thu, 7 Apr 2022 17:47:27 -0400 (EDT) From: ohilyard@iol.unh.edu To: dev@dpdk.org Cc: Honnappa.Nagarahalli@arm.com, thomas@monjalon.net, Owen Hilyard Subject: [PATCH v1 4/4] app/test-pmd-api: Implementation files for the API Date: Thu, 7 Apr 2022 17:47:08 -0400 Message-Id: <20220407214707.29730-5-ohilyard@iol.unh.edu> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220407214707.29730-1-ohilyard@iol.unh.edu> References: <20220407214707.29730-1-ohilyard@iol.unh.edu> MIME-Version: 1.0 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 From: Owen Hilyard As of right now, this is a fairly direct port. As such, most of the main file from test-acl is present in api_impl.cc. If this proof of concept is going to expand into a usable application, the acl test helper can be moved to another file to help keep the service definition file clean. The header file must remain a C header file in order to be able to be included in the main file. At this point, the main file is just a stub that starts the RPC server, but I have left it so that any extensions can be written in C and the C++ parts of this app can be easily encapsulated. Signed-off-by: Owen Hilyard --- app/test-pmd-api/api_impl.cc | 1160 ++++++++++++++++++++++++++++++++++ app/test-pmd-api/api_impl.h | 10 + app/test-pmd-api/main.c | 11 + 3 files changed, 1181 insertions(+) create mode 100644 app/test-pmd-api/api_impl.cc create mode 100644 app/test-pmd-api/api_impl.h create mode 100644 app/test-pmd-api/main.c diff --git a/app/test-pmd-api/api_impl.cc b/app/test-pmd-api/api_impl.cc new file mode 100644 index 0000000000..6972172598 --- /dev/null +++ b/app/test-pmd-api/api_impl.cc @@ -0,0 +1,1160 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * Copyright(c) 2022 University of New Hampshire + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "api.pb.h" +#include "api.grpc.pb.h" + +/* +C++ includes +*/ +#include +#include +#include +#include +#include + +#define PRINT_USAGE_START "%s [EAL options] --\n" + +#define RTE_LOGTYPE_TESTACL RTE_LOGTYPE_USER1 + +#define APP_NAME "TESTACL" + +#define GET_CB_FIELD(in, fd, base, lim, dlm) \ + do { \ + unsigned long val; \ + char *end_fld; \ + errno = 0; \ + val = strtoul((in), &end_fld, (base)); \ + if (errno != 0 || end_fld[0] != (dlm) || val > (lim)) \ + return -EINVAL; \ + (fd) = (typeof(fd))val; \ + (in) = end_fld + 1; \ + } while (0) + +#define OPT_RULE_FILE "rulesf" +#define OPT_TRACE_FILE "tracef" +#define OPT_RULE_NUM "rulenum" +#define OPT_TRACE_NUM "tracenum" +#define OPT_TRACE_STEP "tracestep" +#define OPT_SEARCH_ALG "alg" +#define OPT_BLD_CATEGORIES "bldcat" +#define OPT_RUN_CATEGORIES "runcat" +#define OPT_MAX_SIZE "maxsize" +#define OPT_ITER_NUM "iter" +#define OPT_VERBOSE "verbose" +#define OPT_IPV6 "ipv6" + +#define TRACE_DEFAULT_NUM 0x10000 +#define TRACE_STEP_MAX 0x1000 +#define TRACE_STEP_DEF 0x100 + +#define RULE_NUM 0x10000 + +#define COMMENT_LEAD_CHAR '#' + +enum { + DUMP_NONE, DUMP_SEARCH, DUMP_PKT, DUMP_MAX +}; + +struct acl_alg { + const char *name; + enum rte_acl_classify_alg alg; +}; + +static const struct acl_alg acl_alg[] = { + { + .name = "scalar", + .alg = RTE_ACL_CLASSIFY_SCALAR, + }, + { + .name = "sse", + .alg = RTE_ACL_CLASSIFY_SSE, + }, + { + .name = "avx2", + .alg = RTE_ACL_CLASSIFY_AVX2, + }, + { + .name = "neon", + .alg = RTE_ACL_CLASSIFY_NEON, + }, + { + .name = "altivec", + .alg = RTE_ACL_CLASSIFY_ALTIVEC, + }, + { + .name = "avx512x16", + .alg = RTE_ACL_CLASSIFY_AVX512X16, + }, + { + .name = "avx512x32", + .alg = RTE_ACL_CLASSIFY_AVX512X32, + }, +}; + +static struct { + const char *prgname; + const char *rule_file; + const char *trace_file; + size_t max_size; + uint32_t bld_categories; + uint32_t run_categories; + uint32_t nb_rules; + uint32_t nb_traces; + uint32_t trace_step; + uint32_t trace_sz; + uint32_t iter_num; + uint32_t verbose; + uint32_t ipv6; + struct acl_alg alg; + uint32_t used_traces; + void *traces; + struct rte_acl_ctx *acx; +} config = { + .prgname = NULL, + .rule_file = NULL, + .trace_file = NULL, + .max_size = 0, + .bld_categories = 3, + .run_categories = 1, + .nb_rules = RULE_NUM, + .nb_traces = TRACE_DEFAULT_NUM, + .trace_step = TRACE_STEP_DEF, + .trace_sz = 0, + .iter_num = 1, + .verbose = DUMP_MAX, + .ipv6 = 0, + .alg = { + .name = "default", + .alg = RTE_ACL_CLASSIFY_DEFAULT, + }, + .used_traces = 0, + .traces = NULL, + .acx = NULL, +}; + +static struct rte_acl_param prm = { + .name = APP_NAME, + .socket_id = SOCKET_ID_ANY, + .rule_size = 0, + .max_rule_num = 0, +}; + +/* + * Rule and trace formats definitions. + */ + +struct ipv4_5tuple { + uint8_t proto; + uint32_t ip_src; + uint32_t ip_dst; + uint16_t port_src; + uint16_t port_dst; +}; + +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 rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = { + { + .type = RTE_ACL_FIELD_TYPE_BITMASK, + .size = sizeof(uint8_t), + .field_index = PROTO_FIELD_IPV4, + .input_index = RTE_ACL_IPV4VLAN_PROTO, + .offset = offsetof(struct ipv4_5tuple, proto), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = SRC_FIELD_IPV4, + .input_index = RTE_ACL_IPV4VLAN_SRC, + .offset = offsetof(struct ipv4_5tuple, ip_src), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = DST_FIELD_IPV4, + .input_index = RTE_ACL_IPV4VLAN_DST, + .offset = offsetof(struct ipv4_5tuple, ip_dst), + }, + { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = SRCP_FIELD_IPV4, + .input_index = RTE_ACL_IPV4VLAN_PORTS, + .offset = offsetof(struct ipv4_5tuple, port_src), + }, + { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = DSTP_FIELD_IPV4, + .input_index = RTE_ACL_IPV4VLAN_PORTS, + .offset = offsetof(struct ipv4_5tuple, port_dst), + }, +}; + +#define IPV6_ADDR_LEN 16 +#define IPV6_ADDR_U16 (IPV6_ADDR_LEN / sizeof(uint16_t)) +#define IPV6_ADDR_U32 (IPV6_ADDR_LEN / sizeof(uint32_t)) + +struct ipv6_5tuple { + uint8_t proto; + uint32_t ip_src[IPV6_ADDR_U32]; + uint32_t ip_dst[IPV6_ADDR_U32]; + uint16_t port_src; + uint16_t port_dst; +}; + +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] = { + { + .type = RTE_ACL_FIELD_TYPE_BITMASK, + .size = sizeof(uint8_t), + .field_index = PROTO_FIELD_IPV6, + .input_index = PROTO_FIELD_IPV6, + .offset = offsetof(struct ipv6_5tuple, proto), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = SRC1_FIELD_IPV6, + .input_index = SRC1_FIELD_IPV6, + .offset = offsetof(struct ipv6_5tuple, ip_src[0]), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = SRC2_FIELD_IPV6, + .input_index = SRC2_FIELD_IPV6, + .offset = offsetof(struct ipv6_5tuple, ip_src[1]), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = SRC3_FIELD_IPV6, + .input_index = SRC3_FIELD_IPV6, + .offset = offsetof(struct ipv6_5tuple, ip_src[2]), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = SRC4_FIELD_IPV6, + .input_index = SRC4_FIELD_IPV6, + .offset = offsetof(struct ipv6_5tuple, ip_src[3]), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = DST1_FIELD_IPV6, + .input_index = DST1_FIELD_IPV6, + .offset = offsetof(struct ipv6_5tuple, ip_dst[0]), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = DST2_FIELD_IPV6, + .input_index = DST2_FIELD_IPV6, + .offset = offsetof(struct ipv6_5tuple, ip_dst[1]), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = DST3_FIELD_IPV6, + .input_index = DST3_FIELD_IPV6, + .offset = offsetof(struct ipv6_5tuple, ip_dst[2]), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = DST4_FIELD_IPV6, + .input_index = DST4_FIELD_IPV6, + .offset = offsetof(struct ipv6_5tuple, ip_dst[3]), + }, + { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = SRCP_FIELD_IPV6, + .input_index = SRCP_FIELD_IPV6, + .offset = offsetof(struct ipv6_5tuple, port_src), + }, + { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = DSTP_FIELD_IPV6, + .input_index = SRCP_FIELD_IPV6, + .offset = offsetof(struct ipv6_5tuple, port_dst), + }, +}; + +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_NUM, +}; + +enum { + CB_TRC_SRC_ADDR, + CB_TRC_DST_ADDR, + CB_TRC_SRC_PORT, + CB_TRC_DST_PORT, + CB_TRC_PROTO, + CB_TRC_NUM, +}; + +RTE_ACL_RULE_DEF(acl_rule, RTE_ACL_MAX_FIELDS); + +static const char cb_port_delim[] = ":"; + +static char line[LINE_MAX]; + +#define dump_verbose(lvl, fh, fmt, args...) \ + do { \ + if ((lvl) <= (int32_t)config.verbose) \ + fprintf(fh, fmt, ##args); \ + } while (0) + +/* + * Parse ClassBench input trace (test vectors and expected results) file. + * Expected format: + * \ + * + */ +static int parse_cb_ipv4_trace(char *str, struct ipv4_5tuple *v) { + int i; + char *s, *sp, *in[CB_TRC_NUM]; + static const char *dlm = " \t\n"; + + s = str; + for (i = 0; i != RTE_DIM(in); i++) { + in[i] = strtok_r(s, dlm, &sp); + if (in[i] == NULL) + return -EINVAL; + s = NULL; + } + + GET_CB_FIELD(in[CB_TRC_SRC_ADDR], v->ip_src, 0, UINT32_MAX, 0); + GET_CB_FIELD(in[CB_TRC_DST_ADDR], v->ip_dst, 0, UINT32_MAX, 0); + GET_CB_FIELD(in[CB_TRC_SRC_PORT], v->port_src, 0, UINT16_MAX, 0); + GET_CB_FIELD(in[CB_TRC_DST_PORT], v->port_dst, 0, UINT16_MAX, 0); + GET_CB_FIELD(in[CB_TRC_PROTO], v->proto, 0, UINT8_MAX, 0); + + /* convert to network byte order. */ + v->ip_src = rte_cpu_to_be_32(v->ip_src); + v->ip_dst = rte_cpu_to_be_32(v->ip_dst); + v->port_src = rte_cpu_to_be_16(v->port_src); + v->port_dst = rte_cpu_to_be_16(v->port_dst); + + return 0; +} + +/* + * Parse IPv6 address, expects the following format: + * XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X is a hexadecimal digit). + */ +static int parse_ipv6_addr(const char *in, const char **end, + uint32_t v[IPV6_ADDR_U32], char dlm) { + uint32_t addr[IPV6_ADDR_U16]; + + GET_CB_FIELD(in, addr[0], 16, UINT16_MAX, ':'); + GET_CB_FIELD(in, addr[1], 16, UINT16_MAX, ':'); + GET_CB_FIELD(in, addr[2], 16, UINT16_MAX, ':'); + GET_CB_FIELD(in, addr[3], 16, UINT16_MAX, ':'); + GET_CB_FIELD(in, addr[4], 16, UINT16_MAX, ':'); + GET_CB_FIELD(in, addr[5], 16, UINT16_MAX, ':'); + GET_CB_FIELD(in, addr[6], 16, UINT16_MAX, ':'); + GET_CB_FIELD(in, addr[7], 16, UINT16_MAX, dlm); + + *end = in; + + v[0] = (addr[0] << 16) + addr[1]; + v[1] = (addr[2] << 16) + addr[3]; + v[2] = (addr[4] << 16) + addr[5]; + v[3] = (addr[6] << 16) + addr[7]; + + return 0; +} + +static int parse_cb_ipv6_addr_trace(const char *in, uint32_t v[IPV6_ADDR_U32]) { + int32_t rc; + const char *end; + + rc = parse_ipv6_addr(in, &end, v, 0); + if (rc != 0) + return rc; + + v[0] = rte_cpu_to_be_32(v[0]); + v[1] = rte_cpu_to_be_32(v[1]); + v[2] = rte_cpu_to_be_32(v[2]); + v[3] = rte_cpu_to_be_32(v[3]); + + return 0; +} + +/* + * Parse ClassBench input trace (test vectors and expected results) file. + * Expected format: + * \ + * + */ +static int parse_cb_ipv6_trace(char *str, struct ipv6_5tuple *v) { + int32_t i, rc; + char *s, *sp, *in[CB_TRC_NUM]; + static const char *dlm = " \t\n"; + + s = str; + for (i = 0; i != RTE_DIM(in); i++) { + in[i] = strtok_r(s, dlm, &sp); + if (in[i] == NULL) + return -EINVAL; + s = NULL; + } + + /* get ip6 src address. */ + rc = parse_cb_ipv6_addr_trace(in[CB_TRC_SRC_ADDR], v->ip_src); + if (rc != 0) + return rc; + + /* get ip6 dst address. */ + rc = parse_cb_ipv6_addr_trace(in[CB_TRC_DST_ADDR], v->ip_dst); + if (rc != 0) + return rc; + + GET_CB_FIELD(in[CB_TRC_SRC_PORT], v->port_src, 0, UINT16_MAX, 0); + GET_CB_FIELD(in[CB_TRC_DST_PORT], v->port_dst, 0, UINT16_MAX, 0); + GET_CB_FIELD(in[CB_TRC_PROTO], v->proto, 0, UINT8_MAX, 0); + + /* convert to network byte order. */ + v->port_src = rte_cpu_to_be_16(v->port_src); + v->port_dst = rte_cpu_to_be_16(v->port_dst); + + return 0; +} + +/* Bypass comment and empty lines */ +static int skip_line(const char *buf) { + uint32_t i; + + for (i = 0; isspace(buf[i]) != 0; i++); + + if (buf[i] == 0 || buf[i] == COMMENT_LEAD_CHAR) + return 1; + + return 0; +} + +static void tracef_init(void) { + static const char name[] = APP_NAME; + FILE *f; + size_t sz; + uint32_t i, k, n; + struct ipv4_5tuple *v; + struct ipv6_5tuple *w; + + sz = config.nb_traces * (config.ipv6 ? sizeof(*w) : sizeof(*v)); + config.traces = rte_zmalloc_socket(name, sz, RTE_CACHE_LINE_SIZE, + SOCKET_ID_ANY); + if (config.traces == NULL) + rte_exit(EXIT_FAILURE, + "Cannot allocate %zu bytes for " + "requested %u number of trace records\n", + sz, config.nb_traces); + + f = fopen(config.trace_file, "r"); + if (f == NULL) + rte_exit(-EINVAL, "failed to open file: %s\n", + config.trace_file); + + v = (struct ipv4_5tuple *) config.traces; + w = (struct ipv6_5tuple *) config.traces; + k = 0; + n = 0; + for (i = 0; n != config.nb_traces; i++) { + if (fgets(line, sizeof(line), f) == NULL) + break; + + if (skip_line(line) != 0) { + k++; + continue; + } + + n = i - k; + + if (config.ipv6) { + if (parse_cb_ipv6_trace(line, w + n) != 0) + rte_exit(EXIT_FAILURE, + "%s: failed to parse ipv6 trace " + "record at line %u\n", + config.trace_file, i + 1); + } else { + if (parse_cb_ipv4_trace(line, v + n) != 0) + rte_exit(EXIT_FAILURE, + "%s: failed to parse ipv4 trace " + "record at line %u\n", + config.trace_file, i + 1); + } + } + + config.used_traces = i - k; + fclose(f); +} + +static int parse_ipv6_net(const char *in, struct rte_acl_field field[4]) { + int32_t rc; + const char *mp; + uint32_t i, m, v[4]; + const uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT; + + /* get address. */ + rc = parse_ipv6_addr(in, &mp, v, '/'); + if (rc != 0) + return rc; + + /* get mask. */ + GET_CB_FIELD(mp, m, 0, CHAR_BIT * sizeof(v), 0); + + /* put all together. */ + for (i = 0; i != RTE_DIM(v); i++) { + if (m >= (i + 1) * nbu32) + field[i].mask_range.u32 = nbu32; + else + field[i].mask_range.u32 = + m > (i * nbu32) ? m - (i * 32) : 0; + + field[i].value.u32 = v[i]; + } + + return 0; +} + +static int parse_cb_ipv6_rule(char *str, struct acl_rule *v) { + int i, rc; + char *s, *sp, *in[CB_FLD_NUM]; + static const char *dlm = " \t\n"; + + /* + * Skip leading '@' + */ + if (strchr(str, '@') != str) + return -EINVAL; + + s = str + 1; + + for (i = 0; i != RTE_DIM(in); i++) { + in[i] = strtok_r(s, dlm, &sp); + if (in[i] == NULL) + return -EINVAL; + s = NULL; + } + + rc = parse_ipv6_net(in[CB_FLD_SRC_ADDR], v->field + SRC1_FIELD_IPV6); + if (rc != 0) { + RTE_LOG(ERR, TESTACL, + "failed to read source address/mask: %s\n", + in[CB_FLD_SRC_ADDR]); + return rc; + } + + rc = parse_ipv6_net(in[CB_FLD_DST_ADDR], v->field + DST1_FIELD_IPV6); + if (rc != 0) { + RTE_LOG(ERR, TESTACL, + "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)) != 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)) != 0) + 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); + + return 0; +} + +static int parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len) { + uint8_t a, b, c, d, m; + + GET_CB_FIELD(in, a, 0, UINT8_MAX, '.'); + GET_CB_FIELD(in, b, 0, UINT8_MAX, '.'); + GET_CB_FIELD(in, c, 0, UINT8_MAX, '.'); + GET_CB_FIELD(in, d, 0, UINT8_MAX, '/'); + GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0); + + addr[0] = RTE_IPV4(a, b, c, d); + mask_len[0] = m; + + return 0; +} + +/* + * Parse ClassBench rules file. + * Expected format: + * '@''/' \ + * '/' \ + * ":" \ + * ":" \ + * '/' + */ +static int parse_cb_ipv4_rule(char *str, struct acl_rule *v) { + int i, rc; + char *s, *sp, *in[CB_FLD_NUM]; + static const char *dlm = " \t\n"; + + /* + * Skip leading '@' + */ + if (strchr(str, '@') != str) + return -EINVAL; + + s = str + 1; + + for (i = 0; i != RTE_DIM(in); i++) { + in[i] = strtok_r(s, dlm, &sp); + if (in[i] == NULL) + return -EINVAL; + s = NULL; + } + + rc = 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 != 0) { + RTE_LOG(ERR, TESTACL, + "failed to read source address/mask: %s\n", + in[CB_FLD_SRC_ADDR]); + return rc; + } + + rc = 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 != 0) { + RTE_LOG(ERR, TESTACL, + "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_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)) != 0) + return -EINVAL; + + /* destination port. */ + 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)) != 0) + 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); + + return 0; +} + +typedef int (*parse_5tuple)(char *text, struct acl_rule *rule); + +static int add_cb_rules(FILE *f, struct rte_acl_ctx *ctx) { + int rc; + uint32_t i, k, n; + struct acl_rule v; + parse_5tuple parser; + + memset(&v, 0, sizeof(v)); + parser = (config.ipv6 != 0) ? parse_cb_ipv6_rule : parse_cb_ipv4_rule; + + k = 0; + for (i = 1; fgets(line, sizeof(line), f) != NULL; i++) { + if (skip_line(line) != 0) { + k++; + continue; + } + + n = i - k; + rc = parser(line, &v); + if (rc != 0) { + RTE_LOG(ERR, TESTACL, + "line %u: parse_cb_ipv4vlan_rule" + " failed, error code: %d (%s)\n", + i, rc, strerror(-rc)); + return rc; + } + + v.data.category_mask = RTE_LEN2MASK( + RTE_ACL_MAX_CATEGORIES, typeof(v.data.category_mask)); + v.data.priority = RTE_ACL_MAX_PRIORITY - n; + v.data.userdata = n; + + rc = rte_acl_add_rules(ctx, (struct rte_acl_rule *) &v, 1); + if (rc != 0) { + RTE_LOG(ERR, TESTACL, + "line %u: failed to add rules " + "into ACL context, error code: %d (%s)\n", + i, rc, strerror(-rc)); + return rc; + } + } + + return 0; +} + +static void acx_init(void) { + int ret; + FILE *f; + struct rte_acl_config cfg; + + memset(&cfg, 0, sizeof(cfg)); + + /* setup ACL build config. */ + if (config.ipv6) { + cfg.num_fields = RTE_DIM(ipv6_defs); + memcpy(&cfg.defs, ipv6_defs, sizeof(ipv6_defs)); + } else { + cfg.num_fields = RTE_DIM(ipv4_defs); + memcpy(&cfg.defs, ipv4_defs, sizeof(ipv4_defs)); + } + cfg.num_categories = config.bld_categories; + cfg.max_size = config.max_size; + + /* setup ACL creation parameters. */ + prm.rule_size = RTE_ACL_RULE_SZ(cfg.num_fields); + prm.max_rule_num = config.nb_rules; + + config.acx = rte_acl_create(&prm); + if (config.acx == NULL) + rte_exit(rte_errno, "failed to create ACL context\n"); + + /* set default classify method for this context. */ + if (config.alg.alg != RTE_ACL_CLASSIFY_DEFAULT) { + ret = rte_acl_set_ctx_classify(config.acx, config.alg.alg); + if (ret != 0) + rte_exit(ret, + "failed to setup %s method " + "for ACL context\n", + config.alg.name); + } + + /* add ACL rules. */ + f = fopen(config.rule_file, "r"); + if (f == NULL) + rte_exit(-EINVAL, "failed to open file %s\n", config.rule_file); + + ret = add_cb_rules(f, config.acx); + if (ret != 0) + rte_exit(ret, "failed to add rules into ACL context\n"); + + fclose(f); + + /* perform build. */ + ret = rte_acl_build(config.acx, &cfg); + + dump_verbose(DUMP_NONE, stdout, "rte_acl_build(%u) finished with %d\n", + config.bld_categories, ret); + + rte_acl_dump(config.acx); + + if (ret != 0) + rte_exit(ret, "failed to build search context\n"); +} + +static uint32_t search_ip5tuples_once(uint32_t categories, uint32_t step, + const char *alg) { + int ret; + uint32_t i, j, k, n, r; + const uint8_t *data[step], *v; + uint32_t results[step * categories]; + + v = (const uint8_t *) config.traces; + for (i = 0; i != config.used_traces; i += n) { + n = RTE_MIN(step, config.used_traces - i); + + for (j = 0; j != n; j++) { + data[j] = v; + v += config.trace_sz; + } + + ret = rte_acl_classify(config.acx, data, results, n, + categories); + + if (ret != 0) + rte_exit(ret, "classify for ipv%c_5tuples returns %d\n", + config.ipv6 ? '6' : '4', ret); + + for (r = 0, j = 0; j != n; j++) { + for (k = 0; k != categories; k++, r++) { + dump_verbose(DUMP_PKT, stdout, + "ipv%c_5tuple: %u, category: %u, " + "result: %u\n", + config.ipv6 ? '6' : '4', i + j + 1, + k, results[r] - 1); + } + } + } + + dump_verbose(DUMP_SEARCH, stdout, "%s(%u, %u, %s) returns %u\n", + __func__, categories, step, alg, i); + return i; +} + +static int search_ip5tuples(__rte_unused void *arg) { + uint64_t pkt, start, tm; + uint32_t i, lcore; + long double st; + + lcore = rte_lcore_id(); + start = rte_rdtsc_precise(); + pkt = 0; + + for (i = 0; i != config.iter_num; i++) { + pkt += search_ip5tuples_once(config.run_categories, + config.trace_step, + config.alg.name); + } + + tm = rte_rdtsc_precise() - start; + + st = (long double) tm / rte_get_timer_hz(); + dump_verbose(DUMP_NONE, stdout, + "%s @lcore %u: %" PRIu32 " iterations, %" PRIu64 + " pkts, %" PRIu32 " categories, %" PRIu64 + " cycles (%.2Lf sec), " + "%.2Lf cycles/pkt, %.2Lf pkt/sec\n", + __func__, lcore, i, pkt, config.run_categories, tm, st, + (pkt == 0) ? 0 : (long double) tm / pkt, pkt / st); + + return 0; +} + +static unsigned long get_ulong_opt(const char *opt, const char *name, + size_t min, size_t max) { + unsigned long val; + char *end; + + errno = 0; + val = strtoul(opt, &end, 0); + if (errno != 0 || end[0] != 0 || val > max || val < min) + rte_exit(-EINVAL, "invalid value: \"%s\" for option: %s\n", opt, + name); + return val; +} + +static void get_alg_opt(const char *opt, const char *name) { + uint32_t i; + + for (i = 0; i != RTE_DIM(acl_alg); i++) { + if (strcmp(opt, acl_alg[i].name) == 0) { + config.alg = acl_alg[i]; + return; + } + } + + rte_exit(-EINVAL, "invalid value: \"%s\" for option: %s\n", opt, name); +} + +static void print_usage(const char *prgname) { + uint32_t i, n, rc; + char buf[PATH_MAX]; + + n = 0; + buf[0] = 0; + + for (i = 0; i < RTE_DIM(acl_alg) - 1; i++) { + rc = snprintf(buf + n, sizeof(buf) - n, "%s|", acl_alg[i].name); + if (rc > sizeof(buf) - n) + break; + n += rc; + } + + strlcpy(buf + n, acl_alg[i].name, sizeof(buf) - n); + + fprintf(stdout, + PRINT_USAGE_START + "--" OPT_RULE_FILE "=\n" + "[--" OPT_TRACE_FILE "=]\n" + "[--" OPT_RULE_NUM + "=]\n" + "[--" OPT_TRACE_NUM + "=]\n" + "[--" OPT_TRACE_STEP + "=]\n" + "[--" OPT_BLD_CATEGORIES + "=]\n" + "[--" OPT_RUN_CATEGORIES "= " + "should be either 1 or multiple of %zu, " + "but not greater then %u]\n" + "[--" OPT_MAX_SIZE + "= " + "leave 0 for default behaviour]\n" + "[--" OPT_ITER_NUM "=]\n" + "[--" OPT_VERBOSE "=]\n" + "[--" OPT_SEARCH_ALG "=%s]\n" + "[--" OPT_IPV6 "=]\n", + prgname, RTE_ACL_RESULTS_MULTIPLIER, + (uint32_t) RTE_ACL_MAX_CATEGORIES, buf); +} + +static void dump_config(FILE *f) { + fprintf(f, "%s:\n", __func__); + fprintf(f, "%s:%s\n", OPT_RULE_FILE, config.rule_file); + fprintf(f, "%s:%s\n", OPT_TRACE_FILE, config.trace_file); + fprintf(f, "%s:%u\n", OPT_RULE_NUM, config.nb_rules); + fprintf(f, "%s:%u\n", OPT_TRACE_NUM, config.nb_traces); + fprintf(f, "%s:%u\n", OPT_TRACE_STEP, config.trace_step); + fprintf(f, "%s:%u\n", OPT_BLD_CATEGORIES, config.bld_categories); + fprintf(f, "%s:%u\n", OPT_RUN_CATEGORIES, config.run_categories); + fprintf(f, "%s:%zu\n", OPT_MAX_SIZE, config.max_size); + fprintf(f, "%s:%u\n", OPT_ITER_NUM, config.iter_num); + fprintf(f, "%s:%u\n", OPT_VERBOSE, config.verbose); + fprintf(f, "%s:%u(%s)\n", OPT_SEARCH_ALG, config.alg.alg, + config.alg.name); + fprintf(f, "%s:%u\n", OPT_IPV6, config.ipv6); +} + +static void check_config(void) { + if (config.rule_file == NULL) { + print_usage(config.prgname); + rte_exit(-EINVAL, "mandatory option %s is not specified\n", + OPT_RULE_FILE); + } +} + +static void get_input_opts(int argc, char **argv) { + static struct option lgopts[] = {{OPT_RULE_FILE, 1, 0, 0}, + {OPT_TRACE_FILE, 1, 0, 0}, + {OPT_TRACE_NUM, 1, 0, 0}, + {OPT_RULE_NUM, 1, 0, 0}, + {OPT_MAX_SIZE, 1, 0, 0}, + {OPT_TRACE_STEP, 1, 0, 0}, + {OPT_BLD_CATEGORIES, 1, 0, 0}, + {OPT_RUN_CATEGORIES, 1, 0, 0}, + {OPT_ITER_NUM, 1, 0, 0}, + {OPT_VERBOSE, 1, 0, 0}, + {OPT_SEARCH_ALG, 1, 0, 0}, + {OPT_IPV6, 0, 0, 0}, + {NULL, 0, 0, 0}}; + + int opt, opt_idx; + + while ((opt = getopt_long(argc, argv, "", lgopts, &opt_idx)) != EOF) { + if (opt != 0) { + print_usage(config.prgname); + rte_exit(-EINVAL, "unknown option: %c", opt); + } + + if (strcmp(lgopts[opt_idx].name, OPT_RULE_FILE) == 0) { + config.rule_file = optarg; + } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_FILE) == 0) { + config.trace_file = optarg; + } else if (strcmp(lgopts[opt_idx].name, OPT_RULE_NUM) == 0) { + config.nb_rules = + get_ulong_opt(optarg, lgopts[opt_idx].name, 1, + RTE_ACL_MAX_INDEX + 1); + } else if (strcmp(lgopts[opt_idx].name, OPT_MAX_SIZE) == 0) { + config.max_size = get_ulong_opt( + optarg, lgopts[opt_idx].name, 0, SIZE_MAX); + } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_NUM) == 0) { + config.nb_traces = get_ulong_opt( + optarg, lgopts[opt_idx].name, 1, UINT32_MAX); + } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_STEP) == 0) { + config.trace_step = + get_ulong_opt(optarg, lgopts[opt_idx].name, 1, + TRACE_STEP_MAX); + } else if (strcmp(lgopts[opt_idx].name, OPT_BLD_CATEGORIES) == + 0) { + config.bld_categories = + get_ulong_opt(optarg, lgopts[opt_idx].name, 1, + RTE_ACL_MAX_CATEGORIES); + } else if (strcmp(lgopts[opt_idx].name, OPT_RUN_CATEGORIES) == + 0) { + config.run_categories = + get_ulong_opt(optarg, lgopts[opt_idx].name, 1, + RTE_ACL_MAX_CATEGORIES); + } else if (strcmp(lgopts[opt_idx].name, OPT_ITER_NUM) == 0) { + config.iter_num = get_ulong_opt( + optarg, lgopts[opt_idx].name, 1, INT32_MAX); + } else if (strcmp(lgopts[opt_idx].name, OPT_VERBOSE) == 0) { + config.verbose = + get_ulong_opt(optarg, lgopts[opt_idx].name, + DUMP_NONE, DUMP_MAX); + } else if (strcmp(lgopts[opt_idx].name, OPT_SEARCH_ALG) == 0) { + get_alg_opt(optarg, lgopts[opt_idx].name); + } else if (strcmp(lgopts[opt_idx].name, OPT_IPV6) == 0) { + config.ipv6 = 1; + } + } + config.trace_sz = config.ipv6 ? sizeof(struct ipv6_5tuple) : + sizeof(struct ipv4_5tuple); +} + +class TestpmdAPIImpl final : public ::TestpmdAPI::Service { +public: + virtual ::grpc::Status acl_setup([[maybe_unused]] ::grpc::ServerContext *context, + const ::AclSetupArgs *request, + ::google::protobuf::Empty *response) { + + auto *args = new std::vector(); + + for (auto& arg : request->args()) { + args->push_back((char*) arg.c_str()); + } + + // terminator + args->push_back(nullptr); + + + int ret = rte_eal_init(args->size() - 1, args->data()); + if (ret < 0) + rte_panic("Cannot init EAL\n"); + + config.prgname = args->at(0); + + get_input_opts(args->size() - ret - 1, &(*args)[ret]); + dump_config(stdout); + check_config(); + + acx_init(); + + if (config.trace_file != nullptr) + tracef_init(); + + *response = google::protobuf::Empty(); + + return grpc::Status::OK; + } + + virtual ::grpc::Status + acl_search([[maybe_unused]] ::grpc::ServerContext *context, + [[maybe_unused]] const ::google::protobuf::Empty *request, + ::google::protobuf::Empty *response) { + uint32_t lcore; + + RTE_LCORE_FOREACH_WORKER(lcore)rte_eal_remote_launch(search_ip5tuples, NULL, lcore); + + search_ip5tuples(NULL); + + rte_eal_mp_wait_lcore(); + + *response = google::protobuf::Empty(); + + return grpc::Status::OK; + } + + virtual ::grpc::Status acl_cleanup_config([[maybe_unused]] ::grpc::ServerContext *context, [[maybe_unused]] const ::google::protobuf::Empty *request, + ::google::protobuf::Empty *response) { + rte_acl_free(config.acx); + + *response = google::protobuf::Empty(); + return grpc::Status::OK; + } +}; + +extern "C" { +void rte_testpmd_run() { +#ifdef RTE_RPC_SERVER_PORT + std::string address = "0.0.0.0:" RTE_RPC_SERVER_PORT; +#else + std::string address = "0.0.0.0:8000"; +#endif + + grpc::EnableDefaultHealthCheckService(true); + grpc::reflection::InitProtoReflectionServerBuilderPlugin(); + TestpmdAPIImpl* service = new TestpmdAPIImpl(); + + grpc::ServerBuilder builder; // RAII + builder.AddListeningPort(address, grpc::InsecureServerCredentials()); + builder.RegisterService(service); + RTE_LOG(INFO, PMD, "Starting server on %s", address.c_str()); + std::unique_ptr server(builder.BuildAndStart()); // RAII + server->Wait(); +} +} diff --git a/app/test-pmd-api/api_impl.h b/app/test-pmd-api/api_impl.h new file mode 100644 index 0000000000..5e81aa9804 --- /dev/null +++ b/app/test-pmd-api/api_impl.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 University of New Hampshire + */ + +/* +Dispite this file being attached to a C++ file, all definitions must remain ISO C. In additon, +any exported members from C++ must be in an "extern C" block. +*/ + +void rte_testpmd_run(); \ No newline at end of file diff --git a/app/test-pmd-api/main.c b/app/test-pmd-api/main.c new file mode 100644 index 0000000000..b69d2df814 --- /dev/null +++ b/app/test-pmd-api/main.c @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 University of New Hampshire + */ +#include "api_impl.h" + +int +main() +{ + rte_testpmd_run(); + return 0; +}