211 lines
5.3 KiB
Perl
Executable File
211 lines
5.3 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
# This script can convert data from http://www.iana.org/assignments/ipfix/ipfix.xhtml ipfix standard
|
|
# represented in CSV form into form suitable for us
|
|
# http://www.iana.org/assignments/ipfix/ipfix-information-elements.csv
|
|
# to our C/C++ frndly storage format
|
|
|
|
open my $fl, "<", "ipfix_fields.csv" or die "Can't open input file";
|
|
open my $target_h_file, ">", "ipfix_rfc.h" or die "Can't open file";
|
|
open my $target_cpp_file, ">", "ipfix_rfc.cpp" or die "Can't open file";
|
|
|
|
|
|
my $type_length_hash = {
|
|
unsigned8 => 1,
|
|
unsigned16 => 2,
|
|
unsigned32 => 4,
|
|
unsigned64 => 8,
|
|
|
|
ipv4Address => 4,
|
|
ipv6Address => 16,
|
|
|
|
# types with unknown or variable length
|
|
basicList => 0,
|
|
boolean => 0,
|
|
dateTimeMicroseconds => 0,
|
|
dateTimeMilliseconds => 0,
|
|
dateTimeNanoseconds => 0,
|
|
dateTimeSeconds => 0,
|
|
float64 => 0,
|
|
macAddress => 0,
|
|
octetArray => 0,
|
|
string => 0,
|
|
subTemplateList => 0,
|
|
subTemplateMultiList => 0,
|
|
};
|
|
|
|
my $field_id = 0;
|
|
my @intervals = ();
|
|
|
|
my $fields = {};
|
|
while (<$fl>) {
|
|
chomp;
|
|
|
|
if (/^(\d+\-\d+)/) {
|
|
push @intervals, $1;
|
|
}
|
|
|
|
my $we_will_process_this_line = /^(\d+),/;
|
|
|
|
# Skip descriptions and other crap
|
|
unless ($we_will_process_this_line) {
|
|
next;
|
|
}
|
|
|
|
# Numbers should growth monotonous
|
|
if ($1 < $field_id) {
|
|
next;
|
|
}
|
|
|
|
$field_id++;
|
|
|
|
my @keys = ("id", "name", "data_type", "data_type_semantics", "status", "description",
|
|
"units", "range", "reference", "requester", "revision", "date");
|
|
|
|
my %data = ();
|
|
@data{ @keys } = split /,/, $_;
|
|
|
|
#print "$data{id} $data{name} $data{data_type}\n";
|
|
$fields->{$data{"id"}} = \%data;
|
|
}
|
|
|
|
for my $interval (@intervals) {
|
|
my ($interval_start, $interval_end) = $interval =~ /^(\d+)\-(\d+)$/;
|
|
|
|
# Skip reserved interval up to 32767 because it's so long
|
|
next if $interval_start == 433;
|
|
|
|
for my $field_id ($interval_start .. $interval_end) {
|
|
$fields->{$field_id} = { id => $field_id, name => 'Reserved' };
|
|
}
|
|
|
|
# print "Interval start $interval_start end $interval_end\n";
|
|
}
|
|
|
|
for my $field_id (sort { $a <=> $b } keys %$fields) {
|
|
my $data = $fields->{$field_id};
|
|
|
|
if ($data->{name} eq 'Reserved') {
|
|
#print "$data->{id} $data->{name}\n";
|
|
} else {
|
|
#print "$data->{id} $data->{name} $data->{data_type}\n";
|
|
}
|
|
}
|
|
|
|
print {$target_h_file} <<DOC;
|
|
#ifndef IPFIX_RFC_H
|
|
#define IPFIX_RFC_H
|
|
|
|
/* This file is autogenerated with script ipfix_csv_processor.pl */
|
|
/* Please do not edit it directly */
|
|
|
|
#include <iostream>
|
|
#include <map>
|
|
|
|
class ipfix_information_element_t {
|
|
public:
|
|
ipfix_information_element_t(std::string name, unsigned int length);
|
|
ipfix_information_element_t();
|
|
std::string get_name();
|
|
unsigned int get_length();
|
|
std::string name;
|
|
unsigned int length;
|
|
};
|
|
|
|
typedef std::map<unsigned int, ipfix_information_element_t> ipfix_database_t;
|
|
class ipfix_information_database {
|
|
public:
|
|
ipfix_information_database();
|
|
bool add_element(unsigned int field_id, std::string name, unsigned int length);
|
|
std::string get_name_by_id(unsigned int field_id);
|
|
unsigned int get_length_by_id(unsigned int field_id);
|
|
private:
|
|
ipfix_database_t database;
|
|
};
|
|
|
|
#endif
|
|
DOC
|
|
|
|
print {$target_cpp_file} <<DOC;
|
|
#include <iostream>
|
|
#include <map>
|
|
#include "ipfix_rfc.h"
|
|
|
|
/* This file is autogenerated with script ipfix_csv_processor.pl */
|
|
/* Please do not edit it directly */
|
|
|
|
std::string ipfix_information_element_t::get_name() {
|
|
return this->name;
|
|
}
|
|
|
|
unsigned int ipfix_information_element_t::get_length() {
|
|
return this->length;
|
|
}
|
|
|
|
ipfix_information_element_t::ipfix_information_element_t(std::string name, unsigned int length) {
|
|
this->name = name;
|
|
this->length = length;
|
|
}
|
|
|
|
ipfix_information_element_t::ipfix_information_element_t() {
|
|
this->name = std::string("");
|
|
this->length = 0;
|
|
}
|
|
|
|
std::string ipfix_information_database::get_name_by_id(unsigned int field_id) {
|
|
ipfix_database_t::iterator itr = database.find(field_id);
|
|
|
|
if (itr == database.end()) {
|
|
return std::string("");
|
|
}
|
|
|
|
return itr->second.get_name();
|
|
}
|
|
|
|
unsigned int ipfix_information_database::get_length_by_id(unsigned int field_id) {
|
|
ipfix_database_t::iterator itr = database.find(field_id);
|
|
|
|
if (itr == database.end()) {
|
|
return 0;
|
|
}
|
|
|
|
return itr->second.get_length();
|
|
}
|
|
|
|
bool ipfix_information_database::add_element(unsigned int field_id, std::string name, unsigned int length) {
|
|
ipfix_database_t::iterator itr = database.find(field_id);
|
|
|
|
// Duplicate ID's strictly prohibited
|
|
if (itr != database.end()) {
|
|
return false;
|
|
}
|
|
|
|
database[field_id] = ipfix_information_element_t(name, length);
|
|
return true;
|
|
}
|
|
|
|
ipfix_information_database::ipfix_information_database() {
|
|
DOC
|
|
|
|
for my $field_id (sort { $a <=> $b } keys %$fields) {
|
|
my $data = $fields->{$field_id};
|
|
|
|
my $field_length = 0;
|
|
my $field_name = '"reserved"';
|
|
|
|
if ($data->{"data_type"}) {
|
|
$field_length = $type_length_hash->{ $data->{"data_type"} };
|
|
}
|
|
|
|
if (defined($data->{"name"}) && $data->{"name"}) {
|
|
$field_name = "\"$data->{'name'}\"";
|
|
}
|
|
|
|
print {$target_cpp_file} " this->add_element($field_id, $field_name, $field_length);\n";
|
|
}
|
|
|
|
print {$target_cpp_file} "}\n";
|