diff --git a/custom/README.md b/custom/README.md new file mode 100644 index 000000000..50daccf88 --- /dev/null +++ b/custom/README.md @@ -0,0 +1,9 @@ +SAI Custom Headers Directory +============================================== + +This directory should contains vendor specific custom headers +that are considered vendor internal and should not be available +to public, but they still can have metadata generated for them +for vendor internal use. + +For more information reffer to doc/custom-headers diff --git a/doc/custom-headers/README.md b/doc/custom-headers/README.md new file mode 100644 index 000000000..42f9585ef --- /dev/null +++ b/doc/custom-headers/README.md @@ -0,0 +1,22 @@ +Proposal for SAI Custom Headers Directory +============================================== + +SAI/custom is designed to hold custom headers provided by vendors. + +By default this directory is empty, and no custom headers are present. If +vendor want to provide custom headers, it can just simply copy custom headers +to that directory, and automatically that directory will be used by meta parser +to generate metadata for custom headers as well. + +There is requirement that custom headers must still follow style convention +as regular headers. + +This directory SAI/doc/custom-headers contains sample custom headers and how +they should look like. Base file is saicustom.h file which must be present if +vendor wants to add custom headers. + +Custom headers, can extend existing object type, api, stats, attributes and +provide new apis and totally new enums. + +Examing provided examples in this directory. If there will be problem with +custom headers, meta parser will provide error/warning message. diff --git a/doc/custom-headers/saicustom.h b/doc/custom-headers/saicustom.h new file mode 100644 index 000000000..3302690bd --- /dev/null +++ b/doc/custom-headers/saicustom.h @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2024 Microsoft Open Technologies, 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 + * + * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT + * LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS + * FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT. + * + * See the Apache Version 2.0 License for specific language governing + * permissions and limitations under the License. + * + * Microsoft would like to thank the following companies for their review and + * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, + * Dell Products, L.P., Facebook, Inc., Marvell International Ltd. + * + * @file saicustom.h + * + * @brief This module defines custom of the Switch Abstraction Interface (SAI) + */ + +#ifndef __SAICUSTOM_H_ +#define __SAICUSTOM_H_ + +#include +#include + +/* existing enum custom */ +#include "saitypescustom.h" +#include "saiswitchcustom.h" +#include "saiportcustom.h" + +/* new custom object type includes */ +#include "saicustomone.h" + +/** + * @brief Custom SAI APIs + * + * @flags free + */ +typedef enum _sai_api_custom_t +{ + SAI_API_CUSTOM_RANGE_START = SAI_API_CUSTOM_RANGE_BASE, + + SAI_API_ONE = SAI_API_CUSTOM_RANGE_START, + + /* Add new custom APIs above this line */ + + SAI_API_CUSTOM_RANGE_END + +} sai_api_custom_t; + +#endif /* __SAICUSTOM_H_ */ diff --git a/doc/custom-headers/saicustomone.h b/doc/custom-headers/saicustomone.h new file mode 100644 index 000000000..49dbf3405 --- /dev/null +++ b/doc/custom-headers/saicustomone.h @@ -0,0 +1,136 @@ +/** + * Copyright (c) 2014 Microsoft Open Technologies, 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 + * + * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT + * LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS + * FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT. + * + * See the Apache Version 2.0 License for specific language governing + * permissions and limitations under the License. + * + * Microsoft would like to thank the following companies for their review and + * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, + * Dell Products, L.P., Facebook, Inc., Marvell International Ltd. + * + * @file saicustomone.h + * + * @brief This module defines SAI custom for ONE + * + * @warning This module is a SAI custom module + */ + +#if !defined (__SAICUSTOMONE_H_) +#define __SAICUSTOMONE_H_ + +#include + +/** + * @defgroup SAICUSTOMONE SAI - Custom ONE specific API definitions + * + * @{ + */ + +/** + * @brief Attribute ID for ONE + */ +typedef enum _sai_one_attr_t +{ + /** + * @brief Start of attributes + */ + SAI_ONE_ATTR_START, + + /** + * @brief First parameter + * + * @type sai_uint32_t + * @flags CREATE_AND_SET + * @default 0 + */ + SAI_ONE_ATTR_FIRST = SAI_ONE_ATTR_START, + + /** + * @brief End of attributes + */ + SAI_ONE_ATTR_END, + + /* ironic */ + + /** Custom range base value */ + SAI_ONE_ATTR_CUSTOM_RANGE_START = 0x10000000, + + /** End of custom range base */ + SAI_ONE_ATTR_CUSTOM_RANGE_END, + +} sai_one_attr_t; + +/** + * @brief Create ONE + * + * @param[out] one_id Entry id + * @param[in] switch_id Switch id + * @param[in] attr_count Number of attributes + * @param[in] attr_list Array of attributes + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ +typedef sai_status_t (*sai_create_one_fn)( + _Out_ sai_object_id_t *one_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + +/** + * @brief Remove ONE + * + * @param[in] one_id Entry id + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ +typedef sai_status_t (*sai_remove_one_fn)( + _In_ sai_object_id_t one_id); + +/** + * @brief Set attribute for ONE + * + * @param[in] one_id Entry id + * @param[in] attr Attribute + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ +typedef sai_status_t (*sai_set_one_attribute_fn)( + _In_ sai_object_id_t one_id, + _In_ const sai_attribute_t *attr); + +/** + * @brief Get attribute for ONE + * + * @param[in] one_id Entry id + * @param[in] attr_count Number of attributes + * @param[inout] attr_list Array of attributes + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ +typedef sai_status_t (*sai_get_one_attribute_fn)( + _In_ sai_object_id_t one_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); + +typedef struct _sai_one_api_t +{ + sai_create_one_fn create_one; + sai_remove_one_fn remove_one; + sai_set_one_attribute_fn set_one_attribute; + sai_get_one_attribute_fn get_one_attribute; + +} sai_one_api_t; + +/** + * @} + */ +#endif /** __CUSTOMONE_H_ */ diff --git a/doc/custom-headers/saiportcustom.h b/doc/custom-headers/saiportcustom.h new file mode 100644 index 000000000..7f681713c --- /dev/null +++ b/doc/custom-headers/saiportcustom.h @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2018 Microsoft Open Technologies, 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 + * + * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT + * LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS + * FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT. + * + * See the Apache Version 2.0 License for specific language governing + * permissions and limitations under the License. + * + * Microsoft would like to thank the following companies for their review and + * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, + * Dell Products, L.P., Facebook, Inc., Marvell International Ltd. + * + * @file saiportcustom.h + * + * @brief This module defines port custom of the Switch Abstraction Interface (SAI) + */ + +#ifndef __SAIPORTCUSTOM_H_ +#define __SAIPORTCUSTOM_H_ + +#include +#include + +/** + * @brief SAI port attribute custom. + * + * @flags free + */ +typedef enum _sai_port_attr_custom_t +{ + /** + * @brief Custom 1 + * + * @type sai_uint32_t + * @flags READ_ONLY + */ + SAI_PORT_ATTR_CUSTOM1 = SAI_PORT_ATTR_CUSTOM_RANGE_START, + + /* Add new csutom port attributes above this line */ + +} sai_port_attr_custom_t; + +/** + * @brief SAI port stat custom. + * + * @flags free + */ +typedef enum _sai_port_stat_custom_t +{ + SAI_PORT_STAT_CUSTOM_RANGE_START = SAI_PORT_STAT_CUSTOM_RANGE_BASE, + + SAI_PORT_STAT_CUSTOM1 = SAI_PORT_STAT_CUSTOM_RANGE_START, + + SAI_PORT_STAT_CUSTOM2, + + SAI_PORT_STAT_CUSTOM_RANGE_END + +} sai_port_stat_custom_t; + +#endif /* __SAIPORTCUSTOM_H_ */ diff --git a/doc/custom-headers/saiswitchcustom.h b/doc/custom-headers/saiswitchcustom.h new file mode 100644 index 000000000..74f0e0d8a --- /dev/null +++ b/doc/custom-headers/saiswitchcustom.h @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2018 Microsoft Open Technologies, 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 + * + * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT + * LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS + * FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT. + * + * See the Apache Version 2.0 License for specific language governing + * permissions and limitations under the License. + * + * Microsoft would like to thank the following companies for their review and + * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, + * Dell Products, L.P., Facebook, Inc., Marvell International Ltd. + * + * @file saiswitchcustom.h + * + * @brief This module defines switch custom of the Switch Abstraction Interface (SAI) + */ + +#ifndef __SAISWITCHCUSTOM_H_ +#define __SAISWITCHCUSTOM_H_ + +#include +#include + +/** + * @brief SAI switch attribute custom, + * + * @flags free + */ +typedef enum _sai_switch_attr_custom_t +{ + /** + * @brief Custom 1 + * + * @type sai_uint32_t + * @flags READ_ONLY + */ + SAI_SWITCH_ATTR_CUSTOM1 = SAI_SWITCH_ATTR_CUSTOM_RANGE_START, + + /** + * @brief Custom 2 + * + * @type sai_uint32_t + * @flags CREATE_AND_SET + * @default 0 + */ + SAI_SWITCH_ATTR_CUSTOM2, + +} sai_switch_attr_custom_t; + +#endif /* __SAISWITCHCUSTOM_H_ */ diff --git a/doc/custom-headers/saitypescustom.h b/doc/custom-headers/saitypescustom.h new file mode 100644 index 000000000..ce172fc03 --- /dev/null +++ b/doc/custom-headers/saitypescustom.h @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2018 Microsoft Open Technologies, 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 + * + * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT + * LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS + * FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT. + * + * See the Apache Version 2.0 License for specific language governing + * permissions and limitations under the License. + * + * Microsoft would like to thank the following companies for their review and + * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, + * Dell Products, L.P., Facebook, Inc., Marvell International Ltd. + * + * @file saitypescustom.h + * + * @brief This module defines type custom of the Switch Abstraction Interface (SAI) + */ + +#ifndef __SAITYPESCUSTOM_H_ +#define __SAITYPESCUSTOM_H_ + +#include + +/** + * @brief SAI object type custom + * + * @flags free + */ +typedef enum _sai_object_type_custom_t +{ + SAI_OBJECT_TYPE_CUSTOM_RANGE_START = SAI_OBJECT_TYPE_CUSTOM_RANGE_BASE, + + SAI_OBJECT_TYPE_ONE = SAI_OBJECT_TYPE_CUSTOM_RANGE_START, + + /* Add new custom object types above this line */ + + SAI_OBJECT_TYPE_CUSTOM_RANGE_END + +} sai_object_type_custom_t; + +typedef enum _sai_some_new_type_t +{ + SAI_SOME_NEW_TYPE_A, + + SAI_SOME_NEW_TYPE_B, + +} sai_some_new_type_t; + +#endif /* __SAITYPESCUSTOM_H_ */ + diff --git a/inc/saipoe.h b/inc/saipoe.h old mode 100755 new mode 100644 diff --git a/inc/saiport.h b/inc/saiport.h index 235a799d7..1241d528e 100644 --- a/inc/saiport.h +++ b/inc/saiport.h @@ -3439,6 +3439,8 @@ typedef enum _sai_port_stat_t /** Port stat range end */ SAI_PORT_STAT_END, + SAI_PORT_STAT_CUSTOM_RANGE_BASE = 0x10000000, + /** Extensions range base */ SAI_PORT_STAT_EXTENSIONS_RANGE_BASE = 0x20000000 diff --git a/meta/Doxyfile b/meta/Doxyfile index c0b994189..eff927a5e 100644 --- a/meta/Doxyfile +++ b/meta/Doxyfile @@ -753,6 +753,7 @@ WARN_LOGFILE = INPUT = ../inc/ INPUT += ../experimental/ +INPUT += ../custom/ INPUT += saimetadatatypes.h INPUT += saimetadatautils.h INPUT += saimetadatalogger.h diff --git a/meta/Doxyfile.compat b/meta/Doxyfile.compat index 1048df6c2..c7fe0c7a7 100644 --- a/meta/Doxyfile.compat +++ b/meta/Doxyfile.compat @@ -753,6 +753,7 @@ WARN_LOGFILE = INPUT = ../inc/ INPUT += ../experimental/ +INPUT += ../custom/ INPUT += saimetadatatypes.h INPUT += saimetadatautils.h INPUT += saimetadatalogger.h diff --git a/meta/Makefile b/meta/Makefile index 91014dfcf..8174a9663 100644 --- a/meta/Makefile +++ b/meta/Makefile @@ -34,7 +34,6 @@ WARNINGS = \ -Wdisabled-optimization \ -Werror \ -Wextra \ - -Wextra \ -Wfloat-equal \ -Wformat=2 \ -Wformat-nonliteral \ @@ -69,13 +68,13 @@ BINS = doxygen perl dot $(foreach bin,$(BINS),$(if $(shell which $(bin)),,$(error "Missing $(bin) in PATH"))) -CFLAGS += -I../inc -I../experimental -fPIC $(WARNINGS) +CFLAGS += -I../inc -I../experimental -I../custom -fPIC $(WARNINGS) CC = $(CROSS_COMPILE)gcc CXX = $(CROSS_COMPILE)g++ LD = $(CROSS_COMPILE)ld -DEPS = $(wildcard ../inc/*.h) $(wildcard ../experimental/*.h) +DEPS = $(wildcard ../inc/*.h) $(wildcard ../experimental/*.h) $(wildcard ../custom/*.h) XMLDEPS = $(wildcard xml/*.xml) OBJ = saimetadata.o saimetadatautils.o saiserialize.o diff --git a/meta/attrversion.sh b/meta/attrversion.sh index 5cc72361c..33f6296c6 100755 --- a/meta/attrversion.sh +++ b/meta/attrversion.sh @@ -42,7 +42,7 @@ set -e TAGS=$(git tag --sort=v:refname | grep -P "^v\d+\.\d+.\d+$" | sed -n -e '/'$BASE'/,$p'; echo HEAD) -(for tag in $TAGS; do git grep -P "^\s+SAI_\w+_ATTR_" $tag ../inc ../experimental | cat; done; - grep -P "^\s+SAI_\w+_ATTR_" ../inc/sai*h ../experimental/sai*h | perl -npe '$_.="HEAD:"' ) | \ +(for tag in $TAGS; do git grep -P "^\s+SAI_\w+_ATTR_" $tag ../inc ../experimental ../custom | cat; done; + grep -sP "^\s+SAI_\w+_ATTR_" ../inc/sai*h ../experimental/sai*h ../custom/sai*h | perl -npe '$_.="HEAD:"' ) | \ perl -ne '/^(\S+):..\/(\S+)\/\S+.h:\s+(SAI_\w+_ATTR_\w+)/; print "#define SAI_METADATA_ATTR_VERSION_$3 \"$1\" /* $2 */\n" if not defined $h{$3};$h{$3}=1' > $OUTPUT diff --git a/meta/checkheaders.pl b/meta/checkheaders.pl index 7795f0fd9..037e11818 100755 --- a/meta/checkheaders.pl +++ b/meta/checkheaders.pl @@ -149,7 +149,7 @@ sub GetValues my ($fhb, $bin) = tempfile( SUFFIX => '.bin', UNLINK => 1 ); - system("gcc $src -I. -I '$dir'/../experimental -I '$dir' -o $bin") == 0 or die "gcc failed! $!"; + system("gcc $src -I. -I '$dir'/../experimental -I '$dir/../custom/' -I '$dir' -o $bin") == 0 or die "gcc failed! $!"; close $fhs; close $fhb; diff --git a/meta/parse.pl b/meta/parse.pl index 4b6c6ac9c..fbf7e23e0 100755 --- a/meta/parse.pl +++ b/meta/parse.pl @@ -43,6 +43,7 @@ our $XMLDIR = "xml"; our $INCLUDE_DIR = "../inc/"; our $EXPERIMENTAL_DIR = "../experimental/"; +our $CUSTOM_DIR = "../custom/"; our $MAX_CONDITIONS_LEN = 1; @@ -61,6 +62,9 @@ our %EXTENSIONS_ENUMS = (); our %EXTENSIONS_ATTRS = (); our %EXPERIMENTAL_OBJECTS = (); +our %CUSTOM_ENUMS = (); +our %CUSTOM_ATTRS = (); +our %CUSTOM_OBJECTS = (); our %OBJECT_TYPE_TO_STATS_MAP = (); our %ATTR_TO_CALLBACK = (); our %PRIMITIVE_TYPES = (); @@ -135,7 +139,7 @@ sub ProcessTagType return $val if $val =~ /^(bool|char)$/; - return $val if $val =~ /^sai_\w+_t$/ and not $val =~ /_attr_(extensions_)?t/; + return $val if $val =~ /^sai_\w+_t$/ and not $val =~ /_attr_(extensions_|custom_)?t/; return $val if $val =~ /^sai_pointer_t sai_\w+_notification_fn$/; @@ -573,6 +577,16 @@ sub ProcessEnumSection $EXTENSIONS_ENUMS{$enumtypename} = "${enumprefix}_t"; } + if ($enumtypename =~ /_custom_t$/) + { + LogDebug "removing custom prefix from $enumtypename"; + + # remove custom suffix on all custom since they will be merged together + $enumprefix =~ s/CUSTOM_$//; + + $CUSTOM_ENUMS{$enumtypename} = "${enumprefix}_t"; + } + if (defined $SAI_ENUMS{$enumtypename}) { LogError "duplicated enum $enumtypename"; @@ -670,7 +684,7 @@ sub ProcessEnumSection my $valuescount = @values; # allow empty enum on extensions - if ($valuescount == 0 and not $enumtypename =~ /_extensions_t$/) + if ($valuescount == 0 and not $enumtypename =~ /_(extensions|custom)_t$/) { LogError "enum $enumtypename is empty, after removing suffixed entries _START/_END/_RANGE_BASE"; LogError " those suffixes are reserved for range markers and are removed by metadata parser, don't use them"; @@ -696,7 +710,7 @@ sub ProcessEnumSection $SAI_ENUMS{$enumtypename}{values} = \@values; - if (not $enumtypename =~ /^(sai_(\w+)_attr_(extensions_)?)t$/) + if (not $enumtypename =~ /^(sai_(\w+)_attr_(extensions_|custom_)?)t$/) { for my $ev (@{ $memberdef->{enumvalue} }) { @@ -885,7 +899,7 @@ sub ProcessTypedefSection next; } - next if not $typedefname =~ /^sai_(\w+)_attr_(extensions_)?t$/; + next if not $typedefname =~ /^sai_(\w+)_attr_(extensions_|custom_)?t$/; # this enum is attribute definition for object @@ -1172,6 +1186,7 @@ sub ProcessSingleEnum my ($key, $typedef, $prefix) = @_; $prefix =~ s/EXTENSIONS_$// if ($typedef =~ /_extensions_t$/); + $prefix =~ s/CUSTOM_$// if ($typedef =~ /_custom_t$/); my $enum = $SAI_ENUMS{$key}; @@ -2524,6 +2539,15 @@ sub ProcessAttrVersion WriteHeader "#define SAI_METADATA_HAVE_ATTR_VERSION ($count)"; } +sub ProcessCustomObjectCount +{ + WriteSectionComment "Custom object count"; + + my $count = scalar(keys%CUSTOM_OBJECTS); + + WriteHeader "#define SAI_METADATA_CUSTOM_OBJECT_COUNT ($count)"; +} + sub ProcessSaiStatus { my $filename = "../inc/saistatus.h"; @@ -2647,7 +2671,7 @@ sub CreateEnumHelperMethods for my $key (sort keys %SAI_ENUMS) { - next if $key =~ /_attr_(extensions_)?t$/; + next if $key =~ /_attr_(extensions_|custom_)?t$/; CreateEnumHelperMethod($key); } @@ -3955,6 +3979,15 @@ sub ProcessIsExperimental return "false"; } +sub ProcessIsCustom +{ + my $ot = shift; + + return "true" if defined $CUSTOM_OBJECTS{$ot}; + + return "false"; +} + sub ProcessStatEnum { my $shortot = shift; @@ -4014,6 +4047,7 @@ sub CreateObjectInfo my $revgraphcount = ProcessRevGraphCount($ot); my $isexperimental = ProcessIsExperimental($ot); my $statenum = ProcessStatEnum($shortot); + my $iscustom = ProcessIsCustom($ot); my $attrmetalength = @{ $SAI_ENUMS{$type}{values} }; my $create = ProcessCreate($struct, $ot); @@ -4051,6 +4085,7 @@ sub CreateObjectInfo WriteSource ".clearstats = $clearstats,"; WriteSource ".isexperimental = $isexperimental,"; WriteSource ".statenum = $statenum,"; + WriteSource ".iscustom = $iscustom,"; WriteSource "};"; } @@ -4327,8 +4362,9 @@ sub ExtractStatsFunctionMap my @headers = GetHeaderFiles(); my @exheaders = GetExperimentalHeaderFiles(); + my @cuheaders = GetCustomHeaderFiles(); - my @merged = (@headers, @exheaders); + my @merged = (@headers, @exheaders, @cuheaders); my %otmap = (); @@ -4377,8 +4413,9 @@ sub ExtractObjectTypeBulkMap my @headers = GetHeaderFiles(); my @exheaders = GetExperimentalHeaderFiles(); + my @cuheaders = GetCustomHeaderFiles(); - my @merged = (@headers, @exheaders); + my @merged = (@headers, @exheaders, @cuheaders); my %otmap = (); @@ -4544,10 +4581,12 @@ sub ExtractApiToObjectMap my @headers = GetHeaderFiles(); my @exheaders = GetExperimentalHeaderFiles(); + my @cuheaders = GetCustomHeaderFiles(); my %exh = map { $_ => 1 } @exheaders; + my %cuh = map { $_ => 1 } @cuheaders; - my @merged = (@headers, @exheaders); + my @merged = (@headers, @exheaders, @cuheaders); for my $header (@merged) { @@ -4592,20 +4631,23 @@ sub ExtractApiToObjectMap $shortapi =~ s/_//g; - my $correct = (defined $exh{$header}) ? "saiexperimental$shortapi.h" : "sai$shortapi.h"; + my $correct = (defined $exh{$header}) + ? "saiexperimental$shortapi.h" + : ((defined $cuh{$header}) ? "saicustom$shortapi.h" : "sai$shortapi.h"); if ($header ne $correct) { LogWarning "File $header should be named '$correct'"; } - # NOTE: those maps will include experimental extensions + # NOTE: those maps will include experimental extensions and custom attributes for my $obj(@objects) { $OBJTOAPIMAP{$obj} = $api; $EXPERIMENTAL_OBJECTS{uc($obj)} = 1 if $correct =~ /^saiexperimental/; + $CUSTOM_OBJECTS{uc($obj)} = 1 if $correct =~ /^saicustom/; } $APITOOBJMAP{$api} = \@objects; @@ -5226,12 +5268,14 @@ sub WriteHeaderHeader { WriteSectionComment "AUTOGENERATED FILE! DO NOT EDIT"; + my @ch = GetCustomHeaderFiles(); + WriteHeader "#ifndef __SAI_METADATA_H__"; WriteHeader "#define __SAI_METADATA_H__"; WriteHeader "#include "; WriteHeader "#include "; - + WriteHeader "#include " if scalar@ch; # only if exists WriteHeader "#include \"saimetadatatypes.h\""; WriteHeader "#include \"saimetadatautils.h\""; WriteHeader "#include \"saimetadatalogger.h\""; @@ -5352,6 +5396,43 @@ sub LoadCapabilities %CAPABILITIES = %{ GetCapabilities() }; } +sub MergeCustomEnums +{ + for my $exenum (sort keys%CUSTOM_ENUMS) + { + if (not $exenum =~ /^(sai_\w+)_custom_t$/) + { + LogError "Enum $exenum is not custom enum"; + next; + } + + my $enum = "$1_t"; + + if (not defined $SAI_ENUMS{$enum}) + { + LogError "Enum $exenum is extending not existing enum $enum"; + next; + } + + my @exvalues = @{ $SAI_ENUMS{$exenum}{values} }; + + my @values = @{ $SAI_ENUMS{$enum}{values} }; + + push@values,@exvalues; + + $SAI_ENUMS{$enum}{values} = \@values; + + next if not $exenum =~ /_attr_custom_t/; + + for my $exvalue (@exvalues) + { + $CUSTOM_ATTRS{$exvalue} = 1; + + $METADATA{$enum}{$exvalue} = $METADATA{$exenum}{$exvalue}; + } + } +} + sub MergeExtensionsEnums { for my $exenum (sort keys%EXTENSIONS_ENUMS) @@ -5575,10 +5656,11 @@ sub CreateSaiSwigApiStructs my @headers = GetHeaderFiles(); my @metaheaders = GetMetaHeaderFiles(); my @exheaders = GetExperimentalHeaderFiles(); + my @cuheaders = GetCustomHeaderFiles(); push(@metaheaders, "saimetadata.h"); - my @merged = (@headers, @metaheaders, @exheaders); + my @merged = (@headers, @metaheaders, @exheaders, @cuheaders); WriteSwig "%ignore sai_metadata_log;"; WriteSwig "%ignore sai_metadata_log_level;"; @@ -5621,6 +5703,8 @@ sub CreateDefineMaxConditionsLen ProcessXmlFiles(); +MergeCustomEnums(); + MergeExtensionsEnums(); CreateObjectTypeMap(); @@ -5631,6 +5715,8 @@ sub CreateDefineMaxConditionsLen ProcessAttrVersion(); +ProcessCustomObjectCount(); + ProcessSaiStatus(); ProcessExtraRangeDefines(); diff --git a/meta/saimetadatatypes.h b/meta/saimetadatatypes.h index e8ae8284c..f67ee17bb 100644 --- a/meta/saimetadatatypes.h +++ b/meta/saimetadatatypes.h @@ -1648,6 +1648,11 @@ typedef struct _sai_object_type_info_t */ const sai_enum_metadata_t* const statenum; + /** + * @brief Indicates whether object type is custom. + */ + bool iscustom; + } sai_object_type_info_t; /** diff --git a/meta/saisanitycheck.c b/meta/saisanitycheck.c index 9d4244a3b..f00f03d15 100644 --- a/meta/saisanitycheck.c +++ b/meta/saisanitycheck.c @@ -93,9 +93,20 @@ defined_attr_t* defined_attributes = NULL; /* custom ranges start are the same for all objects */ #define CUSTOM_ATTR_RANGE_START SAI_PORT_ATTR_CUSTOM_RANGE_START +#define CUSTOM_RANGE_START (0x10000000) #define EXTENSION_RANGE_START (0x20000000) #define EXTENSION_OBJECT_TYPE_COUNT (SAI_OBJECT_TYPE_EXTENSIONS_RANGE_END - SAI_OBJECT_TYPE_EXTENSIONS_RANGE_START) -#define TOTAL_OBJECT_TYPE_COUNT (EXTENSION_OBJECT_TYPE_COUNT + SAI_OBJECT_TYPE_MAX) +/* #define CUSTOM_OBJECT_TYPE_COUNT (SAI_OBJECT_TYPE_CUSTOM_RANGE_END - SAI_OBJECT_TYPE_CUSTOM_RANGE_START) */ +#define CUSTOM_OBJECT_TYPE_COUNT (SAI_METADATA_CUSTOM_OBJECT_COUNT) +#define TOTAL_OBJECT_TYPE_COUNT (EXTENSION_OBJECT_TYPE_COUNT + CUSTOM_OBJECT_TYPE_COUNT + SAI_OBJECT_TYPE_MAX) + +#ifndef SAI_OBJECT_TYPE_CUSTOM_RANGE_START +#define SAI_OBJECT_TYPE_CUSTOM_RANGE_START (CUSTOM_RANGE_START) +#endif + +#ifndef SAI_OBJECT_TYPE_CUSTOM_RANGE_END +#define SAI_OBJECT_TYPE_CUSTOM_RANGE_END (CUSTOM_RANGE_START + SAI_METADATA_CUSTOM_OBJECT_COUNT) +#endif bool is_extensions_enum( _In_ const sai_enum_metadata_t* emd) @@ -105,6 +116,14 @@ bool is_extensions_enum( return strstr(emd->name, "_extensions_t") != NULL; } +bool is_custom_enum( + _In_ const sai_enum_metadata_t* emd) +{ + META_LOG_ENTER(); + + return strstr(emd->name, "_custom_t") != NULL; +} + void check_all_enums_name_pointers() { META_LOG_ENTER(); @@ -133,9 +152,16 @@ void check_all_enums_name_pointers() if (emd->valuescount == 0) META_LOG_WARN("enum %s has no values", emd->name); } + else if (is_custom_enum(emd)) + { + /* allow empty custom enums */ + + if (emd->valuescount == 0) + META_LOG_WARN("enum %s has no values", emd->name); + } else { - META_ASSERT_TRUE(emd->valuescount > 0, "enum must have some values"); + META_ASSERT_TRUE(emd->valuescount > 0, "enum must have some values: %s", emd->name); } size_t j = 0; @@ -374,7 +400,11 @@ void check_object_type() int value = sai_metadata_enum_sai_object_type_t.values[i]; - if (last < value && value == EXTENSION_RANGE_START) + if (last < value && value == CUSTOM_RANGE_START) + { + /* ok, but object type can't be used as array index any more */ + } + else if (last < value && value == EXTENSION_RANGE_START) { /* ok, but object type can't be used as array index any more */ } @@ -417,7 +447,7 @@ void check_attr_by_object_type() */ META_ASSERT_TRUE(EXTENSION_OBJECT_TYPE_COUNT < 64, "too many experimental object types"); - META_ASSERT_TRUE(sai_metadata_attr_by_object_type_count == (EXTENSION_OBJECT_TYPE_COUNT + SAI_OBJECT_TYPE_MAX), "invalid object type count in metadata"); + META_ASSERT_TRUE(sai_metadata_attr_by_object_type_count == (EXTENSION_OBJECT_TYPE_COUNT + CUSTOM_OBJECT_TYPE_COUNT + SAI_OBJECT_TYPE_MAX), "invalid object type count in metadata"); size_t idx = 1; @@ -447,6 +477,10 @@ void check_attr_by_object_type() { /* ok */ } + else if (current >= (int)SAI_OBJECT_TYPE_CUSTOM_RANGE_START && current < (int)SAI_OBJECT_TYPE_CUSTOM_RANGE_END) + { + /* ok */ + } else if (current >= (int)SAI_OBJECT_TYPE_EXTENSIONS_RANGE_START && current < (int)SAI_OBJECT_TYPE_EXTENSIONS_RANGE_END) { /* ok */ @@ -480,6 +514,9 @@ bool is_valid_object_type( if (ot >= (int)SAI_OBJECT_TYPE_EXTENSIONS_RANGE_START && ot < (int)SAI_OBJECT_TYPE_EXTENSIONS_RANGE_END) return true; + if (ot >= (int)SAI_OBJECT_TYPE_CUSTOM_RANGE_START && ot < (int)SAI_OBJECT_TYPE_CUSTOM_RANGE_END) + return true; + return false; } @@ -744,6 +781,7 @@ void check_attr_object_type_provided( case SAI_ATTR_VALUE_TYPE_VLAN_LIST: case SAI_ATTR_VALUE_TYPE_UINT32: case SAI_ATTR_VALUE_TYPE_UINT64: + case SAI_ATTR_VALUE_TYPE_INT64: case SAI_ATTR_VALUE_TYPE_MAC: case SAI_ATTR_VALUE_TYPE_POINTER: case SAI_ATTR_VALUE_TYPE_IP_ADDRESS: @@ -2844,6 +2882,7 @@ void check_attr_is_primitive( case SAI_ATTR_VALUE_TYPE_UINT32: case SAI_ATTR_VALUE_TYPE_UINT32_RANGE: case SAI_ATTR_VALUE_TYPE_UINT64: + case SAI_ATTR_VALUE_TYPE_INT64: case SAI_ATTR_VALUE_TYPE_UINT8: case SAI_ATTR_VALUE_TYPE_TIMESPEC: case SAI_ATTR_VALUE_TYPE_IPV4: @@ -4002,11 +4041,18 @@ uint32_t ot2idx( * index in array */ + uint32_t i = 1; + if (ot >= SAI_OBJECT_TYPE_NULL && ot < SAI_OBJECT_TYPE_MAX) return ot; - if (ot >= (int)SAI_OBJECT_TYPE_EXTENSIONS_RANGE_START && ot < (int)SAI_OBJECT_TYPE_EXTENSIONS_RANGE_END) - return SAI_OBJECT_TYPE_MAX + (ot - SAI_OBJECT_TYPE_EXTENSIONS_RANGE_START); + for (; sai_metadata_all_object_type_infos[i]; i++) + { + if (sai_metadata_all_object_type_infos[i]->objecttype == ot) + { + return i; + } + } META_ASSERT_FAIL("invalid object type specified %d", ot); } @@ -5037,6 +5083,12 @@ void check_object_ro_list( return; } + if (oi->iscustom) + { + META_LOG_DEBUG("custom object %s not present on any object list (eg. VLAN_MEMBER is present on SAI_VLAN_ATTR_MEMBER_LIST)", oi->objecttypename); + return; + } + if (SAI_OBJECT_TYPE_DEBUG_COUNTER == oi->objecttype) { META_LOG_WARN("debug counter object %s not present on any object list (eg. VLAN_MEMBER is present on SAI_VLAN_ATTR_MEMBER_LIST)", oi->objecttypename); @@ -5077,11 +5129,19 @@ void check_experimental_flag( if (oi->objecttype >= SAI_OBJECT_TYPE_MAX) { - META_ASSERT_TRUE(oi->isexperimental, "object %s is expected to be marked as experimental", oi->objecttypename); + if (oi->objecttype >= (int)SAI_OBJECT_TYPE_EXTENSIONS_RANGE_START) + { + META_ASSERT_TRUE(oi->isexperimental, "object %s is expected to be marked as experimental", oi->objecttypename); + } + else if (oi->objecttype >= (int)SAI_OBJECT_TYPE_CUSTOM_RANGE_START) + { + META_ASSERT_TRUE(oi->iscustom, "object %s is expected to be marked as custom", oi->objecttypename); + } } else { META_ASSERT_FALSE(oi->isexperimental, "object %s is expected to not be marked as experimental", oi->objecttypename); + META_ASSERT_FALSE(oi->iscustom, "object %s is expected to not be marked as custom", oi->objecttypename); } } @@ -5108,6 +5168,9 @@ void check_attr_end( if (meta[index]->attrid < oi->attridend) continue; + if (meta[index]->iscustom) + continue; + if (meta[index]->isextensionattr) continue; @@ -5239,6 +5302,16 @@ void check_graph_connected() continue; } + if (sai_metadata_all_object_type_infos[i]->iscustom) + { + /* allow custom object types to be disconnected from main graph */ + + META_LOG_WARN("custom object %s is disconnected from graph", + sai_metadata_all_object_type_infos[i]->objecttypename); + + continue; + } + if (SAI_OBJECT_TYPE_DEBUG_COUNTER == idx2ot(i)) { /* @@ -5650,10 +5723,14 @@ void check_enum_flags_type_ranges( /* this check can be relaxed, we allow now 16 types of ranges */ - if (val < EXTENSION_RANGE_START) + if (val < CUSTOM_RANGE_START) { META_ASSERT_TRUE((val < (16*RANGE_BASE)), "range value 0x%x is too high on %s", val, name); } + else if (val < EXTENSION_RANGE_START) + { + META_ASSERT_TRUE((val < (16*RANGE_BASE + CUSTOM_RANGE_START)), "range value 0x%x is too high on %s", val, name); + } else { META_ASSERT_TRUE((val < (16*RANGE_BASE + EXTENSION_RANGE_START)), "range value 0x%x is too high on %s", val, name); @@ -5884,7 +5961,10 @@ void check_object_type_extension_max_value() * */ - META_LOG_INFO("SAI_OBJECT_TYPE_MAX = %d, EXTENSION_OBJECT_TYPE_COUNT = %d", SAI_OBJECT_TYPE_MAX, EXTENSION_OBJECT_TYPE_COUNT); + META_LOG_INFO("SAI_OBJECT_TYPE_MAX = %d, EXTENSION_OBJECT_TYPE_COUNT = %d, CUSTOM_OBJECT_TYPE_COUNT = %d", + SAI_OBJECT_TYPE_MAX, + EXTENSION_OBJECT_TYPE_COUNT, + CUSTOM_OBJECT_TYPE_COUNT); /* * This check may be removed, but it will need to be brought into attention on SAI meeting. diff --git a/meta/test.pm b/meta/test.pm index 9872b34c5..8d0937c0f 100644 --- a/meta/test.pm +++ b/meta/test.pm @@ -395,7 +395,13 @@ sub CreateApiNameTest WriteTest " }"; } - WriteTest " int sum = SAI_OBJECT_TYPE_MAX + (SAI_OBJECT_TYPE_EXTENSIONS_RANGE_END - SAI_OBJECT_TYPE_EXTENSIONS_RANGE_START);"; + WriteTest " int sum = SAI_OBJECT_TYPE_MAX +"; + WriteTest " (SAI_OBJECT_TYPE_EXTENSIONS_RANGE_END - SAI_OBJECT_TYPE_EXTENSIONS_RANGE_START) +"; + + (scalar(%main::CUSTOM_OBJECTS) == 0) + ? WriteTest " 0;" + : WriteTest " (SAI_OBJECT_TYPE_CUSTOM_RANGE_END - SAI_OBJECT_TYPE_CUSTOM_RANGE_START);"; + WriteTest " TEST_ASSERT_TRUE_EXT(sum == visited, \"not all objects were processed, expexted: %d, but got: %d\", sum, visited);"; WriteTest " PP(dummy);"; diff --git a/meta/utils.pm b/meta/utils.pm index 93ab200ea..914854946 100644 --- a/meta/utils.pm +++ b/meta/utils.pm @@ -208,6 +208,11 @@ sub GetExperimentalHeaderFiles return GetHeaderFiles($main::EXPERIMENTAL_DIR); } +sub GetCustomHeaderFiles +{ + return GetHeaderFiles($main::CUSTOM_DIR); +} + sub GetFilesByRegex { my ($dir,$regex) = @_; @@ -247,6 +252,7 @@ sub ReadHeaderFile $filename = "$main::INCLUDE_DIR/$file" if not -e $filename; $filename = "$main::EXPERIMENTAL_DIR/$file" if not -e $filename; + $filename = "$main::CUSTOM_DIR/$file" if not -e $filename; open FILE, $filename or die "Couldn't open file $filename: $!"; @@ -263,7 +269,7 @@ sub GetNonObjectIdStructNames { my %structs; - my @headers = (GetHeaderFiles(), GetExperimentalHeaderFiles()); + my @headers = (GetHeaderFiles(), GetExperimentalHeaderFiles(), GetCustomHeaderFiles()); # TODO must support experimental extensions @@ -295,7 +301,7 @@ sub GetNonObjectIdStructNamesWithBulkApi { my %structs; - my @headers = (GetHeaderFiles(), GetExperimentalHeaderFiles()); + my @headers = (GetHeaderFiles(), GetExperimentalHeaderFiles(), GetCustomHeaderFiles()); for my $header (@headers) { @@ -441,6 +447,7 @@ sub ProcessEnumInitializers my ($arr_ref, $ini_ref, $enumTypeName, $SAI_DEFINES_REF) = @_; return if $enumTypeName =~ /_extensions_t$/; # ignore initializers on extensions + return if $enumTypeName =~ /_custom_t$/; # ignore initializers on custom attributes if (scalar(@$arr_ref) != scalar(@$ini_ref)) { @@ -613,7 +620,7 @@ BEGIN our @ISA = qw(Exporter); our @EXPORT = qw/ LogDebug LogInfo LogWarning LogError - WriteFile GetHeaderFiles GetMetaHeaderFiles GetExperimentalHeaderFiles GetMetadataSourceFiles ReadHeaderFile GetMetaSourceFiles + WriteFile GetHeaderFiles GetMetaHeaderFiles GetExperimentalHeaderFiles GetCustomHeaderFiles GetMetadataSourceFiles ReadHeaderFile GetMetaSourceFiles GetNonObjectIdStructNames GetNonObjectIdStructNamesWithBulkApi IsSpecialObject GetStructLists GetStructKeysInOrder Trim ExitOnErrors ExitOnErrorsOrWarnings ProcessEnumInitializers WriteHeader WriteSource WriteTest WriteSwig WriteMetaDataFiles WriteSectionComment WriteSourceSectionComment