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;