meta/cap.pm (179 lines of code) (raw):

#!/usr/bin/perl # # 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 cap.pm # # @brief This module defines SAI Metadata Capability Parser # package cap; use strict; use warnings; use diagnostics; use Term::ANSIColor; use Data::Dumper; use utils; require Exporter; sub GetCapabilityFiles { my $dir = shift; opendir(my $dh, $dir) or die "Can't opendir $dir: $!"; my @cap = grep { /^\w*\.cap$/ and -f "$dir/$_" } readdir($dh); closedir $dh; return sort @cap; } sub GetVendorCapabilityFiles { # should capability files be in metadata dir or i cap dir ? return GetCapabilityFiles("."); } sub ReadCapFile { my $filename = shift; local $/ = undef; open FILE, $filename or die "Couldn't open file $filename: $!"; binmode FILE; my $string = <FILE>; close FILE; return $string; } sub ProcessCapAttr { my $val = shift; return $val if $val =~ /^SAI_[0-9A-Z_]+_ATTR_[0-9A-Z_]+$/; LogError "wrong attr name: $val"; return undef; } sub ProcessCapVendorId { my $val = shift; # TODO numbers 0xA and 10 and 0xa should be considered the same vendor id return $val if $val =~ /^$NUMBER_REGEX$/; LogError "wrong vendor id $val"; return undef; } sub ProcessCapCapability { my $val = shift; $val =~ s/\s*//g; my @cap = split/[,]/,$val; for my $cap (@cap) { if (not $cap =~ /^(CREATE|GET|SET)$/) { LogError "invalid capability tag value '$val' ($cap)"; return undef; } } return \@cap; } sub ProcessCapEnumCapability { my $val = shift; $val =~ s/\s*//g; my @cap = split/[,]/,$val; for my $cap (@cap) { if (not $cap =~ /^SAI_[0-9A-Z_]+$/) { LogError "invalid enum capability tag value '$val' ($cap)"; return undef; } } return \@cap; } my %CAP_TAGS = ( "attr", \&ProcessCapAttr, "vendorid", \&ProcessCapVendorId, "capability", \&ProcessCapCapability, "enumcapability", \&ProcessCapEnumCapability, ); sub ShallowCopyAttrEnum { my $refHash = shift; my %hash = %{ $refHash }; my %attr = map { $_, $hash{$_} } keys %hash; return \%attr; } sub ProcessCapFile { my $file = shift; my $data = ReadCapFile($file); my %attr = (); my @lines = split/\n/,$data; my %capability = (); for my $line (@lines) { next if $line =~ /^$/; next if $line =~ /^\s*#/; if ($line =~ /\@skip/) { LogInfo "Skipping cap file $file"; return undef; } LogError "non ASCII char in $file: $line" if not $line =~ /^[\x20-\x7e]+$/; if (not $line =~ /^@(\w+)(.*)/) { LogError "unrecognized line $line"; next; } LogDebug "processing $line"; my $tag = $1; my $val = $2; $val =~ s/\s+/ /g; $val =~ s/^\s*//; $val =~ s/\s*$//; if (not defined $CAP_TAGS{$tag}) { LogError "unrecognized tag '$tag' on $line"; next; } $val = $CAP_TAGS{$tag}->($val); if ($tag eq "attr") { if (defined $attr{attr} and defined $attr{vendorid}) { LogDebug "Adding $attr{vendorid} -- $attr{attr}"; $capability{ $attr{attr} }{ $attr{vendorid} } = ShallowCopyAttrEnum(\%attr); } elsif (scalar(keys%attr) == 0) { # ok, first } else { LogError "previous attribute (before $line) does not define attr name or vendor id"; } %attr = (); } $attr{$tag} = $val; } if (defined $attr{attr} and defined $attr{vendorid}) { LogDebug "Adding $attr{vendorid} -- $attr{attr}"; $capability{ $attr{attr} }{ $attr{vendorid} } = ShallowCopyAttrEnum(\%attr); } elsif (scalar(keys%attr) == 0) { # ok, first } else { LogError "previous attribute does not define attr name or vendor id"; } return \%capability; } sub GetCapabilities { my %capabilities = (); my @files = GetVendorCapabilityFiles(); for my $cap (@files) { LogInfo "Processing capability file $cap"; my $caphash = ProcessCapFile($cap); for my $attr (keys %{$caphash}) { for my $vid (keys %{$caphash->{$attr}}) { $capabilities{$attr}{$vid} = $caphash->{$attr}{$vid}; } } } #print Dumper(%capabilities); return \%capabilities; } BEGIN { our @ISA = qw(Exporter); our @EXPORT = qw/ GetCapabilities /; } 1;