mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-04 06:38:04 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			184 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
						|
/* BGP scripting foo
 | 
						|
 * Copyright (C) 2020  NVIDIA Corporation
 | 
						|
 * Quentin Young
 | 
						|
 */
 | 
						|
 | 
						|
#include <zebra.h>
 | 
						|
 | 
						|
#ifdef HAVE_SCRIPTING
 | 
						|
 | 
						|
#include "bgpd.h"
 | 
						|
#include "bgp_script.h"
 | 
						|
#include "bgp_debug.h"
 | 
						|
#include "bgp_aspath.h"
 | 
						|
#include "frratomic.h"
 | 
						|
#include "frrscript.h"
 | 
						|
 | 
						|
void lua_pushpeer(lua_State *L, const struct peer *peer)
 | 
						|
{
 | 
						|
	lua_newtable(L);
 | 
						|
	lua_pushinteger(L, peer->as);
 | 
						|
	lua_setfield(L, -2, "remote_as");
 | 
						|
	lua_pushinteger(L, peer->local_as);
 | 
						|
	lua_setfield(L, -2, "local_as");
 | 
						|
	lua_pushinaddr(L, &peer->remote_id);
 | 
						|
	lua_setfield(L, -2, "remote_id");
 | 
						|
	lua_pushinaddr(L, &peer->local_id);
 | 
						|
	lua_setfield(L, -2, "local_id");
 | 
						|
	lua_pushstring(L, lookup_msg(bgp_status_msg, peer->status, NULL));
 | 
						|
	lua_setfield(L, -2, "state");
 | 
						|
	lua_pushstring(L, peer->desc ? peer->desc : "");
 | 
						|
	lua_setfield(L, -2, "description");
 | 
						|
	lua_pushtimet(L, &peer->uptime);
 | 
						|
	lua_setfield(L, -2, "uptime");
 | 
						|
	lua_pushtimet(L, &peer->readtime);
 | 
						|
	lua_setfield(L, -2, "last_readtime");
 | 
						|
	lua_pushtimet(L, &peer->resettime);
 | 
						|
	lua_setfield(L, -2, "last_resettime");
 | 
						|
	lua_pushsockunion(L, peer->su_local);
 | 
						|
	lua_setfield(L, -2, "local_address");
 | 
						|
	lua_pushsockunion(L, peer->su_remote);
 | 
						|
	lua_setfield(L, -2, "remote_address");
 | 
						|
	lua_pushinteger(L, peer->cap);
 | 
						|
	lua_setfield(L, -2, "capabilities");
 | 
						|
	lua_pushinteger(L, peer->flags);
 | 
						|
	lua_setfield(L, -2, "flags");
 | 
						|
	lua_pushstring(L, peer->password ? peer->password : "");
 | 
						|
	lua_setfield(L, -2, "password");
 | 
						|
 | 
						|
	/* Nested tables here */
 | 
						|
	lua_newtable(L);
 | 
						|
	{
 | 
						|
		lua_newtable(L);
 | 
						|
		{
 | 
						|
			lua_pushinteger(L, peer->holdtime);
 | 
						|
			lua_setfield(L, -2, "hold");
 | 
						|
			lua_pushinteger(L, peer->keepalive);
 | 
						|
			lua_setfield(L, -2, "keepalive");
 | 
						|
			lua_pushinteger(L, peer->connect);
 | 
						|
			lua_setfield(L, -2, "connect");
 | 
						|
			lua_pushinteger(L, peer->routeadv);
 | 
						|
			lua_setfield(L, -2, "route_advertisement");
 | 
						|
		}
 | 
						|
		lua_setfield(L, -2, "configured");
 | 
						|
 | 
						|
		lua_newtable(L);
 | 
						|
		{
 | 
						|
			lua_pushinteger(L, peer->v_holdtime);
 | 
						|
			lua_setfield(L, -2, "hold");
 | 
						|
			lua_pushinteger(L, peer->v_keepalive);
 | 
						|
			lua_setfield(L, -2, "keepalive");
 | 
						|
			lua_pushinteger(L, peer->v_connect);
 | 
						|
			lua_setfield(L, -2, "connect");
 | 
						|
			lua_pushinteger(L, peer->v_routeadv);
 | 
						|
			lua_setfield(L, -2, "route_advertisement");
 | 
						|
		}
 | 
						|
		lua_setfield(L, -2, "negotiated");
 | 
						|
	}
 | 
						|
	lua_setfield(L, -2, "timers");
 | 
						|
 | 
						|
	lua_newtable(L);
 | 
						|
	{
 | 
						|
		lua_pushinteger(L, atomic_load_explicit(&peer->open_in,
 | 
						|
							memory_order_relaxed));
 | 
						|
		lua_setfield(L, -2, "open_in");
 | 
						|
		lua_pushinteger(L, atomic_load_explicit(&peer->open_out,
 | 
						|
							memory_order_relaxed));
 | 
						|
		lua_setfield(L, -2, "open_out");
 | 
						|
		lua_pushinteger(L, atomic_load_explicit(&peer->update_in,
 | 
						|
							memory_order_relaxed));
 | 
						|
		lua_setfield(L, -2, "update_in");
 | 
						|
		lua_pushinteger(L, atomic_load_explicit(&peer->update_out,
 | 
						|
							memory_order_relaxed));
 | 
						|
		lua_setfield(L, -2, "update_out");
 | 
						|
		lua_pushinteger(L, atomic_load_explicit(&peer->update_time,
 | 
						|
							memory_order_relaxed));
 | 
						|
		lua_setfield(L, -2, "update_time");
 | 
						|
		lua_pushinteger(L, atomic_load_explicit(&peer->keepalive_in,
 | 
						|
							memory_order_relaxed));
 | 
						|
		lua_setfield(L, -2, "keepalive_in");
 | 
						|
		lua_pushinteger(L, atomic_load_explicit(&peer->keepalive_out,
 | 
						|
							memory_order_relaxed));
 | 
						|
		lua_setfield(L, -2, "keepalive_out");
 | 
						|
		lua_pushinteger(L, atomic_load_explicit(&peer->notify_in,
 | 
						|
							memory_order_relaxed));
 | 
						|
		lua_setfield(L, -2, "notify_in");
 | 
						|
		lua_pushinteger(L, atomic_load_explicit(&peer->notify_out,
 | 
						|
							memory_order_relaxed));
 | 
						|
		lua_setfield(L, -2, "notify_out");
 | 
						|
		lua_pushinteger(L, atomic_load_explicit(&peer->refresh_in,
 | 
						|
							memory_order_relaxed));
 | 
						|
		lua_setfield(L, -2, "refresh_in");
 | 
						|
		lua_pushinteger(L, atomic_load_explicit(&peer->refresh_out,
 | 
						|
							memory_order_relaxed));
 | 
						|
		lua_setfield(L, -2, "refresh_out");
 | 
						|
		lua_pushinteger(L, atomic_load_explicit(&peer->dynamic_cap_in,
 | 
						|
							memory_order_relaxed));
 | 
						|
		lua_setfield(L, -2, "dynamic_cap_in");
 | 
						|
		lua_pushinteger(L, atomic_load_explicit(&peer->dynamic_cap_out,
 | 
						|
							memory_order_relaxed));
 | 
						|
		lua_setfield(L, -2, "dynamic_cap_out");
 | 
						|
		lua_pushinteger(L, peer->established);
 | 
						|
		lua_setfield(L, -2, "times_established");
 | 
						|
		lua_pushinteger(L, peer->dropped);
 | 
						|
		lua_setfield(L, -2, "times_dropped");
 | 
						|
	}
 | 
						|
	lua_setfield(L, -2, "stats");
 | 
						|
}
 | 
						|
 | 
						|
void lua_pushattr(lua_State *L, const struct attr *attr)
 | 
						|
{
 | 
						|
	lua_newtable(L);
 | 
						|
	lua_pushinteger(L, attr->med);
 | 
						|
	lua_setfield(L, -2, "metric");
 | 
						|
	lua_pushinteger(L, attr->nh_ifindex);
 | 
						|
	lua_setfield(L, -2, "ifindex");
 | 
						|
	lua_pushstring(L, attr->aspath->str);
 | 
						|
	lua_setfield(L, -2, "aspath");
 | 
						|
	lua_pushinteger(L, attr->local_pref);
 | 
						|
	lua_setfield(L, -2, "localpref");
 | 
						|
}
 | 
						|
 | 
						|
void lua_decode_attr(lua_State *L, int idx, struct attr *attr)
 | 
						|
{
 | 
						|
	lua_getfield(L, idx, "metric");
 | 
						|
	attr->med = lua_tointeger(L, -1);
 | 
						|
	lua_pop(L, 1);
 | 
						|
	lua_getfield(L, idx, "ifindex");
 | 
						|
	attr->nh_ifindex = lua_tointeger(L, -1);
 | 
						|
	lua_pop(L, 1);
 | 
						|
	lua_getfield(L, idx, "aspath");
 | 
						|
	attr->aspath = aspath_str2aspath(lua_tostring(L, -1),
 | 
						|
					 bgp_get_asnotation(NULL));
 | 
						|
	lua_pop(L, 1);
 | 
						|
	lua_getfield(L, idx, "localpref");
 | 
						|
	attr->local_pref = lua_tointeger(L, -1);
 | 
						|
	lua_pop(L, 1);
 | 
						|
	lua_pop(L, 1);
 | 
						|
}
 | 
						|
 | 
						|
void *lua_toattr(lua_State *L, int idx)
 | 
						|
{
 | 
						|
	struct attr *attr = XCALLOC(MTYPE_TMP, sizeof(struct attr));
 | 
						|
 | 
						|
	lua_decode_attr(L, idx, attr);
 | 
						|
	return attr;
 | 
						|
}
 | 
						|
 | 
						|
struct frrscript_codec frrscript_codecs_bgpd[] = {
 | 
						|
	{.typename = "peer",
 | 
						|
	 .encoder = (encoder_func)lua_pushpeer,
 | 
						|
	 .decoder = NULL},
 | 
						|
	{.typename = "attr",
 | 
						|
	 .encoder = (encoder_func)lua_pushattr,
 | 
						|
	 .decoder = lua_toattr},
 | 
						|
	{}};
 | 
						|
 | 
						|
void bgp_script_init(void)
 | 
						|
{
 | 
						|
	frrscript_register_type_codecs(frrscript_codecs_bgpd);
 | 
						|
}
 | 
						|
 | 
						|
#endif /* HAVE_SCRIPTING */
 |