From 3cabee828f90de79be8150be47da4d9842a711f6 Mon Sep 17 00:00:00 2001 From: krishna Date: Thu, 29 Sep 2016 17:51:56 -0700 Subject: [PATCH] Merge master to ops --- .travis.yml | 105 +++ CI/travis/install-bmv2.sh | 12 + CI/travis/install-p4c-bmv2.sh | 8 + CI/travis/install-p4ofagent.sh | 17 + CI/travis/install-ptf.sh | 6 + CI/travis/run_of_tests.sh | 5 + CI/travis/run_switch_tests.sh | 17 + CI/travis/veth_setup.sh | 38 + Makefile.am | 1 - bmv2/.gitignore | 8 + bmv2/Makefile.am | 39 + bmv2/bmv2_init.c | 105 +++ bmv2/dummy.p4 | 0 bmv2/main.c | 88 ++ bmv2/run_bm.sh.in | 16 + bmv2/run_drivers.sh.in | 11 + bmv2/run_of_tests.sh.in | 7 + bmv2/run_tests.sh.in | 10 + bmv2/split_pd_thrift.py | 53 ++ m4/adl_recursive_eval.m4 | 15 + m4/ax_prog_doxygen.m4 | 585 +++++++++++++ m4/ax_restore_flags.m4 | 31 + m4/ax_save_flags.m4 | 31 + openflow_mapping/l2.py | 12 + openflow_mapping/mapping_common.py | 10 + p4src/LICENSE | 177 ++++ p4src/acl.p4 | 278 ++++++- p4src/fabric.p4 | 1 + p4src/includes/drop_reasons.h | 55 -- p4src/includes/headers.p4 | 1 + p4src/includes/p4_table_sizes.h | 7 + p4src/includes/p4features.h | 10 + p4src/includes/parser.p4 | 15 - p4src/l2.p4 | 3 +- p4src/l3.p4 | 3 + p4src/meter.p4 | 16 +- p4src/openflow.p4 | 134 ++- p4src/p4_files.am | 29 + p4src/port.p4 | 3 +- p4src/switch.p4 | 14 +- p4src/tunnel.p4 | 7 + switchapi/Doxyfile | 2 +- switchapi/include/switchapi/switch_acl.h | 174 ++-- .../include/switchapi/switch_base_types.h | 2 +- switchapi/include/switchapi/switch_handle.h | 10 +- switchapi/src/switch_acl.c | 466 ++++++++--- switchapi/src/switch_acl_int.h | 7 + switchapi/src/switch_api.thrift | 26 +- switchapi/src/switch_api_rpc_server.cpp | 62 +- switchapi/src/switch_handle.c | 11 +- switchapi/src/switch_hostif.c | 92 ++- switchapi/src/switch_hostif_int.h | 6 +- switchapi/src/switch_init.c | 93 ++- switchapi/src/switch_nhop.c | 2 +- switchapi/src/switch_packet.c | 37 +- switchapi/src/switch_pd.c | 775 ++++++++++++++++-- switchapi/src/switch_pd.h | 87 +- switchapi/src/switch_port.c | 4 +- switchapi/src/switch_scheduler.c | 2 +- switchapi/src/switch_sflow.c | 4 +- switchlink/Makefile.am | 40 +- switchlink/configure.ac | 34 - switchsai/Makefile.am | 128 ++- switchsai/README.md | 2 + switchsai/src/sai.c | 3 + switchsai/src/saiacl.c | 629 ++++++++++---- switchsai/src/saiipmc.c | 3 +- switchsai/src/sail2mc.c | 3 +- switchsai/src/switch_sai.thrift | 10 + switchsai/src/switch_sai_rpc_server.cpp | 65 +- tests/of-tests/common/utils.py | 45 + tests/of-tests/openflow.py | 142 ++-- tests/ptf-tests/api-tests/switch.py | 226 ++--- tests/ptf-tests/api-tests/switch_acl.py | 330 +++++++- tests/ptf-tests/common/pd_utils.py | 41 +- tests/ptf-tests/common/sai_utils.py | 33 + tests/ptf-tests/common/utils.py | 24 +- tests/ptf-tests/sai-tests/switch.py | 200 ++++- tests/run_of_tests.py | 45 + tests/run_tests.py.in | 61 ++ testutils/erspan3.py | 38 + testutils/xnt.py | 75 ++ tools/veth_disable_ipv6.sh | 21 + tools/veth_setup.sh | 38 + tools/veth_teardown.sh | 21 + 85 files changed, 5149 insertions(+), 953 deletions(-) create mode 100644 .travis.yml create mode 100644 CI/travis/install-bmv2.sh create mode 100644 CI/travis/install-p4c-bmv2.sh create mode 100755 CI/travis/install-p4ofagent.sh create mode 100644 CI/travis/install-ptf.sh create mode 100755 CI/travis/run_of_tests.sh create mode 100755 CI/travis/run_switch_tests.sh create mode 100755 CI/travis/veth_setup.sh create mode 100644 bmv2/.gitignore create mode 100644 bmv2/Makefile.am create mode 100644 bmv2/bmv2_init.c create mode 100644 bmv2/dummy.p4 create mode 100644 bmv2/main.c create mode 100644 bmv2/run_bm.sh.in create mode 100644 bmv2/run_drivers.sh.in create mode 100644 bmv2/run_of_tests.sh.in create mode 100644 bmv2/run_tests.sh.in create mode 100644 bmv2/split_pd_thrift.py create mode 100644 m4/adl_recursive_eval.m4 create mode 100644 m4/ax_prog_doxygen.m4 create mode 100644 m4/ax_restore_flags.m4 create mode 100644 m4/ax_save_flags.m4 create mode 100644 openflow_mapping/l2.py create mode 100644 openflow_mapping/mapping_common.py create mode 100644 p4src/LICENSE delete mode 100644 p4src/includes/drop_reasons.h create mode 100644 p4src/p4_files.am delete mode 100644 switchlink/configure.ac create mode 100644 tests/of-tests/common/utils.py create mode 100755 tests/run_of_tests.py create mode 100755 tests/run_tests.py.in create mode 100644 testutils/erspan3.py create mode 100644 testutils/xnt.py create mode 100755 tools/veth_disable_ipv6.sh create mode 100755 tools/veth_setup.sh create mode 100755 tools/veth_teardown.sh diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..0c578ef --- /dev/null +++ b/.travis.yml @@ -0,0 +1,105 @@ +# Config file for automatic testing at travis-ci.org + +sudo: required + +dist: trusty + +language: c + +# My very smart trick to force inclusion of the veth kernel module +# (even though we do not use docker at all her) +services: + - docker + +env: + global: + - PYP_ADD="/usr/local/lib/python2.7/dist-packages:/usr/local/lib/python2.7/site-packages" + matrix: + - TEST_SCENARIO=switch + - TEST_SCENARIO=of + +# There is probably some redundant stuff in this list. If you find one, remove +# it +addons: + apt: + packages: + - libjudy-dev + - libgmp-dev + - libpcap-dev + - libboost-dev + - libboost-test-dev + - libboost-program-options-dev + - libboost-system-dev + - libboost-filesystem-dev + - libboost-thread-dev + - libboost-test-dev + - libevent-dev + - automake + - libtool + - flex + - bison + - pkg-config + - g++ + - libssl-dev + - doxygen + - git + - libedit-dev + - libevent-dev + - libfreetype6-dev + - libpng-dev + - libyaml-0-2 + - libbz2-dev + - libnl-route-3-dev + - openssl + - pkg-config + - python-dev + - python-matplotlib + - python-numpy + - python-pip + - python-scipy + - python-setuptools + - python-yaml + +# need to replace github ssh references with https +before_install: + - git submodule update --init --recursive + - sudo apt-get install ethtool + - sudo pip install --upgrade pip + - sudo pip install --upgrade thrift + - sudo pip install ctypesgen + - sudo pip install crc16 + +# install bmv2 before p4c-bmv2 to get nanomsg +install: + - wget https://s3-us-west-2.amazonaws.com/p4lang/thrift_bin.tar.gz + - tar -xzvf thrift_bin.tar.gz -C $HOME/ + - export PATH=$PATH:$HOME/thrift/bin/ + - export LDFLAGS="$LDFLAGS -L$HOME/thrift/lib" + - export CPPFLAGS="$CPPFLAGS -I$HOME/thrift/include" + - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/thrift/lib + - mkdir install_tmp && cd install_tmp/ + - sudo apt-get remove python-scapy + - git clone https://github.com/p4lang/scapy-vxlan.git && cd scapy-vxlan && sudo python setup.py install && cd .. + - cd .. && sudo rm -rf install_tmp/ + - bash CI/travis/install-ptf.sh + - bash CI/travis/install-bmv2.sh + - bash CI/travis/install-p4c-bmv2.sh + - bash CI/travis/install-p4ofagent.sh + - export CPPFLAGS="$CPPFLAGS -I$HOME/p4ofagent/include" + - export LDFLAGS="$LDFLAGS -L$HOME/p4ofagent/lib" + - git clone https://github.com/floodlight/oftest.git oftest_tmp + - export PYTHONPATH=$PYP_ADD:$PYTHONPATH + - sudo ldconfig + - ./autogen.sh + +before_script: + - cp CI/travis/veth_setup.sh tools/ + - cd tools; sudo ./veth_setup.sh; sudo ./veth_disable_ipv6.sh; cd .. + +script: + - if [ "$TEST_SCENARIO" = "switch" ] ; then ./configure --with-bmv2 --with-switchsai; fi + - if [ "$TEST_SCENARIO" = "of" ] ; then ./configure --with-bmv2 --with-of; fi + - make -j2 + - if [ "$TEST_SCENARIO" = "switch" ] ; then ./CI/travis/run_switch_tests.sh; fi + - if [ "$TEST_SCENARIO" = "of" ] ; then ./CI/travis/run_of_tests.sh; fi + diff --git a/CI/travis/install-bmv2.sh b/CI/travis/install-bmv2.sh new file mode 100644 index 0000000..051197d --- /dev/null +++ b/CI/travis/install-bmv2.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e +git clone https://github.com/p4lang/behavioral-model.git bmv2_tmp +cd bmv2_tmp +bash travis/install-nanomsg.sh +sudo ldconfig +bash travis/install-nnpy.sh +./autogen.sh +./configure 'CXXFLAGS=-O0' --with-pdfixed +make -j2 && sudo make install +cd .. +rm -rf bmv2_tmp diff --git a/CI/travis/install-p4c-bmv2.sh b/CI/travis/install-p4c-bmv2.sh new file mode 100644 index 0000000..97de97c --- /dev/null +++ b/CI/travis/install-p4c-bmv2.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e +git clone https://github.com/p4lang/p4c-bm.git p4c-bmv2 +cd p4c-bmv2 +git submodule update --init --recursive +sudo pip install -r requirements.txt +sudo python setup.py install +cd .. diff --git a/CI/travis/install-p4ofagent.sh b/CI/travis/install-p4ofagent.sh new file mode 100755 index 0000000..1dbdcfa --- /dev/null +++ b/CI/travis/install-p4ofagent.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e +git clone https://github.com/p4lang/p4ofagent.git p4ofagent_tmp +cd p4ofagent_tmp +git submodule update --init +cd submodules/indigo/ +find -name ".gitmodules" -type f -exec sed -i 's/git@github.com:/https:\/\/github.com\//' {} \; +git submodule update --init +cd submodules/bigcode/ +find -name ".gitmodules" -type f -exec sed -i 's/git@github.com:/https:\/\/github.com\//' {} \; +cd ../../../../ +./autogen.sh +./configure --prefix=$HOME/p4ofagent +make p4ofagent CPPFLAGS="-D_BMV2_ -I$HOME/bmv2/include" +make install +cd .. +rm -rf p4ofagent_tmp diff --git a/CI/travis/install-ptf.sh b/CI/travis/install-ptf.sh new file mode 100644 index 0000000..77bf840 --- /dev/null +++ b/CI/travis/install-ptf.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e +git clone https://github.com/p4lang/ptf.git +cd ptf +sudo python setup.py install +cd .. diff --git a/CI/travis/run_of_tests.sh b/CI/travis/run_of_tests.sh new file mode 100755 index 0000000..51da75f --- /dev/null +++ b/CI/travis/run_of_tests.sh @@ -0,0 +1,5 @@ +sudo ./bmv2/run_bm.sh &>/dev/null & +sleep 10 +sudo ./bmv2/run_drivers.sh &>/dev/null & +sleep 10 +sudo ./bmv2/run_of_tests.sh --oft-path oftest_tmp/oft diff --git a/CI/travis/run_switch_tests.sh b/CI/travis/run_switch_tests.sh new file mode 100755 index 0000000..03a549f --- /dev/null +++ b/CI/travis/run_switch_tests.sh @@ -0,0 +1,17 @@ +sudo ./bmv2/run_bm.sh &>/dev/null & +sleep 10 +sudo ./bmv2/run_drivers.sh &>/dev/null & +sleep 10 +sudo ./bmv2/run_tests.sh --test-dir tests/ptf-tests/api-tests +sudo killall bmswitchp4_drivers lt-bmswitchp4_drivers simple_switch lt-simple_switch; echo 0 +sudo ./bmv2/run_bm.sh &>/dev/null & +sleep 10 +sudo ./bmv2/run_drivers.sh &>/dev/null & +sleep 10 +sudo ./bmv2/run_tests.sh --test-dir tests/ptf-tests/sai-tests +sudo killall bmswitchp4_drivers lt-bmswitchp4_drivers simple_switch lt-simple_switch; echo 0 +sudo ./bmv2/run_bm.sh &>/dev/null & +sleep 10 +sudo ./bmv2/run_drivers.sh &>/dev/null & +sleep 10 +sudo ./bmv2/run_tests.sh diff --git a/CI/travis/veth_setup.sh b/CI/travis/veth_setup.sh new file mode 100755 index 0000000..5d53e1d --- /dev/null +++ b/CI/travis/veth_setup.sh @@ -0,0 +1,38 @@ +#!/bin/bash +noOfVeths=18 +if [ $# -eq 1 ]; then + noOfVeths=$1 +fi +echo "No of Veths is $noOfVeths" +idx=0 +let "vethpairs=$noOfVeths/2" +while [ $idx -lt $vethpairs ] +do +#1 2 3 4 5 6 7 125 + intf0="veth$(($idx*2))" + intf1="veth$(($idx*2+1))" + idx=$((idx + 1)) + if ! ip link show $intf0 &> /dev/null; then + ip link add name $intf0 type veth peer name $intf1 + ip link set dev $intf0 up + ip link set dev $intf1 up + TOE_OPTIONS="rx tx sg tso ufo gso gro rxvlan txvlan" + for TOE_OPTION in $TOE_OPTIONS; do + /sbin/ethtool --offload $intf0 "$TOE_OPTION" off + /sbin/ethtool --offload $intf1 "$TOE_OPTION" off + done + fi +done +idx=125 +intf0="veth$(($idx*2))" +intf1="veth$(($idx*2+1))" +if ! ip link show $intf0 &> /dev/null; then + ip link add name $intf0 type veth peer name $intf1 + ip link set dev $intf0 up + ip link set dev $intf1 up + TOE_OPTIONS="rx tx sg tso ufo gso gro rxvlan txvlan" + for TOE_OPTION in $TOE_OPTIONS; do + /sbin/ethtool --offload $intf0 "$TOE_OPTION" off + /sbin/ethtool --offload $intf1 "$TOE_OPTION" off + done +fi diff --git a/Makefile.am b/Makefile.am index 977a684..0fe7298 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,3 @@ ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4 -# P4FLAGS = -I . SUBDIRS = p4src switchapi switchsai switchlink diff --git a/bmv2/.gitignore b/bmv2/.gitignore new file mode 100644 index 0000000..51ad7f3 --- /dev/null +++ b/bmv2/.gitignore @@ -0,0 +1,8 @@ +# This scripts are generated by configure +run_bm.sh +run_drivers.sh +run_tests.sh + +gen-py.tar.lz +p4_pd +switch.json diff --git a/bmv2/Makefile.am b/bmv2/Makefile.am new file mode 100644 index 0000000..9eb67a3 --- /dev/null +++ b/bmv2/Makefile.am @@ -0,0 +1,39 @@ +ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4 + +AM_CPPFLAGS += -DBMV2 +AM_CPPFLAGS += -I$(top_builddir)/p4-build +AM_CPPFLAGS += -isystem$(includedir) + +lib_LTLIBRARIES = libbmswitchp4.la +libbmswitchp4_la_CPPFLAGS = $(AM_CPPFLAGS) +libbmswitchp4_la_LIBADD = +if WITH_SWITCHLINK +libbmswitchp4_la_LIBADD += @top_builddir@/switchlink/libswitchlink.la +endif +if WITH_SWITCHSAI +libbmswitchp4_la_LIBADD += @top_builddir@/switchsai/libbmswitchsai.la +endif +if WITH_SWITCHAPI +libbmswitchp4_la_LIBADD += @top_builddir@/switchapi/libbmswitchapi.la +endif +if WITH_OF +libbmswitchp4_la_LIBADD += @top_builddir@/p4-build/bmv2/libof.la +endif +libbmswitchp4_la_LIBADD += \ +@top_builddir@/p4-build/bmv2/libpd.la \ +@top_builddir@/p4-build/bmv2/libpdthrift.la \ +-lbmpdfixed -lbmpdfixedthrift $(THRIFT_LIB) +libbmswitchp4_la_SOURCES = \ +bmv2_init.c + +bin_PROGRAMS = bmswitchp4_drivers +bmswitchp4_drivers_CPPFLAGS = $(AM_CPPFLAGS) +bmswitchp4_drivers_LDADD = \ +libbmswitchp4.la +if WITH_OF +bmswitchp4_drivers_LDADD += \ +-lp4ofagent @top_builddir@/p4-build/bmv2/libof.la \ +-lbmpdfixed -lpthread -lm +endif +bmswitchp4_drivers_SOURCES = \ +main.c diff --git a/bmv2/bmv2_init.c b/bmv2/bmv2_init.c new file mode 100644 index 0000000..eeba72c --- /dev/null +++ b/bmv2/bmv2_init.c @@ -0,0 +1,105 @@ +/* +Copyright 2013-present Barefoot Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +char *pd_server_str = NULL; +char *of_controller_str = NULL; +int of_ipv6 = 0; + +/** + * The maximum number of ports to support: + * @fixme should be runtime parameter + */ +#define PORT_COUNT 256 +#define PD_SERVER_DEFAULT_PORT 9090 + +/** + * Check an operation and return if there's an error. + */ +#define CHECK(op) \ + do { \ + int _rv; \ + if ((_rv = (op)) < 0) { \ + fprintf(stderr, "%s: ERROR %d at %s:%d", \ + #op, _rv, __FILE__, __LINE__); \ + return _rv; \ + } \ + } while (0) + +#ifdef SWITCHLINK_ENABLE +extern int switchlink_init(void); +#endif /* SWITCHLINK_ENABLE */ + +#ifdef SWITCHAPI_ENABLE +extern int switch_api_init(int device, unsigned int num_ports); +extern int start_switch_api_rpc_server(void); +extern int start_switch_api_packet_driver(void); +#endif /* SWITCHAPI_ENABLE */ + +#ifdef SWITCHSAI_ENABLE +#define SWITCH_SAI_THRIFT_RPC_SERVER_PORT "9092" +extern int start_p4_sai_thrift_rpc_server(char * port); +#endif /* SWITCHSAI_ENABLE */ + +#ifdef OPENFLOW_ENABLE +extern void p4ofagent_init(bool ipv6, char *ip_ctl); +#endif + +int +bmv2_model_init() { + int rv=0; + /* Start up the PD RPC server */ + void *pd_server_cookie; + start_bfn_pd_rpc_server(&pd_server_cookie); + add_to_rpc_server(pd_server_cookie); + + p4_pd_init(); + p4_pd_dc_init(); + p4_pd_dc_assign_device(0, "ipc:///tmp/bmv2-0-notifications.ipc", 10001); + + /* Start up the API RPC server */ +#ifdef SWITCHAPI_ENABLE + CHECK(switch_api_init(0, 256)); + CHECK(start_switch_api_rpc_server()); + CHECK(start_switch_api_packet_driver()); +#endif /* SWITCHAPI_DISABLE */ + +#ifdef SWITCHSAI_ENABLE + CHECK(start_p4_sai_thrift_rpc_server(SWITCH_SAI_THRIFT_RPC_SERVER_PORT)); +#endif /*SWITCHSAI_ENABLE */ + +#ifdef SWITCHLINK_ENABLE + CHECK(switchlink_init()); +#endif /* SWITCHLINK_ENABLE */ + +#ifdef OPENFLOW_ENABLE + p4ofagent_init(of_ipv6, of_controller_str); +#endif + + return rv; +} diff --git a/bmv2/dummy.p4 b/bmv2/dummy.p4 new file mode 100644 index 0000000..e69de29 diff --git a/bmv2/main.c b/bmv2/main.c new file mode 100644 index 0000000..66f3834 --- /dev/null +++ b/bmv2/main.c @@ -0,0 +1,88 @@ +/* +Copyright 2013-present Barefoot Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +extern char *pd_server_str; +extern char *of_controller_str; +extern int of_ipv6; + +extern int bmv2_model_init(); + +static void +parse_options(int argc, char **argv) +{ + while (1) { + int option_index = 0; + /* Options without short equivalents */ + enum long_opts { + OPT_START = 256, + OPT_PDSERVER, + OPT_OFIP, + OPT_OFIPV6, + }; + static struct option long_options[] = { + {"help", no_argument, 0, 'h' }, + {"pd-server", required_argument, 0, OPT_PDSERVER }, + {"of-ip", required_argument, 0, OPT_OFIP }, + {"of-ipv6", no_argument, 0, OPT_OFIPV6 }, + {0, 0, 0, 0 } + }; + int c = getopt_long(argc, argv, "h", + long_options, &option_index); + if (c == -1) { + break; + } + switch (c) { + case OPT_PDSERVER: + pd_server_str = strdup(optarg); + break; + case 'h': + case '?': + printf("Drivers! \n"); + printf("Usage: drivers [OPTION]...\n"); + printf("\n"); + printf(" --pd-server=IP:PORT Listen for PD RPC calls\n"); + printf(" -h,--help Display this help message and exit\n"); + exit(c == 'h' ? 0 : 1); + break; + } + } +} + +int +main(int argc, char* argv[]) +{ + int rv = 0; + + parse_options(argc, argv); + + bmv2_model_init(); + + while (1) pause(); + + return rv; +} diff --git a/bmv2/run_bm.sh.in b/bmv2/run_bm.sh.in new file mode 100644 index 0000000..4acf586 --- /dev/null +++ b/bmv2/run_bm.sh.in @@ -0,0 +1,16 @@ +#!/bin/bash +if [[ $EUID -ne 0 ]]; then + echo "This script should be run using sudo or as the root user" + exit 1 +fi +if [ x@BM_SIMPLE_SWITCH@ = x ]; then + echo "simple_switch executable not found by latest configure run" + echo "have you installed bmv2 since? if yes, you need to run configure again" + exit 1 +fi +JSON_FILE=@abs_top_builddir@/p4-build/bmpd/switch.json +if [ ! -f $JSON_FILE ]; then + echo "switch.json not found; did you run 'make'?" + exit 1 +fi +@BM_SIMPLE_SWITCH@ --log-console -i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 -i 5@veth10 -i 6@veth12 -i 7@veth14 -i 8@veth16 -i 64@veth250 --thrift-port 10001 --pcap $JSON_FILE diff --git a/bmv2/run_drivers.sh.in b/bmv2/run_drivers.sh.in new file mode 100644 index 0000000..83419b3 --- /dev/null +++ b/bmv2/run_drivers.sh.in @@ -0,0 +1,11 @@ +#!/bin/bash +if [[ $EUID -ne 0 ]]; then + echo "This script should be run using sudo or as the root user" + exit 1 +fi +DRIVERS_EXE=@abs_builddir@/bmswitchp4_drivers +if [ ! -f $DRIVERS_EXE ]; then + echo "bmswitchp4_drivers not found; did you run 'make'?" + exit 1 +fi +$DRIVERS_EXE diff --git a/bmv2/run_of_tests.sh.in b/bmv2/run_of_tests.sh.in new file mode 100644 index 0000000..4cebf22 --- /dev/null +++ b/bmv2/run_of_tests.sh.in @@ -0,0 +1,7 @@ +#!/bin/bash +if [[ $EUID -ne 0 ]]; then + echo "This script should be run using sudo or as the root user" + exit 1 +fi +export PYTHONPATH=@MY_PYTHONPATH@/bm/pdfixed:$PYTHONPATH +@PYTHON@ @abs_top_builddir@/tests/run_of_tests.py $* diff --git a/bmv2/run_tests.sh.in b/bmv2/run_tests.sh.in new file mode 100644 index 0000000..4553703 --- /dev/null +++ b/bmv2/run_tests.sh.in @@ -0,0 +1,10 @@ +#!/bin/bash +if [[ $EUID -ne 0 ]]; then + echo "This script should be run using sudo or as the root user" + exit 1 +fi +PD_THRIFT_PY=@abs_top_builddir@/p4-build/bmv2/pd_thrift_gen/gen-py +@PYTHON@ @abs_top_builddir@/tests/run_tests.py \ + --pd-thrift $PD_THRIFT_PY \ + --pd-thrift @MY_PYTHONPATH@/bm/pdfixed \ + $* diff --git a/bmv2/split_pd_thrift.py b/bmv2/split_pd_thrift.py new file mode 100644 index 0000000..5ed25ca --- /dev/null +++ b/bmv2/split_pd_thrift.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +import os +import subprocess +import sys + +def get_output_file_name(output_dir, output_file_num): + return os.path.join(output_dir, 'p4_prefix%d.cpp' % output_file_num) + +def split_pd_thrift(input_file_name, output_dir, num_output_files): + num_input_lines = int(subprocess.check_output( + 'wc -l %s | awk \'{print $1}\'' % input_file_name, + shell=True)) + for output_file_num in range(num_output_files): + output_file_name = get_output_file_name(output_dir, output_file_num) + os.system('grep "^#include" %s > %s' % (input_file_name, + output_file_name)) + os.system('grep namespace\ p4_pd_rpc %s >> %s' % (input_file_name, + output_file_name)) + + output_file_num = 0 + end_namespace = '} // namespace' + output_line_num = 0 + with open(input_file_name) as input_file: + for line in input_file: + if line == 'namespace p4_pd_rpc {\n': + break + for line in input_file: + if output_line_num == 0 and output_file_num < num_output_files: # { + output_file_name = get_output_file_name(output_dir, + output_file_num) + output_file = open(output_file_name, "a") + output_file_num += 1 + # } + output_file.write(line) + output_line_num += 1 + if line == end_namespace: + # Reached the end of the namespace (last line in file) + break + elif (output_line_num > (num_input_lines / num_output_files)) and \ + (line == '}\n'): # { + # Reached end of function. close the file + output_file.write('%s\n' % end_namespace) + output_file.close() + output_line_num = 0 + # } + + +if __name__ == '__main__': + assert len(sys.argv) == 4 + input_file_name = sys.argv[1] + output_dir = sys.argv[2] + num_output_files = sys.argv[3] + split_pd_thrift(input_file_name, output_dir, int(num_output_files)) diff --git a/m4/adl_recursive_eval.m4 b/m4/adl_recursive_eval.m4 new file mode 100644 index 0000000..56bf672 --- /dev/null +++ b/m4/adl_recursive_eval.m4 @@ -0,0 +1,15 @@ +dnl adl_RECURSIVE_EVAL(VALUE, RESULT) +dnl ================================= +dnl Interpolate the VALUE in loop until it doesn't change, +dnl and set the result to $RESULT. +dnl WARNING: It's easy to get an infinite loop with some unsane input. +AC_DEFUN([adl_RECURSIVE_EVAL], +[_lcl_receval="$1" +$2=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" + test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" + _lcl_receval_old='' + while test "[$]_lcl_receval_old" != "[$]_lcl_receval"; do + _lcl_receval_old="[$]_lcl_receval" + eval _lcl_receval="\"[$]_lcl_receval\"" + done + echo "[$]_lcl_receval")`]) diff --git a/m4/ax_prog_doxygen.m4 b/m4/ax_prog_doxygen.m4 new file mode 100644 index 0000000..b2a899f --- /dev/null +++ b/m4/ax_prog_doxygen.m4 @@ -0,0 +1,585 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html +# =========================================================================== +# +# SYNOPSIS +# +# DX_INIT_DOXYGEN(PROJECT-NAME, [DOXYFILE-PATH], [OUTPUT-DIR], ...) +# DX_DOXYGEN_FEATURE(ON|OFF) +# DX_DOT_FEATURE(ON|OFF) +# DX_HTML_FEATURE(ON|OFF) +# DX_CHM_FEATURE(ON|OFF) +# DX_CHI_FEATURE(ON|OFF) +# DX_MAN_FEATURE(ON|OFF) +# DX_RTF_FEATURE(ON|OFF) +# DX_XML_FEATURE(ON|OFF) +# DX_PDF_FEATURE(ON|OFF) +# DX_PS_FEATURE(ON|OFF) +# +# DESCRIPTION +# +# The DX_*_FEATURE macros control the default setting for the given +# Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for +# generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML +# help (for MS users), 'CHI' for generating a seperate .chi file by the +# .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate +# output formats. The environment variable DOXYGEN_PAPER_SIZE may be +# specified to override the default 'a4wide' paper size. +# +# By default, HTML, PDF and PS documentation is generated as this seems to +# be the most popular and portable combination. MAN pages created by +# Doxygen are usually problematic, though by picking an appropriate subset +# and doing some massaging they might be better than nothing. CHM and RTF +# are specific for MS (note that you can't generate both HTML and CHM at +# the same time). The XML is rather useless unless you apply specialized +# post-processing to it. +# +# The macros mainly control the default state of the feature. The use can +# override the default by specifying --enable or --disable. The macros +# ensure that contradictory flags are not given (e.g., +# --enable-doxygen-html and --enable-doxygen-chm, +# --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each +# feature will be automatically disabled (with a warning) if the required +# programs are missing. +# +# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN +# with the following parameters: a one-word name for the project for use +# as a filename base etc., an optional configuration file name (the +# default is '$(srcdir)/Doxyfile', the same as Doxygen's default), and an +# optional output directory name (the default is 'doxygen-doc'). To run +# doxygen multiple times for different configuration files and output +# directories provide more parameters: the second, forth, sixth, etc +# parameter are configuration file names and the third, fifth, seventh, +# etc parameter are output directories. No checking is done to catch +# duplicates. +# +# Automake Support +# +# The DX_RULES substitution can be used to add all needed rules to the +# Makefile. Note that this is a substitution without being a variable: +# only the @DX_RULES@ syntax will work. +# +# The provided targets are: +# +# doxygen-doc: Generate all doxygen documentation. +# +# doxygen-run: Run doxygen, which will generate some of the +# documentation (HTML, CHM, CHI, MAN, RTF, XML) +# but will not do the post processing required +# for the rest of it (PS, PDF). +# +# doxygen-ps: Generate doxygen PostScript documentation. +# +# doxygen-pdf: Generate doxygen PDF documentation. +# +# Note that by default these are not integrated into the automake targets. +# If doxygen is used to generate man pages, you can achieve this +# integration by setting man3_MANS to the list of man pages generated and +# then adding the dependency: +# +# $(man3_MANS): doxygen-doc +# +# This will cause make to run doxygen and generate all the documentation. +# +# The following variable is intended for use in Makefile.am: +# +# DX_CLEANFILES = everything to clean. +# +# Then add this variable to MOSTLYCLEANFILES. +# +# LICENSE +# +# Copyright (c) 2009 Oren Ben-Kiki +# Copyright (c) 2015 Olaf Mandel +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 19 + +## ----------## +## Defaults. ## +## ----------## + +DX_ENV="" +AC_DEFUN([DX_FEATURE_doc], ON) +AC_DEFUN([DX_FEATURE_dot], OFF) +AC_DEFUN([DX_FEATURE_man], OFF) +AC_DEFUN([DX_FEATURE_html], ON) +AC_DEFUN([DX_FEATURE_chm], OFF) +AC_DEFUN([DX_FEATURE_chi], OFF) +AC_DEFUN([DX_FEATURE_rtf], OFF) +AC_DEFUN([DX_FEATURE_xml], OFF) +AC_DEFUN([DX_FEATURE_pdf], ON) +AC_DEFUN([DX_FEATURE_ps], ON) + +## --------------- ## +## Private macros. ## +## --------------- ## + +# DX_ENV_APPEND(VARIABLE, VALUE) +# ------------------------------ +# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen and add it +# as a substitution (but not a Makefile variable). The substitution +# is skipped if the variable name is VERSION. +AC_DEFUN([DX_ENV_APPEND], +[AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])dnl +m4_if([$1], [VERSION], [], [AC_SUBST([$1], [$2])dnl +AM_SUBST_NOTMAKE([$1])])dnl +]) + +# DX_DIRNAME_EXPR +# --------------- +# Expand into a shell expression prints the directory part of a path. +AC_DEFUN([DX_DIRNAME_EXPR], + [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']]) + +# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF) +# ------------------------------------- +# Expands according to the M4 (static) status of the feature. +AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])]) + +# DX_REQUIRE_PROG(VARIABLE, PROGRAM) +# ---------------------------------- +# Require the specified program to be found for the DX_CURRENT_FEATURE to work. +AC_DEFUN([DX_REQUIRE_PROG], [ +AC_PATH_TOOL([$1], [$2]) +if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then + AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION]) + AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0) +fi +]) + +# DX_TEST_FEATURE(FEATURE) +# ------------------------ +# Expand to a shell expression testing whether the feature is active. +AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1]) + +# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE) +# ------------------------------------------------- +# Verify that a required features has the right state before trying to turn on +# the DX_CURRENT_FEATURE. +AC_DEFUN([DX_CHECK_DEPEND], [ +test "$DX_FLAG_$1" = "$2" \ +|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1, + requires, contradicts) doxygen-DX_CURRENT_FEATURE]) +]) + +# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE) +# ---------------------------------------------------------- +# Turn off the DX_CURRENT_FEATURE if the required feature is off. +AC_DEFUN([DX_CLEAR_DEPEND], [ +test "$DX_FLAG_$1" = "$2" || AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0) +]) + +# DX_FEATURE_ARG(FEATURE, DESCRIPTION, +# CHECK_DEPEND, CLEAR_DEPEND, +# REQUIRE, DO-IF-ON, DO-IF-OFF) +# -------------------------------------------- +# Parse the command-line option controlling a feature. CHECK_DEPEND is called +# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND), +# otherwise CLEAR_DEPEND is called to turn off the default state if a required +# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional +# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and +# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature. +AC_DEFUN([DX_ARG_ABLE], [ + AC_DEFUN([DX_CURRENT_FEATURE], [$1]) + AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2]) + AC_ARG_ENABLE(doxygen-$1, + [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1], + [--enable-doxygen-$1]), + DX_IF_FEATURE([$1], [don't $2], [$2]))], + [ +case "$enableval" in +#( +y|Y|yes|Yes|YES) + AC_SUBST([DX_FLAG_$1], 1) + $3 +;; #( +n|N|no|No|NO) + AC_SUBST([DX_FLAG_$1], 0) +;; #( +*) + AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1]) +;; +esac +], [ +AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)]) +$4 +]) +if DX_TEST_FEATURE([$1]); then + $5 + : +fi +if DX_TEST_FEATURE([$1]); then + $6 + : +else + $7 + : +fi +]) + +## -------------- ## +## Public macros. ## +## -------------- ## + +# DX_XXX_FEATURE(DEFAULT_STATE) +# ----------------------------- +AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])]) +AC_DEFUN([DX_DOT_FEATURE], [AC_DEFUN([DX_FEATURE_dot], [$1])]) +AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])]) +AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])]) +AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])]) +AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])]) +AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])]) +AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) +AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) +AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])]) +AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])]) + +# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR], ...) +# -------------------------------------------------------------- +# PROJECT also serves as the base name for the documentation files. +# The default CONFIG-FILE is "$(srcdir)/Doxyfile" and OUTPUT-DOC-DIR is +# "doxygen-doc". +# More arguments are interpreted as interleaved CONFIG-FILE and +# OUTPUT-DOC-DIR values. +AC_DEFUN([DX_INIT_DOXYGEN], [ + +# Files: +AC_SUBST([DX_PROJECT], [$1]) +AC_SUBST([DX_CONFIG], ['ifelse([$2], [], [$(srcdir)/Doxyfile], [$2])']) +AC_SUBST([DX_DOCDIR], ['ifelse([$3], [], [doxygen-doc], [$3])']) +m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 4, m4_count($@), 2, + [AC_SUBST([DX_CONFIG]m4_eval(DX_i[/2]), + 'm4_default_nblank_quoted(m4_argn(DX_i, $@), + [$(srcdir)/Doxyfile])')])])dnl +m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 5, m4_count($@,), 2, + [AC_SUBST([DX_DOCDIR]m4_eval([(]DX_i[-1)/2]), + 'm4_default_nblank_quoted(m4_argn(DX_i, $@), + [doxygen-doc])')])])dnl +m4_define([DX_loop], m4_dquote(m4_if(m4_eval(3 < m4_count($@)), 1, + [m4_for([DX_i], 4, m4_count($@), 2, [, m4_eval(DX_i[/2])])], + [])))dnl + +# Environment variables used inside doxygen.cfg: +DX_ENV_APPEND(SRCDIR, $srcdir) +DX_ENV_APPEND(PROJECT, $DX_PROJECT) +DX_ENV_APPEND(VERSION, $PACKAGE_VERSION) + +# Doxygen itself: +DX_ARG_ABLE(doc, [generate any doxygen documentation], + [], + [], + [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen) + DX_REQUIRE_PROG([DX_PERL], perl)], + [DX_ENV_APPEND(PERL_PATH, $DX_PERL)]) + +# Dot for graphics: +DX_ARG_ABLE(dot, [generate graphics for doxygen documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [DX_REQUIRE_PROG([DX_DOT], dot)], + [DX_ENV_APPEND(HAVE_DOT, YES) + DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])], + [DX_ENV_APPEND(HAVE_DOT, NO)]) + +# Man pages generation: +DX_ARG_ABLE(man, [generate doxygen manual pages], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [], + [DX_ENV_APPEND(GENERATE_MAN, YES)], + [DX_ENV_APPEND(GENERATE_MAN, NO)]) + +# RTF file generation: +DX_ARG_ABLE(rtf, [generate doxygen RTF documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [], + [DX_ENV_APPEND(GENERATE_RTF, YES)], + [DX_ENV_APPEND(GENERATE_RTF, NO)]) + +# XML file generation: +DX_ARG_ABLE(xml, [generate doxygen XML documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [], + [DX_ENV_APPEND(GENERATE_XML, YES)], + [DX_ENV_APPEND(GENERATE_XML, NO)]) + +# (Compressed) HTML help generation: +DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [DX_REQUIRE_PROG([DX_HHC], hhc)], + [DX_ENV_APPEND(HHC_PATH, $DX_HHC) + DX_ENV_APPEND(GENERATE_HTML, YES) + DX_ENV_APPEND(GENERATE_HTMLHELP, YES)], + [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)]) + +# Seperate CHI file generation. +DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file], + [DX_CHECK_DEPEND(chm, 1)], + [DX_CLEAR_DEPEND(chm, 1)], + [], + [DX_ENV_APPEND(GENERATE_CHI, YES)], + [DX_ENV_APPEND(GENERATE_CHI, NO)]) + +# Plain HTML pages generation: +DX_ARG_ABLE(html, [generate doxygen plain HTML documentation], + [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)], + [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)], + [], + [DX_ENV_APPEND(GENERATE_HTML, YES)], + [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)]) + +# PostScript file generation: +DX_ARG_ABLE(ps, [generate doxygen PostScript documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [DX_REQUIRE_PROG([DX_LATEX], latex) + DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) + DX_REQUIRE_PROG([DX_DVIPS], dvips) + DX_REQUIRE_PROG([DX_EGREP], egrep)]) + +# PDF file generation: +DX_ARG_ABLE(pdf, [generate doxygen PDF documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex) + DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) + DX_REQUIRE_PROG([DX_EGREP], egrep)]) + +# LaTeX generation for PS and/or PDF: +if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then + DX_ENV_APPEND(GENERATE_LATEX, YES) +else + DX_ENV_APPEND(GENERATE_LATEX, NO) +fi + +# Paper size for PS and/or PDF: +AC_ARG_VAR(DOXYGEN_PAPER_SIZE, + [a4wide (default), a4, letter, legal or executive]) +case "$DOXYGEN_PAPER_SIZE" in +#( +"") + AC_SUBST(DOXYGEN_PAPER_SIZE, "") +;; #( +a4wide|a4|letter|legal|executive) + DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE) +;; #( +*) + AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE']) +;; +esac + +# Rules: +AS_IF([[test $DX_FLAG_html -eq 1]], +[[DX_SNIPPET_html="## ------------------------------- ## +## Rules specific for HTML output. ## +## ------------------------------- ## + +DX_CLEAN_HTML = \$(DX_DOCDIR)/html]dnl +m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ + \$(DX_DOCDIR]DX_i[)/html]])[ + +"]], +[[DX_SNIPPET_html=""]]) +AS_IF([[test $DX_FLAG_chi -eq 1]], +[[DX_SNIPPET_chi=" +DX_CLEAN_CHI = \$(DX_DOCDIR)/\$(PACKAGE).chi]dnl +m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ + \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).chi]])["]], +[[DX_SNIPPET_chi=""]]) +AS_IF([[test $DX_FLAG_chm -eq 1]], +[[DX_SNIPPET_chm="## ------------------------------ ## +## Rules specific for CHM output. ## +## ------------------------------ ## + +DX_CLEAN_CHM = \$(DX_DOCDIR)/chm]dnl +m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ + \$(DX_DOCDIR]DX_i[)/chm]])[\ +${DX_SNIPPET_chi} + +"]], +[[DX_SNIPPET_chm=""]]) +AS_IF([[test $DX_FLAG_man -eq 1]], +[[DX_SNIPPET_man="## ------------------------------ ## +## Rules specific for MAN output. ## +## ------------------------------ ## + +DX_CLEAN_MAN = \$(DX_DOCDIR)/man]dnl +m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ + \$(DX_DOCDIR]DX_i[)/man]])[ + +"]], +[[DX_SNIPPET_man=""]]) +AS_IF([[test $DX_FLAG_rtf -eq 1]], +[[DX_SNIPPET_rtf="## ------------------------------ ## +## Rules specific for RTF output. ## +## ------------------------------ ## + +DX_CLEAN_RTF = \$(DX_DOCDIR)/rtf]dnl +m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ + \$(DX_DOCDIR]DX_i[)/rtf]])[ + +"]], +[[DX_SNIPPET_rtf=""]]) +AS_IF([[test $DX_FLAG_xml -eq 1]], +[[DX_SNIPPET_xml="## ------------------------------ ## +## Rules specific for XML output. ## +## ------------------------------ ## + +DX_CLEAN_XML = \$(DX_DOCDIR)/xml]dnl +m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ + \$(DX_DOCDIR]DX_i[)/xml]])[ + +"]], +[[DX_SNIPPET_xml=""]]) +AS_IF([[test $DX_FLAG_ps -eq 1]], +[[DX_SNIPPET_ps="## ----------------------------- ## +## Rules specific for PS output. ## +## ----------------------------- ## + +DX_CLEAN_PS = \$(DX_DOCDIR)/\$(PACKAGE).ps]dnl +m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ + \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps]])[ + +DX_PS_GOAL = doxygen-ps + +doxygen-ps: \$(DX_CLEAN_PS) + +]m4_foreach([DX_i], [DX_loop], +[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag + \$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\ + rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\ + \$(DX_LATEX) refman.tex; \\ + \$(DX_MAKEINDEX) refman.idx; \\ + \$(DX_LATEX) refman.tex; \\ + countdown=5; \\ + while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\ + refman.log > /dev/null 2>&1 \\ + && test \$\$countdown -gt 0; do \\ + \$(DX_LATEX) refman.tex; \\ + countdown=\`expr \$\$countdown - 1\`; \\ + done; \\ + \$(DX_DVIPS) -o ../\$(PACKAGE).ps refman.dvi + +]])["]], +[[DX_SNIPPET_ps=""]]) +AS_IF([[test $DX_FLAG_pdf -eq 1]], +[[DX_SNIPPET_pdf="## ------------------------------ ## +## Rules specific for PDF output. ## +## ------------------------------ ## + +DX_CLEAN_PDF = \$(DX_DOCDIR)/\$(PACKAGE).pdf]dnl +m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ + \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf]])[ + +DX_PDF_GOAL = doxygen-pdf + +doxygen-pdf: \$(DX_CLEAN_PDF) + +]m4_foreach([DX_i], [DX_loop], +[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag + \$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\ + rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\ + \$(DX_PDFLATEX) refman.tex; \\ + \$(DX_MAKEINDEX) refman.idx; \\ + \$(DX_PDFLATEX) refman.tex; \\ + countdown=5; \\ + while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\ + refman.log > /dev/null 2>&1 \\ + && test \$\$countdown -gt 0; do \\ + \$(DX_PDFLATEX) refman.tex; \\ + countdown=\`expr \$\$countdown - 1\`; \\ + done; \\ + mv refman.pdf ../\$(PACKAGE).pdf + +]])["]], +[[DX_SNIPPET_pdf=""]]) +AS_IF([[test $DX_FLAG_ps -eq 1 -o $DX_FLAG_pdf -eq 1]], +[[DX_SNIPPET_latex="## ------------------------------------------------- ## +## Rules specific for LaTeX (shared for PS and PDF). ## +## ------------------------------------------------- ## + +DX_V_LATEX = \$(_DX_v_LATEX_\$(V)) +_DX_v_LATEX_ = \$(_DX_v_LATEX_\$(AM_DEFAULT_VERBOSITY)) +_DX_v_LATEX_0 = @echo \" LATEX \" \$][@; + +DX_CLEAN_LATEX = \$(DX_DOCDIR)/latex]dnl +m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ + \$(DX_DOCDIR]DX_i[)/latex]])[ + +"]], +[[DX_SNIPPET_latex=""]]) + +AS_IF([[test $DX_FLAG_doc -eq 1]], +[[DX_SNIPPET_doc="## --------------------------------- ## +## Format-independent Doxygen rules. ## +## --------------------------------- ## + +${DX_SNIPPET_html}\ +${DX_SNIPPET_chm}\ +${DX_SNIPPET_man}\ +${DX_SNIPPET_rtf}\ +${DX_SNIPPET_xml}\ +${DX_SNIPPET_ps}\ +${DX_SNIPPET_pdf}\ +${DX_SNIPPET_latex}\ +DX_V_DXGEN = \$(_DX_v_DXGEN_\$(V)) +_DX_v_DXGEN_ = \$(_DX_v_DXGEN_\$(AM_DEFAULT_VERBOSITY)) +_DX_v_DXGEN_0 = @echo \" DXGEN \" \$<; + +.PHONY: doxygen-run doxygen-doc \$(DX_PS_GOAL) \$(DX_PDF_GOAL) + +.INTERMEDIATE: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL) + +doxygen-run:]m4_foreach([DX_i], [DX_loop], + [[ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag]])[ + +doxygen-doc: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL) + +]m4_foreach([DX_i], [DX_loop], +[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag: \$(DX_CONFIG]DX_i[) \$(pkginclude_HEADERS) + \$(A""M_V_at)rm -rf \$(DX_DOCDIR]DX_i[) + \$(DX_V_DXGEN)\$(DX_ENV) DOCDIR=\$(DX_DOCDIR]DX_i[) \$(DX_DOXYGEN) \$(DX_CONFIG]DX_i[) + \$(A""M_V_at)echo Timestamp >\$][@ + +]])dnl +[DX_CLEANFILES = \\] +m4_foreach([DX_i], [DX_loop], +[[ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag \\ +]])dnl +[ -r \\ + \$(DX_CLEAN_HTML) \\ + \$(DX_CLEAN_CHM) \\ + \$(DX_CLEAN_CHI) \\ + \$(DX_CLEAN_MAN) \\ + \$(DX_CLEAN_RTF) \\ + \$(DX_CLEAN_XML) \\ + \$(DX_CLEAN_PS) \\ + \$(DX_CLEAN_PDF) \\ + \$(DX_CLEAN_LATEX)"]], +[[DX_SNIPPET_doc=""]]) +AC_SUBST([DX_RULES], +["${DX_SNIPPET_doc}"])dnl +AM_SUBST_NOTMAKE([DX_RULES]) + +#For debugging: +#echo DX_FLAG_doc=$DX_FLAG_doc +#echo DX_FLAG_dot=$DX_FLAG_dot +#echo DX_FLAG_man=$DX_FLAG_man +#echo DX_FLAG_html=$DX_FLAG_html +#echo DX_FLAG_chm=$DX_FLAG_chm +#echo DX_FLAG_chi=$DX_FLAG_chi +#echo DX_FLAG_rtf=$DX_FLAG_rtf +#echo DX_FLAG_xml=$DX_FLAG_xml +#echo DX_FLAG_pdf=$DX_FLAG_pdf +#echo DX_FLAG_ps=$DX_FLAG_ps +#echo DX_ENV=$DX_ENV +]) diff --git a/m4/ax_restore_flags.m4 b/m4/ax_restore_flags.m4 new file mode 100644 index 0000000..cf03cae --- /dev/null +++ b/m4/ax_restore_flags.m4 @@ -0,0 +1,31 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_restore_flags.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_RESTORE_FLAGS() +# +# DESCRIPTION +# +# Restore common compilation flags from temporary variables +# +# LICENSE +# +# Copyright (c) 2009 Filippo Giunchedi +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 3 + +AC_DEFUN([AX_RESTORE_FLAGS], [ + CPPFLAGS="${CPPFLAGS_save}" + CFLAGS="${CFLAGS_save}" + CXXFLAGS="${CXXFLAGS_save}" + OBJCFLAGS="${OBJCFLAGS_save}" + LDFLAGS="${LDFLAGS_save}" + LIBS="${LIBS_save}" +]) diff --git a/m4/ax_save_flags.m4 b/m4/ax_save_flags.m4 new file mode 100644 index 0000000..d2a0542 --- /dev/null +++ b/m4/ax_save_flags.m4 @@ -0,0 +1,31 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_save_flags.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_SAVE_FLAGS() +# +# DESCRIPTION +# +# Save common compilation flags into temporary variables +# +# LICENSE +# +# Copyright (c) 2009 Filippo Giunchedi +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 3 + +AC_DEFUN([AX_SAVE_FLAGS], [ + CPPFLAGS_save="${CPPFLAGS}" + CFLAGS_save="${CFLAGS}" + CXXFLAGS_save="${CXXFLAGS}" + OBJCFLAGS_save="${OBJCFLAGS}" + LDFLAGS_save="${LDFLAGS}" + LIBS_save="${LIBS}" +]) diff --git a/openflow_mapping/l2.py b/openflow_mapping/l2.py new file mode 100644 index 0000000..f2981f3 --- /dev/null +++ b/openflow_mapping/l2.py @@ -0,0 +1,12 @@ +from mapping_common import * + +openflow_tables = { + "dmac": OFTable( + match_fields = { + "ingress_metadata_bd": OFMatchField(field="OFPXMT_OFB_VLAN_VID"), + "l2_metadata_lkp_mac_da" : OFMatchField(field="OFPXMT_OFB_ETH_DST") + }, + + id = 0 + ) +} diff --git a/openflow_mapping/mapping_common.py b/openflow_mapping/mapping_common.py new file mode 100644 index 0000000..637b02f --- /dev/null +++ b/openflow_mapping/mapping_common.py @@ -0,0 +1,10 @@ +class OFTable(): + def __init__(self, match_fields, id): + self.match_fields = match_fields + self.id = id + +class OFMatchField(): + def __init__(self, field, match_type="exact", val=None): + self.field = field + self.match_type = match_type + self.testval = val diff --git a/p4src/LICENSE b/p4src/LICENSE new file mode 100644 index 0000000..ddcb230 --- /dev/null +++ b/p4src/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/p4src/acl.p4 b/p4src/acl.p4 index 5897d37..0327690 100644 --- a/p4src/acl.p4 +++ b/p4src/acl.p4 @@ -34,6 +34,12 @@ header_type acl_metadata_t { if_label : 16; /* if label for acls */ bd_label : 16; /* bd label for acls */ acl_stats_index : 14; /* acl stats index */ + egress_if_label : 16; /* if label for egress acls */ + egress_bd_label : 16; /* bd label for egress acls */ + ingress_src_port_range_id : 8; /* ingress src port range id */ + ingress_dst_port_range_id : 8; /* ingress dst port range id */ + egress_src_port_range_id : 8; /* egress src port range id */ + egress_dst_port_range_id : 8; /* egress dst port range id */ } } @@ -47,6 +53,125 @@ header_type i2e_metadata_t { metadata acl_metadata_t acl_metadata; metadata i2e_metadata_t i2e_metadata; +/*****************************************************************************/ +/* Egress ACL l4 port range */ +/*****************************************************************************/ +#ifdef EGRESS_ACL_ENABLE +action set_egress_tcp_port_fields() { + modify_field(l3_metadata.egress_l4_sport, tcp.srcPort); + modify_field(l3_metadata.egress_l4_dport, tcp.dstPort); +} + +action set_egress_udp_port_fields() { + modify_field(l3_metadata.egress_l4_sport, udp.srcPort); + modify_field(l3_metadata.egress_l4_dport, udp.dstPort); +} + +action set_egress_icmp_port_fields() { + modify_field(l3_metadata.egress_l4_sport, icmp.typeCode); +} + +table egress_l4port_fields { + reads { + tcp : valid; + udp : valid; + icmp : valid; + } + actions { + nop; + set_egress_tcp_port_fields; + set_egress_udp_port_fields; + set_egress_icmp_port_fields; + } + size: EGRESS_PORT_LKP_FIELD_SIZE; +} + +#ifndef ACL_RANGE_DISABLE +action set_egress_src_port_range_id(range_id) { + modify_field(acl_metadata.egress_src_port_range_id, range_id); +} + +table egress_l4_src_port { + reads { + l3_metadata.egress_l4_sport : range; + } + actions { + nop; + set_egress_src_port_range_id; + } + size: EGRESS_ACL_RANGE_TABLE_SIZE; +} + +action set_egress_dst_port_range_id(range_id) { + modify_field(acl_metadata.egress_dst_port_range_id, range_id); +} + +table egress_l4_dst_port { + reads { + l3_metadata.egress_l4_dport : range; + } + actions { + nop; + set_egress_dst_port_range_id; + } + size: EGRESS_ACL_RANGE_TABLE_SIZE; +} + +#endif /* ACL_RANGE_DISABLE */ +#endif /* EGRESS_ACL_ENABLE */ + +control process_egress_l4port { +#ifdef EGRESS_ACL_ENABLE + apply(egress_l4port_fields); +#ifndef ACL_RANGE_DISABLE + apply(egress_l4_src_port); + apply(egress_l4_dst_port); +#endif /* ACL_RANGE_DISABLE */ +#endif /* EGRESS_ACL_ENABLE */ +} + +/*****************************************************************************/ +/* Ingress ACL l4 port range */ +/*****************************************************************************/ +#ifndef ACL_RANGE_DISABLE +action set_ingress_src_port_range_id(range_id) { + modify_field(acl_metadata.ingress_src_port_range_id, range_id); +} + +table ingress_l4_src_port { + reads { + l3_metadata.lkp_l4_sport : range; + } + actions { + nop; + set_ingress_src_port_range_id; + } + size: INGRESS_ACL_RANGE_TABLE_SIZE; +} + +action set_ingress_dst_port_range_id(range_id) { + modify_field(acl_metadata.ingress_dst_port_range_id, range_id); +} + +table ingress_l4_dst_port { + reads { + l3_metadata.lkp_l4_dport : range; + } + actions { + nop; + set_ingress_dst_port_range_id; + } + size: INGRESS_ACL_RANGE_TABLE_SIZE; +} +#endif /* ACL_RANGE_DISABLE */ + +control process_ingress_l4port { +#ifndef ACL_RANGE_DISABLE + apply(ingress_l4_src_port); + apply(ingress_l4_dst_port); +#endif /* ACL_RANGE_DISABLE */ +} + /*****************************************************************************/ /* ACL Actions */ /*****************************************************************************/ @@ -185,8 +310,8 @@ table ip_acl { ipv4_metadata.lkp_ipv4_sa : ternary; ipv4_metadata.lkp_ipv4_da : ternary; l3_metadata.lkp_ip_proto : ternary; - l3_metadata.lkp_l4_sport : ternary; - l3_metadata.lkp_l4_dport : ternary; + acl_metadata.ingress_src_port_range_id : exact; + acl_metadata.ingress_dst_port_range_id : exact; tcp.flags : ternary; l3_metadata.lkp_ip_ttl : ternary; @@ -218,8 +343,8 @@ table ipv6_acl { ipv6_metadata.lkp_ipv6_sa : ternary; ipv6_metadata.lkp_ipv6_da : ternary; l3_metadata.lkp_ip_proto : ternary; - l3_metadata.lkp_l4_sport : ternary; - l3_metadata.lkp_l4_dport : ternary; + acl_metadata.ingress_src_port_range_id : exact; + acl_metadata.ingress_dst_port_range_id : exact; tcp.flags : ternary; l3_metadata.lkp_ip_ttl : ternary; @@ -326,8 +451,8 @@ table ipv4_racl { ipv4_metadata.lkp_ipv4_sa : ternary; ipv4_metadata.lkp_ipv4_da : ternary; l3_metadata.lkp_ip_proto : ternary; - l3_metadata.lkp_l4_sport : ternary; - l3_metadata.lkp_l4_dport : ternary; + acl_metadata.ingress_src_port_range_id : exact; + acl_metadata.ingress_dst_port_range_id : exact; } actions { nop; @@ -346,7 +471,6 @@ control process_ipv4_racl { #endif /* IPV4_DISABLE */ } - /*****************************************************************************/ /* IPv6 RACL */ /*****************************************************************************/ @@ -358,8 +482,8 @@ table ipv6_racl { ipv6_metadata.lkp_ipv6_sa : ternary; ipv6_metadata.lkp_ipv6_da : ternary; l3_metadata.lkp_ip_proto : ternary; - l3_metadata.lkp_l4_sport : ternary; - l3_metadata.lkp_l4_dport : ternary; + acl_metadata.ingress_src_port_range_id : exact; + acl_metadata.ingress_dst_port_range_id : exact; } actions { nop; @@ -567,6 +691,112 @@ control process_system_acl { /*****************************************************************************/ /* Egress ACL */ /*****************************************************************************/ + +#ifdef EGRESS_ACL_ENABLE + +/*****************************************************************************/ +/* Egress ACL Actions */ +/*****************************************************************************/ +action egress_acl_deny(acl_copy_reason) { + modify_field(acl_metadata.acl_deny, TRUE); + modify_field(fabric_metadata.reason_code, acl_copy_reason); +} + +action egress_acl_permit(acl_copy_reason) { + modify_field(fabric_metadata.reason_code, acl_copy_reason); +} + +/*****************************************************************************/ +/* Egress Mac ACL */ +/*****************************************************************************/ + +#ifndef L2_DISABLE +table egress_mac_acl { + reads { + acl_metadata.egress_if_label : ternary; + acl_metadata.egress_bd_label : ternary; + + ethernet.srcAddr : ternary; + ethernet.dstAddr : ternary; + ethernet.etherType: ternary; + } + actions { + nop; + egress_acl_deny; + egress_acl_permit; + } + size : EGRESS_MAC_ACL_TABLE_SIZE; +} +#endif /* L2_DISABLE */ + +/*****************************************************************************/ +/* Egress IPv4 ACL */ +/*****************************************************************************/ +#ifndef IPV4_DISABLE +table egress_ip_acl { + reads { + acl_metadata.egress_if_label : ternary; + acl_metadata.egress_bd_label : ternary; + + ipv4.srcAddr : ternary; + ipv4.dstAddr : ternary; + ipv4.protocol : ternary; + acl_metadata.egress_src_port_range_id : exact; + acl_metadata.egress_dst_port_range_id : exact; + } + actions { + nop; + egress_acl_deny; + egress_acl_permit; + } + size : EGRESS_IP_ACL_TABLE_SIZE; +} +#endif /* IPV4_DISABLE */ + +/*****************************************************************************/ +/* Egress IPv6 ACL */ +/*****************************************************************************/ +#ifndef IPV6_DISABLE +table egress_ipv6_acl { + reads { + acl_metadata.egress_if_label : ternary; + acl_metadata.egress_bd_label : ternary; + + ipv6.srcAddr : ternary; + ipv6.dstAddr : ternary; + ipv6.nextHdr : ternary; + acl_metadata.egress_src_port_range_id : exact; + acl_metadata.egress_dst_port_range_id : exact; + } + actions { + nop; + egress_acl_deny; + egress_acl_permit; + } + size : EGRESS_IPV6_ACL_TABLE_SIZE; +} + +#endif /* IPV6_DISABLE */ +#endif /* EGRESS_ACL_ENABLE */ + +control process_egress_acl { +#ifdef EGRESS_ACL_ENABLE + if (valid(ipv4)) { +#ifndef IPV4_DISABLE + apply(egress_ip_acl); +#endif /* IPV4_DISABLE */ + } else { + if (valid(ipv6)) { +#ifndef IPV6_DISABLE + apply(egress_ipv6_acl); +#endif /* IPV6_DISABLE */ + } else { + apply(egress_mac_acl); + } + } +#endif /* EGRESS_ACL_ENABLE */ +} + action egress_mirror(session_id) { modify_field(i2e_metadata.mirror_session_id, session_id); clone_egress_pkt_to_egress(session_id, e2e_mirror_info); @@ -577,33 +807,47 @@ action egress_mirror_drop(session_id) { drop(); } -action egress_redirect_to_cpu(reason_code) { - egress_copy_to_cpu(reason_code); +action egress_copy_to_cpu() { + clone_egress_pkt_to_egress(CPU_MIRROR_SESSION_ID, cpu_info); +} + +action egress_redirect_to_cpu() { + egress_copy_to_cpu(); drop(); } -action egress_copy_to_cpu(reason_code) { +action egress_copy_to_cpu_with_reason(reason_code) { modify_field(fabric_metadata.reason_code, reason_code); - clone_egress_pkt_to_egress(CPU_MIRROR_SESSION_ID, cpu_info); + egress_copy_to_cpu(); } -table egress_acl { +action egress_redirect_to_cpu_with_reason(reason_code) { + egress_copy_to_cpu_with_reason(reason_code); + drop(); +} +table egress_system_acl { reads { + fabric_metadata.reason_code : ternary; standard_metadata.egress_port : ternary; intrinsic_metadata.deflection_flag : ternary; l3_metadata.l3_mtu_check : ternary; + acl_metadata.acl_deny : ternary; } actions { nop; + drop_packet; + egress_copy_to_cpu; + egress_redirect_to_cpu; + egress_copy_to_cpu_with_reason; + egress_redirect_to_cpu_with_reason; egress_mirror; egress_mirror_drop; - egress_redirect_to_cpu; } size : EGRESS_ACL_TABLE_SIZE; } -control process_egress_acl { +control process_egress_system_acl { if (egress_metadata.bypass == FALSE) { - apply(egress_acl); + apply(egress_system_acl); } } diff --git a/p4src/fabric.p4 b/p4src/fabric.p4 index 478c5b6..c3880af 100644 --- a/p4src/fabric.p4 +++ b/p4src/fabric.p4 @@ -40,6 +40,7 @@ action terminate_cpu_packet() { modify_field(standard_metadata.egress_spec, fabric_header.dstPortOrGroup); modify_field(egress_metadata.bypass, fabric_header_cpu.txBypass); + modify_field(intrinsic_metadata.mcast_grp, fabric_header_cpu.mcast_grp); modify_field(ethernet.etherType, fabric_payload_header.etherType); remove_header(fabric_header); diff --git a/p4src/includes/drop_reasons.h b/p4src/includes/drop_reasons.h deleted file mode 100644 index 38ce55c..0000000 --- a/p4src/includes/drop_reasons.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright 2013-present Barefoot Networks, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#define DROP_UNKNOWN 0 - -#define DROP_OUTER_SRC_MAC_ZERO 10 -#define DROP_OUTER_SRC_MAC_MULTICAST 11 -#define DROP_OUTER_DST_MAC_ZERO 12 -#define DROP_OUTER_ETHERNET_MISS 13 -#define DROP_SRC_MAC_ZERO 14 -#define DROP_SRC_MAC_MULTICAST 15 -#define DROP_DST_MAC_ZERO 16 - -#define DROP_OUTER_IP_VERSION_INVALID 25 -#define DROP_OUTER_IP_TTL_ZERO 26 -#define DROP_OUTER_IP_SRC_MULTICAST 27 -#define DROP_OUTER_IP_SRC_LOOPBACK 28 -#define DROP_OUTER_IP_MISS 29 -#define DROP_IP_VERSION_INVALID 30 -#define DROP_IP_TTL_ZERO 31 -#define DROP_IP_SRC_MULTICAST 32 -#define DROP_IP_SRC_LOOPBACK 33 - -#define DROP_PORT_VLAN_MAPPING_MISS 40 -#define DROP_STP_STATE_LEARNING 41 -#define DROP_STP_STATE_BLOCKING 42 -#define DROP_SAME_IFINDEX 43 -#define DROP_MULTICAST_SNOOPING_ENABLED 44 - -#define DROP_ACL_DENY 60 -#define DROP_RACL_DENY 61 -#define DROP_URPF_CHECK_FAIL 62 -#define DROP_IPSG_MISS 63 -#define DROP_IFINDEX 64 - -/* - * other reason codes shared between P4 program and APIs - * Must match the definitions in switch_hostif.h file - */ - -#define CPU_REASON_CODE_SFLOW 0x4 -#define CPU_REASON_CODE_L3_REDIRECT 0x217 diff --git a/p4src/includes/headers.p4 b/p4src/includes/headers.p4 index a0947d6..55b330f 100644 --- a/p4src/includes/headers.p4 +++ b/p4src/includes/headers.p4 @@ -520,6 +520,7 @@ header_type fabric_header_cpu_t { ingressBd : 16; reasonCode : 16; + mcast_grp : 16; } } diff --git a/p4src/includes/p4_table_sizes.h b/p4src/includes/p4_table_sizes.h index 7879bf3..903968f 100644 --- a/p4src/includes/p4_table_sizes.h +++ b/p4src/includes/p4_table_sizes.h @@ -47,6 +47,9 @@ limitations under the License. #define INGRESS_MAC_ACL_TABLE_SIZE MIN_TCAM_TABLE_SIZE #define INGRESS_IP_ACL_TABLE_SIZE MIN_TCAM_TABLE_SIZE #define INGRESS_IPV6_ACL_TABLE_SIZE MIN_TCAM_TABLE_SIZE +#define EGRESS_MAC_ACL_TABLE_SIZE MIN_TCAM_TABLE_SIZE +#define EGRESS_IP_ACL_TABLE_SIZE MIN_TCAM_TABLE_SIZE +#define EGRESS_IPV6_ACL_TABLE_SIZE MIN_TCAM_TABLE_SIZE #define INGRESS_IP_RACL_TABLE_SIZE MIN_TCAM_TABLE_SIZE #define INGRESS_IPV6_RACL_TABLE_SIZE MIN_TCAM_TABLE_SIZE #define IP_NAT_TABLE_SIZE MIN_SRAM_TABLE_SIZE @@ -83,6 +86,8 @@ limitations under the License. #define SPANNING_TREE_TABLE_SIZE MIN_SRAM_TABLE_SIZE #define FABRIC_REWRITE_TABLE_SIZE MIN_TCAM_TABLE_SIZE #define EGRESS_ACL_TABLE_SIZE MIN_TCAM_TABLE_SIZE +#define INGRESS_ACL_RANGE_TABLE_SIZE MIN_TCAM_TABLE_SIZE +#define EGRESS_ACL_RANGE_TABLE_SIZE MIN_TCAM_TABLE_SIZE #define VLAN_DECAP_TABLE_SIZE MIN_SRAM_TABLE_SIZE #define TUNNEL_HEADER_TABLE_SIZE MIN_SRAM_TABLE_SIZE #define TUNNEL_REWRITE_TABLE_SIZE MIN_SRAM_TABLE_SIZE @@ -110,3 +115,5 @@ limitations under the License. #define PCP_TO_TC_AND_COLOR_TABLE_SIZE 64 #define COPP_TABLE_SIZE 128 + +#define EGRESS_PORT_LKP_FIELD_SIZE 4 diff --git a/p4src/includes/p4features.h b/p4src/includes/p4features.h index 978fcde..270a535 100644 --- a/p4src/includes/p4features.h +++ b/p4src/includes/p4features.h @@ -21,6 +21,8 @@ limitations under the License. #define OUTER_PIM_BIDIR_OPTIMIZATION #define PIM_BIDIR_OPTIMIZATION #define SFLOW_ENABLE +#define EGRESS_ACL_ENABLE +#define ACL_RANGE_DISABLE #ifdef MULTICAST_DISABLE #define L2_MULTICAST_DISABLE @@ -115,3 +117,11 @@ limitations under the License. #ifdef METER_DISABLE #define P4_METER_DISABLE #endif + +#ifdef EGRESS_ACL_ENABLE +#define P4_EGRESS_ACL_ENABLE +#endif + +#ifdef ACL_RANGE_DISABLE +#define P4_ACL_RANGE_DISABLE +#endif diff --git a/p4src/includes/parser.p4 b/p4src/includes/parser.p4 index 39f7c6f..50bf5a4 100644 --- a/p4src/includes/parser.p4 +++ b/p4src/includes/parser.p4 @@ -609,22 +609,7 @@ parser parse_erspan_t3 { return parse_inner_ethernet; } -#define ARP_PROTOTYPES_ARP_RARP_IPV4 0x0800 - -header arp_rarp_t arp_rarp; - parser parse_arp_rarp { - extract(arp_rarp); - return select(latest.protoType) { - ARP_PROTOTYPES_ARP_RARP_IPV4 : parse_arp_rarp_ipv4; - default: ingress; - } -} - -header arp_rarp_ipv4_t arp_rarp_ipv4; - -parser parse_arp_rarp_ipv4 { - extract(arp_rarp_ipv4); return parse_set_prio_med; } diff --git a/p4src/l2.p4 b/p4src/l2.p4 index 000c2bc..230ebbb 100644 --- a/p4src/l2.p4 +++ b/p4src/l2.p4 @@ -299,9 +299,10 @@ control process_egress_bd_stats { #endif /* STATS_DISABLE */ } -action set_egress_bd_properties(smac_idx, nat_mode) { +action set_egress_bd_properties(smac_idx, nat_mode, bd_label) { modify_field(egress_metadata.smac_idx, smac_idx); modify_field(nat_metadata.egress_nat_mode, nat_mode); + modify_field(acl_metadata.egress_bd_label, bd_label); } table egress_bd_map { diff --git a/p4src/l3.p4 b/p4src/l3.p4 index 807ca3d..c5b76b6 100644 --- a/p4src/l3.p4 +++ b/p4src/l3.p4 @@ -51,6 +51,9 @@ header_type l3_metadata_t { mtu_index : 8; /* index into mtu table */ l3_copy : 1; /* copy packet to CPU */ l3_mtu_check : 16 (saturating); /* result of mtu check */ + + egress_l4_sport : 16; + egress_l4_dport : 16; } } diff --git a/p4src/meter.p4 b/p4src/meter.p4 index ca8e400..e592cbd 100644 --- a/p4src/meter.p4 +++ b/p4src/meter.p4 @@ -1,18 +1,6 @@ /* -Copyright 2013-present Barefoot Networks, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ + * Meter processing + */ /* * Meter metadata diff --git a/p4src/openflow.p4 b/p4src/openflow.p4 index 66dd965..8b7cc57 100644 --- a/p4src/openflow.p4 +++ b/p4src/openflow.p4 @@ -23,9 +23,14 @@ limitations under the License. #define OPENFLOW_ENABLE_VLAN #define OPENFLOW_ENABLE_L3 -/* enables fabric header for non-switch.p4 targets */ +// adds some handy stuff from switch.p4 for packet in/out //#define OPENFLOW_PACKET_IN_OUT +#define ingress_input_port standard_metadata.ingress_port +#define ingress_egress_port standard_metadata.egress_spec +#define egress_egress_port standard_metadata.egress_port +#define intrinsic_mcast_grp intrinsic_metadata.mcast_grp + header_type openflow_metadata_t { fields { index : 32; @@ -41,10 +46,13 @@ metadata openflow_metadata_t openflow_metadata; #define CPU_PORT_ID 64 #endif +#define TRUE 1 + #ifdef OPENFLOW_PACKET_IN_OUT #define ETHERTYPE_BF_FABRIC 0x9000 -#define TRUE 1 +#define FABRIC_HEADER_TYPE_MULTICAST 2 +#define FABRIC_HEADER_TYPE_CPU 5 header_type fabric_header_t { fields { @@ -61,6 +69,20 @@ header_type fabric_header_t { } } +header_type fabric_header_multicast_t { + fields { + routed : 1; + outerRouted : 1; + tunnelTerminate : 1; + ingressTunnelType : 5; + + ingressIfindex : 16; + ingressBd : 16; + + mcastGrp : 16; + } +} + header_type fabric_header_cpu_t { fields { egressQueue : 5; @@ -83,26 +105,86 @@ header_type fabric_payload_header_t { header fabric_header_t fabric_header; header fabric_header_cpu_t fabric_header_cpu; +header fabric_header_multicast_t fabric_header_multicast; header fabric_payload_header_t fabric_payload_header; -parser fabric_header { + +parser parse_fabric_header { extract(fabric_header); + return select(latest.packetType) { + FABRIC_HEADER_TYPE_MULTICAST : parse_fabric_header_multicast; + FABRIC_HEADER_TYPE_CPU : parse_fabric_header_cpu; + default : ingress; + } +} + +parser parse_fabric_header_multicast { + extract(fabric_header_multicast); + return parse_fabric_payload_header; +} + +parser parse_fabric_header_cpu { extract(fabric_header_cpu); + return parse_fabric_payload_header; +} + +parser parse_fabric_payload_header { extract(fabric_payload_header); - return ingress; + return select(latest.etherType) { + // add more ethertypes here if you want + default: ingress; + } } action nop () { } +// remove the comments in "terminate_cpu_packet" and "terminate_fabric_multicast_packet" +// as necessary. I'm just assuming these features aren't used (Except copying the +// ethertype from the fabric payload header, that's necessary but I don't want to +// assume you've named your ethernet header "ethernet" :) ) + action terminate_cpu_packet() { - modify_field(ingress_egress_port,fabric_header.dstPortOrGroup); - modify_field(ethernet.etherType, fabric_payload_header.etherType); + modify_field(ingress_egress_port, + fabric_header.dstPortOrGroup); +// modify_field(egress_metadata.bypass, fabric_header_cpu.txBypass); + modify_field(ethernet.etherType, fabric_payload_header.etherType); remove_header(fabric_header); remove_header(fabric_header_cpu); remove_header(fabric_payload_header); } + +action terminate_fabric_multicast_packet() { +// modify_field(tunnel_metadata.tunnel_terminate, +// fabric_header_multicast.tunnelTerminate); +// modify_field(tunnel_metadata.ingress_tunnel_type, +// fabric_header_multicast.ingressTunnelType); +// modify_field(l3_metadata.nexthop_index, 0); +// modify_field(l3_metadata.routed, fabric_header_multicast.routed); +// modify_field(l3_metadata.outer_routed, +// fabric_header_multicast.outerRouted); + + modify_field(intrinsic_mcast_grp, + fabric_header_multicast.mcastGrp); + + modify_field(ethernet.etherType, fabric_payload_header.etherType); + remove_header(fabric_header); + remove_header(fabric_header_multicast); + remove_header(fabric_payload_header); +} + +table packet_out { + reads { + fabric_header.packetType : exact; + } + actions { + nop; + terminate_cpu_packet; + terminate_fabric_multicast_packet; + } +} + #endif /* OPENFLOW_PACKET_IN_OUT */ /**************************************************************** @@ -119,6 +201,16 @@ action openflow_apply(bmap, index, group_id) { } action openflow_miss(reason, table_id) { +#ifdef OPENFLOW_PACKET_IN_OUT + add_header(fabric_header); + add_header(fabric_header_cpu); + add_header(fabric_payload_header); + + modify_field(fabric_metadata.etherType, ethernet.etherType); + + modify_field(fabric_metadata.ingressPort, ingress_input_port); +#endif + modify_field(fabric_metadata.reason_code, reason); shift_left(fabric_metadata.reason_code, fabric_metadata.reason_code, 8); @@ -127,35 +219,6 @@ action openflow_miss(reason, table_id) { modify_field(ingress_egress_port, CPU_PORT_ID); } -/*************************************************************** - * Packet Out - ***************************************************************/ - -action packet_out_eth_flood() { - modify_field(intrinsic_metadata.mcast_grp, fabric_header.dstPortOrGroup); - terminate_cpu_packet(); - modify_field(openflow_metadata.ofvalid, TRUE); -} - -action packet_out_unicast() { - modify_field(ingress_egress_port, fabric_header.dstPortOrGroup); - terminate_cpu_packet(); - modify_field(openflow_metadata.ofvalid, TRUE); -} - -table packet_out { - reads { - fabric_header.packetType : exact; - fabric_header_cpu.reasonCode : exact; - } - - actions { - packet_out_eth_flood; - packet_out_unicast; - nop; - } -} - /**************************************************************** * Egress openflow bitmap translation ****************************************************************/ @@ -206,6 +269,7 @@ table ofpat_group_ingress { action ofpat_output(egress_port) { modify_field(ingress_egress_port, egress_port); +// for switch.p4 modify_field(ingress_metadata.egress_ifindex, 0); } diff --git a/p4src/p4_files.am b/p4src/p4_files.am new file mode 100644 index 0000000..3fee0b9 --- /dev/null +++ b/p4src/p4_files.am @@ -0,0 +1,29 @@ +p4_files = \ +$(top_srcdir)/p4src/acl.p4 \ +$(top_srcdir)/p4src/archdeps.p4 \ +$(top_srcdir)/p4src/egress_filter.p4 \ +$(top_srcdir)/p4src/fabric.p4 \ +$(top_srcdir)/p4src/hashes.p4 \ +$(top_srcdir)/p4src/int_transit.p4 \ +$(top_srcdir)/p4src/ipv4.p4 \ +$(top_srcdir)/p4src/ipv6.p4 \ +$(top_srcdir)/p4src/l2.p4 \ +$(top_srcdir)/p4src/l3.p4 \ +$(top_srcdir)/p4src/meter.p4 \ +$(top_srcdir)/p4src/mirror.p4 \ +$(top_srcdir)/p4src/multicast.p4 \ +$(top_srcdir)/p4src/nexthop.p4 \ +$(top_srcdir)/p4src/openflow.p4 \ +$(top_srcdir)/p4src/port.p4 \ +$(top_srcdir)/p4src/rewrite.p4 \ +$(top_srcdir)/p4src/security.p4 \ +$(top_srcdir)/p4src/switch_config.p4 \ +$(top_srcdir)/p4src/switch.p4 \ +$(top_srcdir)/p4src/tunnel.p4 \ +$(top_srcdir)/p4src/includes/defines.p4 \ +$(top_srcdir)/p4src/includes/drop_reasons.h \ +$(top_srcdir)/p4src/includes/headers.p4 \ +$(top_srcdir)/p4src/includes/intrinsic.p4 \ +$(top_srcdir)/p4src/includes/p4features.h \ +$(top_srcdir)/p4src/includes/parser.p4 \ +$(top_srcdir)/p4src/includes/sizes.p4 diff --git a/p4src/port.p4 b/p4src/port.p4 index b083ddb..61d3767 100644 --- a/p4src/port.p4 +++ b/p4src/port.p4 @@ -354,10 +354,11 @@ control process_lag { /*****************************************************************************/ /* Egress port lookup */ /*****************************************************************************/ -action egress_port_type_normal(ifindex, qos_group) { +action egress_port_type_normal(ifindex, qos_group, if_label) { modify_field(egress_metadata.port_type, PORT_TYPE_NORMAL); modify_field(egress_metadata.ifindex, ifindex); modify_field(qos_metadata.egress_qos_group, qos_group); + modify_field(acl_metadata.egress_if_label, if_label); } action egress_port_type_fabric(ifindex) { diff --git a/p4src/switch.p4 b/p4src/switch.p4 index 4fcdd72..a2db625 100644 --- a/p4src/switch.p4 +++ b/p4src/switch.p4 @@ -139,10 +139,12 @@ control ingress { #ifndef MPLS_DISABLE if (not (valid(mpls[0]) and (l3_metadata.fib_hit == TRUE))) { #endif /* MPLS_DISABLE */ - /* validate packet */ process_validate_packet(); + /* perform ingress l4 port range */ + process_ingress_l4port(); + /* l2 lookups */ process_mac(); @@ -292,10 +294,16 @@ control egress { process_egress_bd_stats(); } } - + + /* perform egress l4 port range */ + process_egress_l4port(); + /* perform tunnel encap */ process_tunnel_encap(); + /* egress acl */ + process_egress_acl(); + /* update underlay header based on INT information inserted */ process_int_outer_encap(); @@ -309,7 +317,7 @@ control egress { } /* apply egress acl */ - process_egress_acl(); + process_egress_system_acl(); #ifdef OPENFLOW_ENABLE } #endif /* OPENFLOW_ENABLE */ diff --git a/p4src/tunnel.p4 b/p4src/tunnel.p4 index 58ef42b..ed042cf 100644 --- a/p4src/tunnel.p4 +++ b/p4src/tunnel.p4 @@ -599,6 +599,7 @@ action decap_vxlan_inner_non_ip() { remove_header(vxlan); remove_header(ipv4); remove_header(ipv6); + remove_header(inner_ethernet); } action decap_genv_inner_ipv4() { @@ -624,6 +625,7 @@ action decap_genv_inner_non_ip() { remove_header(genv); remove_header(ipv4); remove_header(ipv6); + remove_header(inner_ethernet); } #ifndef NVGRE_DISABLE @@ -653,6 +655,7 @@ action decap_nvgre_inner_non_ip() { remove_header(gre); remove_header(ipv4); remove_header(ipv6); + remove_header(inner_ethernet); } #endif @@ -1047,6 +1050,8 @@ action f_insert_vxlan_header() { modify_field(udp.srcPort, hash_metadata.entropy_hash); modify_field(udp.dstPort, UDP_PORT_VXLAN); + modify_field(l3_metadata.egress_l4_sport, hash_metadata.entropy_hash); + modify_field(l3_metadata.egress_l4_dport, UDP_PORT_VXLAN); modify_field(udp.checksum, 0); add(udp.length_, egress_metadata.payload_length, 30); @@ -1077,6 +1082,8 @@ action f_insert_genv_header() { modify_field(udp.srcPort, hash_metadata.entropy_hash); modify_field(udp.dstPort, UDP_PORT_GENV); + modify_field(l3_metadata.egress_l4_sport, hash_metadata.entropy_hash); + modify_field(l3_metadata.egress_l4_dport, UDP_PORT_GENV); modify_field(udp.checksum, 0); add(udp.length_, egress_metadata.payload_length, 30); diff --git a/switchapi/Doxyfile b/switchapi/Doxyfile index 550f2c5..5f82571 100644 --- a/switchapi/Doxyfile +++ b/switchapi/Doxyfile @@ -653,7 +653,7 @@ WARN_LOGFILE = # with spaces. INPUT = switchapi/main.dox \ - switchapi/inc/switchapi + switchapi/include/switchapi # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is diff --git a/switchapi/include/switchapi/switch_acl.h b/switchapi/include/switchapi/switch_acl.h index 8b2d682..e6bec99 100644 --- a/switchapi/include/switchapi/switch_acl.h +++ b/switchapi/include/switchapi/switch_acl.h @@ -46,66 +46,66 @@ typedef enum switch_acl_type_ { /** Acl IP field enum */ typedef enum switch_acl_ip_field_ { - SWITCH_ACL_IP_FIELD_IPV4_SRC, /**< IPv4 Source address */ - SWITCH_ACL_IP_FIELD_IPV4_DEST, /**< IPv4 Dest address */ - SWITCH_ACL_IP_FIELD_IP_PROTO, /**< IP Protocol */ - SWITCH_ACL_IP_FIELD_L4_SOURCE_PORT, /**< L4 source port UDP/TCP */ - SWITCH_ACL_IP_FIELD_L4_DEST_PORT, /**< L4 dest port UDP/TCP */ - SWITCH_ACL_IP_FIELD_ICMP_TYPE, /**< ICMP type */ - SWITCH_ACL_IP_FIELD_ICMP_CODE, /**< ICMP code */ - SWITCH_ACL_IP_FIELD_TCP_FLAGS, /**< TCP flags */ - SWITCH_ACL_IP_FIELD_TTL, /**< TTL */ - SWITCH_ACL_IP_FIELD_IP_FLAGS, /**< IP flags */ - SWITCH_ACL_IP_FIELD_IP_FRAGMENT, /**< IP FRAG */ + SWITCH_ACL_IP_FIELD_IPV4_SRC, /**< IPv4 Source address */ + SWITCH_ACL_IP_FIELD_IPV4_DEST, /**< IPv4 Dest address */ + SWITCH_ACL_IP_FIELD_IP_PROTO, /**< IP Protocol */ + SWITCH_ACL_IP_FIELD_L4_SOURCE_PORT_RANGE, /**< L4 source port UDP/TCP */ + SWITCH_ACL_IP_FIELD_L4_DEST_PORT_RANGE, /**< L4 dest port UDP/TCP */ + SWITCH_ACL_IP_FIELD_ICMP_TYPE, /**< ICMP type */ + SWITCH_ACL_IP_FIELD_ICMP_CODE, /**< ICMP code */ + SWITCH_ACL_IP_FIELD_TCP_FLAGS, /**< TCP flags */ + SWITCH_ACL_IP_FIELD_TTL, /**< TTL */ + SWITCH_ACL_IP_FIELD_IP_FLAGS, /**< IP flags */ + SWITCH_ACL_IP_FIELD_IP_FRAGMENT, /**< IP FRAG */ SWITCH_ACL_IP_FIELD_MAX } switch_acl_ip_field_t; /** Acl IPv6 field enum */ typedef enum switch_acl_ipv6_field_ { - SWITCH_ACL_IPV6_FIELD_IPV6_SRC, /**< IPv6 Source address */ - SWITCH_ACL_IPV6_FIELD_IPV6_DEST, /**< IPv6 Destination address */ - SWITCH_ACL_IPV6_FIELD_IP_PROTO, /**< IP protocol */ - SWITCH_ACL_IPV6_FIELD_L4_SOURCE_PORT, /**< L4 source port (UDP/TCP) */ - SWITCH_ACL_IPV6_FIELD_L4_DEST_PORT, /**< L4 Dest port (UDP/TCP) */ - SWITCH_ACL_IPV6_FIELD_ICMP_TYPE, /**< ICMP type */ - SWITCH_ACL_IPV6_FIELD_ICMP_CODE, /**< ICMP code */ - SWITCH_ACL_IPV6_FIELD_TCP_FLAGS, /**< TCP flags */ - SWITCH_ACL_IPV6_FIELD_TTL, /**< TTL */ - SWITCH_ACL_IPV6_FIELD_FLOW_LABEL, /**< Flow Label */ + SWITCH_ACL_IPV6_FIELD_IPV6_SRC, /**< IPv6 Source address */ + SWITCH_ACL_IPV6_FIELD_IPV6_DEST, /**< IPv6 Destination address */ + SWITCH_ACL_IPV6_FIELD_IP_PROTO, /**< IP protocol */ + SWITCH_ACL_IPV6_FIELD_L4_SOURCE_PORT_RANGE, /**< L4 source port (UDP/TCP) */ + SWITCH_ACL_IPV6_FIELD_L4_DEST_PORT_RANGE, /**< L4 Dest port (UDP/TCP) */ + SWITCH_ACL_IPV6_FIELD_ICMP_TYPE, /**< ICMP type */ + SWITCH_ACL_IPV6_FIELD_ICMP_CODE, /**< ICMP code */ + SWITCH_ACL_IPV6_FIELD_TCP_FLAGS, /**< TCP flags */ + SWITCH_ACL_IPV6_FIELD_TTL, /**< TTL */ + SWITCH_ACL_IPV6_FIELD_FLOW_LABEL, /**< Flow Label */ SWITCH_ACL_IPV6_FIELD_MAX } switch_acl_ipv6_field_t; /** Acl IP field list */ typedef union switch_acl_ip_value_ { - unsigned int ipv4_source; /**< v4 source IP */ - unsigned int ipv4_dest; /**< v4 destination IP */ - unsigned char ip_proto; /**< protocol */ - unsigned short l4_source_port; /**< souce port */ - unsigned short l4_dest_port; /**< destination port */ - unsigned char icmp_type; /**< icmp type */ - unsigned char icmp_code; /**< icmp code */ - unsigned char tcp_flags; /**< tcp flags */ - unsigned char ttl; /**< time to live */ - unsigned char dscp; /**< DSCP */ - unsigned char ip_flags; /**< IP flags */ - unsigned char tos; /**< TOS */ - unsigned char ip_frag; /**< IP FRAG */ + unsigned int ipv4_source; /**< v4 source IP */ + unsigned int ipv4_dest; /**< v4 destination IP */ + unsigned char ip_proto; /**< protocol */ + unsigned char icmp_type; /**< icmp type */ + unsigned char icmp_code; /**< icmp code */ + unsigned char tcp_flags; /**< tcp flags */ + unsigned char ttl; /**< time to live */ + unsigned char dscp; /**< DSCP */ + unsigned char ip_flags; /**< IP flags */ + unsigned char tos; /**< TOS */ + unsigned char ip_frag; /**< IP FRAG */ + switch_handle_t sport_range_handle; /**< sport range handle */ + switch_handle_t dport_range_handle; /**< dport range handle */ } switch_acl_ip_value; /** Acl IPv6 field list */ typedef union switch_acl_ipv6_value_ { - uint128_t ipv6_source; /**< v6 souce IP */ - uint128_t ipv6_dest; /**< v6 destination IP */ - unsigned char ip_proto; /**< protocol */ - unsigned short l4_source_port; /**< source port */ - unsigned short l4_dest_port; /**< destination port */ - unsigned char icmp_type; /**< icmp type */ - unsigned char icmp_code; /**< icmp code */ - unsigned char tcp_flags; /**< tcp flags */ - unsigned char ttl; /**< time to live */ - uint32_t flow_label; /**< flow label */ + uint128_t ipv6_source; /**< v6 souce IP */ + uint128_t ipv6_dest; /**< v6 destination IP */ + unsigned char ip_proto; /**< protocol */ + unsigned char icmp_type; /**< icmp type */ + unsigned char icmp_code; /**< icmp code */ + unsigned char tcp_flags; /**< tcp flags */ + unsigned char ttl; /**< time to live */ + uint32_t flow_label; /**< flow label */ + switch_handle_t sport_range_handle; /**< sport range handle */ + switch_handle_t dport_range_handle; /**< dport range handle */ } switch_acl_ipv6_value; /** Acl IP mask */ @@ -196,42 +196,42 @@ typedef struct switch_acl_mac_key_value_pair_ { /** ACL ip racl field enum */ typedef enum switch_acl_ip_racl_field_ { - SWITCH_ACL_IP_RACL_FIELD_IPV4_SRC, /**< IPv4 Source address */ - SWITCH_ACL_IP_RACL_FIELD_IPV4_DEST, /**< IPv4 Dest address */ - SWITCH_ACL_IP_RACL_FIELD_IP_PROTO, /**< IP protocol (TCP/UDP) */ - SWITCH_ACL_IP_RACL_FIELD_L4_SOURCE_PORT, /**< L4 source port */ - SWITCH_ACL_IP_RACL_FIELD_L4_DEST_PORT, /**< L4 dest port */ + SWITCH_ACL_IP_RACL_FIELD_IPV4_SRC, /**< IPv4 Source address */ + SWITCH_ACL_IP_RACL_FIELD_IPV4_DEST, /**< IPv4 Dest address */ + SWITCH_ACL_IP_RACL_FIELD_IP_PROTO, /**< IP protocol (TCP/UDP) */ + SWITCH_ACL_IP_RACL_FIELD_L4_SOURCE_PORT_RANGE, /**< L4 source port */ + SWITCH_ACL_IP_RACL_FIELD_L4_DEST_PORT_RANGE, /**< L4 dest port */ SWITCH_ACL_IP_RACL_FIELD_MAX } switch_acl_ip_racl_field_t; /** ACL ipv6 racl field enum */ typedef enum switch_acl_ipv6_racl_field_ { - SWITCH_ACL_IPV6_RACL_FIELD_IPV6_SRC, /**< IPv6 source address */ - SWITCH_ACL_IPV6_RACL_FIELD_IPV6_DEST, /**< IPv6 dest address */ - SWITCH_ACL_IPV6_RACL_FIELD_IP_PROTO, /**< IPv6 protocol */ - SWITCH_ACL_IPV6_RACL_FIELD_L4_SOURCE_PORT, /**< L4 source port */ - SWITCH_ACL_IPV6_RACL_FIELD_L4_DEST_PORT, /**< L4 dest port */ + SWITCH_ACL_IPV6_RACL_FIELD_IPV6_SRC, /**< IPv6 source address */ + SWITCH_ACL_IPV6_RACL_FIELD_IPV6_DEST, /**< IPv6 dest address */ + SWITCH_ACL_IPV6_RACL_FIELD_IP_PROTO, /**< IPv6 protocol */ + SWITCH_ACL_IPV6_RACL_FIELD_L4_SOURCE_PORT_RANGE, /**< L4 source port */ + SWITCH_ACL_IPV6_RACL_FIELD_L4_DEST_PORT_RANGE, /**< L4 dest port */ SWITCH_ACL_IPV6_RACL_FIELD_MAX } switch_acl_ipv6_racl_field_t; /** Acl ip racl field list */ typedef union switch_acl_ip_racl_value_ { - unsigned int ipv4_source; /**< v4 source IP */ - unsigned int ipv4_dest; /**< v4 destination IP */ - unsigned short ip_proto; /**< protocol */ - unsigned short l4_source_port; /**< source port */ - unsigned short l4_dest_port; /**< destination port */ + unsigned int ipv4_source; /**< v4 source IP */ + unsigned int ipv4_dest; /**< v4 destination IP */ + unsigned short ip_proto; /**< protocol */ + switch_handle_t sport_range_handle; /**< sport range handle */ + switch_handle_t dport_range_handle; /**< dport range handle */ } switch_acl_ip_racl_value; /** Acl ipv6 racl field list */ typedef union switch_acl_ipv6_racl_value_ { - uint128_t ipv6_source; /**< v6 source IP */ - uint128_t ipv6_dest; /**< v6 destination IP */ - unsigned short ip_proto; /**< protocol */ - unsigned short l4_source_port; /**< source port */ - unsigned short l4_dest_port; /**< destination port */ + uint128_t ipv6_source; /**< v6 source IP */ + uint128_t ipv6_dest; /**< v6 destination IP */ + unsigned short ip_proto; /**< protocol */ + switch_handle_t sport_range_handle; /**< sport range handle */ + switch_handle_t dport_range_handle; /**< dport range handle */ } switch_acl_ipv6_racl_value; /** Acl ip racl mask */ @@ -413,6 +413,7 @@ typedef enum switch_acl_egr_field_ { SWITCH_ACL_EGR_DEST_PORT, SWITCH_ACL_EGR_DEFLECT, SWITCH_ACL_EGR_L3_MTU_CHECK, + SWITCH_ACL_EGR_ACL_DENY, SWITCH_ACL_EGR_FIELD_MAX } switch_acl_egr_field_t; @@ -421,6 +422,7 @@ typedef union switch_acl_egr_value_ { switch_handle_t egr_port; /**< egress port */ bool deflection_flag; /**< deflection flag */ unsigned short l3_mtu_check; /**< L3 MTU check */ + bool acl_deny; /**< acl deny */ } switch_acl_egr_value_t; /** Egress ACL match mask */ @@ -445,6 +447,8 @@ typedef enum switch_acl_egr_action_ { SWITCH_ACL_EGR_ACTION_SET_MIRROR, /**< Set mirror session */ SWITCH_ACL_EGR_ACTION_REDIRECT_TO_CPU, /**< redirect to cpu */ SWITCH_ACL_EGR_MIRROR_DROP, /**< negative mirror */ + SWITCH_ACL_EGR_ACTION_DROP, /**< drop packets */ + SWITCH_ACL_EGR_ACTION_PERMIT /**< permit packets */ } switch_acl_egr_action_t; typedef switch_acl_action_t switch_acl_ip_action_t; /**< acl action */ @@ -455,17 +459,32 @@ typedef switch_acl_action_t /** Acl info struct */ typedef struct switch_acl_info_ { - switch_acl_type_t type; /**< acl type */ - void *rules; /**< set of rules */ - tommy_list interface_list; /**< list of interface handles */ + switch_acl_type_t type; /**< acl type */ + switch_direction_t direction; /**< acl direction */ + void *rules; /**< set of rules */ + tommy_list interface_list; /**< list of interface handles */ } switch_acl_info_t; +typedef enum switch_range_type_ { + SWITCH_RANGE_TYPE_NONE = 0x0, + SWITCH_RANGE_TYPE_SRC_PORT = 0x1, + SWITCH_RANGE_TYPE_DST_PORT = 0x2, + SWITCH_RANGE_TYPE_VLAN = 0x3, + SWITCH_RANGE_TYPE_PACKET_LENGTH = 0x4 +} switch_range_type_t; + +typedef struct switch_range_ { + uint32_t start_value; + uint32_t end_value; +} switch_range_t; + /** ACL Key list create @param device device @param type - acl type */ switch_handle_t switch_api_acl_list_create(switch_device_t device, + switch_direction_t direction, switch_acl_type_t type); /** @@ -597,6 +616,27 @@ switch_status_t switch_api_acl_stats_get(switch_device_t device, switch_acl_type_t switch_acl_type_get(switch_device_t device, switch_handle_t acl_handle); +switch_status_t switch_api_acl_range_create(switch_device_t device, + switch_direction_t direction, + switch_range_type_t range_type, + switch_range_t *range, + switch_handle_t *range_handle); + +switch_status_t switch_api_acl_range_update(switch_device_t device, + switch_handle_t range_handle, + switch_range_t *range); + +switch_status_t switch_api_acl_range_type_get(switch_device_t device, + switch_handle_t range_handle, + switch_range_type_t *range_type); + +switch_status_t switch_api_acl_range_get(switch_device_t device, + switch_handle_t range_handle, + switch_range_t *range); + +switch_status_t switch_api_acl_range_delete(switch_device_t device, + switch_handle_t range_handle); + /** @} */ // end of ACL API #ifdef __cplusplus diff --git a/switchapi/include/switchapi/switch_base_types.h b/switchapi/include/switchapi/switch_base_types.h index bc4b45b..d3e67ea 100644 --- a/switchapi/include/switchapi/switch_base_types.h +++ b/switchapi/include/switchapi/switch_base_types.h @@ -44,7 +44,7 @@ extern "C" { #define switch_free(x) free(x) #define switch_realloc(x, sz) realloc(x, sz) -#define HANDLE_TYPE_SHIFT 27 +#define HANDLE_TYPE_SHIFT 26 #define handle_to_id(x) (x & 0x3FFFFFF) #define id_to_handle(t, x) (t << HANDLE_TYPE_SHIFT | (x)) diff --git a/switchapi/include/switchapi/switch_handle.h b/switchapi/include/switchapi/switch_handle.h index 4eeb3df..c8206d2 100644 --- a/switchapi/include/switchapi/switch_handle.h +++ b/switchapi/include/switchapi/switch_handle.h @@ -58,15 +58,16 @@ typedef enum { SWITCH_HANDLE_TYPE_BUFFER_PROFILE, SWITCH_HANDLE_TYPE_VLAN_MEMBER, SWITCH_HANDLE_TYPE_SCHEDULER, + SWITCH_HANDLE_TYPE_RANGE, - SWITCH_HANDLE_TYPE_MAX = 32 + SWITCH_HANDLE_TYPE_MAX = 64 } switch_handle_type_t; /** Generic handle to encode different types of objects handle impicitly encodes the device, type and type specific */ -typedef unsigned long switch_handle_t; +typedef uint64_t switch_handle_t; /** Handle related information */ typedef struct { @@ -140,8 +141,11 @@ switch_handle_type_t switch_handle_get_type(switch_handle_t handle); #define SWITCH_HOSTIF_HANDLE_VALID(handle) \ SWITCH_HANDLE_VALID(handle, SWITCH_HANDLE_TYPE_HOSTIF) +#define SWITCH_RANGE_HANDLE_VALID(handle) \ + SWITCH_HANDLE_VALID(handle, SWITCH_HANDLE_TYPE_RANGE) + // Easy use macros -#define SWITCH_API_INVALID_HANDLE 0xFFFFFFFF +#define SWITCH_API_INVALID_HANDLE ((uint64_t) ~(0)) #define SWITCH_HW_INVALID_HANDLE 0xFFFFFFFF #define _switch_handle_create(_type, _info, _judy, _init, _handle) \ diff --git a/switchapi/src/switch_acl.c b/switchapi/src/switch_acl.c index 8bf5890..a7ef706 100644 --- a/switchapi/src/switch_acl.c +++ b/switchapi/src/switch_acl.c @@ -20,18 +20,21 @@ limitations under the License. #include "switch_acl_int.h" #include "switch_interface_int.h" #include "switch_pd.h" +#include "switch_log_int.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ static void *switch_acl_array; +static void *switch_range_array; switch_api_id_allocator *acl_counter_index = NULL; switch_status_t switch_acl_init(switch_device_t device) { switch_acl_array = NULL; switch_handle_type_init(SWITCH_HANDLE_TYPE_ACL, (4 * 1024)); switch_handle_type_init(SWITCH_HANDLE_TYPE_ACE, (4 * 1024)); + switch_handle_type_init(SWITCH_HANDLE_TYPE_RANGE, (1024)); acl_counter_index = switch_api_id_allocator_new(4 * 1024, FALSE); return SWITCH_STATUS_SUCCESS; } @@ -40,6 +43,7 @@ switch_status_t switch_acl_free(switch_device_t device) { switch_api_id_allocator_destroy(acl_counter_index); switch_handle_type_free(SWITCH_HANDLE_TYPE_ACE); switch_handle_type_free(SWITCH_HANDLE_TYPE_ACL); + switch_handle_type_free(SWITCH_HANDLE_TYPE_RANGE); return SWITCH_STATUS_SUCCESS; } @@ -73,6 +77,7 @@ void switch_acl_counter_index_free(unsigned int index) { } switch_handle_t switch_api_acl_list_create(switch_device_t device, + switch_direction_t direction, switch_acl_type_t type) { switch_acl_info_t *acl_info = NULL; switch_handle_t acl_handle; @@ -83,6 +88,7 @@ switch_handle_t switch_api_acl_list_create(switch_device_t device, return SWITCH_STATUS_NO_MEMORY; } acl_info->type = type; + acl_info->direction = direction; acl_info->rules = NULL; tommy_list_init(&(acl_info->interface_list)); return acl_handle; @@ -141,6 +147,7 @@ static switch_status_t switch_ace_delete(switch_handle_t handle) { static switch_status_t switch_acl_ip_set_fields_actions( switch_device_t device, + switch_direction_t direction, switch_acl_rule_t *p, switch_handle_t interface_handle, p4_pd_entry_hdl_t *entry) { @@ -153,7 +160,7 @@ static switch_status_t switch_acl_ip_set_fields_actions( if (interface_handle) { if (switch_handle_get_type(interface_handle) == SWITCH_HANDLE_TYPE_PORT) { - if_label = handle_to_id(interface_handle); + if_label = handle_to_id(interface_handle) + 1; } else { intf_info = switch_api_interface_get(interface_handle); if (!intf_info) { @@ -161,10 +168,10 @@ static switch_status_t switch_acl_ip_set_fields_actions( } switch (switch_handle_get_type(interface_handle)) { case SWITCH_HANDLE_TYPE_INTERFACE: - if_label = intf_info->api_intf_info.u.port_lag_handle; + if_label = intf_info->api_intf_info.u.port_lag_handle + 1; break; case SWITCH_HANDLE_TYPE_BD: - bd_label = handle_to_id(interface_handle); + bd_label = handle_to_id(interface_handle) + 1; ; break; default: @@ -178,21 +185,35 @@ static switch_status_t switch_acl_ip_set_fields_actions( } ip_acl = (switch_acl_ip_key_value_pair_t *)p->fields; - status = switch_pd_ipv4_acl_table_add_entry(device, - if_label, - bd_label, - p->priority, - p->field_count, - ip_acl, - p->action, - &(p->action_params), - &(p->opt_action_params), - entry); + if (direction == SWITCH_API_DIRECTION_INGRESS) { + status = switch_pd_ipv4_acl_table_add_entry(device, + if_label, + bd_label, + p->priority, + p->field_count, + ip_acl, + p->action, + &(p->action_params), + &(p->opt_action_params), + entry); + } else { + status = switch_pd_egress_ipv4_acl_table_add_entry(device, + if_label, + bd_label, + p->priority, + p->field_count, + ip_acl, + p->action, + &(p->action_params), + &(p->opt_action_params), + entry); + } return status; } static switch_status_t switch_acl_ipv6_set_fields_actions( switch_device_t device, + switch_direction_t direction, switch_acl_rule_t *p, switch_handle_t interface_handle, p4_pd_entry_hdl_t *entry) { @@ -203,38 +224,57 @@ static switch_status_t switch_acl_ipv6_set_fields_actions( switch_status_t status = SWITCH_STATUS_SUCCESS; if (interface_handle) { - intf_info = switch_api_interface_get(interface_handle); - if (!intf_info) { - return SWITCH_STATUS_INVALID_INTERFACE; - } - switch (switch_handle_get_type(interface_handle)) { - case SWITCH_HANDLE_TYPE_INTERFACE: - if_label = intf_info->api_intf_info.u.port_lag_handle; - break; - case SWITCH_HANDLE_TYPE_BD: - bd_label = handle_to_id(interface_handle); - ; - break; - default: - return SWITCH_STATUS_INVALID_HANDLE; + if (switch_handle_get_type(interface_handle) == SWITCH_HANDLE_TYPE_PORT) { + if_label = handle_to_id(interface_handle) + 1; + } else { + intf_info = switch_api_interface_get(interface_handle); + if (!intf_info) { + return SWITCH_STATUS_INVALID_INTERFACE; + } + switch (switch_handle_get_type(interface_handle)) { + case SWITCH_HANDLE_TYPE_INTERFACE: + if_label = intf_info->api_intf_info.u.port_lag_handle + 1; + break; + case SWITCH_HANDLE_TYPE_BD: + bd_label = handle_to_id(interface_handle) + 1; + ; + break; + default: + return SWITCH_STATUS_INVALID_HANDLE; + } } } ipv6_acl = (switch_acl_ipv6_key_value_pair_t *)p->fields; - status = switch_pd_ipv6_acl_table_add_entry(device, - if_label, - bd_label, - p->priority, - p->field_count, - ipv6_acl, - p->action, - &(p->action_params), - &(p->opt_action_params), - entry); + + if (direction == SWITCH_API_DIRECTION_INGRESS) { + status = switch_pd_ipv6_acl_table_add_entry(device, + if_label, + bd_label, + p->priority, + p->field_count, + ipv6_acl, + p->action, + &(p->action_params), + &(p->opt_action_params), + entry); + } else { + status = switch_pd_egress_ipv6_acl_table_add_entry(device, + if_label, + bd_label, + p->priority, + p->field_count, + ipv6_acl, + p->action, + &(p->action_params), + &(p->opt_action_params), + entry); + } return status; } static switch_status_t switch_acl_mac_set_fields_actions( switch_device_t device, + switch_direction_t direction, switch_acl_rule_t *p, switch_handle_t interface_handle, p4_pd_entry_hdl_t *entry) { @@ -251,10 +291,10 @@ static switch_status_t switch_acl_mac_set_fields_actions( } switch (switch_handle_get_type(interface_handle)) { case SWITCH_HANDLE_TYPE_INTERFACE: - if_label = intf_info->api_intf_info.u.port_lag_handle; + if_label = intf_info->api_intf_info.u.port_lag_handle + 1; break; case SWITCH_HANDLE_TYPE_BD: - bd_label = handle_to_id(interface_handle); + bd_label = handle_to_id(interface_handle) + 1; ; break; default: @@ -263,21 +303,36 @@ static switch_status_t switch_acl_mac_set_fields_actions( } mac_acl = (switch_acl_mac_key_value_pair_t *)p->fields; - status = switch_pd_mac_acl_table_add_entry(device, - if_label, - bd_label, - p->priority, - p->field_count, - mac_acl, - p->action, - &(p->action_params), - &(p->opt_action_params), - entry); + if (direction == SWITCH_API_DIRECTION_INGRESS) { + status = switch_pd_mac_acl_table_add_entry(device, + if_label, + bd_label, + p->priority, + p->field_count, + mac_acl, + p->action, + &(p->action_params), + &(p->opt_action_params), + entry); + } else { + status = switch_pd_egress_mac_acl_table_add_entry(device, + if_label, + bd_label, + p->priority, + p->field_count, + mac_acl, + p->action, + &(p->action_params), + &(p->opt_action_params), + entry); + } + return status; } static switch_status_t switch_acl_ip_racl_set_fields_actions( switch_device_t device, + switch_direction_t direction, switch_acl_rule_t *p, switch_handle_t interface_handle, p4_pd_entry_hdl_t *entry) { @@ -289,29 +344,36 @@ static switch_status_t switch_acl_ip_racl_set_fields_actions( if (interface_handle) { switch (switch_handle_get_type(interface_handle)) { case SWITCH_HANDLE_TYPE_BD: - bd_label = handle_to_id(interface_handle); + bd_label = handle_to_id(interface_handle) + 1; ; break; default: return SWITCH_STATUS_INVALID_HANDLE; } } + ip_racl = (switch_acl_ip_racl_key_value_pair_t *)p->fields; - status = switch_pd_ipv4_racl_table_add_entry(device, - if_label, - bd_label, - p->priority, - p->field_count, - ip_racl, - p->action, - &(p->action_params), - &(p->opt_action_params), - entry); + + if (direction == SWITCH_API_DIRECTION_INGRESS) { + status = switch_pd_ipv4_racl_table_add_entry(device, + if_label, + bd_label, + p->priority, + p->field_count, + ip_racl, + p->action, + &(p->action_params), + &(p->opt_action_params), + entry); + } else { + status = SWITCH_STATUS_NOT_SUPPORTED; + } return status; } static switch_status_t switch_acl_ipv6_racl_set_fields_actions( switch_device_t device, + switch_direction_t direction, switch_acl_rule_t *p, switch_handle_t interface_handle, p4_pd_entry_hdl_t *entry) { @@ -323,7 +385,7 @@ static switch_status_t switch_acl_ipv6_racl_set_fields_actions( if (interface_handle) { switch (switch_handle_get_type(interface_handle)) { case SWITCH_HANDLE_TYPE_BD: - bd_label = handle_to_id(interface_handle); + bd_label = handle_to_id(interface_handle) + 1; ; break; default: @@ -332,21 +394,28 @@ static switch_status_t switch_acl_ipv6_racl_set_fields_actions( } } ipv6_racl = (switch_acl_ipv6_racl_key_value_pair_t *)p->fields; - status = switch_pd_ipv6_racl_table_add_entry(device, - if_label, - bd_label, - p->priority, - p->field_count, - ipv6_racl, - p->action, - &(p->action_params), - &(p->opt_action_params), - entry); + + if (direction == SWITCH_API_DIRECTION_INGRESS) { + status = switch_pd_ipv6_racl_table_add_entry(device, + if_label, + bd_label, + p->priority, + p->field_count, + ipv6_racl, + p->action, + &(p->action_params), + &(p->opt_action_params), + entry); + } else { + status = SWITCH_STATUS_NOT_SUPPORTED; + } + return status; } static switch_status_t switch_acl_system_set_fields_actions( switch_device_t device, + switch_direction_t direction, switch_acl_rule_t *p, switch_handle_t interface_handle, p4_pd_entry_hdl_t *entry) { @@ -363,10 +432,10 @@ static switch_status_t switch_acl_system_set_fields_actions( } switch (switch_handle_get_type(interface_handle)) { case SWITCH_HANDLE_TYPE_INTERFACE: - if_label = intf_info->api_intf_info.u.port_lag_handle; + if_label = intf_info->api_intf_info.u.port_lag_handle + 1; break; case SWITCH_HANDLE_TYPE_BD: - bd_label = handle_to_id(interface_handle); + bd_label = handle_to_id(interface_handle) + 1; ; break; default: @@ -374,21 +443,25 @@ static switch_status_t switch_acl_system_set_fields_actions( } } system_acl = (switch_acl_system_key_value_pair_t *)p->fields; - status = switch_pd_system_acl_table_add_entry(device, - if_label, - bd_label, - p->priority, - p->field_count, - system_acl, - p->action, - &p->action_params, - &p->opt_action_params, - entry); + if (direction == SWITCH_API_DIRECTION_INGRESS) { + status = switch_pd_system_acl_table_add_entry(device, + if_label, + bd_label, + p->priority, + p->field_count, + system_acl, + p->action, + &p->action_params, + &p->opt_action_params, + entry); + } else { + } return status; } static switch_status_t switch_acl_egr_set_fields_actions( switch_device_t device, + switch_direction_t direction, switch_acl_rule_t *p, switch_handle_t interface_handle, p4_pd_entry_hdl_t *entry) { @@ -408,10 +481,10 @@ static switch_status_t switch_acl_egr_set_fields_actions( } switch (switch_handle_get_type(interface_handle)) { case SWITCH_HANDLE_TYPE_INTERFACE: - if_label = intf_info->api_intf_info.u.port_lag_handle; + if_label = intf_info->api_intf_info.u.port_lag_handle + 1; break; case SWITCH_HANDLE_TYPE_BD: - bd_label = handle_to_id(interface_handle); + bd_label = handle_to_id(interface_handle) + 1; ; break; default: @@ -421,16 +494,19 @@ static switch_status_t switch_acl_egr_set_fields_actions( } egr_acl = (switch_acl_egr_key_value_pair_t *)p->fields; - status = switch_pd_egr_acl_table_add_entry(device, - if_label, - bd_label, - p->priority, - p->field_count, - egr_acl, - p->action, - &p->action_params, - &p->opt_action_params, - entry); + if (direction == SWITCH_API_DIRECTION_INGRESS) { + } else { + status = switch_pd_egr_acl_table_add_entry(device, + if_label, + bd_label, + p->priority, + p->field_count, + egr_acl, + p->action, + &p->action_params, + &p->opt_action_params, + entry); + } return status; } @@ -447,31 +523,31 @@ static switch_status_t acl_hw_set(switch_device_t device, switch (acl_info->type) { case SWITCH_ACL_TYPE_SYSTEM: status = switch_acl_system_set_fields_actions( - device, p, interface_handle, &entry); + device, acl_info->direction, p, interface_handle, &entry); break; case SWITCH_ACL_TYPE_IP: - status = - switch_acl_ip_set_fields_actions(device, p, interface_handle, &entry); + status = switch_acl_ip_set_fields_actions( + device, acl_info->direction, p, interface_handle, &entry); break; case SWITCH_ACL_TYPE_IPV6: status = switch_acl_ipv6_set_fields_actions( - device, p, interface_handle, &entry); + device, acl_info->direction, p, interface_handle, &entry); break; case SWITCH_ACL_TYPE_IP_RACL: status = switch_acl_ip_racl_set_fields_actions( - device, p, interface_handle, &entry); + device, acl_info->direction, p, interface_handle, &entry); break; case SWITCH_ACL_TYPE_IPV6_RACL: status = switch_acl_ipv6_racl_set_fields_actions( - device, p, interface_handle, &entry); + device, acl_info->direction, p, interface_handle, &entry); break; case SWITCH_ACL_TYPE_MAC: status = switch_acl_mac_set_fields_actions( - device, p, interface_handle, &entry); + device, acl_info->direction, p, interface_handle, &entry); break; case SWITCH_ACL_TYPE_EGRESS_SYSTEM: status = switch_acl_egr_set_fields_actions( - device, p, interface_handle, &entry); + device, acl_info->direction, p, interface_handle, &entry); break; default: break; @@ -504,7 +580,7 @@ static switch_status_t acl_hw_del(switch_device_t device, return SWITCH_STATUS_UNSUPPORTED_TYPE; return switch_pd_system_acl_table_delete_entry( - device, switch_ace_get(ace_handle)->hw_entry); + device, acl_info->direction, switch_ace_get(ace_handle)->hw_entry); } JLG(hw_entry, intf->entries, ace_handle); @@ -512,31 +588,31 @@ static switch_status_t acl_hw_del(switch_device_t device, switch (acl_info->type) { case SWITCH_ACL_TYPE_SYSTEM: status = switch_pd_system_acl_table_delete_entry( - device, *(unsigned long *)hw_entry); + device, acl_info->direction, *(unsigned long *)hw_entry); break; case SWITCH_ACL_TYPE_IP: status = switch_pd_ipv4_acl_table_delete_entry( - device, *(unsigned long *)hw_entry); + device, acl_info->direction, *(unsigned long *)hw_entry); break; case SWITCH_ACL_TYPE_IPV6: status = switch_pd_ipv6_acl_table_delete_entry( - device, *(unsigned long *)hw_entry); + device, acl_info->direction, *(unsigned long *)hw_entry); break; case SWITCH_ACL_TYPE_IP_RACL: status = switch_pd_ipv4_racl_table_delete_entry( - device, *(unsigned long *)hw_entry); + device, acl_info->direction, *(unsigned long *)hw_entry); break; case SWITCH_ACL_TYPE_IPV6_RACL: status = switch_pd_ipv6_racl_table_delete_entry( - device, *(unsigned long *)hw_entry); + device, acl_info->direction, *(unsigned long *)hw_entry); break; case SWITCH_ACL_TYPE_MAC: status = switch_pd_mac_acl_table_delete_entry( - device, *(unsigned long *)hw_entry); + device, acl_info->direction, *(unsigned long *)hw_entry); break; case SWITCH_ACL_TYPE_EGRESS_SYSTEM: status = switch_pd_egr_acl_table_delete_entry( - device, *(unsigned long *)hw_entry); + device, acl_info->direction, *(unsigned long *)hw_entry); break; default: break; @@ -894,6 +970,174 @@ switch_acl_type_t switch_acl_type_get(switch_device_t device, return acl_info->type; } +switch_handle_t switch_range_handle_create() { + switch_handle_t range_handle; + _switch_handle_create(SWITCH_HANDLE_TYPE_RANGE, + switch_range_info_t, + switch_range_array, + NULL, + range_handle); + return range_handle; +} + +switch_range_info_t *switch_range_get(switch_handle_t range_handle) { + switch_range_info_t *range_info = NULL; + _switch_handle_get( + switch_range_info_t, switch_range_array, range_handle, range_info); + return range_info; +} + +switch_status_t switch_range_handle_delete(switch_handle_t handle) { + _switch_handle_delete(switch_range_info_t, switch_range_array, handle); + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t switch_api_acl_range_create(switch_device_t device, + switch_direction_t direction, + switch_range_type_t range_type, + switch_range_t *range, + switch_handle_t *range_handle) { + switch_range_info_t *range_info = NULL; + switch_status_t status = SWITCH_STATUS_SUCCESS; + + *range_handle = switch_range_handle_create(); + range_info = switch_range_get(*range_handle); + if (!range_info) { + SWITCH_API_ERROR("failed to create range handle"); + return SWITCH_STATUS_NO_MEMORY; + } + + if (range_type == SWITCH_RANGE_TYPE_VLAN || + range_type == SWITCH_RANGE_TYPE_PACKET_LENGTH) { + SWITCH_API_ERROR( + "failed to create range handle." + "invalid range type (vlan or packet length)"); + return SWITCH_STATUS_NOT_SUPPORTED; + } + + if (direction != SWITCH_API_DIRECTION_INGRESS && + direction != SWITCH_API_DIRECTION_EGRESS) { + SWITCH_API_ERROR("failed to create range"); + return SWITCH_STATUS_INVALID_PARAMETER; + } + + memcpy(&range_info->range, range, sizeof(switch_range_t)); + range_info->range_type = range_type; + range_info->direction = direction; + + status = switch_pd_range_entry_add(device, + direction, + handle_to_id(*range_handle), + range_type, + range, + &range_info->hw_entry); + + return status; +} + +switch_status_t switch_api_acl_range_update(switch_device_t device, + switch_handle_t range_handle, + switch_range_t *range) { + switch_range_info_t *range_info = NULL; + switch_status_t status = SWITCH_STATUS_SUCCESS; + + if (!SWITCH_RANGE_HANDLE_VALID(range_handle)) { + SWITCH_API_ERROR("failed to update range. invalid range handle"); + return SWITCH_STATUS_INVALID_PARAMETER; + } + + range_info = switch_range_get(range_handle); + if (!range_info) { + SWITCH_API_ERROR("failed to update range. invalid range handle"); + return SWITCH_STATUS_INVALID_PARAMETER; + } + + memcpy(&range_info->range, range, sizeof(switch_range_t)); + + status = switch_pd_range_entry_update(device, + range_info->direction, + handle_to_id(range_handle), + range_info->range_type, + range, + range_info->hw_entry); + return status; +} + +switch_status_t switch_api_acl_range_get(switch_device_t device, + switch_handle_t range_handle, + switch_range_t *range) { + switch_range_info_t *range_info = NULL; + switch_status_t status = SWITCH_STATUS_SUCCESS; + + if (!SWITCH_RANGE_HANDLE_VALID(range_handle)) { + SWITCH_API_ERROR("failed to get range. invalid range handle"); + return SWITCH_STATUS_INVALID_PARAMETER; + } + + range_info = switch_range_get(range_handle); + if (!range_info) { + SWITCH_API_ERROR("failed to get range. invalid range handle"); + return SWITCH_STATUS_INVALID_PARAMETER; + } + + memcpy(range, &range_info->range, sizeof(switch_range_t)); + + return status; +} + +switch_status_t switch_api_acl_range_delete(switch_device_t device, + switch_handle_t range_handle) { + switch_range_info_t *range_info = NULL; + switch_status_t status = SWITCH_STATUS_SUCCESS; + + if (!SWITCH_RANGE_HANDLE_VALID(range_handle)) { + SWITCH_API_ERROR("failed to delete range. invalid range handle"); + return SWITCH_STATUS_INVALID_PARAMETER; + } + + range_info = switch_range_get(range_handle); + if (!range_info) { + SWITCH_API_ERROR("failed to delete range. invalid range handle"); + return SWITCH_STATUS_INVALID_PARAMETER; + } + + status = switch_pd_range_entry_delete(device, + range_info->direction, + range_info->range_type, + range_info->hw_entry); + + if (status != SWITCH_STATUS_SUCCESS) { + SWITCH_API_ERROR("failed to delete range. pd delete failed"); + return status; + } + + switch_range_handle_delete(range_handle); + + return status; +} + +switch_status_t switch_api_acl_range_type_get(switch_device_t device, + switch_handle_t range_handle, + switch_range_type_t *range_type) { + switch_range_info_t *range_info = NULL; + switch_status_t status = SWITCH_STATUS_SUCCESS; + + if (!SWITCH_RANGE_HANDLE_VALID(range_handle)) { + SWITCH_API_ERROR("failed to get range type. invalid range handle"); + return SWITCH_STATUS_INVALID_PARAMETER; + } + + range_info = switch_range_get(range_handle); + if (!range_info) { + SWITCH_API_ERROR("failed to get range type. invalid range handle"); + return SWITCH_STATUS_INVALID_PARAMETER; + } + + *range_type = range_info->range_type; + + return status; +} + #ifdef __cplusplus } #endif diff --git a/switchapi/src/switch_acl_int.h b/switchapi/src/switch_acl_int.h index 34a5dd8..5725c66 100644 --- a/switchapi/src/switch_acl_int.h +++ b/switchapi/src/switch_acl_int.h @@ -33,6 +33,13 @@ typedef struct switch_acl_interface_ { void *entries; } switch_acl_interface_t; +typedef struct switch_range_info_ { + switch_range_t range; + switch_range_type_t range_type; + switch_direction_t direction; + p4_pd_entry_hdl_t hw_entry; +} switch_range_info_t; + typedef struct switch_acl_rule_ { switch_handle_t acl_handle; int priority; diff --git a/switchapi/src/switch_api.thrift b/switchapi/src/switch_api.thrift index 16c47c6..454e2b2 100644 --- a/switchapi/src/switch_api.thrift +++ b/switchapi/src/switch_api.thrift @@ -78,7 +78,7 @@ typedef i32 switcht_handle_type_t typedef byte switcht_device_t typedef i32 switcht_vrf_id_t -typedef i32 switcht_handle_t +typedef i64 switcht_handle_t typedef string switcht_mac_addr_t typedef i32 switcht_port_t typedef i16 switcht_vlan_t @@ -527,6 +527,11 @@ struct switcht_scheduler_info_t { 9: i32 max_rate; } +struct switcht_range_t { + 1: i32 start_value; + 2: i32 end_value; +} + service switch_api_rpc { /* init */ switcht_status_t switcht_api_init(1:switcht_device_t device); @@ -702,7 +707,10 @@ service switch_api_rpc { switcht_status_t switcht_api_nat_delete(1:switcht_device_t device, 2:switcht_nat_info_t nat_info); /* ACL API */ - switcht_handle_t switcht_api_acl_list_create(1:switcht_device_t device, 2:switcht_acl_type_t type); + switcht_handle_t switcht_api_acl_list_create( + 1:switcht_device_t device, + 2:switcht_direction_t direction, + 3:switcht_acl_type_t type); switcht_status_t switcht_api_acl_list_delete(1:switcht_device_t device, 2:switcht_handle_t handle); switcht_handle_t switcht_api_acl_mac_rule_create( 1:switcht_device_t device, @@ -796,6 +804,18 @@ service switch_api_rpc { switcht_counter_t switcht_api_acl_stats_get( 1: switcht_device_t device, 2: switcht_handle_t counter_handle); + switcht_handle_t switcht_api_acl_range_create( + 1: switcht_device_t device, + 2: switcht_direction_t direction, + 3: byte range_type, + 4: switcht_range_t range); + switcht_status_t switcht_api_acl_range_update( + 1: switcht_device_t device, + 2: switcht_handle_t range_handle, + 3: switcht_range_t range); + switcht_status_t switcht_api_acl_range_delete( + 1: switcht_device_t device, + 2: switcht_handle_t range_handle); /* HOSTIF API */ switcht_handle_t switcht_api_hostif_group_create(1:switcht_device_t device, 2:switcht_hostif_group_t hostif_group); @@ -883,7 +903,7 @@ service switch_api_rpc { switcht_status_t switcht_api_sflow_session_delete(1:switcht_device_t device, 2:switcht_handle_t sflow_hdl, 3:bool all_cleanup); - switcht_status_t switcht_api_sflow_session_attach( + switcht_handle_t switcht_api_sflow_session_attach( 1:switcht_device_t device, 2:switcht_handle_t sflow_handle, 3:switcht_direction_t direction, diff --git a/switchapi/src/switch_api_rpc_server.cpp b/switchapi/src/switch_api_rpc_server.cpp index e695887..b7d5e36 100644 --- a/switchapi/src/switch_api_rpc_server.cpp +++ b/switchapi/src/switch_api_rpc_server.cpp @@ -275,7 +275,7 @@ class switch_api_rpcHandler : virtual public switch_api_rpcIf { return switch_api_port_qos_group_egress_set(device, port_handle, qos_handle); } - switcht_status_t switcht_api_vrf_create(const switcht_device_t device, const switcht_vrf_id_t vrf) { + switcht_handle_t switcht_api_vrf_create(const switcht_device_t device, const switcht_vrf_id_t vrf) { printf("switcht_api_l3_vrf_create\n"); return switch_api_vrf_create(device, vrf); } @@ -529,7 +529,7 @@ class switch_api_rpcHandler : virtual public switch_api_rpcIf { return; } - switcht_status_t switcht_api_mac_table_entry_create(const switcht_device_t device, const switcht_handle_t vlan_handle, const switcht_mac_addr_t& mac, const int8_t entry_type, const switcht_interface_handle_t interface_handle) { + switcht_status_t switcht_api_mac_table_entry_create(const switcht_device_t device, const switcht_handle_t vlan_handle, const switcht_mac_addr_t& mac, const int8_t entry_type, const switcht_handle_t interface_handle) { switch_api_mac_entry_t mac_entry; switch_string_to_mac(mac, mac_entry.mac.mac_addr); printf("switcht_api_l2_mac_add\n"); @@ -539,7 +539,7 @@ class switch_api_rpcHandler : virtual public switch_api_rpcIf { return switch_api_mac_table_entry_add(device, &mac_entry); } - switcht_status_t switcht_api_mac_table_entry_update(const switcht_device_t device, const switcht_handle_t vlan_handle, const switcht_mac_addr_t& mac, const int8_t entry_type, const switcht_interface_handle_t interface_handle) { + switcht_status_t switcht_api_mac_table_entry_update(const switcht_device_t device, const switcht_handle_t vlan_handle, const switcht_mac_addr_t& mac, const int8_t entry_type, const switcht_handle_t interface_handle) { switch_api_mac_entry_t mac_entry; switch_string_to_mac(mac, mac_entry.mac.mac_addr); printf("switcht_api_l2_mac_update\n"); @@ -974,9 +974,12 @@ class switch_api_rpcHandler : virtual public switch_api_rpcIf { // ACL - switcht_handle_t switcht_api_acl_list_create(const switcht_device_t device, const switcht_acl_type_t type) { + switcht_handle_t switcht_api_acl_list_create( + const switcht_device_t device, + const switcht_direction_t direction, + const switcht_acl_type_t type) { printf("switcht_api_acl_list_create\n"); - return switch_api_acl_list_create(device, (switch_acl_type_t)type); + return switch_api_acl_list_create(device, (switch_direction_t) direction, (switch_acl_type_t)type); } switcht_status_t switcht_api_acl_list_delete(const switcht_device_t device, const switcht_handle_t handle) { @@ -1000,7 +1003,7 @@ class switch_api_rpcHandler : virtual public switch_api_rpcIf { std::vector::const_iterator f=acl_kvp.begin(); - void *fields = calloc(sizeof(switch_acl_ip_key_value_pair_t)*acl_kvp.size(), 1); + void *fields = calloc(sizeof(switch_acl_mac_key_value_pair_t)*acl_kvp.size(), 1); for(uint32_t i=0;ifield = (switch_acl_mac_field_t)f->field; switch ((switch_acl_mac_field_t) f->field) { @@ -1009,7 +1012,7 @@ class switch_api_rpcHandler : virtual public switch_api_rpcIf { { unsigned char *mac = (unsigned char *) (((switch_acl_mac_key_value_pair_t *) fields + i)->value.source_mac.mac_addr); switch_string_to_mac(f->value.value_str, mac); - unsigned char *mac_mask = (unsigned char *) (((switch_acl_mac_key_value_pair_t *) fields + i)->mask.u.mask); + unsigned char *mac_mask = (unsigned char *) (&(((switch_acl_mac_key_value_pair_t *) fields + i)->mask.u.mask)); switch_string_to_mac(f->mask.value_str, mac_mask); break; } @@ -1382,6 +1385,51 @@ class switch_api_rpcHandler : virtual public switch_api_rpcIf { return; } + switcht_handle_t + switcht_api_acl_range_create( + const switcht_device_t device, + const switcht_direction_t direction, + const int8_t range_type, + const switcht_range_t& range) { + switch_handle_t range_handle = 0; + switch_status_t status = SWITCH_STATUS_SUCCESS; + switch_range_t api_range; + memset(&api_range, 0x0, sizeof(api_range)); + api_range.start_value = range.start_value; + api_range.end_value = range.end_value; + status = switch_api_acl_range_create( + device, + (switch_direction_t) direction, + (switch_range_type_t) range_type, + &api_range, + &range_handle); + return range_handle; + } + + switcht_status_t + switcht_api_acl_range_update( + const switcht_device_t device, + const switcht_handle_t range_handle, + const switcht_range_t& range) { + switch_range_t api_range; + switch_status_t status = SWITCH_STATUS_SUCCESS; + memset(&api_range, 0x0, sizeof(api_range)); + api_range.start_value = range.start_value; + api_range.end_value = range.end_value; + status = switch_api_acl_range_update( + device, + range_handle, + &api_range); + return status; + } + + switcht_status_t switcht_api_acl_range_delete( + const switcht_device_t device, + const switcht_handle_t range_handle) { + return switch_api_acl_range_delete(device, range_handle); + } + + switcht_handle_t switcht_api_multicast_tree_create(const switcht_device_t device) { printf("switcht_api_multicast_tree_create\n"); return switch_api_multicast_tree_create(device); diff --git a/switchapi/src/switch_handle.c b/switchapi/src/switch_handle.c index a677313..3e148af 100644 --- a/switchapi/src/switch_handle.c +++ b/switchapi/src/switch_handle.c @@ -112,17 +112,22 @@ void switch_handle_free(switch_handle_t handle) { switch_handle_info_t *handle_info = NULL; void *p = NULL; - type = (handle & 0xF8000000) >> HANDLE_TYPE_SHIFT; + uint32_t handle_id_mask = ((1 << HANDLE_TYPE_SHIFT) - 1); + uint32_t handle_type_mask = ~(handle_id_mask); + + type = (handle & handle_type_mask) >> HANDLE_TYPE_SHIFT; JLG(p, switch_handle_array, (unsigned int)type); if ((handle_info = (switch_handle_info_t *)(*(unsigned long *)p))) { switch_api_id_allocator_release(handle_info->allocator, - handle & 0x00FFFFFF); + handle & handle_id_mask); handle_info->num_in_use--; } } switch_handle_type_t switch_handle_get_type(switch_handle_t handle) { - switch_handle_type_t type = (handle & 0xF8000000) >> HANDLE_TYPE_SHIFT; + uint32_t handle_id_mask = ((1 << HANDLE_TYPE_SHIFT) - 1); + uint32_t handle_type_mask = ~(handle_id_mask); + switch_handle_type_t type = (handle & handle_type_mask) >> HANDLE_TYPE_SHIFT; return type; } diff --git a/switchapi/src/switch_hostif.c b/switchapi/src/switch_hostif.c index 31d4b28..48d08d6 100644 --- a/switchapi/src/switch_hostif.c +++ b/switchapi/src/switch_hostif.c @@ -170,7 +170,8 @@ switch_status_t switch_api_hostif_reason_code_create( switch (rcode_api_info->reason_code) { case SWITCH_HOSTIF_REASON_CODE_STP: { // stp bpdu, redirect to cpu - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_MAC); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_MAC); switch_acl_mac_key_value_pair_t acl_kvp[SWITCH_ACL_MAC_FIELD_MAX]; memset(&acl_kvp, 0, sizeof(acl_kvp)); field_count = 0; @@ -196,8 +197,8 @@ switch_status_t switch_api_hostif_reason_code_create( &ace_handle); switch_api_acl_reference(device, acl_handle, 0); - system_acl_handle = - switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + system_acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); switch_acl_system_key_value_pair_t system_acl_kvp[SWITCH_ACL_SYSTEM_FIELD_MAX]; memset(&system_acl_kvp, 0, sizeof(system_acl_kvp)); @@ -230,7 +231,8 @@ switch_status_t switch_api_hostif_reason_code_create( } case SWITCH_HOSTIF_REASON_CODE_LACP: { // lacp bpdu, redirect to cpu - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_MAC); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_MAC); switch_acl_mac_key_value_pair_t acl_kvp[SWITCH_ACL_MAC_FIELD_MAX]; memset(&acl_kvp, 0, sizeof(acl_kvp)); field_count = 0; @@ -256,8 +258,8 @@ switch_status_t switch_api_hostif_reason_code_create( &ace_handle); switch_api_acl_reference(device, acl_handle, 0); - system_acl_handle = - switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + system_acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); switch_acl_system_key_value_pair_t system_acl_kvp[SWITCH_ACL_SYSTEM_FIELD_MAX]; memset(&system_acl_kvp, 0, sizeof(system_acl_kvp)); @@ -290,7 +292,8 @@ switch_status_t switch_api_hostif_reason_code_create( } case SWITCH_HOSTIF_REASON_CODE_LLDP: { // lacp frame, redirect to cpu - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_MAC); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_MAC); switch_acl_mac_key_value_pair_t acl_kvp[SWITCH_ACL_MAC_FIELD_MAX]; memset(&acl_kvp, 0, sizeof(acl_kvp)); field_count = 0; @@ -374,8 +377,8 @@ switch_status_t switch_api_hostif_reason_code_create( &ace_handle); switch_api_acl_reference(device, acl_handle, 0); - system_acl_handle = - switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + system_acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); switch_acl_system_key_value_pair_t system_acl_kvp[SWITCH_ACL_SYSTEM_FIELD_MAX]; memset(&system_acl_kvp, 0, sizeof(system_acl_kvp)); @@ -406,7 +409,8 @@ switch_status_t switch_api_hostif_reason_code_create( break; } case SWITCH_HOSTIF_REASON_CODE_OSPF: { - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_IP); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_IP); switch_acl_ip_key_value_pair_t acl_kvp[SWITCH_ACL_IP_FIELD_MAX]; // All OSPF routers 224.0.0.5, copy to cpu @@ -457,8 +461,8 @@ switch_status_t switch_api_hostif_reason_code_create( switch_api_acl_reference(device, acl_handle, 0); - system_acl_handle = - switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + system_acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); switch_acl_system_key_value_pair_t system_acl_kvp[SWITCH_ACL_SYSTEM_FIELD_MAX]; memset(&system_acl_kvp, 0, sizeof(system_acl_kvp)); @@ -494,7 +498,8 @@ switch_status_t switch_api_hostif_reason_code_create( } case SWITCH_HOSTIF_REASON_CODE_OSPFV6: { // All OSPFv3 routers ff02::5, copy to cpu - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_IPV6); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_IPV6); switch_acl_ipv6_key_value_pair_t acl_kvp[SWITCH_ACL_IPV6_FIELD_MAX]; memset(&acl_kvp, 0, sizeof(acl_kvp)); @@ -546,8 +551,8 @@ switch_status_t switch_api_hostif_reason_code_create( switch_api_acl_reference(device, acl_handle, 0); - system_acl_handle = - switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + system_acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); switch_acl_system_key_value_pair_t system_acl_kvp[SWITCH_ACL_SYSTEM_FIELD_MAX]; memset(&system_acl_kvp, 0, sizeof(system_acl_kvp)); @@ -583,7 +588,8 @@ switch_status_t switch_api_hostif_reason_code_create( } case SWITCH_HOSTIF_REASON_CODE_IPV6_NEIGHBOR_DISCOVERY: { // IPV6 ND packet, copy to cpu - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_IPV6); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_IPV6); switch_acl_ipv6_key_value_pair_t acl_kvp[SWITCH_ACL_IPV6_FIELD_MAX]; memset(&acl_kvp, 0, sizeof(acl_kvp)); @@ -648,8 +654,8 @@ switch_status_t switch_api_hostif_reason_code_create( switch_api_acl_reference(device, acl_handle, 0); - system_acl_handle = - switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + system_acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); switch_acl_system_key_value_pair_t system_acl_kvp[SWITCH_ACL_SYSTEM_FIELD_MAX]; memset(&system_acl_kvp, 0, sizeof(system_acl_kvp)); @@ -685,7 +691,8 @@ switch_status_t switch_api_hostif_reason_code_create( } case SWITCH_HOSTIF_REASON_CODE_PIM: { // PIM packet, copy to cpu - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_IP); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_IP); switch_acl_ip_key_value_pair_t acl_kvp[SWITCH_ACL_IP_FIELD_MAX]; memset(&acl_kvp, 0, sizeof(acl_kvp)); field_count = 0; @@ -706,8 +713,8 @@ switch_status_t switch_api_hostif_reason_code_create( &ace_handle); switch_api_acl_reference(device, acl_handle, 0); - system_acl_handle = - switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + system_acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); switch_acl_system_key_value_pair_t system_acl_kvp[SWITCH_ACL_SYSTEM_FIELD_MAX]; memset(&system_acl_kvp, 0, sizeof(system_acl_kvp)); @@ -743,7 +750,8 @@ switch_status_t switch_api_hostif_reason_code_create( } case SWITCH_HOSTIF_REASON_CODE_IGMP_TYPE_V2_REPORT: { // IGMPv2 report packet, copy to cpu - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_IP); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_IP); switch_acl_ip_key_value_pair_t acl_kvp[SWITCH_ACL_IP_FIELD_MAX]; memset(&acl_kvp, 0, sizeof(acl_kvp)); field_count = 0; @@ -764,8 +772,8 @@ switch_status_t switch_api_hostif_reason_code_create( &ace_handle); switch_api_acl_reference(device, acl_handle, 0); - system_acl_handle = - switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + system_acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); switch_acl_system_key_value_pair_t system_acl_kvp[SWITCH_ACL_SYSTEM_FIELD_MAX]; memset(&system_acl_kvp, 0, sizeof(system_acl_kvp)); @@ -796,7 +804,8 @@ switch_status_t switch_api_hostif_reason_code_create( break; } case SWITCH_HOSTIF_REASON_CODE_ARP_REQUEST: { - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_MAC); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_MAC); switch_acl_mac_key_value_pair_t acl_kvp[SWITCH_ACL_MAC_FIELD_MAX]; memset(&acl_kvp, 0, sizeof(acl_kvp)); field_count = 0; @@ -826,8 +835,8 @@ switch_status_t switch_api_hostif_reason_code_create( &ace_handle); switch_api_acl_reference(device, acl_handle, 0); - system_acl_handle = - switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + system_acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); switch_acl_system_key_value_pair_t system_acl_kvp[SWITCH_ACL_SYSTEM_FIELD_MAX]; memset(&system_acl_kvp, 0, sizeof(system_acl_kvp)); @@ -862,7 +871,8 @@ switch_status_t switch_api_hostif_reason_code_create( break; } case SWITCH_HOSTIF_REASON_CODE_ARP_RESPONSE: { - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_MAC); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_MAC); switch_acl_mac_key_value_pair_t acl_kvp[SWITCH_ACL_MAC_FIELD_MAX]; memset(&acl_kvp, 0, sizeof(acl_kvp)); field_count = 0; @@ -883,8 +893,8 @@ switch_status_t switch_api_hostif_reason_code_create( &ace_handle); switch_api_acl_reference(device, acl_handle, 0); - system_acl_handle = - switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + system_acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); switch_acl_system_key_value_pair_t system_acl_kvp[SWITCH_ACL_SYSTEM_FIELD_MAX]; memset(&system_acl_kvp, 0, sizeof(system_acl_kvp)); @@ -923,7 +933,8 @@ switch_status_t switch_api_hostif_reason_code_create( break; } case SWITCH_HOSTIF_REASON_CODE_TTL_ERROR: { - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); switch_acl_system_key_value_pair_t acl_kvp[SWITCH_ACL_SYSTEM_FIELD_MAX]; memset(&acl_kvp, 0, sizeof(acl_kvp)); field_count = 0; @@ -971,7 +982,8 @@ switch_status_t switch_api_hostif_reason_code_create( break; } case SWITCH_HOSTIF_REASON_CODE_BROADCAST: { - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_MAC); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_MAC); switch_acl_mac_key_value_pair_t acl_kvp[SWITCH_ACL_MAC_FIELD_MAX]; memset(&acl_kvp, 0, sizeof(acl_kvp)); field_count = 0; @@ -997,8 +1009,8 @@ switch_status_t switch_api_hostif_reason_code_create( &ace_handle); switch_api_acl_reference(device, acl_handle, 0); - system_acl_handle = - switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + system_acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); switch_acl_system_key_value_pair_t system_acl_kvp[SWITCH_ACL_SYSTEM_FIELD_MAX]; memset(&system_acl_kvp, 0, sizeof(system_acl_kvp)); @@ -1182,12 +1194,8 @@ const char *switch_api_hostif_code_string( } switch_status_t switch_api_hostif_rx_packet_from_hw( - switch_packet_header_t *packet_header, - switch_opt_header_t *opt_header, - char *packet, - int packet_size) { + switch_packet_header_t *packet_header, char *packet, int packet_size) { switch_cpu_header_t *cpu_header = NULL; - switch_sflow_header_t *sflow_header = NULL; switch_hostif_rcode_info_t *rcode_info = NULL; void *temp = NULL; switch_hostif_packet_t hostif_packet; @@ -1218,12 +1226,6 @@ switch_status_t switch_api_hostif_rx_packet_from_hw( hostif_packet.handle = id_to_handle(SWITCH_HANDLE_TYPE_PORT, cpu_header->ingress_port); - if (cpu_header->reason_code == SWITCH_HOSTIF_REASON_CODE_SFLOW_SAMPLE) { - sflow_header = &opt_header->sflow_header; - hostif_packet.sflow_session_id = sflow_header->sflow_session_id; - hostif_packet.egress_ifindex = sflow_header->sflow_egress_ifindex; - } - if (SWITCH_IS_LAG_IFINDEX(cpu_header->ingress_ifindex)) { hostif_packet.is_lag = TRUE; } diff --git a/switchapi/src/switch_hostif_int.h b/switchapi/src/switch_hostif_int.h index f44f574..16047a3 100644 --- a/switchapi/src/switch_hostif_int.h +++ b/switchapi/src/switch_hostif_int.h @@ -71,6 +71,7 @@ typedef struct __attribute__((__packed__)) switch_cpu_header_ { uint16_t ingress_ifindex; uint16_t ingress_bd; uint16_t reason_code; + uint16_t mcast_grp; } switch_cpu_header_t; typedef struct __attribute__((__packed__)) switch_sflow_header_ { @@ -110,10 +111,7 @@ switch_status_t switch_hostif_init(switch_device_t device); switch_status_t switch_hostif_free(switch_device_t device); switch_status_t switch_packet_init(switch_device_t device); switch_status_t switch_api_hostif_rx_packet_from_hw( - switch_packet_header_t *packet_header, - switch_opt_header_t *opt_header, - char *packet, - int packet_size); + switch_packet_header_t *packet_header, char *packet, int packet_size); switch_hostif_info_t *switch_hostif_get(switch_handle_t hostif_handle); void switch_packet_tx_to_host(switch_hostif_info_t *hostif_info, char *packet, diff --git a/switchapi/src/switch_init.c b/switchapi/src/switch_init.c index cb41a08..bc16a7d 100644 --- a/switchapi/src/switch_init.c +++ b/switchapi/src/switch_init.c @@ -152,6 +152,7 @@ switch_status_t switch_api_init_default_entries(switch_device_t device) { switch_pd_l3_rewrite_table_add_default_entry(device); switch_pd_adjust_lkp_fields_table_add_default_entry(device); switch_pd_qos_default_entry_add(device); + switch_pd_l4port_default_entry_add(device); SWITCH_API_TRACE("Programming init entries!!"); switch_pd_learn_notify_table_add_init_entry(device); @@ -168,6 +169,7 @@ switch_status_t switch_api_init_default_entries(switch_device_t device) { switch_pd_replica_type_table_init_entry(device); switch_pd_rewrite_multicast_table_init_entry(device); switch_pd_l3_rewrite_table_init_entry(device); + switch_pd_egress_l4port_fields_init_entry(device); switch_pd_nat_init(device); #ifdef P4_INT_ENABLE @@ -181,8 +183,8 @@ switch_status_t switch_api_init_default_entries(switch_device_t device) { void switch_system_acl_entries_delete(switch_device_t device) { // go over the array, delete dynamic entries switch_default_acl_t *acl = &_switch_system_acl_data[device][0]; - - for (int i = 0; i < SWITCH_INGRESS_ACL_ENTRIES; i++) { + int i = 0; + for (i = 0; i < SWITCH_INGRESS_ACL_ENTRIES; i++) { switch_api_acl_rule_delete(device, acl->acl_handle, acl->ace_handle); acl++; } @@ -195,8 +197,8 @@ void switch_system_acl_entries_add(switch_device_t device) { memset(&opt_action_params, 0, sizeof(switch_acl_opt_action_params_t)); action = SWITCH_ACL_ACTION_DROP; - - for (int i = 0; i < SWITCH_INGRESS_ACL_ENTRIES; i++) { + int i = 0; + for (i = 0; i < SWITCH_INGRESS_ACL_ENTRIES; i++) { switch_api_acl_rule_create(device, acl->acl_handle, acl->priority, @@ -212,8 +214,8 @@ void switch_system_acl_entries_add(switch_device_t device) { void switch_egress_acl_entries_delete(switch_device_t device) { switch_default_acl_t *acl = &_switch_egress_acl_data[device][0]; - - for (int i = 0; i < SWITCH_EGRESS_ACL_ENTRIES; i++) { + int i = 0; + for (i = 0; i < SWITCH_EGRESS_ACL_ENTRIES; i++) { switch_api_acl_rule_delete(device, acl->acl_handle, acl->ace_handle); acl++; } @@ -242,6 +244,23 @@ void switch_egress_acl_entries_add(switch_device_t device) { &acl->action_params, &opt_action_params, &acl->ace_handle); + + acl++; + + memset(egr_acl_kvp, 0, sizeof(egr_acl_kvp)); + egr_acl_kvp[0].field = SWITCH_ACL_EGR_ACL_DENY; + egr_acl_kvp[0].value.acl_deny = 1; + egr_acl_kvp[0].mask.u.mask = 0xFF; + memset(&acl->action_params, 0, sizeof(switch_acl_action_params_t)); + switch_api_acl_rule_create(device, + acl->acl_handle, + acl->priority, + acl->key_value_count, + egr_acl_kvp, + SWITCH_ACL_EGR_ACTION_DROP, + &acl->action_params, + &opt_action_params, + &acl->ace_handle); } switch_status_t switch_negative_mirroring_set(switch_device_t device, @@ -272,7 +291,8 @@ static switch_status_t switch_api_init_default_acl_entries( memset(&opt_action_params, 0, sizeof(switch_acl_opt_action_params_t)); // system acl for dropped packets - dacl->acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + dacl->acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp)); dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_DROP; dacl->acl_kvp[0].value.drop_flag = 1; @@ -283,7 +303,8 @@ static switch_status_t switch_api_init_default_acl_entries( dacl++; // port vlan mapping miss, drop - dacl->acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + dacl->acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp)); dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_PORT_VLAN_MAPPING_MISS; dacl->acl_kvp[0].value.port_vlan_mapping_miss = 1; @@ -295,7 +316,8 @@ static switch_status_t switch_api_init_default_acl_entries( dacl++; // STP state == blocked, drop - dacl->acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + dacl->acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp)); dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_STP_STATE; dacl->acl_kvp[0].value.stp_state = SWITCH_PORT_STP_STATE_BLOCKING; @@ -307,7 +329,8 @@ static switch_status_t switch_api_init_default_acl_entries( dacl++; // STP state == learning, drop - dacl->acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + dacl->acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp)); dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_STP_STATE; dacl->acl_kvp[0].value.stp_state = SWITCH_PORT_STP_STATE_LEARNING; @@ -319,7 +342,8 @@ static switch_status_t switch_api_init_default_acl_entries( dacl++; // ACL deny, drop - dacl->acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + dacl->acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp)); dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_ACL_DENY; dacl->acl_kvp[0].value.acl_deny = 1; @@ -331,7 +355,8 @@ static switch_status_t switch_api_init_default_acl_entries( dacl++; // URPF check fail, drop - dacl->acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + dacl->acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp)); dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_URPF_CHECK; dacl->acl_kvp[0].value.urpf_check_fail = 1; @@ -343,7 +368,8 @@ static switch_status_t switch_api_init_default_acl_entries( dacl++; // same if check fail, drop - dacl->acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + dacl->acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp)); dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_IF_CHECK; dacl->acl_kvp[0].value.if_check = 0; @@ -364,7 +390,8 @@ static switch_status_t switch_api_init_default_acl_entries( dacl++; // egress ifindex is drop ifindex, drop - dacl->acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + dacl->acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp)); dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_EGRESS_IFINDEX; dacl->acl_kvp[0].value.out_ifindex = switch_api_drop_ifindex(); @@ -378,7 +405,8 @@ static switch_status_t switch_api_init_default_acl_entries( switch_system_acl_entries_add(device); // routed, ttl == 1, egress_ifindex == cpu, permit - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(acl_kvp, 0, sizeof(acl_kvp)); acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_ROUTED; acl_kvp[0].value.routed = true; @@ -401,7 +429,8 @@ static switch_status_t switch_api_init_default_acl_entries( &handle); // routed, ttl == 1, redirect to cpu - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(acl_kvp, 0, sizeof(acl_kvp)); acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_ROUTED; acl_kvp[0].value.routed = true; @@ -422,7 +451,8 @@ static switch_status_t switch_api_init_default_acl_entries( &handle); // routed, ipv6_src_is_link_local == 1, egress_ifindex == cpu, permit - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(acl_kvp, 0, sizeof(acl_kvp)); acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_ROUTED; acl_kvp[0].value.routed = true; @@ -447,7 +477,8 @@ static switch_status_t switch_api_init_default_acl_entries( &handle); // routed, ipv6_src_is_link_local == 1, redirect to cpu - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(acl_kvp, 0, sizeof(acl_kvp)); acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_ROUTED; acl_kvp[0].value.routed = true; @@ -469,7 +500,8 @@ static switch_status_t switch_api_init_default_acl_entries( &handle); // routed, ingress bd == egress bd, copy to cpu - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(acl_kvp, 0, sizeof(acl_kvp)); acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_ROUTED; acl_kvp[0].value.routed = true; @@ -491,7 +523,8 @@ static switch_status_t switch_api_init_default_acl_entries( &handle); // l3_copy to cpu - acl_handle = switch_api_acl_list_create(device, SWITCH_ACL_TYPE_SYSTEM); + acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM); memset(acl_kvp, 0, sizeof(acl_kvp)); acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_L3_COPY; acl_kvp[0].value.l3_copy = true; @@ -509,21 +542,29 @@ static switch_status_t switch_api_init_default_acl_entries( switch_default_acl_t *egr_acl = &_switch_egress_acl_data[device][0]; // set acl handler and priority for egress mtu check rule - egr_acl->acl_handle = - switch_api_acl_list_create(device, SWITCH_ACL_TYPE_EGRESS_SYSTEM); + egr_acl->acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_EGRESS, SWITCH_ACL_TYPE_EGRESS_SYSTEM); egr_acl->priority = priority++; egr_acl->key_value_count = 1; switch_api_acl_reference(device, egr_acl->acl_handle, 0); egr_acl++; // set acl handler and priority for egress dod rule - egr_acl->acl_handle = - switch_api_acl_list_create(device, SWITCH_ACL_TYPE_EGRESS_SYSTEM); - egr_acl->priority = priority; + egr_acl->acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_EGRESS, SWITCH_ACL_TYPE_EGRESS_SYSTEM); + egr_acl->priority = priority++; + egr_acl->key_value_count = 1; + switch_api_acl_reference(device, egr_acl->acl_handle, 0); + egr_acl++; + + egr_acl->acl_handle = switch_api_acl_list_create( + device, SWITCH_API_DIRECTION_EGRESS, SWITCH_ACL_TYPE_EGRESS_SYSTEM); + egr_acl->priority = priority++; egr_acl->key_value_count = 1; - switch_egress_acl_entries_add(device); switch_api_acl_reference(device, egr_acl->acl_handle, 0); + switch_egress_acl_entries_add(device); + return SWITCH_STATUS_SUCCESS; } diff --git a/switchapi/src/switch_nhop.c b/switchapi/src/switch_nhop.c index 1d73f1f..293fd7a 100644 --- a/switchapi/src/switch_nhop.c +++ b/switchapi/src/switch_nhop.c @@ -421,7 +421,7 @@ switch_status_t switch_api_nhop_update(switch_device_t device, tunnel, &spath_info->hw_entry); if (status != SWITCH_STATUS_SUCCESS) { - return SWITCH_API_INVALID_HANDLE; + return status; } #endif diff --git a/switchapi/src/switch_packet.c b/switchapi/src/switch_packet.c index 3c5498d..a31a17a 100644 --- a/switchapi/src/switch_packet.c +++ b/switchapi/src/switch_packet.c @@ -139,31 +139,12 @@ void switch_packet_tx_to_hw(switch_packet_header_t *packet_header, // packet_header->fabric_header.dst_port_or_group); } -static void switch_packet_extract_optional_header( - switch_packet_header_t *packet_header, - switch_opt_header_t **opt_header, - uint16_t *opt_length) { - *opt_length = 0; - if (packet_header->cpu_header.reason_code == - SWITCH_HOSTIF_REASON_CODE_SFLOW_SAMPLE) { - *opt_header = - (switch_opt_header_t *)(packet_header + sizeof(switch_packet_header_t)); - (*opt_header)->sflow_header.sflow_session_id = - ntohs((*opt_header)->sflow_header.sflow_session_id); - (*opt_header)->sflow_header.sflow_egress_ifindex = - ntohs((*opt_header)->sflow_header.sflow_egress_ifindex); - *opt_length = sizeof(switch_sflow_header_t); - } -} - static void switch_packet_rx_from_hw() { int packet_size = 0; switch_packet_header_t *packet_header = NULL; - switch_opt_header_t *opt_header = NULL; static char in_packet[SWITCH_PACKET_MAX_BUFFER_SIZE]; static char packet[SWITCH_PACKET_MAX_BUFFER_SIZE]; switch_status_t status = SWITCH_STATUS_SUCCESS; - uint16_t opt_length = 0; // read packet from cpu port while ((packet_size = read(cpu_sock_fd, in_packet, sizeof(in_packet))) > 0) { @@ -171,29 +152,25 @@ static void switch_packet_rx_from_hw() { if (ntohs(ethType) != 0x9000) continue; packet_header = (switch_packet_header_t *)(in_packet + SWITCH_PACKET_HEADER_OFFSET); + packet_size = packet_size - sizeof(switch_packet_header_t); memcpy(packet, in_packet, SWITCH_PACKET_HEADER_OFFSET); + memcpy(packet + SWITCH_PACKET_HEADER_OFFSET, + in_packet + SWITCH_PACKET_HEADER_OFFSET + + sizeof(switch_packet_header_t), + packet_size - SWITCH_PACKET_HEADER_OFFSET); packet_header->cpu_header.reason_code = ntohs(packet_header->cpu_header.reason_code); if (packet_header->cpu_header.reason_code == SWITCH_HOSTIF_REASON_CODE_NULL_DROP) continue; - - switch_packet_extract_optional_header( - packet_header, &opt_header, &opt_length); - packet_size = packet_size - sizeof(switch_packet_header_t) - opt_length; - memcpy(packet + SWITCH_PACKET_HEADER_OFFSET, - in_packet + SWITCH_PACKET_HEADER_OFFSET + - sizeof(switch_packet_header_t) + opt_length, - packet_size - SWITCH_PACKET_HEADER_OFFSET); - packet_header->cpu_header.ingress_port = ntohs(packet_header->cpu_header.ingress_port); packet_header->cpu_header.ingress_ifindex = ntohs(packet_header->cpu_header.ingress_ifindex); packet_header->cpu_header.ingress_bd = ntohs(packet_header->cpu_header.ingress_bd); - status = switch_api_hostif_rx_packet_from_hw( - packet_header, opt_header, packet, packet_size); + status = + switch_api_hostif_rx_packet_from_hw(packet_header, packet, packet_size); if (status != SWITCH_STATUS_SUCCESS) { return; } diff --git a/switchapi/src/switch_pd.c b/switchapi/src/switch_pd.c index 68a0fce..b8c1155 100644 --- a/switchapi/src/switch_pd.c +++ b/switchapi/src/switch_pd.c @@ -826,7 +826,7 @@ p4_pd_status_t switch_pd_src_vtep_table_add_entry( memset(&v4_action_spec, 0, sizeof(p4_pd_dc_src_vtep_hit_action_spec_t)); v4_match_spec.l3_metadata_vrf = handle_to_id(ip_encap->vrf_handle); - v4_match_spec.ipv4_srcAddr = SWITCH_IP_ENCAP_IPV4_SRC_IP(ip_encap); + v4_match_spec.ipv4_srcAddr = SWITCH_IP_ENCAP_IPV4_DST_IP(ip_encap); v4_match_spec.tunnel_metadata_ingress_tunnel_type = switch_tunnel_get_ingress_tunnel_type(ip_encap); v4_action_spec.action_ifindex = ifindex; @@ -844,7 +844,7 @@ p4_pd_status_t switch_pd_src_vtep_table_add_entry( v6_match_spec.l3_metadata_vrf = handle_to_id(ip_encap->vrf_handle); memcpy( - &v6_match_spec.ipv6_srcAddr, SWITCH_IP_ENCAP_IPV6_SRC_IP(ip_encap), 16); + &v6_match_spec.ipv6_srcAddr, SWITCH_IP_ENCAP_IPV6_DST_IP(ip_encap), 16); v6_match_spec.tunnel_metadata_ingress_tunnel_type = switch_tunnel_get_ingress_tunnel_type(ip_encap); v6_action_spec.action_ifindex = ifindex; @@ -894,7 +894,7 @@ p4_pd_status_t switch_pd_dest_vtep_table_add_entry( p4_pd_dc_ipv4_dest_vtep_match_spec_t v4_match_spec; memset(&v4_match_spec, 0, sizeof(p4_pd_dc_ipv4_dest_vtep_match_spec_t)); v4_match_spec.l3_metadata_vrf = handle_to_id(ip_encap->vrf_handle); - v4_match_spec.ipv4_dstAddr = SWITCH_IP_ENCAP_IPV4_DST_IP(ip_encap); + v4_match_spec.ipv4_dstAddr = SWITCH_IP_ENCAP_IPV4_SRC_IP(ip_encap); v4_match_spec.tunnel_metadata_ingress_tunnel_type = switch_tunnel_get_ingress_tunnel_type(ip_encap); status = p4_pd_dc_ipv4_dest_vtep_table_add_with_set_tunnel_termination_flag( @@ -906,7 +906,7 @@ p4_pd_status_t switch_pd_dest_vtep_table_add_entry( memset(&v6_match_spec, 0, sizeof(p4_pd_dc_ipv6_dest_vtep_match_spec_t)); v6_match_spec.l3_metadata_vrf = handle_to_id(ip_encap->vrf_handle); memcpy( - &v6_match_spec.ipv6_dstAddr, SWITCH_IP_ENCAP_IPV6_DST_IP(ip_encap), 16); + &v6_match_spec.ipv6_dstAddr, SWITCH_IP_ENCAP_IPV6_SRC_IP(ip_encap), 16); v6_match_spec.tunnel_metadata_ingress_tunnel_type = switch_tunnel_get_ingress_tunnel_type(ip_encap); status = p4_pd_dc_ipv6_dest_vtep_table_add_with_set_tunnel_termination_flag( @@ -2608,6 +2608,7 @@ p4_pd_status_t switch_pd_egress_bd_map_table_add_entry( match_spec.egress_metadata_bd = handle_to_id(bd_handle); action_spec.action_smac_idx = bd_info->smac_index; action_spec.action_nat_mode = SWITCH_LN_NAT_MODE(bd_info); + action_spec.action_bd_label = handle_to_id(bd_info->ln_info.bd_label); status = p4_pd_dc_egress_bd_map_table_add_with_set_egress_bd_properties( g_sess_hdl, @@ -2633,6 +2634,7 @@ p4_pd_status_t switch_pd_egress_bd_map_table_update_entry( match_spec.egress_metadata_bd = handle_to_id(bd_handle); action_spec.action_smac_idx = bd_info->smac_index; action_spec.action_nat_mode = SWITCH_LN_NAT_MODE(bd_info); + action_spec.action_bd_label = handle_to_id(bd_info->ln_info.bd_label); status = p4_pd_dc_egress_bd_map_table_modify_with_set_egress_bd_properties( g_sess_hdl, device, bd_info->egress_bd_entry, &action_spec); @@ -2816,7 +2818,7 @@ p4_pd_status_t switch_pd_ingress_port_mapping_table_add_entry( action1_spec.action_port_type = port_info->port_type; match2_spec.standard_metadata_ingress_port = SWITCH_PORT_ID(port_info); - action2_spec.action_if_label = SWITCH_PORT_ID(port_info); + action2_spec.action_if_label = SWITCH_PORT_ID(port_info) + 1; action2_spec.action_qos_group = port_info->ingress_qos_group; action2_spec.action_tc_qos_group = port_info->tc_qos_group; action2_spec.action_tc = port_info->tc; @@ -2888,6 +2890,7 @@ p4_pd_status_t switch_pd_egress_port_mapping_table_add_entry( memset(&action_spec, 0, sizeof(action_spec)); action_spec.action_ifindex = ifindex; action_spec.action_qos_group = qos_group; + action_spec.action_if_label = port_id + 1; status = p4_pd_dc_egress_port_mapping_table_add_with_egress_port_type_normal( g_sess_hdl, p4_pd_device, &match_spec, &action_spec, entry_hdl); @@ -2911,6 +2914,7 @@ p4_pd_status_t switch_pd_egress_port_mapping_table_add_entry( memset(&action_spec, 0, sizeof(action_spec)); action_spec.action_ifindex = ifindex; action_spec.action_qos_group = qos_group; + action_spec.action_if_label = port_id + 1; status = p4_pd_dc_egress_port_mapping_table_modify_with_egress_port_type_normal( g_sess_hdl, device, *entry_hdl, &action_spec); @@ -4074,7 +4078,9 @@ p4_pd_status_t switch_pd_system_acl_table_add_entry( } p4_pd_status_t switch_pd_system_acl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl) { + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl) { p4_pd_status_t status = 0; p4_pd_dc_system_acl_table_delete(g_sess_hdl, device, entry_hdl); return status; @@ -4499,25 +4505,21 @@ p4_pd_status_t switch_pd_ipv4_acl_table_add_entry( match_spec.l3_metadata_lkp_ip_proto = ip_acl[i].value.ip_proto; match_spec.l3_metadata_lkp_ip_proto_mask = ip_acl[i].mask.u.mask & 0xFF; break; - case SWITCH_ACL_IP_FIELD_L4_SOURCE_PORT: - match_spec.l3_metadata_lkp_l4_sport = ip_acl[i].value.l4_source_port; - match_spec.l3_metadata_lkp_l4_sport_mask = - ip_acl[i].mask.u.mask & 0xFFFF; + case SWITCH_ACL_IP_FIELD_L4_SOURCE_PORT_RANGE: + match_spec.acl_metadata_ingress_src_port_range_id = + handle_to_id(ip_acl[i].value.sport_range_handle); break; - case SWITCH_ACL_IP_FIELD_L4_DEST_PORT: - match_spec.l3_metadata_lkp_l4_dport = ip_acl[i].value.l4_dest_port; - match_spec.l3_metadata_lkp_l4_dport_mask = - ip_acl[i].mask.u.mask & 0xFFFF; + case SWITCH_ACL_IP_FIELD_L4_DEST_PORT_RANGE: + match_spec.acl_metadata_ingress_dst_port_range_id = + handle_to_id(ip_acl[i].value.dport_range_handle); break; case SWITCH_ACL_IP_FIELD_ICMP_TYPE: - match_spec.l3_metadata_lkp_l4_sport |= ip_acl[i].value.icmp_type << 8; - match_spec.l3_metadata_lkp_l4_sport_mask |= - (ip_acl[i].mask.u.mask & 0xFF) << 8; + match_spec.acl_metadata_ingress_src_port_range_id = + handle_to_id(ip_acl[i].value.sport_range_handle); break; case SWITCH_ACL_IP_FIELD_ICMP_CODE: - match_spec.l3_metadata_lkp_l4_sport |= ip_acl[i].value.icmp_code; - match_spec.l3_metadata_lkp_l4_sport_mask |= - ip_acl[i].mask.u.mask & 0xFF; + match_spec.acl_metadata_ingress_src_port_range_id = + handle_to_id(ip_acl[i].value.sport_range_handle); break; case SWITCH_ACL_IP_FIELD_TCP_FLAGS: match_spec.tcp_flags = ip_acl[i].value.tcp_flags; @@ -4644,11 +4646,113 @@ p4_pd_status_t switch_pd_ipv4_acl_table_add_entry( return status; } +p4_pd_status_t switch_pd_egress_ipv4_acl_table_add_entry( + switch_device_t device, + uint16_t if_label, + uint16_t bd_label, + uint16_t priority, + unsigned int count, + switch_acl_ip_key_value_pair_t *ip_acl, + switch_acl_ip_action_t action, + switch_acl_action_params_t *action_params, + switch_acl_opt_action_params_t *opt_action_params, + p4_pd_entry_hdl_t *entry_hdl) { + p4_pd_status_t status = 0; +#ifdef P4_EGRESS_ACL_ENABLE +#if !defined(P4_ACL_DISABLE) && !defined(P4_IPV4_DISABLE) + p4_pd_dev_target_t p4_pd_device; + p4_pd_dc_egress_ip_acl_match_spec_t match_spec; + unsigned int i = 0; + + p4_pd_device.device_id = device; + p4_pd_device.dev_pipe_id = SWITCH_DEV_PIPE_ID; + + memset(&match_spec, 0, sizeof(match_spec)); + + if (if_label) { + match_spec.acl_metadata_egress_if_label = if_label; + match_spec.acl_metadata_egress_if_label_mask = 0xFFFF; + } + if (bd_label) { + match_spec.acl_metadata_egress_bd_label = bd_label; + match_spec.acl_metadata_egress_bd_label_mask = 0xFFFF; + } + + for (i = 0; i < count; i++) { + switch (ip_acl[i].field) { + case SWITCH_ACL_IP_FIELD_IPV4_SRC: + match_spec.ipv4_srcAddr = ip_acl[i].value.ipv4_source; + match_spec.ipv4_srcAddr_mask = ip_acl[i].mask.u.mask & 0xFFFFFFFF; + break; + case SWITCH_ACL_IP_FIELD_IPV4_DEST: + match_spec.ipv4_dstAddr = ip_acl[i].value.ipv4_dest; + match_spec.ipv4_dstAddr_mask = ip_acl[i].mask.u.mask & 0xFFFFFFFF; + break; + case SWITCH_ACL_IP_FIELD_IP_PROTO: + match_spec.ipv4_protocol = ip_acl[i].value.ip_proto; + match_spec.ipv4_protocol_mask = ip_acl[i].mask.u.mask & 0xFF; + break; + case SWITCH_ACL_IP_FIELD_L4_SOURCE_PORT_RANGE: + match_spec.acl_metadata_egress_src_port_range_id = + handle_to_id(ip_acl[i].value.sport_range_handle); + break; + case SWITCH_ACL_IP_FIELD_L4_DEST_PORT_RANGE: + match_spec.acl_metadata_egress_dst_port_range_id = + handle_to_id(ip_acl[i].value.dport_range_handle); + break; + default: + break; + } + } + switch (action) { + case SWITCH_ACL_ACTION_DROP: { + p4_pd_dc_egress_acl_deny_action_spec_t action_spec; + memset(&action_spec, 0, sizeof(action_spec)); + action_spec.action_acl_copy_reason = + action_params->cpu_redirect.reason_code; + status = + p4_pd_dc_egress_ip_acl_table_add_with_egress_acl_deny(g_sess_hdl, + p4_pd_device, + &match_spec, + priority, + &action_spec, + entry_hdl); + } break; + case SWITCH_ACL_ACTION_PERMIT: { + p4_pd_dc_egress_acl_permit_action_spec_t action_spec; + memset(&action_spec, 0, sizeof(action_spec)); + action_spec.action_acl_copy_reason = + action_params->cpu_redirect.reason_code; + status = + p4_pd_dc_egress_ip_acl_table_add_with_egress_acl_permit(g_sess_hdl, + p4_pd_device, + &match_spec, + priority, + &action_spec, + entry_hdl); + } break; + default: + break; + } +#endif /* P4_ACL_DISABLE && P4_IPV4_DISABLE */ +#endif /* P4_EGRESS_ACL_ENABLE */ + p4_pd_complete_operations(g_sess_hdl); + return status; +} + p4_pd_status_t switch_pd_ipv4_acl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl) { + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl) { p4_pd_status_t status = 0; #if !defined(P4_IPV4_DISABLE) && !defined(P4_ACL_DISABLE) - p4_pd_dc_ip_acl_table_delete(g_sess_hdl, device, entry_hdl); + if (direction == SWITCH_API_DIRECTION_INGRESS) { + status = p4_pd_dc_ip_acl_table_delete(g_sess_hdl, device, entry_hdl); + } else { +#ifdef P4_EGRESS_ACL_ENABLE + status = p4_pd_dc_egress_ip_acl_table_delete(g_sess_hdl, device, entry_hdl); +#endif /* P4_EGRESS_ACL_ENABLE */ + } #endif /* P4_IPV4_DISABLE & P4_ACL_DISABLE */ p4_pd_complete_operations(g_sess_hdl); return status; @@ -4714,25 +4818,21 @@ p4_pd_status_t switch_pd_ipv6_acl_table_add_entry( match_spec.l3_metadata_lkp_ip_proto_mask = ipv6_acl[i].mask.u.mask.u.addr8[0] & 0xFF; break; - case SWITCH_ACL_IPV6_FIELD_L4_SOURCE_PORT: - match_spec.l3_metadata_lkp_l4_sport = ipv6_acl[i].value.l4_source_port; - match_spec.l3_metadata_lkp_l4_sport_mask = - ipv6_acl[i].mask.u.mask.u.addr16[0] & 0xFFFF; + case SWITCH_ACL_IPV6_FIELD_L4_SOURCE_PORT_RANGE: + match_spec.acl_metadata_ingress_src_port_range_id = + handle_to_id(ipv6_acl[i].value.sport_range_handle); break; - case SWITCH_ACL_IPV6_FIELD_L4_DEST_PORT: - match_spec.l3_metadata_lkp_l4_dport = ipv6_acl[i].value.l4_dest_port; - match_spec.l3_metadata_lkp_l4_dport_mask = - ipv6_acl[i].mask.u.mask.u.addr16[0] & 0xFFFF; + case SWITCH_ACL_IPV6_FIELD_L4_DEST_PORT_RANGE: + match_spec.acl_metadata_ingress_dst_port_range_id = + handle_to_id(ipv6_acl[i].value.dport_range_handle); break; case SWITCH_ACL_IPV6_FIELD_ICMP_TYPE: - match_spec.l3_metadata_lkp_l4_sport |= ipv6_acl[i].value.icmp_type << 8; - match_spec.l3_metadata_lkp_l4_sport_mask |= - (ipv6_acl[i].mask.u.mask.u.addr8[0] & 0xFF) << 8; + match_spec.acl_metadata_ingress_src_port_range_id = + handle_to_id(ipv6_acl[i].value.sport_range_handle); break; case SWITCH_ACL_IPV6_FIELD_ICMP_CODE: - match_spec.l3_metadata_lkp_l4_sport |= ipv6_acl[i].value.icmp_code; - match_spec.l3_metadata_lkp_l4_sport_mask |= - ipv6_acl[i].mask.u.mask.u.addr8[0] & 0xFF; + match_spec.acl_metadata_ingress_src_port_range_id = + handle_to_id(ipv6_acl[i].value.sport_range_handle); break; case SWITCH_ACL_IPV6_FIELD_TCP_FLAGS: match_spec.tcp_flags = ipv6_acl[i].value.tcp_flags; @@ -4826,11 +4926,120 @@ p4_pd_status_t switch_pd_ipv6_acl_table_add_entry( return status; } +p4_pd_status_t switch_pd_egress_ipv6_acl_table_add_entry( + switch_device_t device, + uint16_t if_label, + uint16_t bd_label, + uint16_t priority, + unsigned int count, + switch_acl_ipv6_key_value_pair_t *ipv6_acl, + switch_acl_ipv6_action_t action, + switch_acl_action_params_t *action_params, + switch_acl_opt_action_params_t *opt_action_params, + p4_pd_entry_hdl_t *entry_hdl) { + p4_pd_status_t status = 0; +#if !defined(P4_IPV6_DISABLE) && !defined(P4_ACL_DISABLE) +#ifdef P4_EGRESS_ACL_ENABLE + p4_pd_dev_target_t p4_pd_device; + p4_pd_dc_egress_ipv6_acl_match_spec_t match_spec; + unsigned int i = 0; + + p4_pd_device.device_id = device; + p4_pd_device.dev_pipe_id = SWITCH_DEV_PIPE_ID; + + memset(&match_spec, 0, sizeof(match_spec)); + + if (if_label) { + match_spec.acl_metadata_egress_if_label = if_label; + match_spec.acl_metadata_egress_if_label_mask = 0xFFFF; + } + if (bd_label) { + match_spec.acl_metadata_egress_bd_label = bd_label; + match_spec.acl_metadata_egress_bd_label_mask = 0xFFFF; + } + + for (i = 0; i < count; i++) { + switch (ipv6_acl[i].field) { + case SWITCH_ACL_IPV6_FIELD_IPV6_SRC: + memcpy( + match_spec.ipv6_srcAddr, ipv6_acl[i].value.ipv6_source.u.addr8, 16); + memcpy( + match_spec.ipv6_srcAddr_mask, ipv6_acl[i].mask.u.mask.u.addr8, 16); + break; + case SWITCH_ACL_IPV6_FIELD_IPV6_DEST: + memcpy( + match_spec.ipv6_dstAddr, ipv6_acl[i].value.ipv6_dest.u.addr8, 16); + memcpy( + match_spec.ipv6_dstAddr_mask, ipv6_acl[i].mask.u.mask.u.addr8, 16); + break; + case SWITCH_ACL_IPV6_FIELD_IP_PROTO: + match_spec.ipv6_nextHdr = ipv6_acl[i].value.ip_proto; + match_spec.ipv6_nextHdr_mask = + ipv6_acl[i].mask.u.mask.u.addr8[0] & 0xFF; + break; + case SWITCH_ACL_IPV6_FIELD_L4_SOURCE_PORT_RANGE: + match_spec.acl_metadata_egress_src_port_range_id = + handle_to_id(ipv6_acl[i].value.sport_range_handle); + break; + case SWITCH_ACL_IPV6_FIELD_L4_DEST_PORT_RANGE: + match_spec.acl_metadata_egress_dst_port_range_id = + handle_to_id(ipv6_acl[i].value.dport_range_handle); + break; + default: + break; + } + } + switch (action) { + case SWITCH_ACL_ACTION_DROP: { + p4_pd_dc_egress_acl_deny_action_spec_t action_spec; + memset(&action_spec, 0, sizeof(action_spec)); + action_spec.action_acl_copy_reason = + action_params->cpu_redirect.reason_code; + status = + p4_pd_dc_egress_ipv6_acl_table_add_with_egress_acl_deny(g_sess_hdl, + p4_pd_device, + &match_spec, + priority, + &action_spec, + entry_hdl); + } break; + case SWITCH_ACL_ACTION_PERMIT: { + p4_pd_dc_egress_acl_permit_action_spec_t action_spec; + memset(&action_spec, 0, sizeof(action_spec)); + action_spec.action_acl_copy_reason = + action_params->cpu_redirect.reason_code; + status = p4_pd_dc_egress_ipv6_acl_table_add_with_egress_acl_permit( + g_sess_hdl, + p4_pd_device, + &match_spec, + priority, + &action_spec, + entry_hdl); + } break; + default: + break; + } + +#endif /* P4_EGRESS_ACL_ENABLE */ +#endif /* P4_IPV6_DISABLE && P4_ACL_DISABLE */ + p4_pd_complete_operations(g_sess_hdl); + return status; +} + p4_pd_status_t switch_pd_ipv6_acl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl) { + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl) { p4_pd_status_t status = 0; #if !defined(P4_IPV6_DISABLE) && !defined(P4_ACL_DISABLE) - p4_pd_dc_ipv6_acl_table_delete(g_sess_hdl, device, entry_hdl); + if (direction == SWITCH_API_DIRECTION_INGRESS) { + status = p4_pd_dc_ipv6_acl_table_delete(g_sess_hdl, device, entry_hdl); + } else { +#ifdef P4_EGRESS_ACL_ENABLE + status = + p4_pd_dc_egress_ipv6_acl_table_delete(g_sess_hdl, device, entry_hdl); +#endif /* P4_EGRESS_ACL_ENABLE */ + } #endif /* P4_IPV6_DISABLE & P4_ACL_DISABLE */ p4_pd_complete_operations(g_sess_hdl); return status; @@ -4887,15 +5096,13 @@ p4_pd_status_t switch_pd_ipv4_racl_table_add_entry( match_spec.l3_metadata_lkp_ip_proto_mask = ip_racl[i].mask.u.mask & 0xFF; break; - case SWITCH_ACL_IP_RACL_FIELD_L4_SOURCE_PORT: - match_spec.l3_metadata_lkp_l4_sport = ip_racl[i].value.l4_source_port; - match_spec.l3_metadata_lkp_l4_sport_mask = - ip_racl[i].mask.u.mask & 0xFFFF; + case SWITCH_ACL_IP_RACL_FIELD_L4_SOURCE_PORT_RANGE: + match_spec.acl_metadata_ingress_src_port_range_id = + handle_to_id(ip_racl[i].value.sport_range_handle); break; - case SWITCH_ACL_IP_RACL_FIELD_L4_DEST_PORT: - match_spec.l3_metadata_lkp_l4_dport = ip_racl[i].value.l4_dest_port; - match_spec.l3_metadata_lkp_l4_dport_mask = - ip_racl[i].mask.u.mask & 0xFFFF; + case SWITCH_ACL_IP_RACL_FIELD_L4_DEST_PORT_RANGE: + match_spec.acl_metadata_ingress_dst_port_range_id = + handle_to_id(ip_racl[i].value.dport_range_handle); break; default: break; @@ -4980,7 +5187,9 @@ p4_pd_status_t switch_pd_ipv4_racl_table_add_entry( } p4_pd_status_t switch_pd_ipv4_racl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl) { + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl) { p4_pd_status_t status = 0; #if !defined(P4_IPV4_DISABLE) && !defined(P4_ACL_DISABLE) p4_pd_dc_ipv4_racl_table_delete(g_sess_hdl, device, entry_hdl); @@ -5034,15 +5243,13 @@ p4_pd_status_t switch_pd_ipv6_racl_table_add_entry( match_spec.l3_metadata_lkp_ip_proto_mask = ipv6_racl[i].mask.u.mask.u.addr8[0] & 0xFF; break; - case SWITCH_ACL_IPV6_RACL_FIELD_L4_SOURCE_PORT: - match_spec.l3_metadata_lkp_l4_sport = ipv6_racl[i].value.l4_source_port; - match_spec.l3_metadata_lkp_l4_sport_mask = - ipv6_racl[i].mask.u.mask.u.addr16[0] & 0xFFFF; + case SWITCH_ACL_IPV6_RACL_FIELD_L4_SOURCE_PORT_RANGE: + match_spec.acl_metadata_ingress_src_port_range_id = + handle_to_id(ipv6_racl[i].value.sport_range_handle); break; - case SWITCH_ACL_IPV6_RACL_FIELD_L4_DEST_PORT: - match_spec.l3_metadata_lkp_l4_dport = ipv6_racl[i].value.l4_dest_port; - match_spec.l3_metadata_lkp_l4_dport_mask = - ipv6_racl[i].mask.u.mask.u.addr16[0] & 0xFFFF; + case SWITCH_ACL_IPV6_RACL_FIELD_L4_DEST_PORT_RANGE: + match_spec.acl_metadata_ingress_dst_port_range_id = + handle_to_id(ipv6_racl[i].value.dport_range_handle); break; default: break; @@ -5126,7 +5333,9 @@ p4_pd_status_t switch_pd_ipv6_racl_table_add_entry( } p4_pd_status_t switch_pd_ipv6_racl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl) { + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl) { p4_pd_status_t status = 0; #if !defined(P4_IPV6_DISABLE) && !defined(P4_ACL_DISABLE) p4_pd_dc_ipv6_racl_table_delete(g_sess_hdl, device, entry_hdl); @@ -5266,11 +5475,111 @@ p4_pd_status_t switch_pd_mac_acl_table_add_entry( return status; } +p4_pd_status_t switch_pd_egress_mac_acl_table_add_entry( + switch_device_t device, + uint16_t if_label, + uint16_t bd_label, + uint16_t priority, + unsigned int count, + switch_acl_mac_key_value_pair_t *mac_acl, + switch_acl_mac_action_t action, + switch_acl_action_params_t *action_params, + switch_acl_opt_action_params_t *opt_action_params, + p4_pd_entry_hdl_t *entry_hdl) { + p4_pd_status_t status = 0; +#if !defined(P4_L2_DISABLE) && !defined(P4_ACL_DISABLE) +#ifdef P4_EGRESS_ACL_ENABLE + p4_pd_dev_target_t p4_pd_device; + p4_pd_dc_egress_mac_acl_match_spec_t match_spec; + unsigned int i = 0; + + p4_pd_device.device_id = device; + p4_pd_device.dev_pipe_id = SWITCH_DEV_PIPE_ID; + + memset(&match_spec, 0, sizeof(p4_pd_dc_mac_acl_match_spec_t)); + + if (if_label) { + match_spec.acl_metadata_egress_if_label = if_label; + match_spec.acl_metadata_egress_if_label_mask = 0xFFFF; + } + if (bd_label) { + match_spec.acl_metadata_egress_bd_label = bd_label; + match_spec.acl_metadata_egress_bd_label_mask = 0xFFFF; + } + for (i = 0; i < count; i++) { + switch (mac_acl[i].field) { + case SWITCH_ACL_MAC_FIELD_ETH_TYPE: + match_spec.ethernet_etherType = mac_acl[i].value.eth_type; + match_spec.ethernet_etherType_mask = mac_acl[i].mask.u.mask16 & 0xFFFF; + break; + case SWITCH_ACL_MAC_FIELD_SOURCE_MAC: + memcpy(match_spec.ethernet_srcAddr, + mac_acl[i].value.source_mac.mac_addr, + ETH_LEN); + memcpy( + match_spec.ethernet_srcAddr_mask, &mac_acl[i].mask.u.mask, ETH_LEN); + break; + case SWITCH_ACL_MAC_FIELD_DEST_MAC: + memcpy(match_spec.ethernet_dstAddr, + mac_acl[i].value.dest_mac.mac_addr, + ETH_LEN); + memcpy( + match_spec.ethernet_dstAddr_mask, &mac_acl[i].mask.u.mask, ETH_LEN); + break; + default: + break; + } + } + switch (action) { + case SWITCH_ACL_ACTION_DROP: { + p4_pd_dc_egress_acl_deny_action_spec_t action_spec; + memset(&action_spec, 0, sizeof(action_spec)); + action_spec.action_acl_copy_reason = + action_params->cpu_redirect.reason_code; + status = + p4_pd_dc_egress_mac_acl_table_add_with_egress_acl_deny(g_sess_hdl, + p4_pd_device, + &match_spec, + priority, + &action_spec, + entry_hdl); + } break; + case SWITCH_ACL_ACTION_PERMIT: { + p4_pd_dc_egress_acl_permit_action_spec_t action_spec; + memset(&action_spec, 0, sizeof(action_spec)); + action_spec.action_acl_copy_reason = + action_params->cpu_redirect.reason_code; + status = + p4_pd_dc_egress_mac_acl_table_add_with_egress_acl_permit(g_sess_hdl, + p4_pd_device, + &match_spec, + priority, + &action_spec, + entry_hdl); + } break; + default: + break; + } +#endif /* P4_EGRESS_ACL_ENABLE */ +#endif /* P4_L2_DISABLE && P4_ACL_DISABLE */ + p4_pd_complete_operations(g_sess_hdl); + return status; +} + p4_pd_status_t switch_pd_mac_acl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl) { + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl) { p4_pd_status_t status = 0; #if !defined(P4_L2_DISABLE) && !defined(P4_ACL_DISABLE) - p4_pd_dc_mac_acl_table_delete(g_sess_hdl, device, entry_hdl); + if (direction == SWITCH_API_DIRECTION_INGRESS) { + status = p4_pd_dc_mac_acl_table_delete(g_sess_hdl, device, entry_hdl); + } else { +#ifdef P4_EGRESS_ACL_ENABLE + status = + p4_pd_dc_egress_mac_acl_table_delete(g_sess_hdl, device, entry_hdl); +#endif /* P4_EGRESS_ACL_ENABLE */ + } #endif /* P4_L2_DISABLE & P4_ACL_DISABLE */ p4_pd_complete_operations(g_sess_hdl); return status; @@ -5294,12 +5603,12 @@ p4_pd_status_t switch_pd_egr_acl_table_add_entry( #ifndef P4_ACL_DISABLE unsigned int i; p4_pd_dev_target_t p4_pd_device; - p4_pd_dc_egress_acl_match_spec_t match_spec; + p4_pd_dc_egress_system_acl_match_spec_t match_spec; p4_pd_device.device_id = device; p4_pd_device.dev_pipe_id = SWITCH_DEV_PIPE_ID; - memset(&match_spec, 0, sizeof(p4_pd_dc_egress_acl_match_spec_t)); + memset(&match_spec, 0, sizeof(p4_pd_dc_egress_system_acl_match_spec_t)); for (i = 0; i < count; i++) { switch (egr_acl[i].field) { case SWITCH_ACL_EGR_DEST_PORT: { @@ -5316,42 +5625,53 @@ p4_pd_status_t switch_pd_egr_acl_table_add_entry( match_spec.l3_metadata_l3_mtu_check = egr_acl[i].value.l3_mtu_check; match_spec.l3_metadata_l3_mtu_check_mask = 0xFFFF; } break; + case SWITCH_ACL_EGR_ACL_DENY: { + match_spec.acl_metadata_acl_deny = egr_acl[i].value.acl_deny; + match_spec.acl_metadata_acl_deny_mask = 0xFF; + } break; default: break; } } switch (action) { - case SWITCH_ACL_EGR_ACTION_NOP: - status = p4_pd_dc_egress_acl_table_add_with_nop( + case SWITCH_ACL_EGR_ACTION_PERMIT: { + status = p4_pd_dc_egress_system_acl_table_add_with_nop( g_sess_hdl, p4_pd_device, &match_spec, priority, entry_hdl); - break; + } break; + case SWITCH_ACL_EGR_ACTION_DROP: { + status = p4_pd_dc_egress_system_acl_table_add_with_drop_packet( + g_sess_hdl, p4_pd_device, &match_spec, priority, entry_hdl); + } break; case SWITCH_ACL_EGR_ACTION_SET_MIRROR: { #if !defined(P4_MIRROR_DISABLE) p4_pd_dc_egress_mirror_action_spec_t action_spec; action_spec.action_session_id = handle_to_id(opt_action_params->mirror_handle); - status = p4_pd_dc_egress_acl_table_add_with_egress_mirror(g_sess_hdl, - p4_pd_device, - &match_spec, - priority, - &action_spec, - entry_hdl); + status = + p4_pd_dc_egress_system_acl_table_add_with_egress_mirror(g_sess_hdl, + p4_pd_device, + &match_spec, + priority, + &action_spec, + entry_hdl); break; #endif /* P4_MIRROR_DISABLE */ } case SWITCH_ACL_EGR_ACTION_REDIRECT_TO_CPU: { - p4_pd_dc_egress_redirect_to_cpu_action_spec_t action_spec; + p4_pd_dc_egress_redirect_to_cpu_with_reason_action_spec_t action_spec; action_spec.action_reason_code = action_params->cpu_redirect.reason_code; - status = p4_pd_dc_egress_acl_table_add_with_egress_redirect_to_cpu( - g_sess_hdl, - p4_pd_device, - &match_spec, - priority, - &action_spec, - entry_hdl); + status = + p4_pd_dc_egress_system_acl_table_add_with_egress_redirect_to_cpu_with_reason( + g_sess_hdl, + p4_pd_device, + &match_spec, + priority, + &action_spec, + entry_hdl); break; } + default: break; } @@ -5362,10 +5682,13 @@ p4_pd_status_t switch_pd_egr_acl_table_add_entry( } p4_pd_status_t switch_pd_egr_acl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl) { + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl) { p4_pd_status_t status = 0; #ifndef P4_ACL_DISABLE - status = p4_pd_dc_egress_acl_table_delete(g_sess_hdl, device, entry_hdl); + status = + p4_pd_dc_egress_system_acl_table_delete(g_sess_hdl, device, entry_hdl); p4_pd_complete_operations(g_sess_hdl); #endif /* P4_ACL_DISABLE */ return status; @@ -6073,6 +6396,25 @@ p4_pd_status_t switch_pd_acl_table_add_default_entry(switch_device_t device) { #endif /* P4_ACL_DISABLE */ #endif /* P4_STATS_DISABLE */ +#ifndef P4_ACL_DISABLE +#ifdef P4_EGRESS_ACL_ENABLE + + status = p4_pd_dc_egress_mac_acl_set_default_action_nop( + g_sess_hdl, p4_pd_device, &entry_hdl); + +#ifndef P4_IPV4_DISABLE + status = p4_pd_dc_egress_ip_acl_set_default_action_nop( + g_sess_hdl, p4_pd_device, &entry_hdl); +#endif /* P4_IPV4_DISABLE */ + +#ifndef P4_IPV6_DISABLE + status = p4_pd_dc_egress_ipv6_acl_set_default_action_nop( + g_sess_hdl, p4_pd_device, &entry_hdl); +#endif /* P4_IPV6_DISABLE */ + +#endif /* P4_EGRESS_ACL_ENABLE */ +#endif /* P4_ACL_DISABLE */ + p4_pd_complete_operations(g_sess_hdl); return status; } @@ -6362,7 +6704,7 @@ p4_pd_status_t switch_pd_egress_acl_add_default_entry(switch_device_t device) { p4_pd_device.device_id = device; p4_pd_device.dev_pipe_id = SWITCH_DEV_PIPE_ID; - status = p4_pd_dc_egress_acl_set_default_action_nop( + status = p4_pd_dc_egress_system_acl_set_default_action_nop( g_sess_hdl, p4_pd_device, &entry_hdl); #endif /* P4_ACL_DISABLE */ p4_pd_complete_operations(g_sess_hdl); @@ -8796,13 +9138,13 @@ switch_status_t switch_pd_sflow_session_delete( if (sflow_info->mirror_table_ent_hdl != SWITCH_API_INVALID_HANDLE) { p4_pd_dc_mirror_table_delete( g_sess_hdl, device, sflow_info->mirror_table_ent_hdl); - sflow_info->mirror_table_ent_hdl = SWITCH_API_INVALID_HANDLE; + sflow_info->mirror_table_ent_hdl = SWITCH_HW_INVALID_HANDLE; op_started = true; } if (sflow_info->ing_take_sample_table_ent_hdl != SWITCH_API_INVALID_HANDLE) { p4_pd_dc_sflow_ing_take_sample_table_delete( g_sess_hdl, device, sflow_info->ing_take_sample_table_ent_hdl); - sflow_info->ing_take_sample_table_ent_hdl = SWITCH_API_INVALID_HANDLE; + sflow_info->ing_take_sample_table_ent_hdl = SWITCH_HW_INVALID_HANDLE; op_started = true; } if (op_started) { @@ -8929,3 +9271,272 @@ p4_pd_status_t switch_pd_hostif_meter_set(switch_device_t device, return status; } + +p4_pd_status_t switch_pd_range_entry_add(switch_device_t device, + switch_direction_t direction, + uint16_t range_id, + switch_range_type_t range_type, + switch_range_t *range, + p4_pd_entry_hdl_t *entry_hdl) { + p4_pd_status_t status = 0; + +#ifndef P4_ACL_RANGE_DISABLE + + p4_pd_dev_target_t p4_pd_device; + + p4_pd_device.device_id = device; + p4_pd_device.dev_pipe_id = SWITCH_DEV_PIPE_ID; + + switch (range_type) { + case SWITCH_RANGE_TYPE_SRC_PORT: { + if (direction == SWITCH_API_DIRECTION_INGRESS) { + p4_pd_dc_ingress_l4_src_port_match_spec_t match_spec; + p4_pd_dc_set_ingress_src_port_range_id_action_spec_t action_spec; + memset(&match_spec, 0x0, sizeof(match_spec)); + memset(&action_spec, 0x0, sizeof(action_spec)); + match_spec.l3_metadata_lkp_l4_sport_start = range->start_value; + match_spec.l3_metadata_lkp_l4_sport_end = range->end_value; + action_spec.action_range_id = range_id; + status = + p4_pd_dc_ingress_l4_src_port_table_add_with_set_ingress_src_port_range_id( + g_sess_hdl, + p4_pd_device, + &match_spec, + 1000, + &action_spec, + entry_hdl); + } else { +#ifdef P4_EGRESS_ACL_ENABLE + p4_pd_dc_egress_l4_src_port_match_spec_t match_spec; + p4_pd_dc_set_egress_src_port_range_id_action_spec_t action_spec; + memset(&match_spec, 0x0, sizeof(match_spec)); + memset(&action_spec, 0x0, sizeof(action_spec)); + match_spec.l3_metadata_egress_l4_sport_start = range->start_value; + match_spec.l3_metadata_egress_l4_sport_end = range->end_value; + action_spec.action_range_id = range_id; + status = + p4_pd_dc_egress_l4_src_port_table_add_with_set_egress_src_port_range_id( + g_sess_hdl, + p4_pd_device, + &match_spec, + 1000, + &action_spec, + entry_hdl); +#endif /* P4_EGRESS_ACL_ENABLE */ + } + } break; + + case SWITCH_RANGE_TYPE_DST_PORT: { + if (direction == SWITCH_API_DIRECTION_INGRESS) { + p4_pd_dc_ingress_l4_dst_port_match_spec_t match_spec; + p4_pd_dc_set_ingress_dst_port_range_id_action_spec_t action_spec; + memset(&match_spec, 0x0, sizeof(match_spec)); + memset(&action_spec, 0x0, sizeof(action_spec)); + match_spec.l3_metadata_lkp_l4_dport_start = range->start_value; + match_spec.l3_metadata_lkp_l4_dport_end = range->end_value; + action_spec.action_range_id = range_id; + status = + p4_pd_dc_ingress_l4_dst_port_table_add_with_set_ingress_dst_port_range_id( + g_sess_hdl, + p4_pd_device, + &match_spec, + 1000, + &action_spec, + entry_hdl); + } else { +#ifdef P4_EGRESS_ACL_ENABLE + p4_pd_dc_egress_l4_dst_port_match_spec_t match_spec; + p4_pd_dc_set_egress_dst_port_range_id_action_spec_t action_spec; + memset(&match_spec, 0x0, sizeof(match_spec)); + memset(&action_spec, 0x0, sizeof(action_spec)); + match_spec.l3_metadata_egress_l4_dport_start = range->start_value; + match_spec.l3_metadata_egress_l4_dport_end = range->end_value; + action_spec.action_range_id = range_id; + status = + p4_pd_dc_egress_l4_dst_port_table_add_with_set_egress_dst_port_range_id( + g_sess_hdl, + p4_pd_device, + &match_spec, + 1000, + &action_spec, + entry_hdl); +#endif /* P4_EGRESS_ACL_ENABLE */ + } + } break; + default: + return SWITCH_STATUS_NOT_SUPPORTED; + } + +#endif /* P4_ACL_RANGE_DISABLE */ + + return status; +} + +p4_pd_status_t switch_pd_range_entry_update(switch_device_t device, + switch_direction_t direction, + uint16_t range_id, + switch_range_type_t range_type, + switch_range_t *range, + p4_pd_entry_hdl_t entry_hdl) { + p4_pd_status_t status = 0; + +#ifndef P4_ACL_RANGE_DISABLE + + switch (range_type) { + case SWITCH_RANGE_TYPE_SRC_PORT: { + if (direction == SWITCH_API_DIRECTION_INGRESS) { + p4_pd_dc_set_ingress_src_port_range_id_action_spec_t action_spec; + memset(&action_spec, 0x0, sizeof(action_spec)); + action_spec.action_range_id = range_id; + status = + p4_pd_dc_ingress_l4_src_port_table_modify_with_set_ingress_src_port_range_id( + g_sess_hdl, device, entry_hdl, &action_spec); + } else { +#ifdef P4_EGRESS_ACL_ENABLE + p4_pd_dc_set_egress_src_port_range_id_action_spec_t action_spec; + memset(&action_spec, 0x0, sizeof(action_spec)); + action_spec.action_range_id = range_id; + status = + p4_pd_dc_egress_l4_src_port_table_modify_with_set_egress_src_port_range_id( + g_sess_hdl, device, entry_hdl, &action_spec); +#endif /* P4_EGRESS_ACL_ENABLE */ + } + } break; + + case SWITCH_RANGE_TYPE_DST_PORT: { + if (direction == SWITCH_API_DIRECTION_INGRESS) { + p4_pd_dc_set_ingress_dst_port_range_id_action_spec_t action_spec; + memset(&action_spec, 0x0, sizeof(action_spec)); + action_spec.action_range_id = range_id; + status = + p4_pd_dc_ingress_l4_dst_port_table_modify_with_set_ingress_dst_port_range_id( + g_sess_hdl, device, entry_hdl, &action_spec); + } else { +#ifdef P4_EGRESS_ACL_ENABLE + p4_pd_dc_set_egress_dst_port_range_id_action_spec_t action_spec; + memset(&action_spec, 0x0, sizeof(action_spec)); + action_spec.action_range_id = range_id; + status = + p4_pd_dc_egress_l4_dst_port_table_modify_with_set_egress_dst_port_range_id( + g_sess_hdl, device, entry_hdl, &action_spec); +#endif /* P4_EGRESS_ACL_ENABLE */ + } + } break; + default: + return SWITCH_STATUS_NOT_SUPPORTED; + } + +#endif /* P4_ACL_RANGE_DISABLE */ + + return status; +} + +p4_pd_status_t switch_pd_range_entry_delete(switch_device_t device, + switch_direction_t direction, + switch_range_type_t range_type, + p4_pd_entry_hdl_t entry_hdl) { + p4_pd_status_t status = 0; + +#ifndef P4_ACL_RANGE_DISABLE + + switch (range_type) { + case SWITCH_RANGE_TYPE_SRC_PORT: { + if (direction == SWITCH_API_DIRECTION_INGRESS) { + status = p4_pd_dc_ingress_l4_src_port_table_delete( + g_sess_hdl, device, entry_hdl); + } else { +#ifdef P4_EGRESS_ACL_ENABLE + status = p4_pd_dc_egress_l4_src_port_table_delete( + g_sess_hdl, device, entry_hdl); +#endif /* P4_EGRESS_ACL_ENABLE */ + } + break; + + case SWITCH_RANGE_TYPE_DST_PORT: { + if (direction == SWITCH_API_DIRECTION_INGRESS) { + status = p4_pd_dc_ingress_l4_dst_port_table_delete( + g_sess_hdl, device, entry_hdl); + } else { +#ifdef P4_EGRESS_ACL_ENABLE + status = p4_pd_dc_egress_l4_dst_port_table_delete( + g_sess_hdl, device, entry_hdl); +#endif /* P4_EGRESS_ACL_ENABLE */ + } + } break; + default: + return SWITCH_STATUS_NOT_SUPPORTED; + } + } + +#endif /* P4_ACL_RANGE_DISABLE */ + + return status; +} + +p4_pd_status_t switch_pd_egress_l4port_fields_init_entry( + switch_device_t device) { + p4_pd_status_t status = 0; + +#ifdef P4_EGRESS_ACL_ENABLE + p4_pd_dev_target_t p4_pd_device; + + p4_pd_device.device_id = device; + p4_pd_device.dev_pipe_id = SWITCH_DEV_PIPE_ID; + + p4_pd_entry_hdl_t entry_hdl; + p4_pd_dc_egress_l4port_fields_match_spec_t match_spec; + + status = p4_pd_dc_egress_l4port_fields_set_default_action_nop( + g_sess_hdl, p4_pd_device, &entry_hdl); + + memset(&match_spec, 0x0, sizeof(match_spec)); + match_spec.tcp_valid = 1; + status = + p4_pd_dc_egress_l4port_fields_table_add_with_set_egress_tcp_port_fields( + g_sess_hdl, p4_pd_device, &match_spec, &entry_hdl); + + memset(&match_spec, 0x0, sizeof(match_spec)); + match_spec.udp_valid = 1; + status = + p4_pd_dc_egress_l4port_fields_table_add_with_set_egress_udp_port_fields( + g_sess_hdl, p4_pd_device, &match_spec, &entry_hdl); + + memset(&match_spec, 0x0, sizeof(match_spec)); + match_spec.icmp_valid = 1; + status = + p4_pd_dc_egress_l4port_fields_table_add_with_set_egress_icmp_port_fields( + g_sess_hdl, p4_pd_device, &match_spec, &entry_hdl); + +#endif /* P4_EGRESS_ACL_ENABLE */ + + return status; +} + +p4_pd_status_t switch_pd_l4port_default_entry_add(switch_device_t device) { + p4_pd_status_t status = 0; + +#ifndef P4_ACL_RANGE_DISABLE + p4_pd_entry_hdl_t entry_hdl; + p4_pd_dev_target_t p4_pd_device; + + p4_pd_device.device_id = device; + p4_pd_device.dev_pipe_id = SWITCH_DEV_PIPE_ID; + + status = p4_pd_dc_ingress_l4_src_port_set_default_action_nop( + g_sess_hdl, p4_pd_device, &entry_hdl); + + status = p4_pd_dc_ingress_l4_dst_port_set_default_action_nop( + g_sess_hdl, p4_pd_device, &entry_hdl); + +#ifdef P4_EGRESS_ACL_ENABLE + status = p4_pd_dc_egress_l4_src_port_set_default_action_nop( + g_sess_hdl, p4_pd_device, &entry_hdl); + + status = p4_pd_dc_egress_l4_dst_port_set_default_action_nop( + g_sess_hdl, p4_pd_device, &entry_hdl); + +#endif /* P4_EGRESS_ACL_ENABLE */ +#endif /* P4_ACL_RANGE_DISABLE */ + + return status; +} diff --git a/switchapi/src/switch_pd.h b/switchapi/src/switch_pd.h index 482b671..b8ea187 100644 --- a/switchapi/src/switch_pd.h +++ b/switchapi/src/switch_pd.h @@ -563,8 +563,22 @@ p4_pd_status_t switch_pd_ipv4_acl_table_add_entry( switch_acl_opt_action_params_t *opt_action_params, p4_pd_entry_hdl_t *entry_hdl); +p4_pd_status_t switch_pd_egress_ipv4_acl_table_add_entry( + switch_device_t device, + uint16_t if_label, + uint16_t bd_label, + uint16_t priority, + unsigned int count, + switch_acl_ip_key_value_pair_t *ip_acl, + switch_acl_ip_action_t action, + switch_acl_action_params_t *action_params, + switch_acl_opt_action_params_t *opt_action_params, + p4_pd_entry_hdl_t *entry_hdl); + p4_pd_status_t switch_pd_ipv4_acl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl); + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl); p4_pd_status_t switch_pd_ipv6_acl_table_add_entry( switch_device_t device, @@ -578,8 +592,22 @@ p4_pd_status_t switch_pd_ipv6_acl_table_add_entry( switch_acl_opt_action_params_t *opt_action_params, p4_pd_entry_hdl_t *entry_hdl); +p4_pd_status_t switch_pd_egress_ipv6_acl_table_add_entry( + switch_device_t device, + uint16_t if_label, + uint16_t bd_label, + uint16_t priority, + unsigned int count, + switch_acl_ipv6_key_value_pair_t *ipv6_acl, + switch_acl_ipv6_action_t action, + switch_acl_action_params_t *action_params, + switch_acl_opt_action_params_t *opt_action_params, + p4_pd_entry_hdl_t *entry_hdl); + p4_pd_status_t switch_pd_ipv6_acl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl); + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl); p4_pd_status_t switch_pd_ipv4_racl_table_add_entry( switch_device_t device, @@ -594,7 +622,9 @@ p4_pd_status_t switch_pd_ipv4_racl_table_add_entry( p4_pd_entry_hdl_t *entry_hdl); p4_pd_status_t switch_pd_ipv4_racl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl); + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl); p4_pd_status_t switch_pd_ipv6_racl_table_add_entry( switch_device_t device, @@ -609,7 +639,9 @@ p4_pd_status_t switch_pd_ipv6_racl_table_add_entry( p4_pd_entry_hdl_t *entry_hdl); p4_pd_status_t switch_pd_ipv6_racl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl); + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl); p4_pd_status_t switch_pd_mac_acl_table_add_entry( switch_device_t device, @@ -623,8 +655,22 @@ p4_pd_status_t switch_pd_mac_acl_table_add_entry( switch_acl_opt_action_params_t *opt_action_params, p4_pd_entry_hdl_t *entry_hdl); +p4_pd_status_t switch_pd_egress_mac_acl_table_add_entry( + switch_device_t device, + uint16_t if_label, + uint16_t bd_label, + uint16_t priority, + unsigned int count, + switch_acl_mac_key_value_pair_t *mac_acl, + switch_acl_mac_action_t action, + switch_acl_action_params_t *action_params, + switch_acl_opt_action_params_t *opt_action_params, + p4_pd_entry_hdl_t *entry_hdl); + p4_pd_status_t switch_pd_mac_acl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl); + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl); p4_pd_status_t switch_pd_system_acl_table_add_entry( switch_device_t device, @@ -639,7 +685,9 @@ p4_pd_status_t switch_pd_system_acl_table_add_entry( p4_pd_entry_hdl_t *entry_hdl); p4_pd_status_t switch_pd_system_acl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl); + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl); p4_pd_status_t switch_pd_egr_acl_table_add_entry( switch_device_t device, @@ -654,7 +702,9 @@ p4_pd_status_t switch_pd_egr_acl_table_add_entry( p4_pd_entry_hdl_t *entry_hdl); p4_pd_status_t switch_pd_egr_acl_table_delete_entry( - switch_device_t device, p4_pd_entry_hdl_t entry_hdl); + switch_device_t device, + switch_direction_t direction, + p4_pd_entry_hdl_t entry_hdl); p4_pd_status_t switch_pd_bd_ingress_stats_get(switch_device_t device, switch_bd_stats_t *bd_stats); @@ -1174,6 +1224,29 @@ p4_pd_status_t switch_pd_hostif_meter_set(switch_device_t device, switch_meter_info_t *meter_info, bool enable); +p4_pd_status_t switch_pd_range_entry_add(switch_device_t device, + switch_direction_t direction, + uint16_t range_id, + switch_range_type_t range_type, + switch_range_t *range, + p4_pd_entry_hdl_t *entry_hdl); + +p4_pd_status_t switch_pd_range_entry_update(switch_device_t device, + switch_direction_t direction, + uint16_t range_id, + switch_range_type_t range_type, + switch_range_t *range, + p4_pd_entry_hdl_t entry_hdl); + +p4_pd_status_t switch_pd_range_entry_delete(switch_device_t device, + switch_direction_t direction, + switch_range_type_t range_type, + p4_pd_entry_hdl_t entry_hdl); + +p4_pd_status_t switch_pd_egress_l4port_fields_init_entry( + switch_device_t device); + +p4_pd_status_t switch_pd_l4port_default_entry_add(switch_device_t device); #ifdef __cplusplus } #endif diff --git a/switchapi/src/switch_port.c b/switchapi/src/switch_port.c index b25cdd2..b0c661d 100644 --- a/switchapi/src/switch_port.c +++ b/switchapi/src/switch_port.c @@ -331,7 +331,7 @@ switch_status_t switch_api_ppg_delete(switch_device_t device, ppg_info = switch_ppg_get(ppg_handle); if (!ppg_info) { SWITCH_API_ERROR("failed to allocate port_priority group"); - return SWITCH_API_INVALID_HANDLE; + return SWITCH_STATUS_INVALID_HANDLE; } status = switch_pd_ppg_delete(device, ppg_handle); @@ -419,7 +419,7 @@ switch_status_t switch_api_port_qos_group_ingress_set( qos_map_list = switch_qos_map_get(qos_handle); if (!qos_map_list) { SWITCH_API_ERROR("qos map get failed\n"); - return SWITCH_API_INVALID_HANDLE; + return SWITCH_STATUS_INVALID_HANDLE; } port_info->ingress_qos_group = qos_map_list->qos_group; } diff --git a/switchapi/src/switch_scheduler.c b/switchapi/src/switch_scheduler.c index 945ec16..4add559 100644 --- a/switchapi/src/switch_scheduler.c +++ b/switchapi/src/switch_scheduler.c @@ -143,7 +143,7 @@ switch_status_t switch_api_scheduler_delete(switch_device_t device, scheduler_info = switch_scheduler_info_get(scheduler_handle); if (!scheduler_info) { SWITCH_API_ERROR("scheduler create failed"); - return SWITCH_API_INVALID_HANDLE; + return SWITCH_STATUS_INVALID_HANDLE; } status = switch_scheduler_handle_delete(scheduler_handle); diff --git a/switchapi/src/switch_sflow.c b/switchapi/src/switch_sflow.c index c111f8f..382052c 100644 --- a/switchapi/src/switch_sflow.c +++ b/switchapi/src/switch_sflow.c @@ -131,8 +131,8 @@ switch_handle_t switch_api_sflow_session_create( tommy_list_init(&sflow_info->match_list); sflow_info->mirror_hdl = SWITCH_API_INVALID_HANDLE; - sflow_info->mirror_table_ent_hdl = SWITCH_API_INVALID_HANDLE; - sflow_info->ing_take_sample_table_ent_hdl = SWITCH_API_INVALID_HANDLE; + sflow_info->mirror_table_ent_hdl = SWITCH_HW_INVALID_HANDLE; + sflow_info->ing_take_sample_table_ent_hdl = SWITCH_HW_INVALID_HANDLE; // Create a mirror session to send sampled pkts to CPU. // SWITCH_CPU_MIRROR_SESSION_ID mirror-session can be used, except diff --git a/switchlink/Makefile.am b/switchlink/Makefile.am index a6c95b9..096178a 100644 --- a/switchlink/Makefile.am +++ b/switchlink/Makefile.am @@ -2,16 +2,13 @@ ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4 SUBDIRS = third-party/xxhash -libswitchlink_la_CFLAGS = -I$(srcdir)/third-party/xxhash/include -libswitchlink_la_CFLAGS += -I$(SUBMODULE_SWITCHSAI)/submodules/SAI/inc -libswitchlink_la_CFLAGS += -I$(SUBMODULE_SWITCHAPI)/third-party/tommyds/include -libswitchlink_la_CFLAGS += $(shell pkg-config --cflags libnl-3.0) -libswitchlink_a_CFLAGS = $(libswitchlink_la_CFLAGS) +AM_CPPFLAGS += -I$(srcdir)/third-party/xxhash/include +AM_CPPFLAGS += -I$(top_srcdir)/switchsai/submodules/SAI/inc +AM_CPPFLAGS += -I$(top_srcdir)/switchapi/third-party/tommyds/include +# TODO: could this be done in configure? +AM_CPPFLAGS += $(shell pkg-config --cflags libnl-3.0) -lib_LIBRARIES = libswitchlink.a -lib_LTLIBRARIES = libswitchlink.la - -libswitchlink_la_SOURCES = \ +switchlink_sources = \ src/switchlink_address.c \ src/switchlink_db.c \ src/switchlink_db.h \ @@ -32,9 +29,32 @@ src/switchlink_route.h \ src/switchlink_sai.c \ src/switchlink_sai.h -libswitchlink_a_SOURCES = $(libswitchlink_la_SOURCES) +noinst_LTLIBRARIES = +lib_LIBRARIES = +lib_LTLIBRARIES = +if WITH_BMV2 +# has the advantage of avoiding "created both with libtool and without" error +libswitchlink_la_CPPFLAGS = $(AM_CPPFLAGS) +libswitchlink_la_CPPFLAGS += -DBMV2 +noinst_LTLIBRARIES += libswitchlink.la +libswitchlink_la_SOURCES = $(switchlink_sources) libswitchlink_la_LIBADD = third-party/xxhash/libxxhash.la +libswitchlink_la_LIBADD += $(NETLINK_LIBS) +endif + +# FIXME: legacy support, relies on p4factory +if WITH_P4FACTORY +lib_LIBRARIES += libswitchlink.a +libswitchlink_a_SOURCES = $(switchlink_sources) +# FIXME: this also creates shared libraries for p4factory, needs to be +# deprecated +lib_LTLIBRARIES += libswitchlink.la +# has the advantage of avoiding "created both with libtool and without" error +libswitchlink_la_CPPFLAGS = $(AM_CPPFLAGS) +libswitchlink_la_SOURCES = $(switchlink_sources) +endif +# FIXME: dos this really serve a purpose? switch-local: all switch-install-local: install diff --git a/switchlink/configure.ac b/switchlink/configure.ac deleted file mode 100644 index 5542194..0000000 --- a/switchlink/configure.ac +++ /dev/null @@ -1,34 +0,0 @@ -# -*- Autoconf -*- -# Process this file with autoconf to produce a configure script. - -AC_PREREQ([2.69]) -AC_INIT([switchlink], [0.1], []) -AM_INIT_AUTOMAKE([foreign subdir-objects]) -AM_SILENT_RULES([yes]) -AC_CONFIG_HEADERS([config.h]) - -# Checks for programs. -CFLAGS="-g -Wall -Wextra -Wno-unused-parameter" -AC_PROG_CC_STDC -AC_PROG_CXX -LT_INIT - -AC_CONFIG_MACRO_DIR([m4]) - -# Checks for header files. -AC_LANG_PUSH(C) - -AC_CHECK_LIB([pcap], [pcap_create], [], [AC_MSG_ERROR([Missing libpcap])]) -if test -n "$COVERAGE_FLAGS"; then - AC_CHECK_LIB([gcov], [__gcov_init], [], [AC_MSG_ERROR([Missing gcov library])]) -fi - -# Checks for typedefs, structures, and compiler characteristics. -AC_CHECK_HEADER_STDBOOL -AC_TYPE_SIZE_T -AC_TYPE_UINT64_T - -# Generate makefiles -AC_CONFIG_FILES([Makefile third-party/xxhash/Makefile]) - -AC_OUTPUT diff --git a/switchsai/Makefile.am b/switchsai/Makefile.am index 7424732..f894994 100644 --- a/switchsai/Makefile.am +++ b/switchsai/Makefile.am @@ -1,13 +1,14 @@ ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4 -libswitchsai_la_CFLAGS = -I$(srcdir)/submodules/SAI/inc -libswitchsai_la_CFLAGS += -I$(srcdir)/../../modules/BMI/module/inc -libswitchsai_la_CFLAGS += -I$(builddir)/src/gen-cpp -libswitchsai_la_CFLAGS += -I$(top_srcdir)/switchapi/third-party/tommyds/include -libswitchsai_la_CFLAGS += -I$(top_srcdir)/p4src/includes -libswitchsai_la_CXXFLAGS = $(libswitchsai_la_CFLAGS) -libswitchsai_a_CFLAGS = $(libswitchsai_la_CFLAGS) -libswitchsai_a_CXXFLAGS = $(libswitchsai_a_CFLAGS) +AM_CPPFLAGS += -I$(srcdir)/submodules/SAI/inc +AM_CPPFLAGS += -I$(top_srcdir)/switchapi/include +AM_CPPFLAGS += -I$(builddir)/src/gen-cpp +AM_CPPFLAGS += -I$(top_srcdir)/switchapi/third-party/tommyds/include +AM_CPPFLAGS += -I$(top_srcdir)/p4src/includes + +if P4THRIFT + AM_CPPFLAGS += -DP4THRIFT +endif thrift_cpp_sources = \ @builddir@/src/gen-cpp/switch_sai_constants.cpp \ @@ -68,7 +69,12 @@ libswitchsai_a_SOURCES = $(libswitchsai_la_SOURCES) BUILT_SOURCES = \ $(thrift_cpp_sources) \ -$(thrift_py_sources) +$(thrift_py_sources) \ +$(sai_ctypesgen) + +$(sai_ctypesgen) : $(thrift_py_sources) + @$(CTYPESGEN) -I/usr/include -I$(srcdir)/submodules/SAI/inc \ + $(srcdir)/submodules/SAI/inc/*.h -o $@ > /dev/null 2>&1 # The recipe to invoke the thrift compiler is copied from: # http://www.gnu.org/software/automake/manual/html_node/Multiple-Outputs.html @@ -77,9 +83,11 @@ switchsai.ts : @srcdir@/src/switch_sai.thrift @touch switchsai.tmp $(THRIFT) -o @builddir@/src/ --gen cpp -r @srcdir@/src/switch_sai.thrift $(THRIFT) -o @builddir@/src/ --gen py -r @srcdir@/src/switch_sai.thrift +## FIXME: p4factory legacy + cp -r @builddir@/src/gen-py/switch_sai/ @builddir@/switch_sai_thrift @mv -f switchsai.tmp $@ -$(BUILT_SOURCES) : switchsai.ts +$(thrift_cpp_sources) $(thrift_py_sources) : switchsai.ts ## Recover from the removal of $@ @if test -f $@; then :; else \ trap 'rm -rf switchsai.lock switchsai.ts' 1 2 13 15; \ @@ -98,4 +106,102 @@ $(BUILT_SOURCES) : switchsai.ts fi; \ fi -CLEANFILES = $(BUILT_SOURCES) +switchsai_sources = \ +$(thrift_cpp_sources) \ +src/saiacl.c \ +src/sai.c \ +src/sai_bmlib.c \ +src/saibuffer.c \ +src/saifdb.c \ +src/saihash.c \ +src/saihostintf.c \ +src/saiinternal.h \ +src/saiipmc.c \ +src/sail2mc.c \ +src/sailag.c \ +src/saimirror.c \ +src/saineighbor.c \ +src/sainexthop.c \ +src/sainexthopgroup.c \ +src/saiobject.c \ +src/saipolicer.c \ +src/saiport.c \ +src/saiqosmaps.c \ +src/saiqueue.c \ +src/sairoute.c \ +src/sairouter.c \ +src/sairouterintf.c \ +src/saischeduler.c \ +src/saischedulergroup.c \ +src/saistp.c \ +src/saiswitch.c \ +src/saiudf.c \ +src/saiutils.c \ +src/saivlan.c \ +src/switch_sai_rpc_server.cpp + +sai_headers = \ +submodules/SAI/inc/sai.h \ +submodules/SAI/inc/saihash.h \ +submodules/SAI/inc/sailag.h \ +submodules/SAI/inc/sainexthopgroup.h \ +submodules/SAI/inc/saiqosmaps.h \ +submodules/SAI/inc/sairouterintf.h \ +submodules/SAI/inc/saistatus.h \ +submodules/SAI/inc/saitypes.h \ +submodules/SAI/inc/saiacl.h \ +submodules/SAI/inc/saihostintf.h \ +submodules/SAI/inc/saimirror.h \ +submodules/SAI/inc/saiobject.h \ +submodules/SAI/inc/saiqueue.h \ +submodules/SAI/inc/saisamplepacket.h \ +submodules/SAI/inc/saistp.h \ +submodules/SAI/inc/saiudf.h \ +submodules/SAI/inc/saibuffer.h \ +submodules/SAI/inc/saiipmc.h \ +submodules/SAI/inc/saineighbor.h \ +submodules/SAI/inc/saipolicer.h \ +submodules/SAI/inc/sairoute.h \ +submodules/SAI/inc/saischeduler.h \ +submodules/SAI/inc/saiswitch.h \ +submodules/SAI/inc/saivlan.h \ +submodules/SAI/inc/saifdb.h \ +submodules/SAI/inc/sail2mc.h \ +submodules/SAI/inc/sainexthop.h \ +submodules/SAI/inc/saiport.h \ +submodules/SAI/inc/sairouter.h \ +submodules/SAI/inc/saischedulergroup.h \ +submodules/SAI/inc/saitunnel.h \ +submodules/SAI/inc/saiwred.h + +saiincludedir = $(includedir)/sai +saiinclude_HEADERS = $(sai_headers) +noinst_LTLIBRARIES = +lib_LIBRARIES = +lib_LTLIBRARIES = + +if WITH_BMV2 +libbmswitchsai_la_CPPFLAGS = $(AM_CPPFLAGS) +libbmswitchsai_la_CPPFLAGS += -DBMV2 +libbmswitchsai_la_CPPFLAGS += -I$(top_builddir)/p4-build/ +libbmswitchsai_la_CPPFLAGS += -isystem$(includedir) +noinst_LTLIBRARIES += libbmswitchsai.la +libbmswitchsai_la_SOURCES = $(switchsai_sources) +endif + +# FIXME: legacy support, relies on p4factory +if WITH_P4FACTORY +lib_LIBRARIES += libswitchsai.a +libswitchsai_a_SOURCES = $(switchsai_sources) +# FIXME: this also creates shared libraries for p4factory, needs to be +# deprecated +lib_LTLIBRARIES += libswitchsai.la +# has the advantage of avoiding "created both with libtool and without" error +libswitchsai_la_CPPFLAGS = $(AM_CPPFLAGS) +libswitchsai_la_SOURCES = $(switchsai_sources) +endif + +# FIXME: not sure if this serves a real purpose +$(lib_LTLIBRARIES) : $(thrift_py_sources) + +CLEANFILES = $(BUILT_SOURCES) switchsai.ts diff --git a/switchsai/README.md b/switchsai/README.md index be70ff0..d50c33c 100644 --- a/switchsai/README.md +++ b/switchsai/README.md @@ -37,5 +37,7 @@ Supported Features 8. Host interface 9. Ingress Policers 10. Statistics: VLAN, ACL +11. Qos (Quality of Service) - Buffers, Queues +12. CoPP (Control Plane Policing) For the list of supported APIs and attributes, please refer to sai_support.pdf file in the doc directory. diff --git a/switchsai/src/sai.c b/switchsai/src/sai.c index c35c073..0ea0428 100644 --- a/switchsai/src/sai.c +++ b/switchsai/src/sai.c @@ -242,6 +242,9 @@ sai_object_type_t sai_object_type_query(_In_ sai_object_id_t sai_object_id) { case SWITCH_HANDLE_TYPE_ACE: object_type = SAI_OBJECT_TYPE_ACL_ENTRY; break; + case SWITCH_HANDLE_TYPE_RANGE: + object_type = SAI_OBJECT_TYPE_ACL_RANGE; + break; case SWITCH_HANDLE_TYPE_HOSTIF: object_type = SAI_OBJECT_TYPE_HOST_INTERFACE; break; diff --git a/switchsai/src/saiacl.c b/switchsai/src/saiacl.c index 41967ef..92b4b41 100644 --- a/switchsai/src/saiacl.c +++ b/switchsai/src/saiacl.c @@ -29,159 +29,199 @@ scheme will allow for having multiple actions be speicifed in any combination in response to a match */ -typedef int sai_acl_table_match_qualifiers[SAI_ACL_TABLE_ATTR_FIELD_END - - SAI_ACL_TABLE_ATTR_FIELD_START + 1]; - typedef struct sai_handle_node_ { tommy_node node; switch_handle_t handle; } sai_handle_node_t; -static sai_acl_table_match_qualifiers ip_acl = { - -1, - -1, // v6 - -1, - -1, // MAC - SWITCH_ACL_IP_FIELD_IPV4_SRC, - SWITCH_ACL_IP_FIELD_IPV4_DEST, // v4 - -2, - -2, - -2, - -1, - -1, // ports - -1, - -1, - -1, - -1, - -1, - -1, // VLAN outer and inner - SWITCH_ACL_IP_FIELD_L4_SOURCE_PORT, - SWITCH_ACL_IP_FIELD_L4_DEST_PORT, // l4 ports - -1, - SWITCH_ACL_IP_FIELD_IP_PROTO, - -1, // dscp - -1, // ecn - SWITCH_ACL_IP_FIELD_TTL, // ttl - -1, // tos - SWITCH_ACL_IP_FIELD_IP_FLAGS, - SWITCH_ACL_IP_FIELD_TCP_FLAGS, // tcp flags - -1, // ip type - -1, // ip frag - -1, // ipv6 flow - -1 // tc -}; - -static sai_acl_table_match_qualifiers ipv6_acl = { - SWITCH_ACL_IPV6_FIELD_IPV6_SRC, - SWITCH_ACL_IPV6_FIELD_IPV6_DEST, - -1, - -1, // MAC - -1, - -1, // v4 - -2, - -2, - -1, - -1, - -1, // ports - -1, - -1, - -1, - -1, - -1, - -1, // VLAN outer and inner - SWITCH_ACL_IPV6_FIELD_L4_SOURCE_PORT, - SWITCH_ACL_IPV6_FIELD_L4_DEST_PORT, // l4 ports - -1, - SWITCH_ACL_IPV6_FIELD_IP_PROTO, - -1, // dscp - -1, // ecn - SWITCH_ACL_IPV6_FIELD_TTL, // ttl - -1, // tos - -1, // ip flags - SWITCH_ACL_IPV6_FIELD_TCP_FLAGS, // tcp flags - -1, // ip type - -1, // ip frag - SWITCH_ACL_IPV6_FIELD_FLOW_LABEL, - -1 // tc -}; - -static sai_acl_table_match_qualifiers mac_acl = { - -1, - -1, // v6 - SWITCH_ACL_MAC_FIELD_SOURCE_MAC, - SWITCH_ACL_MAC_FIELD_DEST_MAC, // MAC - -1, - -1, // v4 - -2, - -2, - -1, - -1, - -1, // ports - -1, - SWITCH_ACL_MAC_FIELD_VLAN_PRI, - SWITCH_ACL_MAC_FIELD_VLAN_CFI, - -1, - -1, - -1, // VLAN outer and inner - -1, - -1, // l4 ports - SWITCH_ACL_MAC_FIELD_ETH_TYPE, - -1, - -1, - -1, // ecn - -1, // ttl - -1, - -1, - -1, // tcp flags - -1, // ip type - -1, // ip frag - -1, // ipv6 flow - -1 // tc -}; +#define SAI_ACL_FIELD_NOT_SUPPORTED -1 +int switch_acl[SWITCH_ACL_TYPE_MAX][SAI_ACL_TABLE_ATTR_FIELD_END - + SAI_ACL_TABLE_ATTR_FIELD_START + 1]; + +void sai_acl_qualifiers_load() { + switch_acl_type_t acl_type = SWITCH_ACL_TYPE_IP; + sai_acl_table_attr_t acl_table_field = SAI_ACL_TABLE_ATTR_FIELD_START; + int acl_attr_index = 0; + + for (acl_type = SWITCH_ACL_TYPE_IP; acl_type < SWITCH_ACL_TYPE_MAX; + acl_type++) { + acl_attr_index = 0; + for (acl_table_field = SAI_ACL_TABLE_ATTR_FIELD_START; + acl_table_field < SAI_ACL_TABLE_ATTR_FIELD_END; + acl_table_field++, acl_attr_index++) { + switch (acl_type) { + case SWITCH_ACL_TYPE_IP: { + switch (acl_table_field) { + case SAI_ACL_TABLE_ATTR_FIELD_SRC_IP: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_IP_FIELD_IPV4_SRC; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_DST_IP: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_IP_FIELD_IPV4_DEST; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_IP_FIELD_IP_PROTO; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_TTL: + switch_acl[acl_type][acl_attr_index] = SWITCH_ACL_IP_FIELD_TTL; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_IP_FLAGS: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_IP_FIELD_IP_FLAGS; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_TCP_FLAGS: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_IP_FIELD_TCP_FLAGS; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_RANGE: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_IP_FIELD_L4_SOURCE_PORT_RANGE; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_IN_PORTS: + case SAI_ACL_TABLE_ATTR_FIELD_OUT_PORTS: + case SAI_ACL_TABLE_ATTR_FIELD_IN_PORT: + switch_acl[acl_type][acl_attr_index] = -2; + break; + + default: + switch_acl[acl_type][acl_attr_index] = + SAI_ACL_FIELD_NOT_SUPPORTED; + break; + } + } break; + + case SWITCH_ACL_TYPE_IPV6: { + switch (acl_table_field) { + case SAI_ACL_TABLE_ATTR_FIELD_SRC_IPv6: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_IPV6_FIELD_IPV6_SRC; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_DST_IPv6: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_IPV6_FIELD_IPV6_DEST; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_IPV6_FIELD_IP_PROTO; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_TTL: + switch_acl[acl_type][acl_attr_index] = SWITCH_ACL_IPV6_FIELD_TTL; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_TCP_FLAGS: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_IPV6_FIELD_TCP_FLAGS; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_RANGE: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_IPV6_FIELD_L4_SOURCE_PORT_RANGE; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_IPv6_FLOW_LABEL: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_IPV6_FIELD_FLOW_LABEL; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_IN_PORTS: + case SAI_ACL_TABLE_ATTR_FIELD_OUT_PORTS: + case SAI_ACL_TABLE_ATTR_FIELD_IN_PORT: + switch_acl[acl_type][acl_attr_index] = -2; + break; + + default: + switch_acl[acl_type][acl_attr_index] = + SAI_ACL_FIELD_NOT_SUPPORTED; + break; + } + } break; + + case SWITCH_ACL_TYPE_MAC: { + switch (acl_table_field) { + case SAI_ACL_TABLE_ATTR_FIELD_SRC_MAC: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_MAC_FIELD_SOURCE_MAC; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_DST_MAC: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_MAC_FIELD_DEST_MAC; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_PRI: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_MAC_FIELD_VLAN_PRI; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_CFI: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_MAC_FIELD_VLAN_CFI; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE: + switch_acl[acl_type][acl_attr_index] = + SWITCH_ACL_MAC_FIELD_ETH_TYPE; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_IN_PORTS: + case SAI_ACL_TABLE_ATTR_FIELD_OUT_PORTS: + case SAI_ACL_TABLE_ATTR_FIELD_IN_PORT: + switch_acl[acl_type][acl_attr_index] = -2; + break; + + default: + switch_acl[acl_type][acl_attr_index] = + SAI_ACL_FIELD_NOT_SUPPORTED; + break; + } + } break; + + case SWITCH_ACL_TYPE_EGRESS_SYSTEM: { + switch (acl_table_field) { + case SAI_ACL_TABLE_ATTR_FIELD_OUT_PORT: + switch_acl[acl_type][acl_attr_index] = SWITCH_ACL_EGR_DEST_PORT; + break; + + case SAI_ACL_TABLE_ATTR_FIELD_IN_PORTS: + case SAI_ACL_TABLE_ATTR_FIELD_OUT_PORTS: + case SAI_ACL_TABLE_ATTR_FIELD_IN_PORT: + switch_acl[acl_type][acl_attr_index] = -2; + break; + + default: + switch_acl[acl_type][acl_attr_index] = + SAI_ACL_FIELD_NOT_SUPPORTED; + break; + } + } break; -static sai_acl_table_match_qualifiers egress_acl = { - -1, - -1, // v6 - -1, - -1, // MAC - -1, - -1, // v4 - -2, - -2, - -1, - SWITCH_ACL_EGR_DEST_PORT, // ports - -1, - -1, - -1, - -1, - -1, - -1, // VLAN outer and inner - -1, - -1, // l4 ports - -1, - -1, - -1, - -1, // ecn - -1, // ttl - -1, - -1, - -1, // tcp flags - -1, // ip type - -1, // ip frag - -1, // ipv6 flow - -1 // tc -}; + default: + switch_acl[acl_type][acl_attr_index] = SAI_ACL_FIELD_NOT_SUPPORTED; + break; + } + } + } +} static int *sai_acl_p4_match_table_get(switch_acl_type_t table_type) { switch (table_type) { case SWITCH_ACL_TYPE_IP: - return ip_acl; case SWITCH_ACL_TYPE_IPV6: - return ipv6_acl; case SWITCH_ACL_TYPE_MAC: - return mac_acl; case SWITCH_ACL_TYPE_EGRESS_SYSTEM: - return egress_acl; + return switch_acl[table_type]; default: return NULL; } @@ -211,11 +251,9 @@ static sai_status_t sai_acl_match_table_type_get( case SAI_ACL_TABLE_ATTR_PRIORITY: case SAI_ACL_TABLE_ATTR_SIZE: case SAI_ACL_TABLE_ATTR_GROUP_ID: - case SAI_ACL_ENTRY_ATTR_FIELD_IN_PORTS: - case SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORTS: - case SAI_ACL_ENTRY_ATTR_FIELD_IN_PORT: - case SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_ID: - case SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_ID: + case SAI_ACL_TABLE_ATTR_FIELD_IN_PORTS: + case SAI_ACL_TABLE_ATTR_FIELD_OUT_PORTS: + case SAI_ACL_TABLE_ATTR_FIELD_IN_PORT: break; // ignore above for matching fields default: @@ -272,6 +310,8 @@ static sai_status_t sai_acl_xform_field_value( _In_ int field, _In_ void *dest, _In_ const sai_acl_field_data_t *source) { + sai_object_id_t *objlist = NULL; + uint32_t index = 0; switch (acl_type) { case SWITCH_ACL_TYPE_IP: { switch_acl_ip_key_value_pair_t *kvp = @@ -289,14 +329,6 @@ static sai_status_t sai_acl_xform_field_value( kvp->value.ip_proto = source->data.u16; kvp->mask.u.mask = source->mask.u16; break; - case SWITCH_ACL_IP_FIELD_L4_SOURCE_PORT: - kvp->value.l4_source_port = source->data.u16; - kvp->mask.u.mask = source->mask.u16; - break; - case SWITCH_ACL_IP_FIELD_L4_DEST_PORT: - kvp->value.l4_dest_port = source->data.u16; - kvp->mask.u.mask = source->mask.u16; - break; case SWITCH_ACL_IP_FIELD_ICMP_TYPE: case SWITCH_ACL_IP_FIELD_ICMP_CODE: case SWITCH_ACL_IP_FIELD_TCP_FLAGS: @@ -315,23 +347,71 @@ static sai_status_t sai_acl_xform_field_value( kvp->value.ip_frag = source->data.u8; kvp->mask.u.mask = source->mask.u8; break; + + case SWITCH_ACL_IP_FIELD_L4_SOURCE_PORT_RANGE: + case SWITCH_ACL_IP_FIELD_L4_DEST_PORT_RANGE: + objlist = source->data.objlist.list; + for (index = 0; index < source->data.objlist.count; index++) { + switch_handle_t range_handle = 0; + range_handle = (switch_handle_t)objlist[index]; + switch_range_type_t range_type = SWITCH_RANGE_TYPE_NONE; + switch_api_acl_range_type_get(device, range_handle, &range_type); + if (range_type == SWITCH_RANGE_TYPE_SRC_PORT) { + kvp->value.sport_range_handle = range_handle; + } + if (range_type == SWITCH_RANGE_TYPE_DST_PORT) { + kvp->value.dport_range_handle = range_handle; + } + } + break; default: break; } } break; case SWITCH_ACL_TYPE_IPV6: { + switch_acl_ipv6_key_value_pair_t *kvp = + (switch_acl_ipv6_key_value_pair_t *)dest; switch (field) { case SWITCH_ACL_IPV6_FIELD_IPV6_SRC: + memcpy(kvp->value.ipv6_source.u.addr8, source->data.ip6, 16); + memcpy(kvp->mask.u.mask.u.addr8, source->mask.ip6, 16); + break; case SWITCH_ACL_IPV6_FIELD_IPV6_DEST: + memcpy(kvp->value.ipv6_dest.u.addr8, source->data.ip6, 16); + memcpy(kvp->mask.u.mask.u.addr8, source->mask.ip6, 16); + break; case SWITCH_ACL_IPV6_FIELD_IP_PROTO: - case SWITCH_ACL_IPV6_FIELD_L4_SOURCE_PORT: - case SWITCH_ACL_IPV6_FIELD_L4_DEST_PORT: + kvp->value.ip_proto = source->data.u16; + kvp->mask.u.mask.u.addr8[0] = source->mask.u16; + break; case SWITCH_ACL_IPV6_FIELD_ICMP_TYPE: case SWITCH_ACL_IPV6_FIELD_ICMP_CODE: case SWITCH_ACL_IPV6_FIELD_TCP_FLAGS: + kvp->value.tcp_flags = source->data.u8; + kvp->mask.u.mask.u.addr8[0] = source->mask.u8; + break; case SWITCH_ACL_IPV6_FIELD_TTL: + kvp->value.ttl = source->data.u8; + kvp->mask.u.mask.u.addr8[0] = source->mask.u8; + break; case SWITCH_ACL_IPV6_FIELD_FLOW_LABEL: break; + case SWITCH_ACL_IP_FIELD_L4_SOURCE_PORT_RANGE: + case SWITCH_ACL_IP_FIELD_L4_DEST_PORT_RANGE: + objlist = source->data.objlist.list; + for (index = 0; index < source->data.objlist.count; index++) { + switch_handle_t range_handle = 0; + range_handle = (switch_handle_t)objlist[index]; + switch_range_type_t range_type = SWITCH_RANGE_TYPE_NONE; + switch_api_acl_range_type_get(device, range_handle, &range_type); + if (range_type == SWITCH_RANGE_TYPE_SRC_PORT) { + kvp->value.sport_range_handle = range_handle; + } + if (range_type == SWITCH_RANGE_TYPE_DST_PORT) { + kvp->value.dport_range_handle = range_handle; + } + } + break; default: break; } @@ -382,6 +462,34 @@ static sai_status_t sai_acl_xform_field_value( return SAI_STATUS_SUCCESS; } +sai_status_t sai_acl_direction_get(uint32_t attr_count, + const sai_attribute_t *attr_list, + switch_direction_t *direction) { + sai_status_t status = SAI_STATUS_SUCCESS; + uint32_t index = 0; + *direction = SWITCH_API_DIRECTION_INGRESS; + + for (index = 0; index < attr_count; index++) { + // skip ports and VLAN attributes on check + switch (attr_list[index].id) { + case SAI_ACL_TABLE_ATTR_STAGE: { + sai_acl_stage_t acl_stage = attr_list[index].value.s32; + switch (acl_stage) { + case SAI_ACL_STAGE_EGRESS: + *direction = SWITCH_API_DIRECTION_EGRESS; + break; + case SAI_ACL_STAGE_INGRESS: + default: + *direction = SWITCH_API_DIRECTION_INGRESS; + break; + } + } + } + } + + return status; +} + /* * Routine Description: * Create an ACL table @@ -402,6 +510,7 @@ sai_status_t sai_create_acl_table(_Out_ sai_object_id_t *acl_table_id, sai_status_t status = SAI_STATUS_SUCCESS; switch_acl_type_t acl_type = 0; + switch_direction_t direction = SWITCH_API_DIRECTION_INGRESS; if (!attr_list) { status = SAI_STATUS_INVALID_PARAMETER; @@ -417,7 +526,16 @@ sai_status_t sai_create_acl_table(_Out_ sai_object_id_t *acl_table_id, return status; } - *acl_table_id = (sai_object_id_t)switch_api_acl_list_create(device, acl_type); + status = sai_acl_direction_get(attr_count, attr_list, &direction); + if (status != SAI_STATUS_SUCCESS) { + status = SAI_STATUS_INVALID_PARAMETER; + SAI_LOG_ERROR("failed to get acl direction: %s", + sai_status_to_string(status)); + return status; + } + + *acl_table_id = + (sai_object_id_t)switch_api_acl_list_create(device, direction, acl_type); status = (*acl_table_id == SWITCH_API_INVALID_HANDLE) ? SAI_STATUS_FAILURE : SAI_STATUS_SUCCESS; @@ -927,6 +1045,198 @@ sai_status_t sai_get_acl_counter_attribute(_In_ sai_object_id_t acl_counter_id, return (sai_status_t)status; } +sai_status_t sai_acl_range_attribute_to_switch_acl_range_attrbute( + sai_acl_range_type_t range_type, switch_range_type_t *switch_range_type) { + sai_status_t status = SAI_STATUS_SUCCESS; + switch (range_type) { + case SAI_ACL_RANGE_L4_SRC_PORT_RANGE: + *switch_range_type = SWITCH_RANGE_TYPE_SRC_PORT; + break; + + case SAI_ACL_RANGE_L4_DST_PORT_RANGE: + *switch_range_type = SWITCH_RANGE_TYPE_DST_PORT; + break; + + case SAI_ACL_RANGE_OUTER_VLAN: + case SAI_ACL_RANGE_INNER_VLAN: + *switch_range_type = SWITCH_RANGE_TYPE_VLAN; + break; + + case SAI_ACL_RANGE_PACKET_LENGTH: + *switch_range_type = SWITCH_RANGE_TYPE_PACKET_LENGTH; + break; + + default: + *switch_range_type = SWITCH_RANGE_TYPE_NONE; + } + + return status; +} + +/** + * Routine Description: + * @brief Create an ACL Range + * + * Arguments: + * @param[out] acl_range_id - the acl range id + * @param[in] attr_count - number of attributes + * @param[in] attr_list - array of attributes + * + * Return Values: + * @return SAI_STATUS_SUCCESS on success + * Failure status code on error + */ +sai_status_t sai_create_acl_range(_Out_ sai_object_id_t *acl_range_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list) { + const sai_attribute_t *attribute = NULL; + sai_status_t status = SAI_STATUS_SUCCESS; + switch_status_t switch_status = SWITCH_STATUS_SUCCESS; + switch_range_type_t range_type = SWITCH_RANGE_TYPE_NONE; + switch_range_t switch_range; + switch_direction_t direction = SWITCH_API_DIRECTION_INGRESS; + switch_handle_t range_handle = 0; + uint32_t i = 0; + + SAI_LOG_ENTER(); + + if (!attr_list) { + status = SAI_STATUS_INVALID_PARAMETER; + SAI_LOG_ERROR("null attribute: %s", sai_status_to_string(status)); + return status; + } + + for (i = 0; i < attr_count; i++) { + attribute = &attr_list[i]; + switch (attribute->id) { + case SAI_ACL_RANGE_ATTR_TYPE: + sai_acl_range_attribute_to_switch_acl_range_attrbute( + attribute->value.s32, &range_type); + break; + + case SAI_ACL_RANGE_ATTR_LIMIT: + switch_range.start_value = attribute->value.s32range.min; + switch_range.end_value = attribute->value.s32range.max; + break; + } + } + + *acl_range_id = 0; + + switch_status = switch_api_acl_range_create( + device, direction, range_type, &switch_range, &range_handle); + status = sai_switch_status_to_sai_status(switch_status); + + if (status != SAI_STATUS_SUCCESS) { + SAI_LOG_ERROR("failed to create acl range : %s", + sai_status_to_string(status)); + } + + *acl_range_id = (sai_object_id_t)range_handle; + + SAI_LOG_EXIT(); + + return status; +} + +/** + * Routine Description: + * @brief Remove an ACL Range + * + * Arguments: + * @param[in] acl_range_id - the acl range id + * + * Return Values: + * @return SAI_STATUS_SUCCESS on success + * Failure status code on error + */ +sai_status_t sai_remove_acl_range(_In_ sai_object_id_t acl_range_id) { + SAI_LOG_ENTER(); + + sai_status_t status = SAI_STATUS_SUCCESS; + switch_status_t switch_status = SWITCH_STATUS_SUCCESS; + + SAI_ASSERT(sai_object_type_query(acl_range_id) == SAI_OBJECT_TYPE_ACL_RANGE); + + switch_status = + switch_api_acl_range_delete(device, (switch_handle_t)acl_range_id); + status = sai_switch_status_to_sai_status(switch_status); + + if (status != SAI_STATUS_SUCCESS) { + SAI_LOG_ERROR("failed to delete acl range%lx : %s", + acl_range_id, + sai_status_to_string(status)); + } + + SAI_LOG_EXIT(); + + return (sai_status_t)status; +} + +/** + * Routine Description: + * @brief Set ACL range attribute + * + * Arguments: + * @param[in] acl_range_id - the acl range id + * @param[in] attr - attribute + * + * Return Values: + * @return SAI_STATUS_SUCCESS on success + * Failure status code on error + */ +sai_status_t sai_set_acl_range_attribute(_In_ sai_object_id_t acl_range_id, + _In_ const sai_attribute_t *attr) { + SAI_LOG_ENTER(); + + sai_status_t status = SAI_STATUS_SUCCESS; + + SAI_ASSERT(sai_object_type_query(acl_range_id) == SAI_OBJECT_TYPE_ACL_RANGE); + + if (!attr) { + status = SAI_STATUS_INVALID_PARAMETER; + SAI_LOG_ERROR("null attribute: %s", sai_status_to_string(status)); + return status; + } + + SAI_LOG_EXIT(); + + return (sai_status_t)status; +} + +/** + * Routine Description: + * @brief Get ACL range attribute + * + * Arguments: + * @param[in] acl_range_id - acl range id + * @param[in] attr_count - number of attributes + * @param[out] attr_list - array of attributes + * + * Return Values: + * @return SAI_STATUS_SUCCESS on success + * Failure status code on error + */ +sai_status_t sai_get_acl_range_attribute(_In_ sai_object_id_t acl_range_id, + _In_ uint32_t attr_count, + _Out_ sai_attribute_t *attr_list) { + SAI_LOG_ENTER(); + + sai_status_t status = SAI_STATUS_SUCCESS; + + SAI_ASSERT(sai_object_type_query(acl_range_id) == SAI_OBJECT_TYPE_ACL_RANGE); + + if (!attr_list) { + status = SAI_STATUS_INVALID_PARAMETER; + SAI_LOG_ERROR("null attribute list: %s", sai_status_to_string(status)); + return status; + } + + SAI_LOG_EXIT(); + + return (sai_status_t)status; +} + /* * ACL methods table retrieved with sai_api_query() */ @@ -938,12 +1248,17 @@ sai_acl_api_t acl_api = { .create_acl_counter = sai_create_acl_counter, .delete_acl_counter = sai_delete_acl_counter, .set_acl_counter_attribute = sai_set_acl_counter_attribute, - .get_acl_counter_attribute = sai_get_acl_counter_attribute + .get_acl_counter_attribute = sai_get_acl_counter_attribute, + .create_acl_range = sai_create_acl_range, + .remove_acl_range = sai_remove_acl_range, + .set_acl_range_attribute = sai_set_acl_range_attribute, + .get_acl_range_attribute = sai_get_acl_range_attribute }; sai_status_t sai_acl_initialize(sai_api_service_t *sai_api_service) { SAI_LOG_DEBUG("Initializing acl"); sai_api_service->acl_api = acl_api; + sai_acl_qualifiers_load(); return SAI_STATUS_SUCCESS; } diff --git a/switchsai/src/saiipmc.c b/switchsai/src/saiipmc.c index b21282b..695a774 100644 --- a/switchsai/src/saiipmc.c +++ b/switchsai/src/saiipmc.c @@ -126,7 +126,8 @@ static switch_handle_t sai_ipmc_tree_create( mbrs = switch_malloc(sizeof(switch_vlan_interface_t), oif_list_count); mcast_handle = switch_api_multicast_tree_create(device); - for (int i = 0; i < oif_list_count; i++) { + int i = 0; + for (i = 0; i < oif_list_count; i++) { switch_handle_t intf_handle = oif_list_handle[i]; switch_interface_type_t type; status = switch_api_interface_get_type(intf_handle, &type); diff --git a/switchsai/src/sail2mc.c b/switchsai/src/sail2mc.c index 33d598a..1704716 100644 --- a/switchsai/src/sail2mc.c +++ b/switchsai/src/sail2mc.c @@ -155,7 +155,8 @@ sai_status_t sai_create_l2mc_entry(_In_ const sai_l2mc_entry_t *l2mc_entry, switch_vlan_interface_t *mbrs; mbrs = switch_malloc(sizeof(switch_vlan_interface_t), port_list_count); - for (int i = 0; i < port_list_count; i++) { + int i = 0; + for (i = 0; i < port_list_count; i++) { mbrs[i].vlan_handle = vlan_handle; mbrs[i].intf_handle = port_list_handle[i]; } diff --git a/switchsai/src/switch_sai.thrift b/switchsai/src/switch_sai.thrift index 6c0ee5c..78878c4 100644 --- a/switchsai/src/switch_sai.thrift +++ b/switchsai/src/switch_sai.thrift @@ -133,6 +133,11 @@ struct sai_thrift_qos_map_list_t { 2: list data; } +struct sai_thrift_range_t { + 1: i32 min; + 2: i32 max; +} + union sai_thrift_attribute_value_t { 1: bool booldata; 2: string chardata; @@ -154,6 +159,8 @@ union sai_thrift_attribute_value_t { 18: sai_thrift_acl_field_data_t aclfield; 19: sai_thrift_acl_action_data_t aclaction; 20: sai_thrift_qos_map_list_t qosmap; + 21: sai_thrift_range_t s32range; + 22: sai_thrift_range_t u32range; } struct sai_thrift_attribute_t { @@ -268,6 +275,9 @@ service switch_sai_rpc { 1: sai_thrift_object_id_t acl_counter_id, 2: list thrift_attr_ids); + sai_thrift_object_id_t sai_thrift_create_acl_range(1: list thrift_attr_list); + sai_thrift_status_t sai_thrift_delete_acl_range(1: sai_thrift_object_id_t acl_range_id); + // Mirror API sai_thrift_object_id_t sai_thrift_create_mirror_session(1: list thrift_attr_list); sai_thrift_status_t sai_thrift_remove_mirror_session(1: sai_thrift_object_id_t session_id); diff --git a/switchsai/src/switch_sai_rpc_server.cpp b/switchsai/src/switch_sai_rpc_server.cpp index acbffc7..ce2c44f 100644 --- a/switchsai/src/switch_sai_rpc_server.cpp +++ b/switchsai/src/switch_sai_rpc_server.cpp @@ -1276,6 +1276,10 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { attribute = (sai_thrift_attribute_t)*it; attr_list[i].id = attribute.id; switch (attribute.id) { + case SAI_ACL_TABLE_ATTR_STAGE: + attr_list[i].value.s32 = attribute.value.s32; + break; + case SAI_ACL_TABLE_ATTR_FIELD_SRC_IPv6: case SAI_ACL_TABLE_ATTR_FIELD_DST_IPv6: case SAI_ACL_TABLE_ATTR_FIELD_SRC_MAC: @@ -1410,12 +1414,44 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { case SAI_ACL_ENTRY_ATTR_PACKET_ACTION: attr_list[i].value.aclfield.data.s32 = attribute.value.aclfield.data.s32; break; + case SAI_ACL_ENTRY_ATTR_FIELD_RANGE: + { + int count = attribute.value.aclfield.data.objlist.object_id_list.size(); + sai_object_id_t *oid_list = NULL; + std::vector::const_iterator it = attribute.value.aclfield.data.objlist.object_id_list.begin(); + oid_list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * count); + for(int j = 0; j < count; j++, it++) + *(oid_list + j) = (sai_object_id_t) *it; + attr_list[i].value.aclfield.data.objlist.list = oid_list; + attr_list[i].value.aclfield.data.objlist.count = count; + } + break; default: break; } } } + void sai_thrift_convert_to_acl_range_attributes( + const std::vector &thrift_attr_list, + sai_attribute_t *attr_list) { + std::vector::const_iterator it = thrift_attr_list.begin(); + sai_thrift_attribute_t attribute; + for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) { + attribute = (sai_thrift_attribute_t)*it; + attr_list[i].id = attribute.id; + switch (attribute.id) { + case SAI_ACL_RANGE_ATTR_TYPE: + attr_list[i].value.s32 = attribute.value.s32; + break; + case SAI_ACL_RANGE_ATTR_LIMIT: + attr_list[i].value.u32range.min = attribute.value.u32range.min; + attr_list[i].value.u32range.max = attribute.value.u32range.max; + break; + } + } + } + void sai_thrift_convert_to_acl_counter_attributes( const std::vector &thrift_attr_list, sai_attribute_t *attr_list) { @@ -1443,7 +1479,6 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { } } } - void sai_thrift_convert_to_acl_thrift_counter_attributes( sai_attribute_t *attr_list, uint32_t attr_count, @@ -1588,6 +1623,34 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { return; } + sai_thrift_object_id_t sai_thrift_create_acl_range(const std::vector & thrift_attr_list) { + sai_object_id_t acl_range_id = 0ULL; + sai_acl_api_t *acl_api; + sai_status_t status = SAI_STATUS_SUCCESS; + status = sai_api_query(SAI_API_ACL, (void **) &acl_api); + if (status != SAI_STATUS_SUCCESS) { + return status; + } + sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); + sai_thrift_convert_to_acl_range_attributes(thrift_attr_list, attr_list); + uint32_t attr_count = thrift_attr_list.size(); + status = acl_api->create_acl_range(&acl_range_id, attr_count, attr_list); + free(attr_list); + return acl_range_id; + } + + sai_thrift_status_t sai_thrift_delete_acl_range(const sai_thrift_object_id_t acl_range_id) { + sai_object_id_t acl_entry = 0ULL; + sai_acl_api_t *acl_api; + sai_status_t status = SAI_STATUS_SUCCESS; + status = sai_api_query(SAI_API_ACL, (void **) &acl_api); + if (status != SAI_STATUS_SUCCESS) { + return status; + } + status = acl_api->remove_acl_range(acl_range_id); + return status; + } + void sai_thrift_parse_mirror_session_attributes(const std::vector &thrift_attr_list, sai_attribute_t *attr_list) { std::vector::const_iterator it = thrift_attr_list.begin(); sai_thrift_attribute_t attribute; diff --git a/tests/of-tests/common/utils.py b/tests/of-tests/common/utils.py new file mode 100644 index 0000000..7067c62 --- /dev/null +++ b/tests/of-tests/common/utils.py @@ -0,0 +1,45 @@ +import struct + +# thrift does not support unsigned integers +def hex_to_i16(h): + x = int(h) + if (x > 0x7FFF): x-= 0x10000 + return x +def hex_to_i32(h): + x = int(h) + if (x > 0x7FFFFFFF): x-= 0x100000000 + return x +def hex_to_byte(h): + x = int(h) + if (x > 0x7F): x-= 0x100 + return x +def uint_to_i32(u): + if (u > 0x7FFFFFFF): u-= 0x100000000 + return u + +def bytes_to_string(byte_array): + form = 'B' * len(byte_array) + return struct.pack(form, *byte_array) + +def string_to_bytes(string): + form = 'B' * len(string) + return list(struct.unpack(form, string)) + +def macAddr_to_string(addr): + byte_array = [int(b, 16) for b in addr.split(':')] + return bytes_to_string(byte_array) + +def ipv4Addr_to_i32(addr): + byte_array = [int(b) for b in addr.split('.')] + res = 0 + for b in byte_array: res = res * 256 + b + return uint_to_i32(res) + +def stringify_macAddr(addr): + return ':'.join('%02x' % byte_to_u(x) for x in addr) + +def i32_to_ipv4Addr(addr): + return socket.inet_ntoa(struct.pack("!I", addr)) + +def ipv6Addr_to_string(addr): + return (str(socket.inet_pton(socket.AF_INET6, addr))) diff --git a/tests/of-tests/openflow.py b/tests/of-tests/openflow.py index 0b89814..a91239c 100644 --- a/tests/of-tests/openflow.py +++ b/tests/of-tests/openflow.py @@ -5,7 +5,6 @@ import os import time - import logging from oftest import config import oftest.base_tests as base_tests @@ -16,19 +15,19 @@ import openflow_base_tests -sys.path.append(os.path.join(sys.path[0], '..', '..', '..', '..', - 'testutils')) +root_dir = os.path.dirname(os.path.realpath(__file__)) + +sys.path.append(os.path.join(root_dir, 'common')) from utils import * -sys.path.append(os.path.join(sys.path[0], '..', '..', '..', '..', - 'targets', 'switch', 'tests', 'pd_thrift')) +sys.path.append(os.path.join(root_dir, '..', '..', 'p4-build', 'bmv2', + 'pd_thrift_gen', 'gen-py')) from p4_pd_rpc.ttypes import * from res_pd_rpc.ttypes import * -sys.path.append(os.path.join(sys.path[0], '..', '..', '..', '..', - 'targets', 'switch', 'openflow_mapping')) +sys.path.append(os.path.join(root_dir, '..', '..', 'openflow_mapping')) from l2 import * ### TODO: generate expected packets @@ -168,6 +167,42 @@ def setup_default_table_configurations(client, sess_hdl, dev_tgt): sess_hdl, dev_tgt, match_spec, mbr_hdl) + ifindex = 0x41 + action_spec = dc_set_bd_properties_action_spec_t( + action_bd=0, + action_vrf=0, + action_rmac_group=0, + action_bd_label=0, + action_ipv4_unicast_enabled=True, + action_ipv6_unicast_enabled=False, + action_ipv4_multicast_enabled=False, + action_ipv6_multicast_enabled=False, + action_igmp_snooping_enabled=0, + action_mld_snooping_enabled=0, + action_ipv4_urpf_mode=0, + action_ipv6_urpf_mode=0, + action_stp_group=0, + action_mrpf_group=0, + action_ipv4_mcast_key_type=0, + action_ipv4_mcast_key=0, + action_ipv6_mcast_key_type=0, + action_ipv6_mcast_key=0, + action_stats_idx=0, + action_learning_enabled=0) + + mbr_hdl = client.bd_action_profile_add_member_with_set_bd_properties( + sess_hdl, dev_tgt, + action_spec) + match_spec = dc_port_vlan_mapping_match_spec_t( + ingress_metadata_ifindex=ifindex, + vlan_tag__0__valid=0, + vlan_tag__0__vid=0, + vlan_tag__1__valid=0, + vlan_tag__1__vid=0) + client.port_vlan_mapping_add_entry( + sess_hdl, dev_tgt, + match_spec, mbr_hdl) + def setup_pre(mc, sess_hdl, dev_tgt): mgrp_hdl = mc.mc_mgrp_create(sess_hdl, dev_tgt.dev_id, 1) port_map = [0] * 32 @@ -180,7 +215,7 @@ def setup_pre(mc, sess_hdl, dev_tgt): mc.mc_associate_node(sess_hdl, dev_tgt.dev_id, mgrp_hdl, node_hdl) def setup(self): - sess_hdl = self.conn_mgr.client_init(16) + sess_hdl = self.conn_mgr.client_init() dev_tgt = DevTarget_t(0, hex_to_i16(0xFFFF)) setup_default_table_configurations(self.client, sess_hdl, dev_tgt) setup_pre(self.mc, sess_hdl, dev_tgt) @@ -420,61 +455,6 @@ def runTest(self): self.controller.message_send(req) do_barrier(self.controller) -class TableStatsGet(openflow_base_tests.OFTestInterface): - """ - """ - def __init__(self): - openflow_base_tests.OFTestInterface.__init__(self, "dc") - - def runTest(self): - setup(self) - - req = table_stats_req() - (reply, pkt) = self.controller.transact(req) - initial_matched_count = reply.entries[0].matched_count - initial_lookup_count = reply.entries[0].lookup_count - - ports = sorted(config["port_map"].keys()) - out_port = ports[0] - - table = openflow_tables["dmac"] - table.match_fields[eth_dst_addr].testval = TEST_ETH_DST - table.match_fields[ingress_vlan].testval = TEST_VLAN - hit_pkt, match = get_match(table.match_fields) - - output = { - "OUTPUT": out_port - } - - instr = get_apply_actions(output) - req = flow_add(table_id=table.id, match=match, instructions=instr, - buffer_id=buf, priority=1, cookie=45) - self.controller.message_send(req) - do_barrier(self.controller) - - num_hit_packets = 10 - for _ in xrange(num_hit_packets): - self.dataplane.send(ports[0], hit_pkt) - - miss_pkt = str(simple_tcp_packet(eth_dst="00:77:22:55:99:11", - dl_vlan_enable=True, vlan_vid=3)) - - num_miss_packets = 7 - for _ in xrange(num_miss_packets): - self.dataplane.send(ports[0], miss_pkt) - - time.sleep(3) - - req = table_stats_req() - (reply, pkt) = self.controller.transact(req) - - req = flow_delete(cookie=45, table_id=0) - self.controller.message_send(req) - do_barrier(self.controller) - - assert reply.entries[0].lookup_count == num_miss_packets + num_hit_packets + initial_lookup_count - assert reply.entries[0].matched_count == num_hit_packets + initial_matched_count - class PacketIn(openflow_base_tests.OFTestInterface): """ """ @@ -510,3 +490,39 @@ def runTest(self): self.controller.message_send(req) do_barrier(self.controller) +class PacketOut(openflow_base_tests.OFTestInterface): + """ + """ + def __init__(self): + openflow_base_tests.OFTestInterface.__init__(self, "dc") + + def runTest(self): + setup(self) + + ports = sorted(config["port_map"].keys()) + port1 = ports[1] + + outpkt = simple_tcp_packet() + + # flood packet out + flood = ofp.message.packet_out() + flood.data = str(outpkt) + flood_act = ofp.action.output() + flood_act.port = 0xfffffffb + flood.actions.append(flood_act) + flood.buffer_id = 0xffffffff + self.controller.message_send(flood) + verify_packets(self, outpkt, ports) + + time.sleep(2) + + # unicast packet out + unicast = ofp.message.packet_out() + unicast.data = str(outpkt) + unicast_act = ofp.action.output() + unicast_act.port = port1 + unicast.actions.append(unicast_act) + unicast.buffer_id = 0xffffffff + self.controller.message_send(unicast) + verify_packet(self, outpkt, port1) + diff --git a/tests/ptf-tests/api-tests/switch.py b/tests/ptf-tests/api-tests/switch.py index 4c705af..badf9c6 100644 --- a/tests/ptf-tests/api-tests/switch.py +++ b/tests/ptf-tests/api-tests/switch.py @@ -2803,8 +2803,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -3025,8 +3025,8 @@ def runTest(self): vxlan_pkt = simple_vxlanv6_packet( eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', - ipv6_dst=ipv6_dst_addr, - ipv6_src=ipv6_src_addr, + ipv6_dst=ipv6_src_addr, + ipv6_src=ipv6_dst_addr, ipv6_hlim=64, udp_sport=0, with_udp_chksum=False, @@ -3143,8 +3143,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, nvgre_tni=0x1234, inner_frame=pkt) @@ -3239,8 +3239,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, nvgre_tni=0x1234, inner_frame=pkt) @@ -3364,8 +3364,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -3529,8 +3529,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -3636,8 +3636,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -3782,8 +3782,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, nvgre_tni=0x1234, inner_frame=pkt) @@ -4021,8 +4021,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -4056,8 +4056,8 @@ def runTest(self): eth_dst='00:77:66:55:44:33', eth_src='00:44:44:44:44:44', ip_id=0, - ip_dst='2.2.2.3', - ip_src='2.2.2.1', + ip_dst='2.2.2.1', + ip_src='2.2.2.3', ip_ttl=64, udp_sport=574, with_udp_chksum=False, @@ -4205,8 +4205,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -4242,8 +4242,8 @@ def runTest(self): eth_dst='00:77:66:55:44:33', eth_src='00:44:44:44:44:44', ip_id=0, - ip_dst='2.2.2.3', - ip_src='2.2.2.1', + ip_dst='2.2.2.1', + ip_src='2.2.2.3', ip_ttl=64, udp_sport=574, with_udp_chksum=False, @@ -4374,8 +4374,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -4503,8 +4503,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -4672,8 +4672,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -4706,8 +4706,8 @@ def runTest(self): eth_dst='00:77:66:55:44:33', eth_src='00:44:44:44:44:44', ip_id=0, - ip_dst='2.2.2.3', - ip_src='2.2.2.1', + ip_dst='2.2.2.1', + ip_src='2.2.2.3', ip_ttl=64, udp_sport=574, with_udp_chksum=False, @@ -4856,8 +4856,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -4896,8 +4896,8 @@ def runTest(self): eth_dst='00:77:66:55:44:33', eth_src='00:44:44:44:44:44', ip_id=0, - ip_dst='2.2.2.3', - ip_src='2.2.2.1', + ip_dst='2.2.2.1', + ip_src='2.2.2.3', ip_ttl=64, udp_sport=574, with_udp_chksum=False, @@ -5034,8 +5034,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -5198,8 +5198,8 @@ def runTest(self): eth_src='00:44:44:44:44:44', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -5905,8 +5905,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -5939,8 +5939,8 @@ def runTest(self): eth_dst='00:77:66:55:44:33', eth_src='00:44:44:44:44:44', ip_id=0, - ip_dst='2.2.2.3', - ip_src='2.2.2.1', + ip_dst='2.2.2.1', + ip_src='2.2.2.3', ip_ttl=64, udp_sport=574, with_udp_chksum=False, @@ -5973,8 +5973,8 @@ def runTest(self): eth_dst='00:77:66:55:44:33', eth_src='00:44:44:44:44:44', ip_id=0, - ip_dst='2.2.2.3', - ip_src='2.2.2.1', + ip_dst='2.2.2.1', + ip_src='2.2.2.3', ip_ttl=64, udp_sport=574, with_udp_chksum=False, @@ -6002,8 +6002,8 @@ def runTest(self): eth_dst='00:77:66:55:44:33', eth_src='00:33:33:33:33:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -6376,8 +6376,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -6410,8 +6410,8 @@ def runTest(self): eth_dst='00:77:66:55:44:33', eth_src='00:44:44:44:44:44', ip_id=0, - ip_dst='2.2.2.3', - ip_src='2.2.2.1', + ip_dst='2.2.2.1', + ip_src='2.2.2.3', ip_ttl=64, udp_sport=574, with_udp_chksum=False, @@ -6444,8 +6444,8 @@ def runTest(self): eth_dst='00:77:66:55:44:33', eth_src='00:44:44:44:44:44', ip_id=0, - ip_dst='2.2.2.3', - ip_src='2.2.2.1', + ip_dst='2.2.2.1', + ip_src='2.2.2.3', ip_ttl=64, udp_sport=574, with_udp_chksum=False, @@ -6473,8 +6473,8 @@ def runTest(self): eth_dst='00:77:66:55:44:33', eth_src='00:33:33:33:33:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -6530,8 +6530,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -6563,8 +6563,8 @@ def runTest(self): eth_dst='00:77:66:55:44:33', eth_src='00:44:44:44:44:44', ip_id=0, - ip_dst='2.2.2.3', - ip_src='2.2.2.1', + ip_dst='2.2.2.1', + ip_src='2.2.2.3', ip_ttl=64, udp_sport=574, with_udp_chksum=False, @@ -6596,8 +6596,8 @@ def runTest(self): eth_src='00:66:66:66:66:66', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='3.3.3.3', - ip_src='3.3.3.1', + ip_dst='3.3.3.1', + ip_src='3.3.3.3', ip_ttl=64, nvgre_tni=0x4545, inner_frame=pkt) @@ -6628,8 +6628,8 @@ def runTest(self): eth_src='00:66:66:66:66:66', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='3.3.3.3', - ip_src='3.3.3.1', + ip_dst='3.3.3.1', + ip_src='3.3.3.3', ip_ttl=64, nvgre_tni=0x4545, inner_frame=pkt) @@ -6661,8 +6661,8 @@ def runTest(self): eth_dst='00:77:66:55:44:33', eth_src='00:66:66:66:66:66', ip_id=0, - ip_dst='3.3.3.3', - ip_src='3.3.3.1', + ip_dst='3.3.3.1', + ip_src='3.3.3.3', ip_ttl=64, nvgre_tni=0x4545, inner_frame=pkt) @@ -6914,8 +6914,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -8463,8 +8463,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -8483,8 +8483,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -8502,8 +8502,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -8521,8 +8521,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -8540,8 +8540,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -8559,8 +8559,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -8592,8 +8592,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -8609,8 +8609,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -8644,8 +8644,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -8662,8 +8662,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -8681,7 +8681,7 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', + ip_dst='1.1.1.1', ip_src='127.1.1.1', ip_ttl=64, udp_sport=11638, @@ -8700,7 +8700,7 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', + ip_dst='1.1.1.1', ip_src='225.1.1.1', ip_ttl=64, udp_sport=11638, @@ -8720,8 +8720,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -8740,8 +8740,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -8763,8 +8763,8 @@ def runTest(self): eth_src='00:33:33:33:33:33', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='1.1.1.3', - ip_src='1.1.1.1', + ip_dst='1.1.1.1', + ip_src='1.1.1.3', ip_ttl=64, udp_sport=11638, with_udp_chksum=False, @@ -9773,8 +9773,8 @@ def runTest(self): ipip_pkt = simple_gre_packet(eth_src='00:55:55:55:55:55', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='10.200.1.3', - ip_src='10.100.1.1', + ip_dst='10.100.1.1', + ip_src='10.200.1.3', ip_ttl=64, inner_frame=pkt1['IP']) pkt2 = simple_tcp_packet(eth_src='00:77:66:55:44:33', @@ -9795,8 +9795,8 @@ def runTest(self): ipip_pkt = simple_gre_packet(eth_src='00:55:55:55:55:55', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='10.200.1.3', - ip_src='10.100.1.1', + ip_dst='10.100.1.1', + ip_src='10.200.1.3', ip_ttl=64, inner_frame=pkt1['IPv6']) pkt2 = simple_tcpv6_packet(eth_src='00:77:66:55:44:33', @@ -9816,8 +9816,8 @@ def runTest(self): ip_ttl=64) ipip_pkt = simple_grev6_packet(eth_src='00:55:55:55:55:55', eth_dst='00:77:66:55:44:33', - ipv6_dst='3ffe::2', - ipv6_src='3ffe::1', + ipv6_dst='3ffe::1', + ipv6_src='3ffe::2', ipv6_hlim=64, inner_frame=pkt1['IP']) pkt2 = simple_tcp_packet(eth_src='00:77:66:55:44:33', @@ -9837,8 +9837,8 @@ def runTest(self): ipv6_hlim=64) ipip_pkt = simple_grev6_packet(eth_src='00:55:55:55:55:55', eth_dst='00:77:66:55:44:33', - ipv6_dst='3ffe::2', - ipv6_src='3ffe::1', + ipv6_dst='3ffe::1', + ipv6_src='3ffe::2', ipv6_hlim=64, inner_frame=pkt1['IPv6']) pkt2 = simple_tcpv6_packet(eth_src='00:77:66:55:44:33', @@ -9859,8 +9859,8 @@ def runTest(self): ipip_pkt = simple_ipv4ip_packet(eth_src='00:55:55:55:55:55', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='10.200.1.3', - ip_src='10.100.1.1', + ip_dst='10.100.1.1', + ip_src='10.200.1.3', ip_ttl=64, inner_frame=pkt1['IP']) pkt2 = simple_tcp_packet(eth_src='00:77:66:55:44:33', @@ -9881,8 +9881,8 @@ def runTest(self): ipip_pkt = simple_ipv4ip_packet(eth_src='00:55:55:55:55:55', eth_dst='00:77:66:55:44:33', ip_id=0, - ip_dst='10.200.1.3', - ip_src='10.100.1.1', + ip_dst='10.100.1.1', + ip_src='10.200.1.3', ip_ttl=64, inner_frame=pkt1['IPv6']) pkt2 = simple_tcpv6_packet(eth_src='00:77:66:55:44:33', @@ -9902,8 +9902,8 @@ def runTest(self): ip_ttl=64) ipip_pkt = simple_ipv6ip_packet(eth_src='00:55:55:55:55:55', eth_dst='00:77:66:55:44:33', - ipv6_dst='3ffe::2', - ipv6_src='3ffe::1', + ipv6_dst='3ffe::1', + ipv6_src='3ffe::2', ipv6_hlim=64, inner_frame=pkt1['IP']) pkt2 = simple_tcp_packet(eth_src='00:77:66:55:44:33', @@ -9923,8 +9923,8 @@ def runTest(self): ipv6_hlim=64) ipip_pkt = simple_ipv6ip_packet(eth_src='00:55:55:55:55:55', eth_dst='00:77:66:55:44:33', - ipv6_dst='3ffe::2', - ipv6_src='3ffe::1', + ipv6_dst='3ffe::1', + ipv6_src='3ffe::2', ipv6_hlim=64, inner_frame=pkt1['IPv6']) pkt2 = simple_tcpv6_packet(eth_src='00:77:66:55:44:33', @@ -10274,7 +10274,7 @@ def setUp(self): neighbor_entry) # create NAT ACL (permit all) - self.acl = self.client.switcht_api_acl_list_create(device, 0) + self.acl = self.client.switcht_api_acl_list_create(device, SWITCH_API_DIRECTION_INGRESS, 0) kvp = [] acl_priority = 10 action = 2 diff --git a/tests/ptf-tests/api-tests/switch_acl.py b/tests/ptf-tests/api-tests/switch_acl.py index 2323543..f35a117 100644 --- a/tests/ptf-tests/api-tests/switch_acl.py +++ b/tests/ptf-tests/api-tests/switch_acl.py @@ -100,7 +100,7 @@ def runTest(self): # setup a deny ACL to verify that the same packet does not make it # ip acl - acl = self.client.switcht_api_acl_list_create(0, 0) + acl = self.client.switcht_api_acl_list_create(0, SWITCH_API_DIRECTION_INGRESS, 0) # create kvp to match destination IP kvp = [] kvp_val = switcht_acl_value_t(value_num=int("0a0a0a01", 16)) @@ -142,6 +142,107 @@ def runTest(self): self.client.switcht_api_router_mac_group_delete(0, rmac) self.client.switcht_api_vrf_delete(0, vrf) +############################################################################### +@group('acl') +@group('maxsizes') +class IPEgressAclTest(api_base_tests.ThriftInterfaceDataPlane): + def runTest(self): + print + + print "Sending packet port %d" % swports[1], " -> port %d" % swports[2], " (192.168.0.1 -> 10.0.0.1 [id = 101])" + self.client.switcht_api_init(0) + vrf = self.client.switcht_api_vrf_create(0, 1) + + rmac = self.client.switcht_api_router_mac_group_create(0) + self.client.switcht_api_router_mac_add(0, rmac, '00:77:66:55:44:33') + + iu1 = interface_union(port_lag_handle = swports[1]) + i_info1 = switcht_interface_info_t(device=0, type=SWITCH_API_INTERFACE_L3, u=iu1, mac='00:77:66:55:44:33', label=0, vrf_handle=vrf, rmac_handle=rmac) + if1 = self.client.switcht_api_interface_create(0, i_info1) + i_ip1 = switcht_ip_addr_t(ipaddr='192.168.0.2', prefix_length=16) + self.client.switcht_api_l3_interface_address_add(0, if1, vrf, i_ip1) + + iu2 = interface_union(port_lag_handle = swports[2]) + i_info2 = switcht_interface_info_t(device=0, type=SWITCH_API_INTERFACE_L3, u=iu2, mac='00:77:66:55:44:33', label=0, vrf_handle=vrf, rmac_handle=rmac) + if2 = self.client.switcht_api_interface_create(0, i_info2) + i_ip2 = switcht_ip_addr_t(ipaddr='10.0.0.2', prefix_length=16) + self.client.switcht_api_l3_interface_address_add(0, if2, vrf, i_ip2) + + # Add a static route + i_ip3 = switcht_ip_addr_t(ipaddr='10.10.10.1', prefix_length=32) + nhop_key = switcht_nhop_key_t(intf_handle=if2, ip_addr_valid=0) + nhop = self.client.switcht_api_nhop_create(0, nhop_key) + neighbor_entry = switcht_neighbor_info_t(nhop_handle=nhop, + interface_handle=if2, + mac_addr='00:11:22:33:44:55', + ip_addr=i_ip3, + rw_type=SWITCH_API_NEIGHBOR_RW_TYPE_L3) + neighbor = self.client.switcht_api_neighbor_entry_add(0, neighbor_entry) + self.client.switcht_api_l3_route_add(0, vrf, i_ip3, nhop) + + # send the test packet(s) + pkt = simple_tcp_packet( eth_dst='00:77:66:55:44:33', + eth_src='00:22:22:22:22:22', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=64) + send_packet(self, swports[1], str(pkt)) + + exp_pkt = simple_tcp_packet( + eth_dst='00:11:22:33:44:55', + eth_src='00:77:66:55:44:33', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + #ip_tos=3, + ip_ttl=63) + verify_packets(self, exp_pkt, [swports[2]]) + + + # setup a deny ACL to verify that the same packet does not make it + # ip acl + acl = self.client.switcht_api_acl_list_create(0, SWITCH_API_DIRECTION_EGRESS, 0) + # create kvp to match destination IP + kvp = [] + kvp_val = switcht_acl_value_t(value_num=int("0a0a0a01", 16)) + kvp_mask = switcht_acl_value_t(value_num=int("ffffffff", 16)) + kvp.append(switcht_acl_key_value_pair_t(SWITCH_ACL_IP_FIELD_IPV4_DEST, kvp_val, kvp_mask)) + action = 1 + action_params = switcht_acl_action_params_t(redirect = switcht_acl_action_redirect(handle = 0)) + opt_action_params = switcht_acl_opt_action_params_t() + ace = self.client.switcht_api_acl_ip_rule_create(0, acl, 10, 1, kvp, action, + action_params, + opt_action_params) + self.client.switcht_api_acl_reference(0, acl, if2) + send_packet(self, swports[1], str(pkt)) + + # check for absence of packet here! + try: + verify_packets(self, exp_pkt, [swports[2]]) + print 'FAILED - did not expect packet' + except: + print 'Success' + + # ip_acl + self.client.switcht_api_acl_remove(0, acl, if2) + self.client.switcht_api_acl_rule_delete(0, acl, ace) + self.client.switcht_api_acl_list_delete(0, acl) + + #cleanup + self.client.switcht_api_neighbor_entry_remove(0, neighbor) + self.client.switcht_api_nhop_delete(0, nhop) + self.client.switcht_api_l3_route_delete(0, vrf, i_ip3, if2) + + self.client.switcht_api_l3_interface_address_delete(0, if1, vrf, i_ip1) + self.client.switcht_api_l3_interface_address_delete(0, if2, vrf, i_ip2) + + self.client.switcht_api_interface_delete(0, if1) + self.client.switcht_api_interface_delete(0, if2) + + self.client.switcht_api_router_mac_delete(0, rmac, '00:77:66:55:44:33') + self.client.switcht_api_router_mac_group_delete(0, rmac) + self.client.switcht_api_vrf_delete(0, vrf) ############################################################################### @group('acl') @@ -210,7 +311,7 @@ def runTest(self): # setup a Mirror acl # ip acl print "Create Mirror ACL to mirror i2e from 1->4" - acl = self.client.switcht_api_acl_list_create(0, 0) + acl = self.client.switcht_api_acl_list_create(0, SWITCH_API_DIRECTION_INGRESS, 0) # create kvp to match destination IP kvp = [] kvp_val = switcht_acl_value_t(value_num=int("0a0a0a01", 16)) @@ -353,7 +454,7 @@ def runTest(self): # setup a egress Mirror acl print "Create Egress Mirror ACL to mirror e2e from %d -> %d" % (swports[2], swports[4]) - acl = self.client.switcht_api_acl_list_create(0, 6) + acl = self.client.switcht_api_acl_list_create(0, SWITCH_API_DIRECTION_EGRESS, 6) # create kvp to match egress port and deflect bit kvp = [] kvp_val = switcht_acl_value_t(value_num=swports[2]) @@ -518,7 +619,7 @@ def runTest(self): mirror1 = self.client.switcht_api_mirror_session_create(0, minfo1) print "Create Mirror ACL to mirror i2e from 1->4" - acl = self.client.switcht_api_acl_list_create(0, 0) + acl = self.client.switcht_api_acl_list_create(0, SWITCH_API_DIRECTION_INGRESS, 0) # create kvp to match destination IP kvp = [] kvp_val = switcht_acl_value_t(value_num=int("0a0a0a01", 16)) @@ -624,7 +725,7 @@ def runTest(self): counter = self.client.switcht_api_acl_counter_create(0) - acl = self.client.switcht_api_acl_list_create(0, 0) + acl = self.client.switcht_api_acl_list_create(0, SWITCH_API_DIRECTION_INGRESS, 0) kvp = [] kvp_val1 = switcht_acl_value_t(value_num=int("0a0a0a01", 16)) kvp_mask1 = switcht_acl_value_t(value_num=int("ffffffff", 16)) @@ -727,3 +828,222 @@ def runTest(self): self.client.switcht_api_router_mac_delete(0, rmac, '00:77:66:55:44:33') self.client.switcht_api_router_mac_group_delete(0, rmac) self.client.switcht_api_vrf_delete(0, vrf) + +############################################################################### +@group('acl') +@group('maxsizes') +class IPIngressAclRangeTcamTest(api_base_tests.ThriftInterfaceDataPlane): + def runTest(self): + print + print "Sending packet port %d" % swports[1], " -> port %d" % swports[2], " (192.168.0.1 -> 10.0.0.1 [id = 101])" + self.client.switcht_api_init(0) + vrf = self.client.switcht_api_vrf_create(0, 1) + + rmac = self.client.switcht_api_router_mac_group_create(0) + self.client.switcht_api_router_mac_add(0, rmac, '00:77:66:55:44:33') + + iu1 = interface_union(port_lag_handle = swports[1]) + i_info1 = switcht_interface_info_t(device=0, type=SWITCH_API_INTERFACE_L3, u=iu1, mac='00:77:66:55:44:33', label=0, vrf_handle=vrf, rmac_handle=rmac) + if1 = self.client.switcht_api_interface_create(0, i_info1) + i_ip1 = switcht_ip_addr_t(ipaddr='192.168.0.2', prefix_length=16) + self.client.switcht_api_l3_interface_address_add(0, if1, vrf, i_ip1) + + iu2 = interface_union(port_lag_handle = swports[2]) + i_info2 = switcht_interface_info_t(device=0, type=SWITCH_API_INTERFACE_L3, u=iu2, mac='00:77:66:55:44:33', label=0, vrf_handle=vrf, rmac_handle=rmac) + if2 = self.client.switcht_api_interface_create(0, i_info2) + i_ip2 = switcht_ip_addr_t(ipaddr='10.0.0.2', prefix_length=16) + self.client.switcht_api_l3_interface_address_add(0, if2, vrf, i_ip2) + + # Add a static route + i_ip3 = switcht_ip_addr_t(ipaddr='10.10.10.1', prefix_length=32) + nhop_key = switcht_nhop_key_t(intf_handle=if2, ip_addr_valid=0) + nhop = self.client.switcht_api_nhop_create(0, nhop_key) + neighbor_entry = switcht_neighbor_info_t(nhop_handle=nhop, + interface_handle=if2, + mac_addr='00:11:22:33:44:55', + ip_addr=i_ip3, + rw_type=SWITCH_API_NEIGHBOR_RW_TYPE_L3) + neighbor = self.client.switcht_api_neighbor_entry_add(0, neighbor_entry) + self.client.switcht_api_l3_route_add(0, vrf, i_ip3, nhop) + + # send the test packet(s) + pkt = simple_tcp_packet( eth_dst='00:77:66:55:44:33', + eth_src='00:22:22:22:22:22', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=64) + send_packet(self, swports[1], str(pkt)) + + exp_pkt = simple_tcp_packet( + eth_dst='00:11:22:33:44:55', + eth_src='00:77:66:55:44:33', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + #ip_tos=3, + ip_ttl=63) + verify_packets(self, exp_pkt, [swports[2]]) + + switch_range = switcht_range_t(start_value = 1000, end_value=2000) + acl_range_handle = self.client.switcht_api_acl_range_create( + 0, + SWITCH_API_DIRECTION_INGRESS, + SWITCH_RANGE_TYPE_SRC_PORT, + switch_range) + + # setup a deny ACL to verify that the same packet does not make it + # ip acl + acl = self.client.switcht_api_acl_list_create(0, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_IP) + # create kvp to match destination IP + kvp = [] + kvp_val = switcht_acl_value_t(value_num=acl_range_handle) + kvp_mask = switcht_acl_value_t(value_num=0xffffffff) + kvp.append(switcht_acl_key_value_pair_t(SWITCH_ACL_IP_FIELD_L4_SOURCE_PORT_RANGE, kvp_val, kvp_mask)) + action = SWITCH_ACL_ACTION_DROP + action_params = switcht_acl_action_params_t(redirect = switcht_acl_action_redirect(handle = 0)) + opt_action_params = switcht_acl_opt_action_params_t() + ace = self.client.switcht_api_acl_ip_rule_create(0, acl, 10, 1, kvp, action, + action_params, + opt_action_params) + self.client.switcht_api_acl_reference(0, acl, if1) + send_packet(self, swports[1], str(pkt)) + + # check for absence of packet here! + try: + verify_packets(self, exp_pkt, [swports[2]]) + print 'FAILED - did not expect packet' + except: + print 'Success' + + # ip_acl + self.client.switcht_api_acl_remove(0, acl, if1) + self.client.switcht_api_acl_rule_delete(0, acl, ace) + self.client.switcht_api_acl_list_delete(0, acl) + self.client.switcht_api_acl_range_delete(0, acl_range_handle) + + #cleanup + self.client.switcht_api_neighbor_entry_remove(0, neighbor) + self.client.switcht_api_nhop_delete(0, nhop) + self.client.switcht_api_l3_route_delete(0, vrf, i_ip3, if2) + + self.client.switcht_api_l3_interface_address_delete(0, if1, vrf, i_ip1) + self.client.switcht_api_l3_interface_address_delete(0, if2, vrf, i_ip2) + + self.client.switcht_api_interface_delete(0, if1) + self.client.switcht_api_interface_delete(0, if2) + + self.client.switcht_api_router_mac_delete(0, rmac, '00:77:66:55:44:33') + self.client.switcht_api_router_mac_group_delete(0, rmac) + self.client.switcht_api_vrf_delete(0, vrf) + +############################################################################### +@group('acl') +@group('maxsizes') +class IPEgressAclRangeTcamTest(api_base_tests.ThriftInterfaceDataPlane): + def runTest(self): + print + + print "Sending packet port %d" % swports[1], " -> port %d" % swports[2], " (192.168.0.1 -> 10.0.0.1 [id = 101])" + self.client.switcht_api_init(0) + vrf = self.client.switcht_api_vrf_create(0, 1) + + rmac = self.client.switcht_api_router_mac_group_create(0) + self.client.switcht_api_router_mac_add(0, rmac, '00:77:66:55:44:33') + + iu1 = interface_union(port_lag_handle = swports[1]) + i_info1 = switcht_interface_info_t(device=0, type=SWITCH_API_INTERFACE_L3, u=iu1, mac='00:77:66:55:44:33', label=0, vrf_handle=vrf, rmac_handle=rmac) + if1 = self.client.switcht_api_interface_create(0, i_info1) + i_ip1 = switcht_ip_addr_t(ipaddr='192.168.0.2', prefix_length=16) + self.client.switcht_api_l3_interface_address_add(0, if1, vrf, i_ip1) + + iu2 = interface_union(port_lag_handle = swports[2]) + i_info2 = switcht_interface_info_t(device=0, type=SWITCH_API_INTERFACE_L3, u=iu2, mac='00:77:66:55:44:33', label=0, vrf_handle=vrf, rmac_handle=rmac) + if2 = self.client.switcht_api_interface_create(0, i_info2) + i_ip2 = switcht_ip_addr_t(ipaddr='10.0.0.2', prefix_length=16) + self.client.switcht_api_l3_interface_address_add(0, if2, vrf, i_ip2) + + # Add a static route + i_ip3 = switcht_ip_addr_t(ipaddr='10.10.10.1', prefix_length=32) + nhop_key = switcht_nhop_key_t(intf_handle=if2, ip_addr_valid=0) + nhop = self.client.switcht_api_nhop_create(0, nhop_key) + neighbor_entry = switcht_neighbor_info_t(nhop_handle=nhop, + interface_handle=if2, + mac_addr='00:11:22:33:44:55', + ip_addr=i_ip3, + rw_type=SWITCH_API_NEIGHBOR_RW_TYPE_L3) + neighbor = self.client.switcht_api_neighbor_entry_add(0, neighbor_entry) + self.client.switcht_api_l3_route_add(0, vrf, i_ip3, nhop) + + # send the test packet(s) + pkt = simple_tcp_packet( eth_dst='00:77:66:55:44:33', + eth_src='00:22:22:22:22:22', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + tcp_dport=1500, + ip_id=105, + ip_ttl=64) + send_packet(self, swports[1], str(pkt)) + + exp_pkt = simple_tcp_packet( + eth_dst='00:11:22:33:44:55', + eth_src='00:77:66:55:44:33', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + tcp_dport=1500, + #ip_tos=3, + ip_ttl=63) + verify_packets(self, exp_pkt, [swports[2]]) + + switch_range = switcht_range_t(start_value = 1000, end_value=2000) + acl_range_handle = self.client.switcht_api_acl_range_create( + 0, + SWITCH_API_DIRECTION_EGRESS, + SWITCH_RANGE_TYPE_DST_PORT, + switch_range) + + # setup a deny ACL to verify that the same packet does not make it + # ip acl + acl = self.client.switcht_api_acl_list_create(0, SWITCH_API_DIRECTION_EGRESS, SWITCH_ACL_TYPE_IP) + # create kvp to match destination IP + kvp = [] + kvp_val = switcht_acl_value_t(value_num=acl_range_handle) + kvp_mask = switcht_acl_value_t(value_num=0xffffffff) + kvp.append(switcht_acl_key_value_pair_t(SWITCH_ACL_IP_FIELD_L4_DEST_PORT_RANGE, kvp_val, kvp_mask)) + action = SWITCH_ACL_ACTION_DROP + action_params = switcht_acl_action_params_t(redirect = switcht_acl_action_redirect(handle = 0)) + opt_action_params = switcht_acl_opt_action_params_t() + ace = self.client.switcht_api_acl_ip_rule_create(0, acl, 10, 1, kvp, action, + action_params, + opt_action_params) + self.client.switcht_api_acl_reference(0, acl, if2) + send_packet(self, swports[1], str(pkt)) + + # check for absence of packet here! + try: + verify_packets(self, exp_pkt, [swports[2]]) + print 'FAILED - did not expect packet' + except: + print 'Success' + + # ip_acl + self.client.switcht_api_acl_remove(0, acl, if2) + self.client.switcht_api_acl_rule_delete(0, acl, ace) + self.client.switcht_api_acl_list_delete(0, acl) + self.client.switcht_api_acl_range_delete(0, acl_range_handle) + + #cleanup + self.client.switcht_api_neighbor_entry_remove(0, neighbor) + self.client.switcht_api_nhop_delete(0, nhop) + self.client.switcht_api_l3_route_delete(0, vrf, i_ip3, if2) + + self.client.switcht_api_l3_interface_address_delete(0, if1, vrf, i_ip1) + self.client.switcht_api_l3_interface_address_delete(0, if2, vrf, i_ip2) + + self.client.switcht_api_interface_delete(0, if1) + self.client.switcht_api_interface_delete(0, if2) + + self.client.switcht_api_router_mac_delete(0, rmac, '00:77:66:55:44:33') + self.client.switcht_api_router_mac_group_delete(0, rmac) + self.client.switcht_api_vrf_delete(0, vrf) diff --git a/tests/ptf-tests/common/pd_utils.py b/tests/ptf-tests/common/pd_utils.py index aa77333..a4ee913 100644 --- a/tests/ptf-tests/common/pd_utils.py +++ b/tests/ptf-tests/common/pd_utils.py @@ -10,6 +10,7 @@ default_entries = {} stats_enabled = 1 nat_enabled = 1 +egress_acl_enabled = 1 def port_to_pipe(port): return port >> 7 @@ -86,7 +87,7 @@ def populate_default_fabric_entries(client, sess_hdl, dev_tgt, ipv6_enabled=0, if acl_enabled: client.ip_acl_set_default_action_nop(sess_hdl, dev_tgt) client.ipv4_racl_set_default_action_nop(sess_hdl, dev_tgt) - client.egress_acl_set_default_action_nop(sess_hdl, dev_tgt) + client.egress_system_acl_set_default_action_nop(sess_hdl, dev_tgt) client.validate_packet_set_default_action_nop(sess_hdl, dev_tgt) if tunnel_enabled: client.outer_rmac_set_default_action_on_miss(sess_hdl, dev_tgt) @@ -136,6 +137,16 @@ def populate_default_fabric_entries(client, sess_hdl, dev_tgt, ipv6_enabled=0, client.nat_src_set_default_action_on_miss(sess_hdl, dev_tgt) client.nat_flow_set_default_action_nop(sess_hdl, dev_tgt) + if egress_acl_enabled: + client.egress_mac_acl_set_default_action_nop(sess_hdl, dev_tgt) + client.egress_ip_acl_set_default_action_nop(sess_hdl, dev_tgt) + client.egress_ipv6_acl_set_default_action_nop(sess_hdl, dev_tgt) + client.ingress_l4_src_port_set_default_action_nop(sess_hdl, dev_tgt) + client.ingress_l4_dst_port_set_default_action_nop(sess_hdl, dev_tgt) + client.egress_l4_src_port_set_default_action_nop(sess_hdl, dev_tgt) + client.egress_l4_dst_port_set_default_action_nop(sess_hdl, dev_tgt) + client.egress_l4port_fields_set_default_action_nop(sess_hdl, dev_tgt) + def populate_default_entries(client, sess_hdl, dev_tgt, ipv6_enabled, acl_enabled, tunnel_enabled, multicast_enabled, int_enabled): index = 0 @@ -197,7 +208,10 @@ def populate_default_entries(client, sess_hdl, dev_tgt, ipv6_enabled, sess_hdl, dev_tgt) client.rewrite_set_default_action_set_l2_rewrite( sess_hdl, dev_tgt) - action_spec = dc_egress_port_type_normal_action_spec_t(action_ifindex=0, action_qos_group=0) + action_spec = dc_egress_port_type_normal_action_spec_t( + action_ifindex=0, + action_qos_group=0, + action_if_label=0) client.egress_port_mapping_set_default_action_egress_port_type_normal( sess_hdl, dev_tgt, action_spec) client.mtu_set_default_action_mtu_miss( @@ -235,7 +249,7 @@ def populate_default_entries(client, sess_hdl, dev_tgt, ipv6_enabled, sess_hdl, dev_tgt) client.ipv4_racl_set_default_action_nop( sess_hdl, dev_tgt) - client.egress_acl_set_default_action_nop( + client.egress_system_acl_set_default_action_nop( sess_hdl, dev_tgt) client.acl_stats_set_default_action_acl_stats_update( sess_hdl, dev_tgt) @@ -322,6 +336,16 @@ def populate_default_entries(client, sess_hdl, dev_tgt, ipv6_enabled, client.nat_src_set_default_action_on_miss(sess_hdl, dev_tgt) client.nat_flow_set_default_action_nop(sess_hdl, dev_tgt) + if egress_acl_enabled: + client.egress_mac_acl_set_default_action_nop(sess_hdl, dev_tgt) + client.egress_ip_acl_set_default_action_nop(sess_hdl, dev_tgt) + client.egress_ipv6_acl_set_default_action_nop(sess_hdl, dev_tgt) + client.ingress_l4_src_port_set_default_action_nop(sess_hdl, dev_tgt) + client.ingress_l4_dst_port_set_default_action_nop(sess_hdl, dev_tgt) + client.egress_l4_src_port_set_default_action_nop(sess_hdl, dev_tgt) + client.egress_l4_dst_port_set_default_action_nop(sess_hdl, dev_tgt) + client.egress_l4port_fields_set_default_action_nop(sess_hdl, dev_tgt) + def delete_default_entries(client, sess_hdl, dev_id): return @@ -654,7 +678,8 @@ def program_ports(client, sess_hdl, dev_tgt, port_count): standard_metadata_egress_port=count) action_spec = dc_egress_port_type_normal_action_spec_t( action_ifindex=count, - action_qos_group=0) + action_qos_group=0, + action_if_label=0) egress_hdl = client.egress_port_mapping_table_add_with_egress_port_type_normal( sess_hdl, dev_tgt, @@ -705,7 +730,8 @@ def program_emulation_ports(client, sess_hdl, dev_tgt, port_count): eg_intr_md_egress_port=count) action_spec = dc_egress_port_type_normal_action_spec_t( action_ifindex=count, - action_qos_group=0) + action_qos_group=0, + action_if_label=0) egress_hdl = client.egress_port_mapping_table_add_with_egress_port_type_normal( sess_hdl, dev_tgt, @@ -834,7 +860,7 @@ def program_vlan(client, sess_hdl, dev_tgt, vrf, inner_rmac_group, def program_egress_bd_map(client, sess_hdl, dev_tgt, smac_index, vlan): match_spec = dc_egress_bd_map_match_spec_t(egress_metadata_bd=vlan) action_spec = dc_set_egress_bd_properties_action_spec_t( - action_smac_idx=smac_index, action_nat_mode=0) + action_smac_idx=smac_index, action_nat_mode=0, action_bd_label=0) client.egress_bd_map_table_add_with_set_egress_bd_properties( sess_hdl, dev_tgt, match_spec, action_spec) @@ -1415,7 +1441,8 @@ def program_egress_bd_properties(client, sess_hdl, dev_tgt, bd, rewrite_index): egress_metadata_bd=bd) action_spec = dc_set_egress_bd_properties_action_spec_t( action_smac_idx=rewrite_index, - action_nat_mode=0) + action_nat_mode=0, + action_bd_label=0) hdl = client.egress_bd_map_table_add_with_set_egress_bd_properties( sess_hdl, dev_tgt, match_spec, action_spec) return hdl diff --git a/tests/ptf-tests/common/sai_utils.py b/tests/ptf-tests/common/sai_utils.py index de1953f..9fbcbcc 100644 --- a/tests/ptf-tests/common/sai_utils.py +++ b/tests/ptf-tests/common/sai_utils.py @@ -304,6 +304,7 @@ def sai_thrift_create_hostif(client, rif_or_port_id, intf_name): return hif_id def sai_thrift_create_acl_table(client, + acl_stage = SAI_ACL_STAGE_INGRESS, addr_family = False, ip_src = False, ip_dst = False, @@ -313,6 +314,12 @@ def sai_thrift_create_acl_table(client, in_port = False, out_port = False): acl_attr_list = [] + + attribute_value = sai_thrift_attribute_value_t(s32=acl_stage) + attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_STAGE, + value=attribute_value) + acl_attr_list.append(attribute) + if ip_src: attribute_value = sai_thrift_attribute_value_t(booldata=1) attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_FIELD_SRC_IP, @@ -364,6 +371,7 @@ def sai_thrift_create_acl_entry(client, acl_table_id, out_ports = None, in_port = None, out_port = None, + range_list = None, packet_action = None, ingress_mirror_id = None, egress_mirror_id = None, @@ -426,6 +434,13 @@ def sai_thrift_create_acl_entry(client, acl_table_id, value=attribute_value) acl_attr_list.append(attribute) + if range_list != None: + acl_range_list = sai_thrift_object_list_t(count=len(range_list), object_id_list=range_list) + attribute_value = sai_thrift_attribute_value_t(aclfield=sai_thrift_acl_field_data_t(data = sai_thrift_acl_data_t(objlist=acl_range_list))) + attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_FIELD_RANGE, + value=attribute_value) + acl_attr_list.append(attribute) + #Packet action for action in action_list: if action == SAI_ACL_ENTRY_ATTR_PACKET_ACTION: @@ -501,6 +516,24 @@ def sai_thrift_create_acl_counter(client, acl_table_id, packet_enable = True, by acl_counter_id = client.sai_thrift_create_acl_counter(attr_list) return acl_counter_id +def sai_thrift_create_acl_range(client, range_type, range_value): + attr_list = [] + + attribute1_value = sai_thrift_attribute_value_t(s32=range_type) + attribute1 = sai_thrift_attribute_t( + id=SAI_ACL_RANGE_ATTR_TYPE, + value=attribute1_value) + attr_list.append(attribute1) + + attribute2_value = sai_thrift_attribute_value_t(u32range=range_value) + attribute2 = sai_thrift_attribute_t( + id=SAI_ACL_RANGE_ATTR_LIMIT, + value=attribute2_value) + attr_list.append(attribute2) + + acl_range_id = client.sai_thrift_create_acl_range(attr_list) + return acl_range_id + def sai_thrift_create_mirror_session(client, mirror_type, port, vlan, vlan_priority, vlan_tpid, src_mac, dst_mac, diff --git a/tests/ptf-tests/common/utils.py b/tests/ptf-tests/common/utils.py index cd6e912..233ee29 100644 --- a/tests/ptf-tests/common/utils.py +++ b/tests/ptf-tests/common/utils.py @@ -81,7 +81,15 @@ class FabricCpuHeader(Packet): XShortField("ingress_ifindex", 0), XShortField("ingress_bd", 0), - XShortField("reason_code", 0) + XShortField("reason_code", 0), + XShortField("mcast_grp", 0) + ] + +class FabricCpuSflowHeader(Packet): + name = "Fabric Cpu Sflow Header" + fields_desc = [ + XShortField("sflow_sid", 0), + XShortField("sflow_egress_port", 0), ] class FabricCpuSflowHeader(Packet): @@ -133,6 +141,7 @@ def simple_cpu_packet(header_version = 0, dst_port_or_group = 0, ingress_ifindex = 1, ingress_bd = 0, + mcast_grp = 0, egress_queue = 0, tx_bypass = False, ingress_port = 1, @@ -160,7 +169,8 @@ def simple_cpu_packet(header_version = 0, ingress_port = ingress_port, ingress_ifindex = ingress_ifindex, ingress_bd = ingress_bd, - reason_code = reason_code) + reason_code = reason_code, + mcast_grp = mcast_grp) fabric_payload_header = FabricPayloadHeader(ether_type = eth_type) @@ -295,12 +305,14 @@ def crc16_regular(buff, crc = 0, poly = 0xa001): i += 1 return crc -def entropy_hash(pkt, layer='ipv4'): - buff = pkt[Ether].src.translate(None, ':') +def entropy_hash(pkt, layer='ipv4', ifindex=0): + buff='' + if layer == 'ether': + buff += str(ifindex).zfill(4) + buff += pkt[Ether].src.translate(None, ':') buff += pkt[Ether].dst.translate(None, ':') if layer == 'ether': - #buff += str(hex(pkt[Ether].type)[2:]).zfill(4) - buff += ''.zfill(26) + buff += str(hex(pkt[Ether].type)[2:]).zfill(4) elif layer == 'ipv4': buff += socket.inet_aton(pkt[IP].src).encode('hex') buff += socket.inet_aton(pkt[IP].dst).encode('hex') diff --git a/tests/ptf-tests/sai-tests/switch.py b/tests/ptf-tests/sai-tests/switch.py index f3c0790..f7aeffc 100644 --- a/tests/ptf-tests/sai-tests/switch.py +++ b/tests/ptf-tests/sai-tests/switch.py @@ -1475,11 +1475,6 @@ def runTest(self): ip_src='192.168.0.1', ip_id=105, ip_ttl=63) -# try: -# send_packet(self, 2, str(pkt)) -# verify_packets(self, exp_pkt, [1]) -# -# finally: if True: # setup ACL to block based on Source IP @@ -1534,6 +1529,198 @@ def runTest(self): self.client.sai_thrift_remove_virtual_router(vr_id) +class IPIngressAclRangeTcamTest(sai_base_test.ThriftInterfaceDataPlane): + def runTest(self): + print + print "Sending packet port 1 -> port 2 (192.168.0.1 -> 10.10.10.1 [id = 101])" + switch_init(self.client) + port1 = port_list[1] + port2 = port_list[2] + v4_enabled = 1 + v6_enabled = 1 + mac = '' + + vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) + + rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, port1, 0, v4_enabled, v6_enabled, mac) + rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port2, 0, v4_enabled, v6_enabled, mac) + + addr_family = SAI_IP_ADDR_FAMILY_IPV4 + ip_addr1 = '10.10.10.1' + ip_mask1 = '255.255.255.255' + dmac1 = '00:11:22:33:44:55' + nhop1 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif_id1) + sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, nhop1) + sai_thrift_create_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) + + # send the test packet(s) + pkt = simple_tcp_packet(eth_dst='00:77:66:55:44:33', + eth_src='00:22:22:22:22:22', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=64) + exp_pkt = simple_tcp_packet( + eth_dst='00:11:22:33:44:55', + eth_src='00:77:66:55:44:33', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=63) + if True: + + u32range = sai_thrift_range_t(min=1000, max=2000) + acl_range_id = sai_thrift_create_acl_range(self.client, SAI_ACL_RANGE_L4_SRC_PORT_RANGE, u32range) + range_list = [acl_range_id] + + # setup ACL to block based on Source IP + action_list = [SAI_ACL_ENTRY_ATTR_PACKET_ACTION] + packet_action = SAI_PACKET_ACTION_DROP + in_ports = [port1, port2] + ip_src = "192.168.0.1" + ip_src_mask = "255.255.255.0" + + acl_table_id = sai_thrift_create_acl_table( + client = self.client, + ip_src = True, + in_ports = True) + + acl_entry_id = sai_thrift_create_acl_entry( + client = self.client, + acl_table_id = acl_table_id, + action_list = action_list, + range_list = range_list, + ip_src = ip_src, + ip_src_mask = ip_src_mask, + in_ports = in_ports) + + # send the same packet + failed = 0 + send_packet(self, 2, str(pkt)) + + # ensure packet is dropped + # check for absence of packet here! + try: + verify_packets(self, exp_pkt, [1]) + print 'FAILED - did not expect packet' + failed = 1 + except: + print 'Success' + + finally: + if failed == 1: + self.assertFalse() + + + # delete ACL + self.client.sai_thrift_delete_acl_entry(acl_entry_id) + self.client.sai_thrift_delete_acl_table(acl_table_id) + self.client.sai_thrift_delete_acl_range(acl_range_id) + + # cleanup + sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) + sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, nhop1) + self.client.sai_thrift_remove_next_hop(nhop1) + + self.client.sai_thrift_remove_router_interface(rif_id1) + self.client.sai_thrift_remove_router_interface(rif_id2) + + self.client.sai_thrift_remove_virtual_router(vr_id) + +class IPEgressAclTest(sai_base_test.ThriftInterfaceDataPlane): + def runTest(self): + print + + print "Sending packet port 1 -> port 2 (192.168.0.1 -> 10.10.10.1 [id = 101])" + switch_init(self.client) + port1 = port_list[1] + port2 = port_list[2] + v4_enabled = 1 + v6_enabled = 1 + mac = '' + + vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) + + rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, port1, 0, v4_enabled, v6_enabled, mac) + rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port2, 0, v4_enabled, v6_enabled, mac) + + addr_family = SAI_IP_ADDR_FAMILY_IPV4 + ip_addr1 = '10.10.10.1' + ip_mask1 = '255.255.255.255' + dmac1 = '00:11:22:33:44:55' + nhop1 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif_id1) + sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, nhop1) + sai_thrift_create_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) + + # send the test packet(s) + pkt = simple_tcp_packet(eth_dst='00:77:66:55:44:33', + eth_src='00:22:22:22:22:22', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=64) + exp_pkt = simple_tcp_packet( + eth_dst='00:11:22:33:44:55', + eth_src='00:77:66:55:44:33', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=63) + if True: + + # setup ACL to block based on Source IP + action_list = [SAI_ACL_ENTRY_ATTR_PACKET_ACTION] + packet_action = SAI_PACKET_ACTION_DROP + in_ports = [port1, port2] + ip_src = "192.168.0.1" + ip_src_mask = "255.255.255.0" + + acl_table_id = sai_thrift_create_acl_table( + client = self.client, + acl_stage = SAI_ACL_STAGE_EGRESS, + ip_src = True, + in_ports = True) + + acl_entry_id = sai_thrift_create_acl_entry( + client = self.client, + acl_table_id = acl_table_id, + action_list = action_list, + ip_src = ip_src, + ip_src_mask = ip_src_mask, + in_ports = in_ports) + + # send the same packet + failed = 0 + send_packet(self, 2, str(pkt)) + + # ensure packet is dropped + # check for absence of packet here! + try: + verify_packets(self, exp_pkt, [1]) + print 'FAILED - did not expect packet' + failed = 1 + except: + print 'Success' + + finally: + if failed == 1: + self.assertFalse() + + + # delete ACL + self.client.sai_thrift_delete_acl_entry(acl_entry_id) + self.client.sai_thrift_delete_acl_table(acl_table_id) + + # cleanup + sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) + sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, nhop1) + self.client.sai_thrift_remove_next_hop(nhop1) + + self.client.sai_thrift_remove_router_interface(rif_id1) + self.client.sai_thrift_remove_router_interface(rif_id2) + + self.client.sai_thrift_remove_virtual_router(vr_id) + class L3VIIPv4HostTest(sai_base_test.ThriftInterfaceDataPlane): def runTest(self): print @@ -1925,6 +2112,7 @@ def runTest(self): acl_table_id = sai_thrift_create_acl_table( client = self.client, + acl_stage = SAI_ACL_STAGE_EGRESS, out_port = True) acl_entry_id = sai_thrift_create_acl_entry( @@ -2013,6 +2201,7 @@ def runTest(self): acl_table_id = sai_thrift_create_acl_table( client = self.client, + acl_stage=SAI_ACL_STAGE_EGRESS, out_port = True) acl_entry_id = sai_thrift_create_acl_entry( @@ -2293,7 +2482,6 @@ def runTest(self): class NexthopGetSetTest(sai_base_test.ThriftInterfaceDataPlane): def runTest(self): - return switch_init(self.client) port1 = port_list[1] port2 = port_list[2] diff --git a/tests/run_of_tests.py b/tests/run_of_tests.py new file mode 100755 index 0000000..f1968a8 --- /dev/null +++ b/tests/run_of_tests.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +# Copyright 2013-present Barefoot Networks, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys +import os +from subprocess import Popen +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument("--oft-path", required=True, + help="Location of oftest framework oft") +args, unknown_args = parser.parse_known_args() + +root_dir = os.path.dirname(os.path.realpath(__file__)) +oft_path = args.oft_path +test_dir = os.path.join(root_dir, "of-tests") + +if __name__ == "__main__": + new_args = unknown_args + new_args += ["-S 127.0.0.1", "-V1.3"] + new_args += ["--test-dir", test_dir] + new_args += ["--interface", "0@veth1"] + new_args += ["--interface", "2@veth5"] + new_args += ["--interface", "3@veth7"] + new_args += ["--interface", "4@veth9"] + new_args += ["--interface", "5@veth11"] + new_args += ["--interface", "6@veth13"] + new_args += ["--interface", "7@veth15"] + + child = Popen([oft_path] + new_args) + child.wait() + sys.exit(child.returncode) diff --git a/tests/run_tests.py.in b/tests/run_tests.py.in new file mode 100755 index 0000000..b871088 --- /dev/null +++ b/tests/run_tests.py.in @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +# Copyright 2013-present Barefoot Networks, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys +import os +from subprocess import Popen +import argparse + +root_dir = "@abs_srcdir@" +default_test_dir = os.path.join(root_dir, "ptf-tests", "pd-tests") + +parser = argparse.ArgumentParser() +parser.add_argument("--test-dir", required=False, + default=default_test_dir, + help="directory containing the tests (default %s)" % default_test_dir) +parser.add_argument("--pd-thrift", action="append", + help="a directory containing PD Thrift Python bindings, can be used multiple times") +args, unknown_args = parser.parse_known_args() + +testutils_dir = os.path.join(root_dir, '..', 'testutils') + +max_ports = 9 +cpu_port = 64 +cpu_veth = 251 + +if __name__ == "__main__": + if "@PTF@" == "": + print "configure could not find an installed version of ptf" + sys.exit(1) + new_args = [] + if args.pd_thrift: + for p in args.pd_thrift: + new_args += ["--pypath", p] + switchapi_py = os.path.join("@abs_top_builddir@", "switchapi") + if os.path.exists(switchapi_py): + new_args += ["--pypath", switchapi_py] + switchsai_py = os.path.join("@abs_top_builddir@", "switchsai") + if os.path.exists(switchsai_py): + new_args += ["--pypath", switchsai_py] + new_args += ["--pypath", testutils_dir] + new_args += ["--test-dir", args.test_dir] + for port in xrange(max_ports): + new_args += ["--interface", "%d@veth%d" % (port, 2 * port + 1)] + new_args += ["--interface", "%s@veth%s" % (cpu_port, cpu_veth)] + new_args += unknown_args + child = Popen(["@PTF@"] + new_args) + child.wait() + sys.exit(child.returncode) diff --git a/testutils/erspan3.py b/testutils/erspan3.py new file mode 100644 index 0000000..120b1c0 --- /dev/null +++ b/testutils/erspan3.py @@ -0,0 +1,38 @@ +import ptf.dataplane as dataplane + +def match_erspan3_pkt(exp_pkt, pkt, ignore_tstamp=True): + """ + Compare ERSPAN_III packets, ignore the timestamp value. Just make sure + it is non-zero + """ + if ignore_tstamp: + erspan3 = pkt.getlayer(ERSPAN_III) + if erspan3 == None: + #self.logger.error("No ERSPAN pkt received") + return False + + #if erspan3.timestamp == 0: + # #self.logger.error("Invalid ERSPAN timestamp") + # return False + + #fix the exp_pkt timestamp and compare + exp_erspan3 = exp_pkt.getlayer(ERSPAN_III) + if erspan3 == None: + #self.logger.error("Test user error - exp_pkt is not ERSPAN_III packet") + return False + + exp_erspan3.timestamp = 0 + erspan3.timestamp = 0 + + return dataplane.match_exp_pkt(exp_pkt, pkt) + +def verify_erspan3_packet(test, pkt, ofport): + """ + Check that an expected packet is received + """ + logging.debug("Checking for pkt on port %r", ofport) + (_, rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, timeout=2, exp_pkt=None) + test.assertTrue(rcv_pkt != None, "Did not receive pkt on %r" % ofport) + # convert rcv_pkt string back to layered pkt + nrcv = pkt.__class__(rcv_pkt) + test.assertTrue(match_erspan3_pkt(pkt, nrcv), "Received packet did not match expected packet") diff --git a/testutils/xnt.py b/testutils/xnt.py new file mode 100644 index 0000000..d5d5247 --- /dev/null +++ b/testutils/xnt.py @@ -0,0 +1,75 @@ +import sys + +from ptf.testutils import * + +try: + import scapy.config + import scapy.route + import scapy.layers.l2 + import scapy.layers.inet + import scapy.main +except ImportError: + sys.exit("Need to install scapy for packet parsing") + +try: + scapy.main.load_contrib("vxlan") + scapy.main.load_contrib("xnt") + VXLAN_GPE = scapy.contrib.vxlan.VXLAN_GPE + VXLAN_GPE_INT = scapy.contrib.xnt.VXLAN_GPE_INT + INT_META_HDR = scapy.contrib.xnt.INT_META_HDR + INT_hop_info = scapy.contrib.xnt.INT_hop_info +except: + pass + +def vxlan_gpe_int_src_packet(eth_dst='00:77:66:55:44:33', + eth_src='00:22:22:22:22:22', + ip_id=0x0, + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_ttl=64, + udp_sport=101, + with_udp_chksum=False, + vxlan_vni=0x1234, + int_inst_mask=0xAC00, + int_inst_cnt=4, + max_hop_cnt=32, + inner_frame=None): + + udp_pkt = simple_udp_packet( + pktlen=0, + eth_dst=eth_dst, + eth_src=eth_src, + ip_dst=ip_dst, + ip_src=ip_src, + ip_ttl=ip_ttl, + udp_sport=udp_sport, + udp_dport=4790, + with_udp_chksum=with_udp_chksum, + ) + + vxlan_pkt = udp_pkt / VXLAN_GPE(vni = vxlan_vni) + + vxlan_pkt['VXLAN_GPE'].next_proto = 0x5 + int_header = VXLAN_GPE_INT() + int_header.length = 3 # this header(4) + INT meta header (8) + int_meta_header = INT_META_HDR(ins_cnt=int_inst_cnt, + max_hop_cnt=max_hop_cnt, inst_mask=int_inst_mask) + return vxlan_pkt / int_header / int_meta_header / inner_frame + +def vxlan_gpe_int_packet_add_hop_info(Packet, + bos=False, + val=0x7FFFFFFF, incr_cnt=0): + # Find the start of INT data (following INT_META_HDR) + meta_hdr = Packet[INT_META_HDR] + if meta_hdr == None: + return Packet + + # copy the packet and truncate everything after META_HDR + new_pkt = Packet.copy() + new_pkt[INT_META_HDR].remove_payload() + new_pkt = new_pkt/INT_hop_info(bos=bos, val=val)/Packet[INT_META_HDR].payload + # update all the headers - IP UDP header lens are updated automatically + new_pkt[INT_META_HDR].total_hop_cnt += incr_cnt + new_pkt[VXLAN_GPE_INT].length += 1 + + return new_pkt diff --git a/tools/veth_disable_ipv6.sh b/tools/veth_disable_ipv6.sh new file mode 100755 index 0000000..88c2d41 --- /dev/null +++ b/tools/veth_disable_ipv6.sh @@ -0,0 +1,21 @@ +#!/bin/bash +noOfVeths=18 +if [ $# -eq 1 ]; then + noOfVeths=$1 +fi +echo "No of Veths is $noOfVeths" +idx=0 +let "vethpairs=$noOfVeths/2" +while [ $idx -lt $vethpairs ] +do + intf0="veth$(($idx*2))" + intf1="veth$(($idx*2+1))" + sysctl net.ipv6.conf.$intf0.disable_ipv6=1 + sysctl net.ipv6.conf.$intf1.disable_ipv6=1 + idx=$((idx + 1)) +done +idx=125 +intf0="veth$(($idx*2))" +intf1="veth$(($idx*2+1))" +sysctl net.ipv6.conf.$intf0.disable_ipv6=1 +sysctl net.ipv6.conf.$intf1.disable_ipv6=1 diff --git a/tools/veth_setup.sh b/tools/veth_setup.sh new file mode 100755 index 0000000..ded6d9f --- /dev/null +++ b/tools/veth_setup.sh @@ -0,0 +1,38 @@ +#!/bin/bash +noOfVeths=18 +if [ $# -eq 1 ]; then + noOfVeths=$1 +fi +echo "No of Veths is $noOfVeths" +idx=0 +let "vethpairs=$noOfVeths/2" +while [ $idx -lt $vethpairs ] +do +#1 2 3 4 5 6 7 125 + intf0="veth$(($idx*2))" + intf1="veth$(($idx*2+1))" + idx=$((idx + 1)) + if ! ip link show $intf0 &> /dev/null; then + ip link add name $intf0 type veth peer name $intf1 + ip link set dev $intf0 up + ip link set dev $intf1 up + TOE_OPTIONS="rx tx sg tso ufo gso gro lro rxvlan txvlan rxhash" + for TOE_OPTION in $TOE_OPTIONS; do + /sbin/ethtool --offload $intf0 "$TOE_OPTION" off + /sbin/ethtool --offload $intf1 "$TOE_OPTION" off + done + fi +done +idx=125 +intf0="veth$(($idx*2))" +intf1="veth$(($idx*2+1))" +if ! ip link show $intf0 &> /dev/null; then + ip link add name $intf0 type veth peer name $intf1 + ip link set dev $intf0 up + ip link set dev $intf1 up + TOE_OPTIONS="rx tx sg tso ufo gso gro lro rxvlan txvlan rxhash" + for TOE_OPTION in $TOE_OPTIONS; do + /sbin/ethtool --offload $intf0 "$TOE_OPTION" off + /sbin/ethtool --offload $intf1 "$TOE_OPTION" off + done +fi diff --git a/tools/veth_teardown.sh b/tools/veth_teardown.sh new file mode 100755 index 0000000..b96591e --- /dev/null +++ b/tools/veth_teardown.sh @@ -0,0 +1,21 @@ +#!/bin/bash +noOfVeths=18 +if [ $# -eq 1 ]; then + noOfVeths=$1 +fi +echo "No of Veths is $noOfVeths" +idx=0 +while [ $idx -lt $noOfVeths ] +do +#for idx in 0 1 2 3 4 5 6 7 125; do + intf="veth$(($idx*2))" + if ip link show $intf &> /dev/null; then + ip link delete $intf type veth + fi + idx=$((idx + 1)) +done +idx=125 +intf="veth$(($idx*2))" +if ip link show $intf &> /dev/null; then + ip link delete $intf type veth +fi