Skip to content

Commit

Permalink
es lebt
Browse files Browse the repository at this point in the history
  • Loading branch information
spolack committed Nov 8, 2024
1 parent 4ec9f23 commit 330012b
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 53 deletions.
75 changes: 44 additions & 31 deletions packages/bgpdisco/bgpdisco.uc
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,27 @@ let tty;
let bird;
let plugins;

let cache_neighbors;
let cache_data;

let timer_sync_peers;
let timer_refresh_data;

function render_bird_config() {
DBG('render_bird_config()');
let plugin_data = plugins.provide_data();
return render(cfg.bird_config_template, proto({
index: index, hexenc, hexenc, neighbors: cache_neighbors, data: plugin_data
return render('/usr/share/ucode/bgpdisco/bird_config_template.ut', proto({
index: index, hexenc, replace,
neighbors: cache_neighbors, data: plugins.provide_data()
}, {}));
}

function configure_bird() {
DBG('configure_bird()');

let config = render_bird_config();

DBG('write rendered config');
if (!fs.writefile(cfg.bird_config_file, config)) {
if (!fs.writefile('/dev/shm/bird_bgpdisco.conf', config)) {
ERR('cant write bird config to filesystem');
}

Expand All @@ -37,14 +44,14 @@ function retrieve_data_from_bird() {
DBG('retrieve_data_from_bird()');

DBG('remove old mrt dump');
fs.unlink(cfg.bird_mrt_file);
fs.unlink('/tmp/bird_bgpdisco.mrt');

DBG('request new mrt dump');
bird.cmd('mrt dump table "*_nameservice" to "' + cfg.bird_mrt_file + '"');
bird.cmd('mrt dump table "*_bgpdisco" to "' + '/tmp/bird_bgpdisco.mrt' + '"');


DBG('parse mrt dump');
let data = mrtdump.get_routes(cfg.bird_mrt_file);
let data = mrtdump.get_routes('/tmp/bird_bgpdisco.mrt');

DBG('processing routes');
let parsed_data = {};
Expand All @@ -69,31 +76,35 @@ function cb_refresh_data() {
DBG('cb_refresh_data()');
let data = retrieve_data_from_bird();
if (sprintf('%s', data) == sprintf('%s', cache_data)) {
DBG('received data matches cache - no need to trigger handler plugins');
DBG('Received data matches cache - no need to trigger handler plugins');
return;
};
DBG('received data differs from cache - triggering handler plugins');
DBG('Received data differs from cache - trigger handler plugins');
cache_data = data;
plugins.handle_data(data);
uloop.timer(cfg.interval_refresh_data, cb_refresh_data);
}

function cb_sync_peers() {
DBG('cb_sync_peers');

DBG('cb_sync_peers()');
let neighbors = bird.get_babel_neighbors();
if (sprintf('%s', neighbors) == sprintf('%s', cache_neighbors)) {
debug('cb_sync_peers: neighbors match - no sync required');
DBG('No change in babel neighbors - no sync required');
return;
}
INFO('Detected change in babel neighbors - sync neighbors to BGP');
INFO('Babel neighbors have changed - sync to BGP');
cache_neighbors = neighbors;

configure_bird();
uloop.timer(cfg.interval_sync_peers, cb_sync_peers);
}

function trigger_sync_peers() {
cb_sync_peers();
timer_sync_peers.set(300000);
}

function trigger_refresh_data() {
cb_refresh_data();
timer_refresh_data.set(10000);
}

function cb_nl_newneigh(ev) {
DBG('cb_nl_newneigh(%s)', ev);
Expand All @@ -108,9 +119,9 @@ function cb_nl_newneigh(ev) {
}

// Ignore other interfaces
if (index(cfg.mesh_ifaces, ev.msg.dev) == -1 ) {
return;
}
// if (index(cfg.mesh_ifaces, ev.msg.dev) == -1 ) {
// return;
// }

// Ignore other state changes than reachable
if (ev.msg.state != rtnl.const.NUD_REACHABLE) {
Expand All @@ -122,25 +133,27 @@ function cb_nl_newneigh(ev) {
return;
}


DBG('new ip neighbor - triggering resync', ev);
DBG('Learned new neighbor - triggering peer syncronization. IP: %s, Dev:', ev.msg.dst, ev.msg.dev);
trigger_sync_peers();
}


INFO('start');
INFO('Start');

bird = birdctl.init();
plugins = plugin.init('/usr/share/ucode/bgpdisco/plugins');


// Setup Sync Peers Timer
//interval_sync_peers = uloop.interval(null, cb_sync_peers);
// setup sync peers timer - unarmed, because we launch it right away in next lines
timer_sync_peers = uloop.timer(-1, trigger_sync_peers);

// setup refresh data timer - armed, but after uloop.run
timer_refresh_data = uloop.timer(5000, trigger_refresh_data);

// Setup RTNL Listener to catch new peers quickly
// rtnl.listener(cb_nl_newneigh, [rtnl.const.RTM_NEWNEIGH], [rtnl.const.RTNLGRP_NEIGH]);
// sync peers right away
trigger_sync_peers();

// Setup Refresh Data Timer
//interval_refresh_data = uloop.interval(cfg.interval_refresh_data, cb_refresh_data);
//cb_refresh_data();
// setup netlink listener to catch new peers quickly
rtnl.listener(cb_nl_newneigh, [rtnl.const.RTM_NEWNEIGH], [rtnl.const.RTNLGRP_NEIGH]);

//uloop.run();
// get the party started :)
uloop.run();
30 changes: 14 additions & 16 deletions packages/bgpdisco/bird_config_template.ut
Original file line number Diff line number Diff line change
@@ -1,45 +1,43 @@
ipv6 table v6_nameservice;
ipv4 table v4_nameservice;
ipv6 table v6_bgpdisco
ipv4 table v4_bgpdisco;

# Define BGP attribute 250 for our custom nameservice extension :)
attribute bgp 250 bytestring bgp_nameservice;
attribute bgp 250 bytestring bgpdisco;

protocol static static_nameservice_v4 {
ipv4 { table v4_nameservice; };
protocol static static_bgpdisco_v4 {
ipv4 { table v4_bgpdisco; };
{% for (let _rt in data): if (index(_rt, ':') == -1): %}
route {{ _rt }}/32 blackhole { bgp_nameservice = hex:{{ hexenc(data[_rt]) }}; };
route {{ _rt }}/32 blackhole { bgpdisco = hex:{{ hexenc(data[_rt]) }}; };
{% endif; endfor %}
};

protocol static static_nameservice_v6 {
ipv6 { table v6_nameservice; };
protocol static static_bgpdisco_v6 {
ipv6 { table v6_bgpdisco; };
{% for (let _rt in data): if (index(_rt, ':') != -1): %}
route {{ _rt }}/128 blackhole { bgp_nameservice = hex:{{ hexenc(data[_rt]) }}; };
route {{ _rt }}/128 blackhole { bgpdisco = hex:{{ hexenc(data[_rt]) }}; };
{% endif; endfor %}
}

{% let i = 1; %}
{% for (let neigh in neighbors): %}
protocol bgp nameservice{{ i++ }} {
protocol bgp bgpdisco_{{ replace(neigh.iface, '.', '_') }} {
local as 65000;
debug {states,events};
interface "{{ neigh[0] }}";
neighbor {{ neigh[1] }} as 65000 internal;
interface "{{ neigh.iface }}";
neighbor {{ neigh.ip }} as 65000 internal;
direct;
ipv4 {
table v4_nameservice;
table v4_bgpdisco;
import all;
export all;
gateway recursive;
next hop address 192.0.2.0;
};
ipv6 {
table v6_nameservice;
table v6_bgpdisco;
import all;
export all;
gateway recursive;
next hop address 2001:db8::; # Safe some memory by using IPv4 NH
};

}
{% endfor %}
16 changes: 11 additions & 5 deletions packages/bgpdisco/birdctl.uc
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import {popen} from 'fs';

import { DBG, INFO, WARN, ERR } from 'bgpdisco.logger';

let sock_bctl_path = '/var/run/bird.ctl';
const BIRDC_PATH = '/usr/sbin/birdc';
const RE_BABEL_NEIGHBORS = regexp('(fe80\S*) (\S*)', 'g');
const RE_BABEL_NEIGHBORS = regexp('(fe80\\S*) (\\S*)', 'g');

function cmd(cmd) {
let escaped_command = replace(cmd,'"','\\"');
DBG('cmd()');
let escaped_command = replace(cmd,'"','\\\"');

let cmd_string = sprintf('%s -s %s %s', BIRDC_PATH, sock_bctl_path, cmd);
let cmd_string = sprintf('%s -s %s %s', BIRDC_PATH, sock_bctl_path, escaped_command);
DBG('Popen: %s', cmd_string);
let p = popen(cmd_string);
let response = p.read('all');
DBG('Output: %s', response);
p.close();

return response;
}

function get_babel_neighbors() {
let response = send_command('show babel neighbors');
DBG('get_babel_neighbors()');
let response = cmd('show babel neighbors');
let matches = match(response, RE_BABEL_NEIGHBORS); // returns [[fe80.., iface], [fe80.., iface]]
let result = [];
for (let _m in matches) {
Expand All @@ -27,6 +31,8 @@ function get_babel_neighbors() {
}

function init(bird_ctl) {
DBG('init()');

if (bird_ctl) {
sock_bctl_path = bird_ctl;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/bgpdisco/plugin.uc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function provide_data() {

let res_cb = call(cb);
for (let _ip in res_cb) {
res_cb_data = res_cb[_ip];
let res_cb_data = res_cb[_ip];
data[_ip] ??= [];

let darr = [];
Expand Down

0 comments on commit 330012b

Please sign in to comment.