Skip to content

Instantly share code, notes, and snippets.

@jplitza
Created March 1, 2014 14:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jplitza/9290756 to your computer and use it in GitHub Desktop.
Save jplitza/9290756 to your computer and use it in GitHub Desktop.
FFMap backend in NodeJS
#!/usr/bin/env nodejs
var fs = require('fs');
var _ = require('underscore');
var RRD = require('rrd').RRD;
var argv = require('optimist')
.usage('Usage: $0 -b <batvis file> -a <alias file> <destination dir>')
.options('b', {alias: 'batvis', describe: 'File containing output of batadv-vis -f jsondoc', demand: true, string: true})
.options('d', {alias: 'details', describe: 'File containing details sent by the nodes', demand: true, string: true})
.argv;
var batvis, details;
var inputs = 2;
var directory = argv._[0];
var macmap = {};
var nodes = [];
if(!directory) {
console.error("Missing target directory!");
process.exit(1);
}
function fuzz_mac_address(addr) {
var fuzzes = [
addr,
(parseInt(addr.substr(0,2), 16) ^ 2).toString(16) + addr.substr(2),
addr.substr(0, 9) + ((parseInt(addr.substr(9, 2), 16) + 1) % 0x100).toString(16) + addr.substr(11),
(parseInt(addr.substr(0,2), 16) ^ 2).toString(16) + addr.substr(2, 7) + ((parseInt(addr.substr(9, 2), 16) + 1) % 0x100).toString(16) + addr.substr(11),
addr.substr(0, 9) + ((parseInt(addr.substr(9, 2), 16) - 1) % 0x100).toString(16) + addr.substr(11),
(parseInt(addr.substr(0,2), 16) ^ 2).toString(16) + addr.substr(2, 7) + ((parseInt(addr.substr(9, 2), 16) - 1) % 0x100).toString(16) + addr.substr(11),
];
return fuzzes;
}
function vpn_neighbors(neighbors) {
var counter = 0;
for(var i = 0; i < neighbors.length; i++) {
if(details[macmap[neighbors[i].neighbor]].vpn)
counter++;
}
return counter;
}
function create_or_update_rrds(node) {
var nodedir = directory + "/" + node.macs[0];
fs.mkdir(nodedir, 0755, function() {
for(var rrd_name in rrds) {
create_or_update_rrd(rrd_name, node);
}
});
}
function create_or_update_rrd(rrd_name, node) {
// XXX: Sanitise filename!
var filename = directory + "/" + node.macs[0] + "/" + rrd_name + ".rrd";
var rrd = new RRD(filename);
var values = _.map(rrds[rrd_name], function(ds) {
try {
return eval(ds.attr);
} catch(e) {
return null;
}
});
rrd.update(new Date, values, function(err, out) {
if(out == null) {
console.log_bak = console.log;
console.log = function() {};
rrd.create(rras.concat(_.map(rrds[rrd_name], function(ds) { return ds.DS; })), {}, function(err, out) {
if(out == null) {
console.error("Error creating " + filename);
console.error(err)
return false;
}
rrd.update(new Date, values, function(err, out) {});
});
console.log = console.log_bak;
}
});
}
var rras = [
"RRA:AVERAGE:0.5:1:360", // 30 hours of 5 minute samples
"RRA:AVERAGE:0.5:12:192", // 8 days of 1 hour samples
"RRA:AVERAGE:0.5:36:224", // 4 weeks of 3 hour samples
"RRA:AVERAGE:0.5:144:365", // half a year of 12 hour samples
]
var rrds = {
"uptime": [{attr: "node.statistics.uptime", DS: "DS:uptime:GAUGE:600:0:U"}],
"loadavg": [{attr: "node.statistics.loadavg", DS: "DS:loadavg:GAUGE:600:0:U"}],
"traffic_bytes": [
{attr: "node.statistics.traffic.rx.bytes", DS: "DS:rx:DERIVE:600:0:U"},
{attr: "node.statistics.traffic.tx.bytes", DS: "DS:tx:DERIVE:600:0:U"},
{attr: "node.statistics.traffic.mgmt_rx.bytes", DS: "DS:mgmt_rx:DERIVE:600:0:U"},
{attr: "node.statistics.traffic.mgmt_tx.bytes", DS: "DS:mgmt_tx:DERIVE:600:0:U"},
{attr: "node.statistics.traffic.forward.bytes", DS: "DS:forward:DERIVE:600:0:U"},
],
"traffic_packets": [
{attr: "node.statistics.traffic.rx.packets", DS: "DS:rx:DERIVE:600:0:U"},
{attr: "node.statistics.traffic.tx.packets", DS: "DS:tx:DERIVE:600:0:U"},
{attr: "node.statistics.traffic.mgmt_rx.packets", DS: "DS:mgmt_rx:DERIVE:600:0:U"},
{attr: "node.statistics.traffic.mgmt_tx.packets", DS: "DS:mgmt_tx:DERIVE:600:0:U"},
{attr: "node.statistics.traffic.forward.packets", DS: "DS:forward:DERIVE:600:0:U"},
],
"clients": [{attr: "node.clients.length-1", DS: "DS:clients:GAUGE:600:0:U"}],
"neighbors": [
{attr: "node.neighbors.length", DS: "DS:neighbors:GAUGE:600:0:U"},
{attr: "vpn_neighbors(node.neighbors)", DS: "DS:vpn_neighbors:GAUGE:600:0:U"},
],
};
function merge() {
var vis = batvis.vis;
for(var i = 0; i < vis.length; i++) {
var macs = [vis[i].primary];
if(vis[i].secondary)
macs = macs.concat(vis[i].secondary);
macloop: for(var j = 0; j < macs.length; j++) {
var fuzzes = fuzz_mac_address(macs[j]);
for(var k = 0; k < fuzzes.length; k++) {
if(fuzzes[k] in details) {
macs.unshift(fuzzes[k]);
break macloop;
}
}
}
for(var j = 0; j < macs.length; j++) {
macmap[macs[j]] = macs[0];
}
if(!details[macs[0]])
details[macs[0]] = {};
for(var property in vis[i]) {
details[macs[0]][property] = vis[i][property];
}
details[macs[0]].macs = macs;
nodes.push(details[macs[0]]);
}
fs.writeFile(directory + "/nodes.json", JSON.stringify(nodes), {mode: 0644}, function(err) {
if(err) throw err;
});
for(var i = 0; i < nodes.length; i++) {
create_or_update_rrds(nodes[i], nodes);
}
}
fs.readFile(argv.batvis, 'utf-8', function(err, data) {
if (err) throw err;
batvis = JSON.parse(data);
if(--inputs == 0) merge();
});
fs.readFile(argv.details, 'utf-8', function(err, data) {
if (err) throw err;
details = JSON.parse(data);
if(--inputs == 0) merge();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment