From patchwork Fri Oct 23 23:29:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Owen Hilyard X-Patchwork-Id: 82030 Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6F4D5A04DD; Sat, 24 Oct 2020 01:29:27 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 66450B62; Sat, 24 Oct 2020 01:29:26 +0200 (CEST) Received: from mail-qt1-f195.google.com (mail-qt1-f195.google.com [209.85.160.195]) by dpdk.org (Postfix) with ESMTP id 883F868F0 for ; Sat, 24 Oct 2020 01:29:23 +0200 (CEST) Received: by mail-qt1-f195.google.com with SMTP id e6so2558806qtw.10 for ; Fri, 23 Oct 2020 16:29:23 -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=1G6hnSpAiM/QgYg6ofwB6ybDltOajTeATsrIzBkou3M=; b=hxmTTfbSP9HhhHJ9oNS2yu99FPsuL4Ayg9o2WwdRq+UhbHfqrCTz5jJFSd8uxo6qmo hb+C0njwRlI+X5HpU1ULiHoKJbgzjHVQdLi5g2yyx+lSrL7dwFOzz2lF1CJ/N0uXdZEQ 8Pp8FGqw2RN7F5kssY+f1RRtUmbFnQftzIrj0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1G6hnSpAiM/QgYg6ofwB6ybDltOajTeATsrIzBkou3M=; b=akOfQzQY/zeaG0ua9DuwmyjM8ROAEPY7QreVllpzGk+s/IqHcQ/lxxM8GRIhpWlXul yRpACO0Y20USNaW9OUNn//5ZC08NFrWQLAW7KaCIjcw3Po8uGTCbS4exVF9vW2EH8jfs 8BLOnNsrXKIqGZRljq6QI0WyCcuLeS2vhblpoyGrSq9z3+yfBXsRZ4JFSGAZlH7mezxb TAqucumi3XHoULIhtAoFqKJmEjC7fy1dEYIXbGMebkgHOPxJIm714kV9OOUwgljhhBlo zLHoYgJCIgSW0AYF0iAo41shVHsLq9eqPbD0bxev+8kynOMTZay7kn6V1Z3Bbrg8LATX JPRA== X-Gm-Message-State: AOAM530qflVd8BaJbbLo1Ed0OQlPtj6o6htX0hA0bNbAW2ZoFf7dmaTr MldNElrZr+A/Xt5lQ3lt1ejazhzgE1nWEw== X-Google-Smtp-Source: ABdhPJxiYYHmEiha0/rGWF5YA2m47+gAeJYac5zyGlcifdTc2IHBSZhyZfX4dYBWhh5e9wqYemfyqg== X-Received: by 2002:ac8:6b95:: with SMTP id z21mr4288880qts.359.1603495761549; Fri, 23 Oct 2020 16:29:21 -0700 (PDT) Received: from ohilyard-Alienware-m17.iol.unh.edu (nt-238-66.w4.unh.edu. [132.177.238.66]) by smtp.googlemail.com with ESMTPSA id j16sm1851673qkg.26.2020.10.23.16.29.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Oct 2020 16:29:21 -0700 (PDT) From: Owen Hilyard To: ohilyard@iol.unh.edu, dts@dpdk.org, lijuan.tu@intel.com Cc: shall@iol.unh.edu, lihongx.ma@intel.com, lylavoie@iol.unh.edu, zhaoyan.chen@intel.com, yuan.peng@intel.com Date: Fri, 23 Oct 2020 19:29:00 -0400 Message-Id: <20201023232903.37387-5-ohilyard@iol.unh.edu> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201023232903.37387-4-ohilyard@iol.unh.edu> References: <20201023232903.37387-1-ohilyard@iol.unh.edu> <20201023232903.37387-2-ohilyard@iol.unh.edu> <20201023232903.37387-3-ohilyard@iol.unh.edu> <20201023232903.37387-4-ohilyard@iol.unh.edu> MIME-Version: 1.0 Subject: [dts] [PATCH v2 5/7] rte flow: add action items X-BeenThere: dts@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: test suite reviews and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dts-bounces@dpdk.org Sender: "dts" This file contains the action flow item definitions and supporting information. Signed-off-by: Owen Hilyard --- framework/flow/flow_action_items.py | 1050 +++++++++++++++++++++++++++ 1 file changed, 1050 insertions(+) create mode 100644 framework/flow/flow_action_items.py diff --git a/framework/flow/flow_action_items.py b/framework/flow/flow_action_items.py new file mode 100644 index 0000000..b08272f --- /dev/null +++ b/framework/flow/flow_action_items.py @@ -0,0 +1,1050 @@ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# Copyright © 2018[, 2019] The University of New Hampshire. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from typing import FrozenSet, Dict, Tuple + +from flow.enums import FlowActionType +from flow.flow_pattern_items import FlowItem + +ALWAYS_ALLOWED_ACTIONS = {FlowActionType.VOID} + +ENTRY_POINTS = { + FlowActionType.VOID, + FlowActionType.PASSTHRU, + FlowActionType.FLAG, + FlowActionType.DROP, + FlowActionType.COUNT, + FlowActionType.MAC_SWAP, + FlowActionType.DEC_TTL, + FlowActionType.JUMP, + FlowActionType.MARK, + FlowActionType.QUEUE, + FlowActionType.RSS, + FlowActionType.PF, + FlowActionType.VF, + FlowActionType.PHY_PORT, + FlowActionType.PORT_ID, + FlowActionType.SECURITY, + FlowActionType.OF_SET_MPLS_TTL, + FlowActionType.OF_DEC_MPLS_TTL, + FlowActionType.OF_SET_NW_TTL, + FlowActionType.OF_DEC_NW_TTL, + FlowActionType.OF_COPY_TTL_OUT, + FlowActionType.OF_COPY_TTL_IN, + FlowActionType.OF_POP_VLAN, + FlowActionType.OF_PUSH_VLAN, + FlowActionType.OF_SET_VLAN_VID, + FlowActionType.OF_SET_VLAN_PCP, + FlowActionType.OF_POP_MPLS, + FlowActionType.OF_PUSH_MPLS, + FlowActionType.VXLAN_ENCAP, + FlowActionType.VXLAN_DECAP, + FlowActionType.NVGRE_ENCAP, + FlowActionType.NVGRE_DECAP, + FlowActionType.RAW_ENCAP, + FlowActionType.RAW_DECAP, + FlowActionType.SET_IPV4_SRC, + FlowActionType.SET_IPV4_DST, + FlowActionType.SET_IPV6_SRC, + FlowActionType.SET_IPV6_DST, + FlowActionType.SET_TP_SRC, + FlowActionType.SET_TP_DST, + FlowActionType.SET_TTL, + FlowActionType.SET_MAC_SRC, + FlowActionType.SET_MAC_DST, + FlowActionType.INC_TCP_SEQ, + FlowActionType.DEC_TCP_SEQ, + FlowActionType.INC_TCP_ACK, + FlowActionType.DEC_TCP_ACK, + FlowActionType.SET_TAG, + FlowActionType.SET_META, + FlowActionType.SET_IPV4_DSCP, + FlowActionType.SET_IPV6_DSCP, + FlowActionType.AGE, +} + + +class ActionFlowItem(FlowItem): + allowed_with: FrozenSet[FlowActionType] = \ + frozenset({item for item in FlowActionType}) + + valid_next_items: FrozenSet[FlowActionType] = \ + frozenset({item for item in FlowActionType}) + + test_case: Dict[str, Tuple[str, frozenset, frozenset]] = dict() + +class FlowActionVoid(ActionFlowItem): + type = FlowActionType.VOID + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions void / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionPassthru(ActionFlowItem): + type = FlowActionType.PASSTHRU + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions passthru / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionFlag(ActionFlowItem): + type = FlowActionType.FLAG + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions flag / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionDrop(ActionFlowItem): + type = FlowActionType.DROP + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions drop / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionCount(ActionFlowItem): + type = FlowActionType.COUNT + test_case = { + 'test_shared': ('ingress pattern eth / ipv4 src is 192.168.0.1' + ' / udp / end actions count shared 0 id 1 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + 'test_id': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions count id 1 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionMac_swap(ActionFlowItem): + type = FlowActionType.MAC_SWAP + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions mac_swap / end', + frozenset({"Ether(src=\"90:61:ae:fd:41:43\", dst = \"ab:cd:ef:12:34:56\") " + "/ IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether(src=\"90:61:ae:fd:41:43\", dst = \"ab:cd:ef:12:34:56\") " + "/ IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether(src=\"90:61:ae:fd:41:43\", dst = \"ab:cd:ef:12:34:56\") " + "/ IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether(src=\"90:61:ae:fd:41:43\", dst = \"ab:cd:ef:12:34:56\") " + "/ IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether(src=\"90:61:ae:fd:41:43\", dst = \"ab:cd:ef:12:34:56\") " + "/ IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionDec_ttl(ActionFlowItem): + type = FlowActionType.DEC_TTL + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions dec_ttl / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\", ttl = 128) / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\", ttl = 128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\", ttl = 128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\", ttl = 128 ) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\", ttl = 128) / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionJump(ActionFlowItem): + type = FlowActionType.JUMP + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions jump group 1 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionMark(ActionFlowItem): + type = FlowActionType.MARK + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions mark id 0xABCDEF / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionQueue(ActionFlowItem): + type = FlowActionType.QUEUE + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions queue index 1 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionRss(ActionFlowItem): + type = FlowActionType.RSS + + # RSS already has a test suite. + ''' + test_case = { + 'case1': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + ''' + + +class FlowActionPf(ActionFlowItem): + type = FlowActionType.PF + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions pf / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionVf(ActionFlowItem): + type = FlowActionType.VF + test_case = { + 'test_original': ('ingress pattern eth / ipv4 src is 192.168.0.1 /' + ' udp / end actions vf original 1/ end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + 'test_id': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions vf id 1 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionPhy_port(ActionFlowItem): + type = FlowActionType.PHY_PORT + + test_case = { + # original port index + 'test_original': ('ingress pattern eth / ipv4 src is 192.168.0.1' + ' / udp / end actions phy_port original / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + # physical port index + 'test_index': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions phy_port index 1 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionPort_id(ActionFlowItem): + type = FlowActionType.PORT_ID + + test_case = { + # original DPDK port ID + 'test_original': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions port_id original / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + # DPDK port ID + 'test_id': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions port_id id 1 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionMeter(ActionFlowItem): + type = FlowActionType.METER + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions meter mtr_id 1 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionSecurity(ActionFlowItem): + type = FlowActionType.SECURITY + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1' + ' / udp / end actions security security_session 1 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionOf_set_mpls_ttl(ActionFlowItem): + type = FlowActionType.OF_SET_MPLS_TTL + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions of_set_mpls_ttl mpls_ttl 64 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / MPLS(label = 0xab, ttl=128)" + " / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / MPLS(label = 0xab, ttl=128)" + " / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionOf_dec_mpls_ttl(ActionFlowItem): + type = FlowActionType.OF_DEC_MPLS_TTL + + test_case = { + 'test': ( + 'ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions of_dec_mpls_ttl / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionOf_set_nw_ttl(ActionFlowItem): + type = FlowActionType.OF_SET_NW_TTL + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions of_set_nw_ttl nw_ttl 64 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\", ttl=128) / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\", ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\", ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\", ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\", ttl=128) / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionOf_dec_nw_ttl(ActionFlowItem): + type = FlowActionType.OF_DEC_NW_TTL + test_case = { + 'test': ( + 'ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions of_dec_nw_ttl / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\", ttl=128) / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\", ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\", ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\", ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\", ttl=128) / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionOf_copy_ttl_out(ActionFlowItem): + type = FlowActionType.OF_COPY_TTL_OUT + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions of_copy_ttl_out / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionOf_copy_ttl_in(ActionFlowItem): + type = FlowActionType.OF_COPY_TTL_IN + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions of_copy_ttl_out / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionOf_pop_vlan(ActionFlowItem): + type = FlowActionType.OF_POP_VLAN + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions of_pop_vlan / end', + frozenset({"Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"192.168.0.1\") " + "/ UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"192.168.0.2\") " + "/ UDP() / ('\\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"10.0.30.99\") " + "/ UDP() / ('\\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"8.8.8.8\") " + "/ UDP() / ('\\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"132.177.0.99\")" + " / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionOf_push_vlan(ActionFlowItem): + type = FlowActionType.OF_PUSH_VLAN + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1' + ' / udp / end actions of_push_vlan ethertype 0x8100 / end', + frozenset({"Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"192.168.0.1\") " + "/ UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"192.168.0.2\") " + "/ UDP() / ('\\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"10.0.30.99\") " + "/ UDP() / ('\\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"8.8.8.8\") " + "/ UDP() / ('\\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"132.177.0.99\")" + " / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionOf_set_vlan_vid(ActionFlowItem): + type = FlowActionType.OF_SET_VLAN_VID + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions of_set_vlan_vid vlan_vid 0xbbb / end', + frozenset({ + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"192.168.0.1\")" + " / UDP() / ('\\x00' * 64)"}), + frozenset({ + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"192.168.0.2\") " + "/ UDP() / ('\\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"10.0.30.99\") " + "/ UDP() / ('\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"8.8.8.8\") " + "/ UDP() / ('\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"132.177.0.99\") " + "/ UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionOf_set_vlan_pcp(ActionFlowItem): + type = FlowActionType.OF_SET_VLAN_PCP + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1' + ' / udp / end actions of_set_vlan_vid vlan_pcp 0x7 / end', + frozenset({ + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"192.168.0.1\") " + "/ UDP() / ('\\x00' * 64)"}), + frozenset({ + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"192.168.0.2\") " + "/ UDP() / ('\\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"10.0.30.99\") " + "/ UDP() / ('\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"8.8.8.8\") " + "/ UDP() / ('\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xaaa) / IP(src=\"132.177.0.99\") " + "/ UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionOf_pop_mpls(ActionFlowItem): + type = FlowActionType.OF_POP_MPLS + test_case = { + 'test': ( + 'ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions of_pop_mpls ethertype 0x0806 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionOf_push_mpls(ActionFlowItem): + type = FlowActionType.OF_PUSH_MPLS + + test_case = { + 'test': ( + 'ingress pattern eth / ipv4 src is 192.168.0.1' + ' / udp / end actions of_push_mpls ethertype 0x0806 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / MPLS(label = 0xab, ttl=128) / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionVxlan_encap(ActionFlowItem): + type = FlowActionType.VXLAN_ENCAP + + test_case = { + # VXLAN encap definition is the VNI? + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1' + ' / udp / end actions vxlan_encap definition 0x112233 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionVxlan_decap(ActionFlowItem): + type = FlowActionType.VXLAN_DECAP + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions vxlan_decap / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / VXLAN() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / VXLAN() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / VXLAN() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / VXLAN() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / VXLAN() / ('\\x00' * 64)"})), + } + + +class FlowActionNvgre_encap(ActionFlowItem): + type = FlowActionType.NVGRE_ENCAP + # NVGRE PACKETS NOT SUPPORTED BY SCAPY. + ''' + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 + / udp / end actions nvgre_encap definition 0x112233 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / NVGRE() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / NVGRE() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / NVGRE() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / NVGRE() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / NVGRE() / ('\\x00' * 64)"})), + } + ''' + + +class FlowActionNvgre_decap(ActionFlowItem): + type = FlowActionType.NVGRE_DECAP + # NVGRE PACKETS NOT SUPPORTED BY SCAPY. + ''' + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / udp / end actions nvgre_decap / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / NVGRE() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / NVGRE() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / NVGRE() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / NVGRE() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / NVGRE() / ('\\x00' * 64)"})), + } + ''' + + +class FlowActionRaw_encap(ActionFlowItem): + type = FlowActionType.RAW_ENCAP + # Assume we are encapsulating with a VLAN header with the following values: + # TPID: 0x8100 + # Prio: 0x5 + # PCP: 0 + # VID: 0xaaa + # This makes the full header: 0x8100aaaa + test_case = { + 'test_data': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions raw_encap data 0x8100aaaa / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + + 'test_preserve': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions raw_encap data 0x8100aaaa preserve 0xffffffff / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + # Is "size" in bits or bytes? Unclear in documentation, defaulting to bits. + 'test_size': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions raw_encap data 0x8100aaaa size 32 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionRaw_decap(ActionFlowItem): + type = FlowActionType.RAW_DECAP + test_case = { + 'test_data': ( + 'ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions raw_decap data 0x8100aaaa / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xbbb) / IP(src=\"192.168.0.2\")" + " / UDP() / ('\\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xbbb) / IP(src=\"10.0.30.99\") " + "/ UDP() / ('\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xbbb) / IP(src=\"8.8.8.8\")" + " / UDP() / ('\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xbbb) / IP(src=\"132.177.0.99\") " + "/ UDP() / ('\\x00' * 64)"})), + + # Is "size" in bits or bytes? Unclear in documentation, defaulting to bits. + 'test_size': ( + 'ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions raw_decap data 0x8100aaaa size 32 / end', + frozenset({"Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xbbb) / IP(src=\"192.168.0.1\") " + "/ UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xbbb) / IP(src=\"192.168.0.2\") " + "/ UDP() / ('\\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xbbb) / IP(src=\"10.0.30.99\")" + " / UDP() / ('\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xbbb) / IP(src=\"8.8.8.8\") " + "/ UDP() / ('\x00' * 64)", + "Ether() / Dot1Q(prio = 0x5, id = 0x0, vlan = 0xbbb) / IP(src=\"132.177.0.99\") " + "/ UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionSet_ipv4_src(ActionFlowItem): + type = FlowActionType.SET_IPV4_SRC + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions set_ipv4_src ipv4_addr 172.16.0.10 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionSet_ipv4_dst(ActionFlowItem): + type = FlowActionType.SET_IPV4_DST + + test_case = { + 'test': ('ingress pattern eth / ipv4 dst is 192.168.0.1' + ' / udp / end actions set_ipv4_dst ipv4_addr 172.16.0.10 / end', + frozenset({"Ether() / IP(dst=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(dst=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(dst=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(dst=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(dst=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionSet_ipv6_src(ActionFlowItem): + type = FlowActionType.SET_IPV6_SRC + + test_case = { + 'test': ('ingress pattern eth / ipv6 src is 2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c2 ' + '/ udp / end actions set_ipv6_src ipv6_addr 2001:0000:9d38:6ab8:1c48:9999:aaaa:bbbb', + frozenset({"Ether() / IPv6(src=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c2\") " + "/ UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IPv6(src=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c3\") / UDP() / ('\\x00' * 64)", + "Ether() / IPv6(src=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c4\") / UDP() / ('\x00' * 64)", + "Ether() / IPv6(src=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c5\") / UDP() / ('\x00' * 64)", + "Ether() / IPv6(src=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c6\") " + "/ UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionSet_ipv6_dst(ActionFlowItem): + type = FlowActionType.SET_IPV6_DST + + test_case = { + 'test': ('ingress pattern eth / ipv6 dst is 2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c2 ' + '/ udp / end actions set_ipv6_dst ipv6_addr 2001:0000:9d38:6ab8:1c48:9999:aaaa:bbbb', + frozenset({"Ether() / IPv6(dst=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c2\")" + " / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IPv6(dst=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c3\") / UDP() / ('\\x00' * 64)", + "Ether() / IPv6(dst=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c4\") / UDP() / ('\x00' * 64)", + "Ether() / IPv6(dst=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c5\") / UDP() / ('\x00' * 64)", + "Ether() / IPv6(dst=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c6\") " + "/ UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionSet_tp_src(ActionFlowItem): + type = FlowActionType.SET_TP_SRC + + test_case = { + # UDP + 'test_udp': ('ingress pattern eth / ipv4 src is 192.168.0.1' + ' / udp / end actions set_tp_src port 1998 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") UDP(sport=3838) / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") UDP(sport=3838) / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") UDP(sport=3838) / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") UDP(sport=3838) / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") UDP(sport=3838) / ('\\x00' * 64)"})), + + # TCP + 'test_tcp': ( + 'ingress pattern eth / ipv4 src is 192.168.0.1 / tcp / end actions set_tp_src port 1998 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") TCP(sport=3838) / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") TCP(sport=3838) / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") TCP(sport=3838) / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") TCP(sport=3838) / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") TCP(sport=3838) / ('\\x00' * 64)"})), + } + + +class FlowActionSet_tp_dst(ActionFlowItem): + type = FlowActionType.SET_TP_DST + + test_case = { + # UDP + 'test_udp': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions set_tp_dst port 1998 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") UDP(dport=3838) / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") UDP(dport=3838) / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") UDP(dport=3838) / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") UDP(dport=3838) / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") UDP(dport=3838) / ('\\x00' * 64)"})), + + # TCP + 'test_tcp': ( + 'ingress pattern eth / ipv4 src is 192.168.0.1 / tcp / end actions set_tp_dst port 1998 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") TCP(dport=3838) / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") TCP(dport=3838) / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") TCP(dport=3838) / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") TCP(dport=3838) / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") TCP(dport=3838) / ('\\x00' * 64)"})), + + } + + +class FlowActionSet_ttl(ActionFlowItem): + type = FlowActionType.SET_TTL + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1' + ' / udp / end actions set_ttl ttl_value 64 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\" , ttl=128 ) / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\" , ttl=128 ) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\" , ttl=128 ) / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\", ttl=128 ) / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\", ttl=128 ) / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionSet_mac_src(ActionFlowItem): + type = FlowActionType.SET_MAC_SRC + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1' + ' / udp / end actions set_mac_src mac_addr 10:20:30:40:50:60 / end', + frozenset({"Ether(src=\"90:61:ae:fd:41:43\") / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether(src=\"90:61:ae:fd:41:43\") / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether(src=\"90:61:ae:fd:41:43\") / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether(src=\"90:61:ae:fd:41:43\") / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether(src=\"90:61:ae:fd:41:43\") / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionSet_mac_dst(ActionFlowItem): + type = FlowActionType.SET_MAC_DST + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1' + ' / udp / end actions set_mac_dst mac_addr 10:20:30:40:50:60 / end', + frozenset({"Ether(dst=\"90:61:ae:fd:41:43\") / IP(src=\"192.168.0.1\") " + "/ UDP() / ('\\x00' * 64)"}), + frozenset({"Ether(dst=\"90:61:ae:fd:41:43\") / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether(dst=\"90:61:ae:fd:41:43\") / IP(src=\"10.0.30.99\") / UDP() / ('\x00' * 64)", + "Ether(dst=\"90:61:ae:fd:41:43\") / IP(src=\"8.8.8.8\") / UDP() / ('\x00' * 64)", + "Ether(dst=\"90:61:ae:fd:41:43\") / IP(src=\"132.177.0.99\") " + "/ UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionInc_tcp_seq(ActionFlowItem): + type = FlowActionType.INC_TCP_SEQ + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / tcp / end actions inc_tcp_seq / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / TCP(seq=2) / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / TCP(seq=2) / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / TCP(seq=2) / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / TCP(seq=2) / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / TCP(seq=2) / ('\\x00' * 64)"})), + } + + +class FlowActionDec_tcp_seq(ActionFlowItem): + type = FlowActionType.DEC_TCP_SEQ + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / tcp / end actions dec_tcp_seq / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / TCP(seq=2) / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / TCP(seq=2) / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / TCP(seq=2) / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / TCP(seq=2) / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / TCP(seq=2) / ('\\x00' * 64)"})), + } + + +class FlowActionInc_tcp_ack(ActionFlowItem): + type = FlowActionType.INC_TCP_ACK + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / tcp / end actions inc_tcp_ack / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / TCP(ack=2) / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / TCP(ack=2) / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / TCP(ack=2) / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / TCP(ack=2) / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / TCP(ack=2) / ('\\x00' * 64)"})), + } + + +class FlowActionDec_tcp_ack(ActionFlowItem): + type = FlowActionType.DEC_TCP_ACK + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 / tcp / end actions dec_tcp_ack / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / TCP(ack=2) / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / TCP(ack=2) / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / TCP(ack=2) / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / TCP(ack=2) / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / TCP(ack=2) / ('\\x00' * 64)"})), + } + + +class FlowActionSet_tag(ActionFlowItem): + type = FlowActionType.SET_TAG + + test_case = { + 'test_data': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions set_tag data 0xabc / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + # bit-mask applies to "data" + 'test_mask': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions set_tag data 0xabc mask 0xcba / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + 'test_index': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions set_tag data 0xabc index 1 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionSet_meta(ActionFlowItem): + type = FlowActionType.SET_META + + test_case = { + 'test_data': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions set_meta data 0xabc / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + # bit-mask applies to "data" + 'test_mask': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions set_meta data 0xabc mask 0xcb / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionSet_ipv4_dscp(ActionFlowItem): + type = FlowActionType.SET_IPV4_DSCP + + test_case = { + 'test': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions set_ipv4_dscp dscp 2 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\", tos = 0) / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\", tos = 0) / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\", tos = 0) / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\", tos = 0) / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\", tos = 0) / UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionSet_ipv6_dscp(ActionFlowItem): + type = FlowActionType.SET_IPV6_DSCP + + test_case = { + 'test': ('ingress pattern eth / ipv6 src is 2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c2 ' + '/ udp / end actions set_ipv6_dscp dscp 0x30', + frozenset({"Ether() / IPv6(src=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c2\", tc = 0) " + "/ UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IPv6(src=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c3\", tc = 0) " + "/ UDP() / ('\\x00' * 64)", + "Ether() / IPv6(src=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c4\", tc = 0) " + "/ UDP() / ('\x00' * 64)", + "Ether() / IPv6(src=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c5\", tc = 0) " + "/ UDP() / ('\x00' * 64)", + "Ether() / IPv6(src=\"2001:0000:9d38:6ab8:1c48:3a1c:a95a:b1c6\", tc = 0) " + "/ UDP() / ('\\x00' * 64)"})), + } + + +class FlowActionAge(ActionFlowItem): + type = FlowActionType.AGE + + test_case = { + 'test_timeout': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions age timeout 128 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + # 8 bits reserved, must be zero + 'test_reserved': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions age timeout 128 reserved 0 / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + # The user flow context, NULL means the rte_flow pointer. + 'test_context': ('ingress pattern eth / ipv4 src is 192.168.0.1 ' + '/ udp / end actions age timeout 128 context NULL / end', + frozenset({"Ether() / IP(src=\"192.168.0.1\") / UDP() / ('\\x00' * 64)"}), + frozenset({"Ether() / IP(src=\"192.168.0.2\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"10.0.30.99\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"8.8.8.8\") / UDP() / ('\\x00' * 64)", + "Ether() / IP(src=\"132.177.0.99\") / UDP() / ('\\x00' * 64)"})), + + } + + +ACTION_ITEMS_TYPE_CLASS_MAPPING: Dict[FlowActionType, ActionFlowItem] = { + FlowActionType.PASSTHRU: FlowActionPassthru, + FlowActionType.FLAG: FlowActionFlag, + FlowActionType.DROP: FlowActionDrop, + FlowActionType.COUNT: FlowActionCount, + FlowActionType.MAC_SWAP: FlowActionMac_swap, + FlowActionType.DEC_TTL: FlowActionDec_ttl, + FlowActionType.JUMP: FlowActionJump, + FlowActionType.MARK: FlowActionMark, + FlowActionType.QUEUE: FlowActionQueue, + FlowActionType.RSS: FlowActionRss, + FlowActionType.PF: FlowActionPf, + FlowActionType.VF: FlowActionVf, + FlowActionType.PHY_PORT: FlowActionPhy_port, + FlowActionType.PORT_ID: FlowActionPort_id, + FlowActionType.METER: FlowActionMeter, + FlowActionType.SECURITY: FlowActionSecurity, + FlowActionType.OF_SET_MPLS_TTL: FlowActionOf_set_mpls_ttl, + FlowActionType.OF_DEC_MPLS_TTL: FlowActionOf_dec_mpls_ttl, + FlowActionType.OF_SET_NW_TTL: FlowActionOf_set_nw_ttl, + FlowActionType.OF_DEC_NW_TTL: FlowActionOf_dec_nw_ttl, + FlowActionType.OF_COPY_TTL_OUT: FlowActionOf_copy_ttl_out, + FlowActionType.OF_COPY_TTL_IN: FlowActionOf_copy_ttl_in, + FlowActionType.OF_POP_VLAN: FlowActionOf_pop_vlan, + FlowActionType.OF_PUSH_VLAN: FlowActionOf_push_vlan, + FlowActionType.OF_SET_VLAN_VID: FlowActionOf_set_vlan_vid, + FlowActionType.OF_SET_VLAN_PCP: FlowActionOf_set_vlan_pcp, + FlowActionType.OF_POP_MPLS: FlowActionOf_pop_mpls, + FlowActionType.OF_PUSH_MPLS: FlowActionOf_push_mpls, + FlowActionType.VXLAN_ENCAP: FlowActionVxlan_encap, + FlowActionType.VXLAN_DECAP: FlowActionVxlan_decap, + FlowActionType.NVGRE_ENCAP: FlowActionNvgre_encap, + FlowActionType.NVGRE_DECAP: FlowActionNvgre_decap, + FlowActionType.RAW_ENCAP: FlowActionRaw_encap, + FlowActionType.RAW_DECAP: FlowActionRaw_decap, + FlowActionType.SET_IPV4_SRC: FlowActionSet_ipv4_src, + FlowActionType.SET_IPV4_DST: FlowActionSet_ipv4_dst, + FlowActionType.SET_IPV6_SRC: FlowActionSet_ipv6_src, + FlowActionType.SET_IPV6_DST: FlowActionSet_ipv6_dst, + FlowActionType.SET_TP_SRC: FlowActionSet_tp_src, + FlowActionType.SET_TP_DST: FlowActionSet_tp_dst, + FlowActionType.SET_TTL: FlowActionSet_ttl, + FlowActionType.SET_MAC_SRC: FlowActionSet_mac_src, + FlowActionType.SET_MAC_DST: FlowActionSet_mac_dst, + FlowActionType.INC_TCP_SEQ: FlowActionInc_tcp_seq, + FlowActionType.DEC_TCP_SEQ: FlowActionDec_tcp_seq, + FlowActionType.INC_TCP_ACK: FlowActionInc_tcp_ack, + FlowActionType.DEC_TCP_ACK: FlowActionDec_tcp_ack, + FlowActionType.SET_TAG: FlowActionSet_tag, + FlowActionType.SET_META: FlowActionSet_meta, + FlowActionType.SET_IPV4_DSCP: FlowActionSet_ipv4_dscp, + FlowActionType.SET_IPV6_DSCP: FlowActionSet_ipv6_dscp, + FlowActionType.AGE: FlowActionAge +}