fastnetmon-ng/src/ipfix_csv_processor.pl

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";