2023-02-08 13:17:09 +01:00
|
|
|
// SPDX-License-Identifier: MIT
|
2017-05-13 20:59:41 +02:00
|
|
|
/*
|
|
|
|
Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
#include "command.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "table.h"
|
|
|
|
#include "distribute.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "filter.h"
|
|
|
|
#include "plist.h"
|
2018-06-18 19:38:21 +02:00
|
|
|
#include "lib_errors.h"
|
2020-04-17 15:35:15 +02:00
|
|
|
#include "network.h"
|
2022-05-02 18:00:12 +02:00
|
|
|
#include "if.h"
|
2017-05-13 20:59:41 +02:00
|
|
|
|
|
|
|
#include "babel_main.h"
|
|
|
|
#include "babeld.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "net.h"
|
|
|
|
#include "kernel.h"
|
|
|
|
#include "babel_interface.h"
|
|
|
|
#include "neighbour.h"
|
|
|
|
#include "route.h"
|
|
|
|
#include "message.h"
|
|
|
|
#include "resend.h"
|
|
|
|
#include "babel_filter.h"
|
|
|
|
#include "babel_zebra.h"
|
2018-06-18 19:38:21 +02:00
|
|
|
#include "babel_errors.h"
|
2017-05-13 20:59:41 +02:00
|
|
|
|
2023-01-14 13:02:41 +01:00
|
|
|
#ifndef VTYSH_EXTRACT_PL
|
|
|
|
#include "babeld/babeld_clippy.c"
|
|
|
|
#endif
|
|
|
|
|
2019-06-21 08:14:58 +02:00
|
|
|
DEFINE_MGROUP(BABELD, "babeld");
|
|
|
|
DEFINE_MTYPE_STATIC(BABELD, BABEL, "Babel Structure");
|
|
|
|
|
2022-03-01 22:18:12 +01:00
|
|
|
static void babel_init_routing_process(struct event *thread);
|
2017-05-13 20:59:41 +02:00
|
|
|
static void babel_get_myid(void);
|
|
|
|
static void babel_initial_noise(void);
|
2022-03-01 22:18:12 +01:00
|
|
|
static void babel_read_protocol(struct event *thread);
|
|
|
|
static void babel_main_loop(struct event *thread);
|
2017-05-13 20:59:41 +02:00
|
|
|
static void babel_set_timer(struct timeval *timeout);
|
|
|
|
static void babel_fill_with_next_timeout(struct timeval *tv);
|
lib, rip, ripng, babel, eigrp: add ctx pointer to distribute api
a distribute_ctx context pointer is returned after initialisation to the
calling daemon. this context pointer will be further used to do
discussion with distribute service. Today, there is no specific problem
with old api, since the pointer is the same in all the memory process.
but the pointer will be different if we have multiple instances. Right
now, this is not the case, but if that happens, that work will be used
for that.
distribute-list initialisation is split in two. the vty initialisation
is done at global level, while the context initialisation is done for
each routing daemon instance.
babel daemon is being equipped with a routing returning the main babel
instance.
also, a delete routine is available when the daemon routing instance is
suppressed.
a list of contexts is used inside distribute_list. This will permit
distribute_list utility to handle in the same daemon to handle more than
one context. This will be very useful in the vrf context.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-12-04 15:45:57 +01:00
|
|
|
static void
|
|
|
|
babel_distribute_update (struct distribute_ctx *ctx, struct distribute *dist);
|
2017-05-13 20:59:41 +02:00
|
|
|
|
|
|
|
/* Informations relative to the babel running daemon. */
|
|
|
|
static struct babel *babel_routing_process = NULL;
|
|
|
|
static unsigned char *receive_buffer = NULL;
|
|
|
|
static int receive_buffer_size = 0;
|
|
|
|
|
|
|
|
/* timeouts */
|
|
|
|
struct timeval check_neighbours_timeout;
|
|
|
|
static time_t expiry_time;
|
|
|
|
static time_t source_expiry_time;
|
|
|
|
|
|
|
|
/* Babel node structure. */
|
2018-09-08 22:31:43 +02:00
|
|
|
static int babel_config_write (struct vty *vty);
|
2017-05-13 20:59:41 +02:00
|
|
|
static struct cmd_node cmd_babel_node =
|
|
|
|
{
|
2018-09-09 00:15:50 +02:00
|
|
|
.name = "babel",
|
2017-05-13 20:59:41 +02:00
|
|
|
.node = BABEL_NODE,
|
2018-09-08 23:15:09 +02:00
|
|
|
.parent_node = CONFIG_NODE,
|
2017-05-13 20:59:41 +02:00
|
|
|
.prompt = "%s(config-router)# ",
|
2018-09-08 22:31:43 +02:00
|
|
|
.config_write = babel_config_write,
|
2017-05-13 20:59:41 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/* print current babel configuration on vty */
|
|
|
|
static int
|
|
|
|
babel_config_write (struct vty *vty)
|
|
|
|
{
|
|
|
|
int lines = 0;
|
2017-07-26 16:31:54 +02:00
|
|
|
int afi;
|
2017-05-13 20:59:41 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
/* list enabled debug modes */
|
|
|
|
lines += debug_babel_config_write (vty);
|
|
|
|
|
|
|
|
if (!babel_routing_process)
|
|
|
|
return lines;
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out (vty, "router babel\n");
|
2017-05-13 20:59:41 +02:00
|
|
|
if (diversity_kind != DIVERSITY_NONE)
|
|
|
|
{
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out (vty, " babel diversity\n");
|
2017-05-13 20:59:41 +02:00
|
|
|
lines++;
|
|
|
|
}
|
|
|
|
if (diversity_factor != BABEL_DEFAULT_DIVERSITY_FACTOR)
|
|
|
|
{
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out (vty, " babel diversity-factor %d\n",diversity_factor);
|
2017-05-13 20:59:41 +02:00
|
|
|
lines++;
|
|
|
|
}
|
|
|
|
if (resend_delay != BABEL_DEFAULT_RESEND_DELAY)
|
|
|
|
{
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out (vty, " babel resend-delay %u\n", resend_delay);
|
2017-05-13 20:59:41 +02:00
|
|
|
lines++;
|
|
|
|
}
|
|
|
|
if (smoothing_half_life != BABEL_DEFAULT_SMOOTHING_HALF_LIFE)
|
|
|
|
{
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out (vty, " babel smoothing-half-life %u\n",
|
2017-06-21 05:10:57 +02:00
|
|
|
smoothing_half_life);
|
2017-05-13 20:59:41 +02:00
|
|
|
lines++;
|
|
|
|
}
|
|
|
|
/* list enabled interfaces */
|
|
|
|
lines = 1 + babel_enable_if_config_write (vty);
|
|
|
|
/* list redistributed protocols */
|
2017-07-26 16:31:54 +02:00
|
|
|
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
|
|
|
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
2025-01-24 20:44:46 +01:00
|
|
|
if (i != babel_zclient->redist_default &&
|
|
|
|
vrf_bitmap_check(&babel_zclient->redist[afi][i], VRF_DEFAULT)) {
|
2023-04-19 14:13:18 +02:00
|
|
|
vty_out(vty, " redistribute %s %s\n",
|
|
|
|
(afi == AFI_IP) ? "ipv4" : "ipv6",
|
|
|
|
zebra_route_string(i));
|
|
|
|
lines++;
|
|
|
|
}
|
|
|
|
}
|
2017-07-26 16:31:54 +02:00
|
|
|
}
|
2017-05-13 20:59:41 +02:00
|
|
|
|
lib, rip, ripng, babel, eigrp: add ctx pointer to distribute api
a distribute_ctx context pointer is returned after initialisation to the
calling daemon. this context pointer will be further used to do
discussion with distribute service. Today, there is no specific problem
with old api, since the pointer is the same in all the memory process.
but the pointer will be different if we have multiple instances. Right
now, this is not the case, but if that happens, that work will be used
for that.
distribute-list initialisation is split in two. the vty initialisation
is done at global level, while the context initialisation is done for
each routing daemon instance.
babel daemon is being equipped with a routing returning the main babel
instance.
also, a delete routine is available when the daemon routing instance is
suppressed.
a list of contexts is used inside distribute_list. This will permit
distribute_list utility to handle in the same daemon to handle more than
one context. This will be very useful in the vrf context.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-12-04 15:45:57 +01:00
|
|
|
lines += config_write_distribute (vty, babel_routing_process->distribute_ctx);
|
2017-05-13 20:59:41 +02:00
|
|
|
|
2021-08-08 21:38:50 +02:00
|
|
|
vty_out (vty, "exit\n");
|
|
|
|
|
2017-05-13 20:59:41 +02:00
|
|
|
return lines;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
babel_create_routing_process (void)
|
|
|
|
{
|
|
|
|
assert (babel_routing_process == NULL);
|
|
|
|
|
|
|
|
/* Allocaste Babel instance. */
|
2020-03-08 20:43:26 +01:00
|
|
|
babel_routing_process = XCALLOC(MTYPE_BABEL, sizeof(struct babel));
|
2017-05-13 20:59:41 +02:00
|
|
|
|
|
|
|
/* Initialize timeouts */
|
|
|
|
gettime(&babel_now);
|
|
|
|
expiry_time = babel_now.tv_sec + roughly(30);
|
|
|
|
source_expiry_time = babel_now.tv_sec + roughly(300);
|
|
|
|
|
|
|
|
/* Make socket for Babel protocol. */
|
|
|
|
protocol_socket = babel_socket(protocol_port);
|
|
|
|
if (protocol_socket < 0) {
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET, "Couldn't create link local socket: %s",
|
2018-06-18 19:38:21 +02:00
|
|
|
safe_strerror(errno));
|
2017-05-13 20:59:41 +02:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Threads. */
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_read(master, babel_read_protocol, NULL, protocol_socket,
|
|
|
|
&babel_routing_process->t_read);
|
2017-05-13 20:59:41 +02:00
|
|
|
/* wait a little: zebra will announce interfaces, addresses, routes... */
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_timer_msec(master, babel_init_routing_process, NULL, 200L,
|
|
|
|
&babel_routing_process->t_update);
|
2017-05-13 20:59:41 +02:00
|
|
|
|
lib, rip, ripng, babel, eigrp: add ctx pointer to distribute api
a distribute_ctx context pointer is returned after initialisation to the
calling daemon. this context pointer will be further used to do
discussion with distribute service. Today, there is no specific problem
with old api, since the pointer is the same in all the memory process.
but the pointer will be different if we have multiple instances. Right
now, this is not the case, but if that happens, that work will be used
for that.
distribute-list initialisation is split in two. the vty initialisation
is done at global level, while the context initialisation is done for
each routing daemon instance.
babel daemon is being equipped with a routing returning the main babel
instance.
also, a delete routine is available when the daemon routing instance is
suppressed.
a list of contexts is used inside distribute_list. This will permit
distribute_list utility to handle in the same daemon to handle more than
one context. This will be very useful in the vrf context.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-12-04 15:45:57 +01:00
|
|
|
/* Distribute list install. */
|
|
|
|
babel_routing_process->distribute_ctx = distribute_list_ctx_create (vrf_lookup_by_id(VRF_DEFAULT));
|
|
|
|
distribute_list_add_hook (babel_routing_process->distribute_ctx, babel_distribute_update);
|
|
|
|
distribute_list_delete_hook (babel_routing_process->distribute_ctx, babel_distribute_update);
|
|
|
|
return 0;
|
2017-05-13 20:59:41 +02:00
|
|
|
fail:
|
|
|
|
XFREE(MTYPE_BABEL, babel_routing_process);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* thread reading entries form others babel daemons */
|
2022-03-01 22:18:12 +01:00
|
|
|
static void babel_read_protocol(struct event *thread)
|
2017-05-13 20:59:41 +02:00
|
|
|
{
|
|
|
|
int rc;
|
2017-10-03 03:06:01 +02:00
|
|
|
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
2017-05-13 20:59:41 +02:00
|
|
|
struct interface *ifp = NULL;
|
|
|
|
struct sockaddr_in6 sin6;
|
|
|
|
|
|
|
|
assert(babel_routing_process != NULL);
|
|
|
|
assert(protocol_socket >= 0);
|
|
|
|
|
|
|
|
rc = babel_recv(protocol_socket,
|
|
|
|
receive_buffer, receive_buffer_size,
|
|
|
|
(struct sockaddr*)&sin6, sizeof(sin6));
|
|
|
|
if(rc < 0) {
|
|
|
|
if(errno != EAGAIN && errno != EINTR) {
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET, "recv: %s", safe_strerror(errno));
|
2017-05-13 20:59:41 +02:00
|
|
|
}
|
|
|
|
} else {
|
2025-04-05 21:14:12 +02:00
|
|
|
if(ntohs(sin6.sin6_port) != BABEL_PORT) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-10-03 03:06:01 +02:00
|
|
|
FOR_ALL_INTERFACES(vrf, ifp) {
|
2017-05-13 20:59:41 +02:00
|
|
|
if(!if_up(ifp))
|
|
|
|
continue;
|
|
|
|
if(ifp->ifindex == (ifindex_t)sin6.sin6_scope_id) {
|
|
|
|
parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
|
|
|
|
receive_buffer, rc);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* re-add thread */
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_read(master, &babel_read_protocol, NULL, protocol_socket,
|
|
|
|
&babel_routing_process->t_read);
|
2017-05-13 20:59:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Zebra will give some information, especially about interfaces. This function
|
|
|
|
must be call with a litte timeout wich may give zebra the time to do his job,
|
|
|
|
making these inits have sense. */
|
2022-03-01 22:18:12 +01:00
|
|
|
static void babel_init_routing_process(struct event *thread)
|
2017-05-13 20:59:41 +02:00
|
|
|
{
|
2024-09-06 03:32:51 +02:00
|
|
|
myseqno = CHECK_FLAG(frr_weak_random(), 0xFFFF);
|
2017-05-13 20:59:41 +02:00
|
|
|
babel_get_myid();
|
|
|
|
babel_load_state_file();
|
|
|
|
debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid));
|
|
|
|
babel_initial_noise();
|
|
|
|
babel_main_loop(thread);/* this function self-add to the t_update thread */
|
|
|
|
}
|
|
|
|
|
2025-04-05 21:21:27 +02:00
|
|
|
/* fill "myid" with an unique id (only if myid != {0} and myid != {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}). */
|
2017-05-13 20:59:41 +02:00
|
|
|
static void
|
|
|
|
babel_get_myid(void)
|
|
|
|
{
|
2017-10-03 03:06:01 +02:00
|
|
|
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
2017-05-13 20:59:41 +02:00
|
|
|
struct interface *ifp = NULL;
|
|
|
|
int rc;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* if we already have an id (from state file), we return. */
|
2025-04-05 21:21:27 +02:00
|
|
|
if (memcmp(myid, zeroes, 8) != 0 && memcmp(myid, ones, 8) != 0) {
|
2017-05-13 20:59:41 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-10-03 03:06:01 +02:00
|
|
|
FOR_ALL_INTERFACES(vrf, ifp) {
|
2017-05-13 20:59:41 +02:00
|
|
|
/* ifp->ifindex is not necessarily valid at this point */
|
|
|
|
int ifindex = if_nametoindex(ifp->name);
|
|
|
|
if(ifindex > 0) {
|
|
|
|
unsigned char eui[8];
|
2017-12-05 01:29:42 +01:00
|
|
|
rc = if_eui64(ifindex, eui);
|
2017-05-13 20:59:41 +02:00
|
|
|
if(rc < 0)
|
|
|
|
continue;
|
|
|
|
memcpy(myid, eui, 8);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We failed to get a global EUI64 from the interfaces we were given.
|
|
|
|
Let's try to find an interface with a MAC address. */
|
|
|
|
for(i = 1; i < 256; i++) {
|
2023-11-21 14:08:29 +01:00
|
|
|
char buf[IFNAMSIZ], *ifname;
|
2017-05-13 20:59:41 +02:00
|
|
|
unsigned char eui[8];
|
|
|
|
ifname = if_indextoname(i, buf);
|
|
|
|
if(ifname == NULL)
|
|
|
|
continue;
|
2017-12-05 01:29:42 +01:00
|
|
|
rc = if_eui64(i, eui);
|
2017-05-13 20:59:41 +02:00
|
|
|
if(rc < 0)
|
|
|
|
continue;
|
|
|
|
memcpy(myid, eui, 8);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-10 16:09:38 +01:00
|
|
|
flog_err(EC_BABEL_CONFIG, "Couldn't find router id -- using random value.");
|
2017-05-13 20:59:41 +02:00
|
|
|
|
|
|
|
rc = read_random_bytes(myid, 8);
|
|
|
|
if(rc < 0) {
|
2018-09-13 21:01:19 +02:00
|
|
|
flog_err(EC_BABEL_CONFIG, "read(random): %s (cannot assign an ID)",
|
2018-06-18 20:08:34 +02:00
|
|
|
safe_strerror(errno));
|
2017-05-13 20:59:41 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
/* Clear group and global bits */
|
2023-02-14 11:29:29 +01:00
|
|
|
UNSET_FLAG (myid[0], 3);
|
2017-05-13 20:59:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Make some noise so that others notice us, and send retractions in
|
|
|
|
case we were restarted recently */
|
|
|
|
static void
|
|
|
|
babel_initial_noise(void)
|
|
|
|
{
|
2017-10-03 03:06:01 +02:00
|
|
|
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
2017-05-13 20:59:41 +02:00
|
|
|
struct interface *ifp = NULL;
|
|
|
|
|
2017-10-03 03:06:01 +02:00
|
|
|
FOR_ALL_INTERFACES(vrf, ifp) {
|
2017-05-13 20:59:41 +02:00
|
|
|
if(!if_up(ifp))
|
|
|
|
continue;
|
|
|
|
/* Apply jitter before we send the first message. */
|
|
|
|
usleep(roughly(10000));
|
|
|
|
gettime(&babel_now);
|
|
|
|
send_hello(ifp);
|
|
|
|
send_wildcard_retraction(ifp);
|
|
|
|
}
|
|
|
|
|
2017-10-03 03:06:01 +02:00
|
|
|
FOR_ALL_INTERFACES(vrf, ifp) {
|
2017-05-13 20:59:41 +02:00
|
|
|
if(!if_up(ifp))
|
|
|
|
continue;
|
|
|
|
usleep(roughly(10000));
|
|
|
|
gettime(&babel_now);
|
|
|
|
send_hello(ifp);
|
|
|
|
send_wildcard_retraction(ifp);
|
|
|
|
send_self_update(ifp);
|
|
|
|
send_request(ifp, NULL, 0);
|
|
|
|
flushupdates(ifp);
|
|
|
|
flushbuf(ifp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Delete all the added babel routes, make babeld only speak to zebra. */
|
2024-08-13 20:12:05 +02:00
|
|
|
void babel_clean_routing_process(void)
|
2017-05-13 20:59:41 +02:00
|
|
|
{
|
|
|
|
flush_all_routes();
|
|
|
|
babel_interface_close_all();
|
|
|
|
|
2024-12-20 08:43:30 +01:00
|
|
|
/* Clean babel config */
|
|
|
|
diversity_kind = DIVERSITY_NONE;
|
|
|
|
diversity_factor = BABEL_DEFAULT_DIVERSITY_FACTOR;
|
|
|
|
resend_delay = BABEL_DEFAULT_RESEND_DELAY;
|
|
|
|
change_smoothing_half_life(BABEL_DEFAULT_SMOOTHING_HALF_LIFE);
|
|
|
|
|
2020-07-06 18:55:03 +02:00
|
|
|
/* cancel events */
|
2022-12-10 15:08:37 +01:00
|
|
|
event_cancel(&babel_routing_process->t_read);
|
|
|
|
event_cancel(&babel_routing_process->t_update);
|
2017-05-13 20:59:41 +02:00
|
|
|
|
lib, rip, ripng, babel, eigrp: add ctx pointer to distribute api
a distribute_ctx context pointer is returned after initialisation to the
calling daemon. this context pointer will be further used to do
discussion with distribute service. Today, there is no specific problem
with old api, since the pointer is the same in all the memory process.
but the pointer will be different if we have multiple instances. Right
now, this is not the case, but if that happens, that work will be used
for that.
distribute-list initialisation is split in two. the vty initialisation
is done at global level, while the context initialisation is done for
each routing daemon instance.
babel daemon is being equipped with a routing returning the main babel
instance.
also, a delete routine is available when the daemon routing instance is
suppressed.
a list of contexts is used inside distribute_list. This will permit
distribute_list utility to handle in the same daemon to handle more than
one context. This will be very useful in the vrf context.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-12-04 15:45:57 +01:00
|
|
|
distribute_list_delete(&babel_routing_process->distribute_ctx);
|
2017-05-13 20:59:41 +02:00
|
|
|
XFREE(MTYPE_BABEL, babel_routing_process);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Function used with timeout. */
|
2022-03-01 22:18:12 +01:00
|
|
|
static void babel_main_loop(struct event *thread)
|
2017-05-13 20:59:41 +02:00
|
|
|
{
|
|
|
|
struct timeval tv;
|
2017-10-03 03:06:01 +02:00
|
|
|
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
2017-05-13 20:59:41 +02:00
|
|
|
struct interface *ifp = NULL;
|
|
|
|
|
|
|
|
while(1) {
|
|
|
|
gettime(&babel_now);
|
|
|
|
|
|
|
|
/* timeouts --------------------------------------------------------- */
|
|
|
|
/* get the next timeout */
|
|
|
|
babel_fill_with_next_timeout(&tv);
|
|
|
|
/* if there is no timeout, we must wait. */
|
|
|
|
if(timeval_compare(&tv, &babel_now) > 0) {
|
|
|
|
timeval_minus(&tv, &tv, &babel_now);
|
2017-08-26 01:14:25 +02:00
|
|
|
debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %lld msecs",
|
|
|
|
(long long)tv.tv_sec * 1000 + tv.tv_usec / 1000);
|
2017-05-13 20:59:41 +02:00
|
|
|
/* it happens often to have less than 1 ms, it's bad. */
|
|
|
|
timeval_add_msec(&tv, &tv, 300);
|
|
|
|
babel_set_timer(&tv);
|
2022-02-23 01:04:25 +01:00
|
|
|
return;
|
|
|
|
}
|
2017-05-13 20:59:41 +02:00
|
|
|
|
|
|
|
gettime(&babel_now);
|
|
|
|
|
|
|
|
/* update database -------------------------------------------------- */
|
|
|
|
if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) {
|
|
|
|
int msecs;
|
|
|
|
msecs = check_neighbours();
|
|
|
|
/* Multiply by 3/2 to allow neighbours to expire. */
|
|
|
|
msecs = MAX(3 * msecs / 2, 10);
|
|
|
|
schedule_neighbours_check(msecs, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(babel_now.tv_sec >= expiry_time) {
|
|
|
|
expire_routes();
|
|
|
|
expire_resend();
|
|
|
|
expiry_time = babel_now.tv_sec + roughly(30);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(babel_now.tv_sec >= source_expiry_time) {
|
|
|
|
expire_sources();
|
|
|
|
source_expiry_time = babel_now.tv_sec + roughly(300);
|
|
|
|
}
|
|
|
|
|
2017-10-03 03:06:01 +02:00
|
|
|
FOR_ALL_INTERFACES(vrf, ifp) {
|
2017-05-13 20:59:41 +02:00
|
|
|
babel_interface_nfo *babel_ifp = NULL;
|
|
|
|
if(!if_up(ifp))
|
|
|
|
continue;
|
|
|
|
babel_ifp = babel_get_if_nfo(ifp);
|
|
|
|
if(timeval_compare(&babel_now, &babel_ifp->hello_timeout) >= 0)
|
|
|
|
send_hello(ifp);
|
|
|
|
if(timeval_compare(&babel_now, &babel_ifp->update_timeout) >= 0)
|
|
|
|
send_update(ifp, 0, NULL, 0);
|
|
|
|
if(timeval_compare(&babel_now,
|
|
|
|
&babel_ifp->update_flush_timeout) >= 0)
|
|
|
|
flushupdates(ifp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(resend_time.tv_sec != 0) {
|
|
|
|
if(timeval_compare(&babel_now, &resend_time) >= 0)
|
|
|
|
do_resend();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(unicast_flush_timeout.tv_sec != 0) {
|
|
|
|
if(timeval_compare(&babel_now, &unicast_flush_timeout) >= 0)
|
|
|
|
flush_unicast(1);
|
|
|
|
}
|
|
|
|
|
2017-10-03 03:06:01 +02:00
|
|
|
FOR_ALL_INTERFACES(vrf, ifp) {
|
2017-05-13 20:59:41 +02:00
|
|
|
babel_interface_nfo *babel_ifp = NULL;
|
|
|
|
if(!if_up(ifp))
|
|
|
|
continue;
|
|
|
|
babel_ifp = babel_get_if_nfo(ifp);
|
|
|
|
if(babel_ifp->flush_timeout.tv_sec != 0) {
|
|
|
|
if(timeval_compare(&babel_now, &babel_ifp->flush_timeout) >= 0)
|
|
|
|
flushbuf(ifp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(0); /* this line should never be reach */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname)
|
|
|
|
{
|
|
|
|
static struct timeval curr_tv;
|
|
|
|
static char buffer[200];
|
|
|
|
static const char *curr_tag = NULL;
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case 0: /* reset timeval */
|
|
|
|
curr_tv = *tv;
|
|
|
|
if(ifname != NULL) {
|
|
|
|
snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
|
|
|
|
curr_tag = buffer;
|
|
|
|
} else {
|
|
|
|
curr_tag = tag;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1: /* take the min */
|
|
|
|
if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec &&
|
|
|
|
tv->tv_usec < curr_tv.tv_usec)) {
|
|
|
|
curr_tv = *tv;
|
|
|
|
if(ifname != NULL) {
|
|
|
|
snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
|
|
|
|
curr_tag = buffer;
|
|
|
|
} else {
|
|
|
|
curr_tag = tag;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2: /* print message */
|
|
|
|
debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
babel_fill_with_next_timeout(struct timeval *tv)
|
|
|
|
{
|
|
|
|
#if (defined NO_DEBUG)
|
|
|
|
#define printIfMin(a,b,c,d)
|
|
|
|
#else
|
2024-09-06 03:32:51 +02:00
|
|
|
#define printIfMin(a, b, c, d) \
|
|
|
|
if (unlikely(CHECK_FLAG(debug, BABEL_DEBUG_TIMEOUT))) { \
|
2023-02-17 20:56:48 +01:00
|
|
|
printIfMin(a, b, c, d); \
|
|
|
|
}
|
2017-05-13 20:59:41 +02:00
|
|
|
|
2023-02-17 20:56:48 +01:00
|
|
|
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
|
|
|
struct interface *ifp = NULL;
|
|
|
|
|
|
|
|
*tv = check_neighbours_timeout;
|
|
|
|
printIfMin(tv, 0, "check_neighbours_timeout", NULL);
|
|
|
|
timeval_min_sec(tv, expiry_time);
|
|
|
|
printIfMin(tv, 1, "expiry_time", NULL);
|
|
|
|
timeval_min_sec(tv, source_expiry_time);
|
|
|
|
printIfMin(tv, 1, "source_expiry_time", NULL);
|
|
|
|
timeval_min(tv, &resend_time);
|
|
|
|
printIfMin(tv, 1, "resend_time", NULL);
|
|
|
|
FOR_ALL_INTERFACES (vrf, ifp) {
|
|
|
|
babel_interface_nfo *babel_ifp = NULL;
|
|
|
|
if (!if_up(ifp))
|
|
|
|
continue;
|
|
|
|
babel_ifp = babel_get_if_nfo(ifp);
|
|
|
|
timeval_min(tv, &babel_ifp->flush_timeout);
|
|
|
|
printIfMin(tv, 1, "flush_timeout", ifp->name);
|
|
|
|
timeval_min(tv, &babel_ifp->hello_timeout);
|
|
|
|
printIfMin(tv, 1, "hello_timeout", ifp->name);
|
|
|
|
timeval_min(tv, &babel_ifp->update_timeout);
|
|
|
|
printIfMin(tv, 1, "update_timeout", ifp->name);
|
|
|
|
timeval_min(tv, &babel_ifp->update_flush_timeout);
|
|
|
|
printIfMin(tv, 1, "update_flush_timeout", ifp->name);
|
|
|
|
}
|
|
|
|
timeval_min(tv, &unicast_flush_timeout);
|
|
|
|
printIfMin(tv, 1, "unicast_flush_timeout", NULL);
|
|
|
|
printIfMin(tv, 2, NULL, NULL);
|
2017-05-13 20:59:41 +02:00
|
|
|
#undef printIfMin
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set the t_update thread of the babel routing process to be launch in
|
|
|
|
'timeout' (approximate at the milisecond) */
|
|
|
|
static void
|
|
|
|
babel_set_timer(struct timeval *timeout)
|
|
|
|
{
|
|
|
|
long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
|
2022-12-10 15:08:37 +01:00
|
|
|
event_cancel(&(babel_routing_process->t_update));
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_timer_msec(master, babel_main_loop, NULL, msecs,
|
|
|
|
&babel_routing_process->t_update);
|
2017-05-13 20:59:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
schedule_neighbours_check(int msecs, int override)
|
|
|
|
{
|
|
|
|
struct timeval timeout;
|
|
|
|
|
|
|
|
timeval_add_msec(&timeout, &babel_now, msecs);
|
|
|
|
if(override)
|
|
|
|
check_neighbours_timeout = timeout;
|
|
|
|
else
|
|
|
|
timeval_min(&check_neighbours_timeout, &timeout);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
resize_receive_buffer(int size)
|
|
|
|
{
|
|
|
|
if(size <= receive_buffer_size)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if(receive_buffer == NULL) {
|
|
|
|
receive_buffer = malloc(size);
|
|
|
|
if(receive_buffer == NULL) {
|
2018-09-13 21:01:19 +02:00
|
|
|
flog_err(EC_BABEL_MEMORY, "malloc(receive_buffer): %s",
|
2018-06-18 19:38:21 +02:00
|
|
|
safe_strerror(errno));
|
2017-05-13 20:59:41 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
receive_buffer_size = size;
|
|
|
|
} else {
|
|
|
|
unsigned char *new;
|
|
|
|
new = realloc(receive_buffer, size);
|
|
|
|
if(new == NULL) {
|
2018-09-13 21:01:19 +02:00
|
|
|
flog_err(EC_BABEL_MEMORY, "realloc(receive_buffer): %s",
|
2018-06-18 19:38:21 +02:00
|
|
|
safe_strerror(errno));
|
2017-05-13 20:59:41 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
receive_buffer = new;
|
|
|
|
receive_buffer_size = size;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2025-02-10 07:13:05 +01:00
|
|
|
babel_distribute_update (struct distribute_ctx *ctx __attribute__((__unused__)), struct distribute *dist)
|
2017-05-13 20:59:41 +02:00
|
|
|
{
|
|
|
|
struct interface *ifp;
|
|
|
|
babel_interface_nfo *babel_ifp;
|
|
|
|
int type;
|
|
|
|
int family;
|
|
|
|
|
|
|
|
if (! dist->ifname)
|
|
|
|
return;
|
|
|
|
|
2019-06-24 01:46:39 +02:00
|
|
|
ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT);
|
2017-05-13 20:59:41 +02:00
|
|
|
if (ifp == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
babel_ifp = babel_get_if_nfo(ifp);
|
|
|
|
|
|
|
|
for (type = 0; type < DISTRIBUTE_MAX; type++) {
|
|
|
|
family = type == DISTRIBUTE_V4_IN || type == DISTRIBUTE_V4_OUT ?
|
|
|
|
AFI_IP : AFI_IP6;
|
|
|
|
if (dist->list[type])
|
|
|
|
babel_ifp->list[type] = access_list_lookup (family,
|
|
|
|
dist->list[type]);
|
|
|
|
else
|
|
|
|
babel_ifp->list[type] = NULL;
|
|
|
|
if (dist->prefix[type])
|
|
|
|
babel_ifp->prefix[type] = prefix_list_lookup (family,
|
|
|
|
dist->prefix[type]);
|
|
|
|
else
|
|
|
|
babel_ifp->prefix[type] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
babel_distribute_update_interface (struct interface *ifp)
|
|
|
|
{
|
lib, rip, ripng, babel, eigrp: add ctx pointer to distribute api
a distribute_ctx context pointer is returned after initialisation to the
calling daemon. this context pointer will be further used to do
discussion with distribute service. Today, there is no specific problem
with old api, since the pointer is the same in all the memory process.
but the pointer will be different if we have multiple instances. Right
now, this is not the case, but if that happens, that work will be used
for that.
distribute-list initialisation is split in two. the vty initialisation
is done at global level, while the context initialisation is done for
each routing daemon instance.
babel daemon is being equipped with a routing returning the main babel
instance.
also, a delete routine is available when the daemon routing instance is
suppressed.
a list of contexts is used inside distribute_list. This will permit
distribute_list utility to handle in the same daemon to handle more than
one context. This will be very useful in the vrf context.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-12-04 15:45:57 +01:00
|
|
|
struct distribute *dist = NULL;
|
2017-05-13 20:59:41 +02:00
|
|
|
|
lib, rip, ripng, babel, eigrp: add ctx pointer to distribute api
a distribute_ctx context pointer is returned after initialisation to the
calling daemon. this context pointer will be further used to do
discussion with distribute service. Today, there is no specific problem
with old api, since the pointer is the same in all the memory process.
but the pointer will be different if we have multiple instances. Right
now, this is not the case, but if that happens, that work will be used
for that.
distribute-list initialisation is split in two. the vty initialisation
is done at global level, while the context initialisation is done for
each routing daemon instance.
babel daemon is being equipped with a routing returning the main babel
instance.
also, a delete routine is available when the daemon routing instance is
suppressed.
a list of contexts is used inside distribute_list. This will permit
distribute_list utility to handle in the same daemon to handle more than
one context. This will be very useful in the vrf context.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-12-04 15:45:57 +01:00
|
|
|
if (babel_routing_process)
|
|
|
|
dist = distribute_lookup(babel_routing_process->distribute_ctx, ifp->name);
|
2017-05-13 20:59:41 +02:00
|
|
|
if (dist)
|
lib, rip, ripng, babel, eigrp: add ctx pointer to distribute api
a distribute_ctx context pointer is returned after initialisation to the
calling daemon. this context pointer will be further used to do
discussion with distribute service. Today, there is no specific problem
with old api, since the pointer is the same in all the memory process.
but the pointer will be different if we have multiple instances. Right
now, this is not the case, but if that happens, that work will be used
for that.
distribute-list initialisation is split in two. the vty initialisation
is done at global level, while the context initialisation is done for
each routing daemon instance.
babel daemon is being equipped with a routing returning the main babel
instance.
also, a delete routine is available when the daemon routing instance is
suppressed.
a list of contexts is used inside distribute_list. This will permit
distribute_list utility to handle in the same daemon to handle more than
one context. This will be very useful in the vrf context.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-12-04 15:45:57 +01:00
|
|
|
babel_distribute_update (babel_routing_process->distribute_ctx, dist);
|
2017-05-13 20:59:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Update all interface's distribute list. */
|
|
|
|
static void
|
|
|
|
babel_distribute_update_all (struct prefix_list *notused)
|
|
|
|
{
|
2017-10-03 03:06:01 +02:00
|
|
|
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
2017-05-13 20:59:41 +02:00
|
|
|
struct interface *ifp;
|
|
|
|
|
2017-10-06 20:25:58 +02:00
|
|
|
FOR_ALL_INTERFACES (vrf, ifp)
|
2017-05-13 20:59:41 +02:00
|
|
|
babel_distribute_update_interface (ifp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2025-02-10 07:13:05 +01:00
|
|
|
babel_distribute_update_all_wrapper (struct access_list *notused __attribute__((__unused__)))
|
2017-05-13 20:59:41 +02:00
|
|
|
{
|
|
|
|
babel_distribute_update_all(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* [Command] */
|
2017-05-14 05:36:52 +02:00
|
|
|
DEFUN_NOSH (router_babel,
|
|
|
|
router_babel_cmd,
|
|
|
|
"router babel",
|
|
|
|
"Enable a routing process\n"
|
|
|
|
"Make Babel instance command\n")
|
2017-05-13 20:59:41 +02:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
vty->node = BABEL_NODE;
|
|
|
|
|
|
|
|
if (!babel_routing_process) {
|
|
|
|
ret = babel_create_routing_process ();
|
|
|
|
|
|
|
|
/* Notice to user we couldn't create Babel. */
|
|
|
|
if (ret < 0) {
|
|
|
|
zlog_warn ("can't create Babel");
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* [Command] */
|
|
|
|
DEFUN (no_router_babel,
|
|
|
|
no_router_babel_cmd,
|
|
|
|
"no router babel",
|
|
|
|
NO_STR
|
|
|
|
"Disable a routing process\n"
|
2017-07-05 20:30:36 +02:00
|
|
|
"Remove Babel instance command\n")
|
2017-05-13 20:59:41 +02:00
|
|
|
{
|
|
|
|
if(babel_routing_process)
|
|
|
|
babel_clean_routing_process();
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* [Babel Command] */
|
|
|
|
DEFUN (babel_diversity,
|
|
|
|
babel_diversity_cmd,
|
|
|
|
"babel diversity",
|
|
|
|
"Babel commands\n"
|
|
|
|
"Enable diversity-aware routing.\n")
|
|
|
|
{
|
|
|
|
diversity_kind = DIVERSITY_CHANNEL;
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* [Babel Command] */
|
|
|
|
DEFUN (no_babel_diversity,
|
|
|
|
no_babel_diversity_cmd,
|
|
|
|
"no babel diversity",
|
|
|
|
NO_STR
|
|
|
|
"Babel commands\n"
|
|
|
|
"Disable diversity-aware routing.\n")
|
|
|
|
{
|
|
|
|
diversity_kind = DIVERSITY_NONE;
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* [Babel Command] */
|
2023-01-14 13:02:41 +01:00
|
|
|
DEFPY (babel_diversity_factor,
|
2017-05-13 20:59:41 +02:00
|
|
|
babel_diversity_factor_cmd,
|
2023-01-14 13:02:41 +01:00
|
|
|
"[no] babel diversity-factor (1-256)$factor",
|
|
|
|
NO_STR
|
2017-05-13 20:59:41 +02:00
|
|
|
"Babel commands\n"
|
|
|
|
"Set the diversity factor.\n"
|
|
|
|
"Factor in units of 1/256.\n")
|
|
|
|
{
|
2023-01-14 13:02:41 +01:00
|
|
|
diversity_factor = no ? BABEL_DEFAULT_DIVERSITY_FACTOR : factor;
|
2017-05-13 20:59:41 +02:00
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* [Babel Command] */
|
2023-01-14 13:02:41 +01:00
|
|
|
DEFPY (babel_set_resend_delay,
|
2017-05-13 20:59:41 +02:00
|
|
|
babel_set_resend_delay_cmd,
|
2023-01-14 13:02:41 +01:00
|
|
|
"[no] babel resend-delay (20-655340)$delay",
|
|
|
|
NO_STR
|
2017-05-13 20:59:41 +02:00
|
|
|
"Babel commands\n"
|
|
|
|
"Time before resending a message\n"
|
|
|
|
"Milliseconds\n")
|
|
|
|
{
|
2023-01-14 13:02:41 +01:00
|
|
|
resend_delay = no ? BABEL_DEFAULT_RESEND_DELAY : delay;
|
2017-05-13 20:59:41 +02:00
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* [Babel Command] */
|
2023-01-14 13:02:41 +01:00
|
|
|
DEFPY (babel_set_smoothing_half_life,
|
2017-05-13 20:59:41 +02:00
|
|
|
babel_set_smoothing_half_life_cmd,
|
2023-01-14 13:02:41 +01:00
|
|
|
"[no] babel smoothing-half-life (0-65534)$seconds",
|
|
|
|
NO_STR
|
2017-05-13 20:59:41 +02:00
|
|
|
"Babel commands\n"
|
|
|
|
"Smoothing half-life\n"
|
|
|
|
"Seconds (0 to disable)\n")
|
|
|
|
{
|
2023-01-14 13:02:41 +01:00
|
|
|
change_smoothing_half_life(no ? BABEL_DEFAULT_SMOOTHING_HALF_LIFE
|
|
|
|
: seconds);
|
2017-05-13 20:59:41 +02:00
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2021-02-08 17:44:41 +01:00
|
|
|
DEFUN (babel_distribute_list,
|
|
|
|
babel_distribute_list_cmd,
|
2024-01-22 22:21:02 +01:00
|
|
|
"distribute-list ACCESSLIST4_NAME <in|out> [WORD]",
|
2021-02-08 17:44:41 +01:00
|
|
|
"Filter networks in routing updates\n"
|
|
|
|
"Access-list name\n"
|
|
|
|
"Filter incoming routing updates\n"
|
|
|
|
"Filter outgoing routing updates\n"
|
|
|
|
"Interface name\n")
|
|
|
|
{
|
|
|
|
const char *ifname = NULL;
|
|
|
|
int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0;
|
|
|
|
|
|
|
|
if (argv[argc - 1]->type == VARIABLE_TKN)
|
|
|
|
ifname = argv[argc - 1]->arg;
|
|
|
|
|
2024-01-22 22:00:18 +01:00
|
|
|
return distribute_list_parser(babel_routing_process->distribute_ctx,
|
|
|
|
prefix, true, argv[2 + prefix]->text,
|
2021-02-08 17:44:41 +01:00
|
|
|
argv[1 + prefix]->arg, ifname);
|
|
|
|
}
|
|
|
|
|
2024-01-22 22:21:02 +01:00
|
|
|
ALIAS (babel_distribute_list,
|
|
|
|
babel_distribute_list_prefix_cmd,
|
|
|
|
"distribute-list prefix PREFIXLIST4_NAME <in|out> [WORD]",
|
|
|
|
"Filter networks in routing updates\n"
|
|
|
|
"Specify a prefix list\n"
|
|
|
|
"Prefix-list name\n"
|
|
|
|
"Filter incoming routing updates\n"
|
|
|
|
"Filter outgoing routing updates\n"
|
|
|
|
"Interface name\n")
|
|
|
|
|
2021-02-08 17:44:41 +01:00
|
|
|
DEFUN (babel_no_distribute_list,
|
|
|
|
babel_no_distribute_list_cmd,
|
2024-01-22 22:21:02 +01:00
|
|
|
"no distribute-list ACCESSLIST4_NAME <in|out> [WORD]",
|
2021-02-08 17:44:41 +01:00
|
|
|
NO_STR
|
|
|
|
"Filter networks in routing updates\n"
|
|
|
|
"Access-list name\n"
|
|
|
|
"Filter incoming routing updates\n"
|
|
|
|
"Filter outgoing routing updates\n"
|
|
|
|
"Interface name\n")
|
|
|
|
{
|
|
|
|
const char *ifname = NULL;
|
|
|
|
int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
|
|
|
|
|
|
|
|
if (argv[argc - 1]->type == VARIABLE_TKN)
|
|
|
|
ifname = argv[argc - 1]->arg;
|
|
|
|
|
2024-01-22 22:00:18 +01:00
|
|
|
return distribute_list_no_parser(babel_routing_process->distribute_ctx,
|
|
|
|
vty, prefix, true,
|
2021-02-08 17:44:41 +01:00
|
|
|
argv[3 + prefix]->text,
|
|
|
|
argv[2 + prefix]->arg, ifname);
|
|
|
|
}
|
|
|
|
|
2024-01-22 22:21:02 +01:00
|
|
|
ALIAS (babel_no_distribute_list,
|
|
|
|
babel_no_distribute_list_prefix_cmd,
|
|
|
|
"no distribute-list prefix PREFIXLIST4_NAME <in|out> [WORD]",
|
|
|
|
NO_STR
|
|
|
|
"Filter networks in routing updates\n"
|
|
|
|
"Specify a prefix list\n"
|
|
|
|
"Prefix-list name\n"
|
|
|
|
"Filter incoming routing updates\n"
|
|
|
|
"Filter outgoing routing updates\n"
|
|
|
|
"Interface name\n")
|
|
|
|
|
2021-02-08 17:44:41 +01:00
|
|
|
DEFUN (babel_ipv6_distribute_list,
|
|
|
|
babel_ipv6_distribute_list_cmd,
|
2024-01-22 22:21:02 +01:00
|
|
|
"ipv6 distribute-list ACCESSLIST6_NAME <in|out> [WORD]",
|
2021-02-08 17:44:41 +01:00
|
|
|
"IPv6\n"
|
|
|
|
"Filter networks in routing updates\n"
|
|
|
|
"Access-list name\n"
|
|
|
|
"Filter incoming routing updates\n"
|
|
|
|
"Filter outgoing routing updates\n"
|
|
|
|
"Interface name\n")
|
|
|
|
{
|
|
|
|
const char *ifname = NULL;
|
|
|
|
int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
|
|
|
|
|
|
|
|
if (argv[argc - 1]->type == VARIABLE_TKN)
|
|
|
|
ifname = argv[argc - 1]->arg;
|
|
|
|
|
2024-01-22 22:00:18 +01:00
|
|
|
return distribute_list_parser(babel_routing_process->distribute_ctx,
|
|
|
|
prefix, false, argv[3 + prefix]->text,
|
2021-02-08 17:44:41 +01:00
|
|
|
argv[2 + prefix]->arg, ifname);
|
|
|
|
}
|
|
|
|
|
2024-01-22 22:21:02 +01:00
|
|
|
ALIAS (babel_ipv6_distribute_list,
|
|
|
|
babel_ipv6_distribute_list_prefix_cmd,
|
|
|
|
"ipv6 distribute-list prefix PREFIXLIST6_NAME <in|out> [WORD]",
|
|
|
|
"IPv6\n"
|
|
|
|
"Filter networks in routing updates\n"
|
|
|
|
"Specify a prefix list\n"
|
|
|
|
"Prefix-list name\n"
|
|
|
|
"Filter incoming routing updates\n"
|
|
|
|
"Filter outgoing routing updates\n"
|
|
|
|
"Interface name\n")
|
|
|
|
|
2021-02-08 17:44:41 +01:00
|
|
|
DEFUN (babel_no_ipv6_distribute_list,
|
|
|
|
babel_no_ipv6_distribute_list_cmd,
|
2024-01-22 22:21:02 +01:00
|
|
|
"no ipv6 distribute-list ACCESSLIST6_NAME <in|out> [WORD]",
|
2021-02-08 17:44:41 +01:00
|
|
|
NO_STR
|
|
|
|
"IPv6\n"
|
|
|
|
"Filter networks in routing updates\n"
|
|
|
|
"Access-list name\n"
|
|
|
|
"Filter incoming routing updates\n"
|
|
|
|
"Filter outgoing routing updates\n"
|
|
|
|
"Interface name\n")
|
|
|
|
{
|
|
|
|
const char *ifname = NULL;
|
|
|
|
int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0;
|
|
|
|
|
|
|
|
if (argv[argc - 1]->type == VARIABLE_TKN)
|
|
|
|
ifname = argv[argc - 1]->arg;
|
|
|
|
|
2024-01-22 22:00:18 +01:00
|
|
|
return distribute_list_no_parser(babel_routing_process->distribute_ctx,
|
|
|
|
vty, prefix, false,
|
2021-02-08 17:44:41 +01:00
|
|
|
argv[4 + prefix]->text,
|
|
|
|
argv[3 + prefix]->arg, ifname);
|
|
|
|
}
|
|
|
|
|
2024-01-22 22:21:02 +01:00
|
|
|
ALIAS (babel_no_ipv6_distribute_list,
|
|
|
|
babel_no_ipv6_distribute_list_prefix_cmd,
|
|
|
|
"no ipv6 distribute-list prefix PREFIXLIST6_NAME <in|out> [WORD]",
|
|
|
|
NO_STR
|
|
|
|
"IPv6\n"
|
|
|
|
"Filter networks in routing updates\n"
|
|
|
|
"Specify a prefix list\n"
|
|
|
|
"Prefix-list name\n"
|
|
|
|
"Filter incoming routing updates\n"
|
|
|
|
"Filter outgoing routing updates\n"
|
|
|
|
"Interface name\n")
|
|
|
|
|
2017-05-13 20:59:41 +02:00
|
|
|
void
|
|
|
|
babeld_quagga_init(void)
|
|
|
|
{
|
|
|
|
|
2018-09-08 22:31:43 +02:00
|
|
|
install_node(&cmd_babel_node);
|
2017-05-13 20:59:41 +02:00
|
|
|
|
|
|
|
install_element(CONFIG_NODE, &router_babel_cmd);
|
|
|
|
install_element(CONFIG_NODE, &no_router_babel_cmd);
|
|
|
|
|
|
|
|
install_default(BABEL_NODE);
|
|
|
|
install_element(BABEL_NODE, &babel_diversity_cmd);
|
|
|
|
install_element(BABEL_NODE, &no_babel_diversity_cmd);
|
|
|
|
install_element(BABEL_NODE, &babel_diversity_factor_cmd);
|
|
|
|
install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
|
|
|
|
install_element(BABEL_NODE, &babel_set_smoothing_half_life_cmd);
|
|
|
|
|
2021-02-08 17:44:41 +01:00
|
|
|
install_element(BABEL_NODE, &babel_distribute_list_cmd);
|
2024-01-22 22:21:02 +01:00
|
|
|
install_element(BABEL_NODE, &babel_distribute_list_prefix_cmd);
|
2021-02-08 17:44:41 +01:00
|
|
|
install_element(BABEL_NODE, &babel_no_distribute_list_cmd);
|
2024-01-22 22:21:02 +01:00
|
|
|
install_element(BABEL_NODE, &babel_no_distribute_list_prefix_cmd);
|
2021-02-08 17:44:41 +01:00
|
|
|
install_element(BABEL_NODE, &babel_ipv6_distribute_list_cmd);
|
2024-01-22 22:21:02 +01:00
|
|
|
install_element(BABEL_NODE, &babel_ipv6_distribute_list_prefix_cmd);
|
2021-02-08 17:44:41 +01:00
|
|
|
install_element(BABEL_NODE, &babel_no_ipv6_distribute_list_cmd);
|
2024-01-22 22:21:02 +01:00
|
|
|
install_element(BABEL_NODE, &babel_no_ipv6_distribute_list_prefix_cmd);
|
2021-02-08 17:44:41 +01:00
|
|
|
|
2021-08-25 18:29:42 +02:00
|
|
|
vrf_cmd_init(NULL);
|
2021-06-21 17:04:46 +02:00
|
|
|
|
2017-05-13 20:59:41 +02:00
|
|
|
babel_if_init();
|
|
|
|
|
|
|
|
/* Access list install. */
|
|
|
|
access_list_init ();
|
|
|
|
access_list_add_hook (babel_distribute_update_all_wrapper);
|
|
|
|
access_list_delete_hook (babel_distribute_update_all_wrapper);
|
|
|
|
|
|
|
|
/* Prefix list initialize.*/
|
|
|
|
prefix_list_init ();
|
|
|
|
prefix_list_add_hook (babel_distribute_update_all);
|
|
|
|
prefix_list_delete_hook (babel_distribute_update_all);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
|
|
|
|
|
|
|
|
int
|
2025-02-10 07:13:05 +01:00
|
|
|
input_filter(const unsigned char *id __attribute__((__unused__)),
|
2017-05-13 20:59:41 +02:00
|
|
|
const unsigned char *prefix, unsigned short plen,
|
2025-02-10 07:13:05 +01:00
|
|
|
const unsigned char *neigh __attribute__((__unused__)),
|
|
|
|
unsigned int ifindex)
|
2017-05-13 20:59:41 +02:00
|
|
|
{
|
|
|
|
return babel_filter(0, prefix, plen, ifindex);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2025-02-10 07:13:05 +01:00
|
|
|
output_filter(const unsigned char *id __attribute__((__unused__)),
|
|
|
|
const unsigned char *prefix, unsigned short plen,
|
|
|
|
unsigned int ifindex)
|
2017-05-13 20:59:41 +02:00
|
|
|
{
|
|
|
|
return babel_filter(1, prefix, plen, ifindex);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* There's no redistribute filter in Quagga -- the zebra daemon does its
|
|
|
|
own filtering. */
|
|
|
|
int
|
|
|
|
redistribute_filter(const unsigned char *prefix, unsigned short plen,
|
|
|
|
unsigned int ifindex, int proto)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
lib, rip, ripng, babel, eigrp: add ctx pointer to distribute api
a distribute_ctx context pointer is returned after initialisation to the
calling daemon. this context pointer will be further used to do
discussion with distribute service. Today, there is no specific problem
with old api, since the pointer is the same in all the memory process.
but the pointer will be different if we have multiple instances. Right
now, this is not the case, but if that happens, that work will be used
for that.
distribute-list initialisation is split in two. the vty initialisation
is done at global level, while the context initialisation is done for
each routing daemon instance.
babel daemon is being equipped with a routing returning the main babel
instance.
also, a delete routine is available when the daemon routing instance is
suppressed.
a list of contexts is used inside distribute_list. This will permit
distribute_list utility to handle in the same daemon to handle more than
one context. This will be very useful in the vrf context.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-12-04 15:45:57 +01:00
|
|
|
struct babel *babel_lookup(void)
|
|
|
|
{
|
|
|
|
return babel_routing_process;
|
|
|
|
}
|