% vim set ft=prolog :- module(bgp, [ warning/1, neighbor/2, bgp_config/2, bird_config/1, remote_network/2, remote_networks/2]). :- use_module(hosts, [ host/1, host_config/2, router_link/3, attached_network/2]). :- discontiguous bgp:to_dict/2. %host(H) :- router_link(H, _, _). %host(H) :- router_link(_, H, _). % host(H). router(R) :- host(R), hosts:host_config(R, _). routers(Routers) :- setof(router(R), router(R), Routers). to_dict(router(R), Dict) :- bgp:neighbors(R, Neighbors), maplist(bgp:to_dict(), Neighbors, NeighborDicts), Dict = _{ host: R, neighbors: NeighborDicts}. neighbor(H, R) :- router(H), router(R), router_link(H, _, R), router_link(R, _, H). warning(Msg) :- host(H), host(R), router_link(H, _, R), \+ router_link(R, _, H), format(string(Msg), "Missing router_link from ~w to ~w", [R, H]). neighbors(H, Cs) :- findall(neighbor(H, Name), neighbor(H, Name), Cs). bgp_config(H, Connections) :- neighbor(H, Connections). % bgp_config(H)? bird_protocol_bgp(Router, Neighbor, Address, AllowedNetworks) :- router_link(Router, _, Neighbor), router_link(Neighbor, Address, Router), AllowedNetworks = []. % edge(a, b). edge(b, c). edge(c, d). edge(d, a). % path(X, Y) :- edge(X, Y). % path(X, Y) :- edge(X, Z), path(Z, Y). attached_networks(Router, Ns) :- findall(N, attached_network(Router, N), Ns). remote_network(Router, N) :- router_link(Router, _, Remote), attached_network(Remote, N). remote_networks(Router, Ns) :- router_link(Router, _, Remote), attached_networks(Remote, Ns). % doesn't recurse % available_networks(R, Ns) :- % attached_networks(R, Attached), % setof(N, remote_network(R, N), Remote), % union(Attached, Remote, Xs), router_path(X, Y) :- router_path(X, Y, []). router_path(X, Y, _) :- router_link(X, _, Y). router_path(X, Y, V) :- \+ member(X, V), router_link(X, _, Z), router_path(Z, Y, [X|V]). to_yaml(neighbor(H, Remote), Dict) :- Dict = yaml(router(H), remote(Remote)). to_json(neighbor(H, Remote), Dict) :- Dict = json(router(H), remote(Remote)). to_dict(neighbor(_, Remote), Dict) :- host_config(Remote, RC), Dict = neighbor{ neighbor:_{ name: Remote, hostname: RC.ip } }. routers_entry(router(R), Dict) :- D = to_dict(router(R)), pairs_keys_values(Data, [R], [D]), dict_create(Dict, _, Data). bird_config(Dict) :- bgp:routers(Routers), maplist(to_dict(), Routers, RouterDicts), % maplist(routers_entry(), Routers, RouterDicts), Dict = _{routers:RouterDicts}. % findall(neighbor(H, R), (host(H), host(R), neighbor(H, R)), Routers), % yaml_write(current_output, _{neighbors:BgpConnectionDicts}).