From 330012b58e40c1fce807bb7394bb032221620387 Mon Sep 17 00:00:00 2001 From: Simon Polack Date: Fri, 8 Nov 2024 02:42:40 +0100 Subject: [PATCH] es lebt --- packages/bgpdisco/bgpdisco.uc | 75 +++++++++++++---------- packages/bgpdisco/bird_config_template.ut | 30 +++++---- packages/bgpdisco/birdctl.uc | 16 +++-- packages/bgpdisco/plugin.uc | 2 +- 4 files changed, 70 insertions(+), 53 deletions(-) diff --git a/packages/bgpdisco/bgpdisco.uc b/packages/bgpdisco/bgpdisco.uc index 5ee7cfb4..d29f14f4 100644 --- a/packages/bgpdisco/bgpdisco.uc +++ b/packages/bgpdisco/bgpdisco.uc @@ -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'); } @@ -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 = {}; @@ -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); @@ -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) { @@ -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(); diff --git a/packages/bgpdisco/bird_config_template.ut b/packages/bgpdisco/bird_config_template.ut index ebdaf69e..6ce38e9c 100644 --- a/packages/bgpdisco/bird_config_template.ut +++ b/packages/bgpdisco/bird_config_template.ut @@ -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 %} diff --git a/packages/bgpdisco/birdctl.uc b/packages/bgpdisco/birdctl.uc index 6669056b..cfb1b7bd 100644 --- a/packages/bgpdisco/birdctl.uc +++ b/packages/bgpdisco/birdctl.uc @@ -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) { @@ -27,6 +31,8 @@ function get_babel_neighbors() { } function init(bird_ctl) { + DBG('init()'); + if (bird_ctl) { sock_bctl_path = bird_ctl; } diff --git a/packages/bgpdisco/plugin.uc b/packages/bgpdisco/plugin.uc index fa3dfb84..189d54d6 100644 --- a/packages/bgpdisco/plugin.uc +++ b/packages/bgpdisco/plugin.uc @@ -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 = [];