frr/babeld/babel_zebra.c

254 lines
6.2 KiB
C

// SPDX-License-Identifier: MIT
/*
Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
*/
/* FRR's includes */
#include <zebra.h>
#include "command.h"
#include "zclient.h"
#include "stream.h"
/* babel's includes*/
#include "babel_zebra.h"
#include "babel_interface.h"
#include "xroute.h"
#include "util.h"
void babelz_zebra_init(void);
/* we must use a pointer because of zclient.c's functions (new, free). */
struct zclient *zclient;
/* Debug types */
static const struct {
int type;
int str_min_len;
const char *str;
} debug_type[] = {
{BABEL_DEBUG_COMMON, 1, "common"},
{BABEL_DEBUG_KERNEL, 1, "kernel"},
{BABEL_DEBUG_FILTER, 1, "filter"},
{BABEL_DEBUG_TIMEOUT, 1, "timeout"},
{BABEL_DEBUG_IF, 1, "interface"},
{BABEL_DEBUG_ROUTE, 1, "route"},
{BABEL_DEBUG_ALL, 1, "all"},
{0, 0, NULL}
};
/* Zebra route add and delete treatment. */
static int
babel_zebra_read_route (ZAPI_CALLBACK_ARGS)
{
struct zapi_route api;
if (zapi_route_decode(zclient->ibuf, &api) < 0)
return -1;
/* we completely ignore srcdest routes for now. */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
return 0;
if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
babel_route_add(&api);
} else {
babel_route_delete(&api);
}
return 0;
}
/* [Babel Command] */
DEFUN (babel_redistribute_type,
babel_redistribute_type_cmd,
"[no] redistribute <ipv4 " FRR_IP_REDIST_STR_BABELD "|ipv6 " FRR_IP6_REDIST_STR_BABELD ">",
NO_STR
"Redistribute\n"
"Redistribute IPv4 routes\n"
FRR_IP_REDIST_HELP_STR_BABELD
"Redistribute IPv6 routes\n"
FRR_IP6_REDIST_HELP_STR_BABELD)
{
int negate = 0;
int family;
int afi;
int type;
int idx = 0;
if (argv_find(argv, argc, "no", &idx))
negate = 1;
argv_find(argv, argc, "redistribute", &idx);
family = str2family(argv[idx + 1]->text);
if (family < 0)
return CMD_WARNING_CONFIG_FAILED;
afi = family2afi(family);
if (!afi)
return CMD_WARNING_CONFIG_FAILED;
type = proto_redistnum(afi, argv[idx + 2]->text);
if (type < 0) {
vty_out (vty, "Invalid type %s\n", argv[idx + 2]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
if (!negate)
zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, 0, VRF_DEFAULT);
else {
zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type, 0, VRF_DEFAULT);
/* perhaps should we remove xroutes having the same type... */
}
return CMD_SUCCESS;
}
#ifndef NO_DEBUG
/* [Babel Command] */
DEFUN (debug_babel,
debug_babel_cmd,
"debug babel <common|kernel|filter|timeout|interface|route|all>",
"Enable debug messages for specific or all part.\n"
"Babel information\n"
"Common messages (default)\n"
"Kernel messages\n"
"Filter messages\n"
"Timeout messages\n"
"Interface messages\n"
"Route messages\n"
"All messages\n")
{
int i;
for(i = 0; debug_type[i].str != NULL; i++) {
if (strncmp (debug_type[i].str, argv[2]->arg,
debug_type[i].str_min_len) == 0) {
SET_FLAG(debug, debug_type[i].type);
return CMD_SUCCESS;
}
}
vty_out (vty, "Invalid type %s\n", argv[2]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
/* [Babel Command] */
DEFUN (no_debug_babel,
no_debug_babel_cmd,
"no debug babel <common|kernel|filter|timeout|interface|route|all>",
NO_STR
"Disable debug messages for specific or all part.\n"
"Babel information\n"
"Common messages (default)\n"
"Kernel messages\n"
"Filter messages\n"
"Timeout messages\n"
"Interface messages\n"
"Route messages\n"
"All messages\n")
{
int i;
for (i = 0; debug_type[i].str; i++) {
if (strncmp(debug_type[i].str, argv[3]->arg,
debug_type[i].str_min_len) == 0) {
UNSET_FLAG(debug, debug_type[i].type);
return CMD_SUCCESS;
}
}
vty_out (vty, "Invalid type %s\n", argv[3]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
#endif /* NO_DEBUG */
/* Output "debug" statement lines, if necessary. */
int
debug_babel_config_write (struct vty * vty)
{
#ifdef NO_DEBUG
return 0;
#else
int i, lines = 0;
if (debug == BABEL_DEBUG_ALL)
{
vty_out (vty, "debug babel all\n");
lines++;
}
else
{
for (i = 0; debug_type[i].str != NULL; i++)
{
if (debug_type[i].type != BABEL_DEBUG_ALL
&& CHECK_FLAG (debug, debug_type[i].type))
{
vty_out (vty, "debug babel %s\n", debug_type[i].str);
lines++;
}
}
}
if (lines)
{
vty_out (vty, "!\n");
lines++;
}
return lines;
#endif /* NO_DEBUG */
}
DEFUN_NOSH (show_debugging_babel,
show_debugging_babel_cmd,
"show debugging [babel]",
SHOW_STR
DEBUG_STR
"Babel")
{
vty_out(vty, "BABEL debugging status\n");
debug_babel_config_write(vty);
cmd_show_lib_debugs(vty);
return CMD_SUCCESS;
}
static void
babel_zebra_connected (struct zclient *zclient)
{
zclient_send_reg_requests (zclient, VRF_DEFAULT);
}
static zclient_handler *const babel_handlers[] = {
[ZEBRA_INTERFACE_ADDRESS_ADD] = babel_interface_address_add,
[ZEBRA_INTERFACE_ADDRESS_DELETE] = babel_interface_address_delete,
[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = babel_zebra_read_route,
[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = babel_zebra_read_route,
};
void babelz_zebra_init(void)
{
zclient = zclient_new(master, &zclient_options_default, babel_handlers,
array_size(babel_handlers));
zclient_init(zclient, ZEBRA_ROUTE_BABEL, 0, &babeld_privs);
zclient->zebra_connected = babel_zebra_connected;
install_element(BABEL_NODE, &babel_redistribute_type_cmd);
install_element(ENABLE_NODE, &debug_babel_cmd);
install_element(ENABLE_NODE, &no_debug_babel_cmd);
install_element(CONFIG_NODE, &debug_babel_cmd);
install_element(CONFIG_NODE, &no_debug_babel_cmd);
install_element(ENABLE_NODE, &show_debugging_babel_cmd);
}
void
babel_zebra_close_connexion(void)
{
zclient_stop(zclient);
zclient_free(zclient);
}