mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
RPKI: Add the basis for manager
This commit is contained in:
parent
a3cc5d7697
commit
27d7aae89f
@ -24,8 +24,22 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include "rpki.h"
|
||||
|
||||
static const char *mgr_str_status[] = {
|
||||
[RTR_MGR_CLOSED] = "RTR_MGR_CLOSED",
|
||||
[RTR_MGR_CONNECTING] = "RTR_MGR_CONNECTING",
|
||||
[RTR_MGR_ESTABLISHED] = "RTR_MGR_ESTABLISHED",
|
||||
[RTR_MGR_ERROR] = "RTR_MGR_ERROR",
|
||||
};
|
||||
|
||||
const char *
|
||||
get_group_status(struct rpki_cache_group *group)
|
||||
{
|
||||
return mgr_str_status[group->status];
|
||||
}
|
||||
|
||||
static struct proto *
|
||||
rpki_init(struct proto_config *C)
|
||||
{
|
||||
@ -44,6 +58,22 @@ get_cache_ident(struct rpki_cache *cache)
|
||||
return tr_ident(cache->rtr_socket->tr_socket);
|
||||
}
|
||||
|
||||
void
|
||||
debug_print_groups(struct rpki_proto *p)
|
||||
{
|
||||
struct rpki_cache_group *g;
|
||||
WALK_LIST(g, p->group_list)
|
||||
{
|
||||
DBG("Group(%u) %s \n", g->preference, get_group_status(g));
|
||||
|
||||
struct rpki_cache *c;
|
||||
WALK_LIST(c, g->cache_list)
|
||||
{
|
||||
DBG(" Cache(%s) %s \n", get_cache_ident(c), rtr_state_to_str(c->rtr_socket->state));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct rpki_cache_group *
|
||||
rpki_cache_group_alloc(struct rpki_proto *p, u8 preference)
|
||||
{
|
||||
@ -76,6 +106,7 @@ rpki_insert_cache_into_group(struct rpki_cache *cache)
|
||||
if (group_iter->preference == cache->cfg->preference)
|
||||
{
|
||||
add_tail(&group_iter->cache_list, &cache->n);
|
||||
cache->group = group_iter;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -83,6 +114,7 @@ rpki_insert_cache_into_group(struct rpki_cache *cache)
|
||||
{
|
||||
struct rpki_cache_group *new_group = rpki_new_cache_group_before(p, group_iter, &p->group_list, cache->cfg->preference);
|
||||
add_tail(&new_group->cache_list, &cache->n);
|
||||
cache->group = new_group;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -90,6 +122,7 @@ rpki_insert_cache_into_group(struct rpki_cache *cache)
|
||||
struct rpki_cache_group *new_group = rpki_cache_group_alloc(p, cache->cfg->preference);
|
||||
add_tail(&p->group_list, &new_group->n);
|
||||
add_tail(&new_group->cache_list, &cache->n);
|
||||
cache->group = new_group;
|
||||
}
|
||||
|
||||
struct rpki_cache_cfg *
|
||||
@ -227,8 +260,11 @@ rpki_open_connection(struct rpki_cache *cache)
|
||||
return TR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open connections to all caches in group
|
||||
*/
|
||||
static void
|
||||
rpki_open_group(struct rpki_proto *p, struct rpki_cache_group *group)
|
||||
rpki_open_group(struct rpki_cache_group *group)
|
||||
{
|
||||
struct rpki_cache *cache;
|
||||
WALK_LIST(cache, group->cache_list)
|
||||
@ -239,7 +275,7 @@ rpki_open_group(struct rpki_proto *p, struct rpki_cache_group *group)
|
||||
}
|
||||
|
||||
static void
|
||||
rpki_close_group(struct rpki_proto *p, struct rpki_cache_group *group)
|
||||
rpki_close_group(struct rpki_cache_group *group)
|
||||
{
|
||||
struct rpki_cache *cache;
|
||||
WALK_LIST(cache, group->cache_list)
|
||||
@ -347,11 +383,8 @@ find_cache_in_proto_by_host_and_port(struct rpki_proto *p, struct rpki_cache_cfg
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove empty cache groups in list
|
||||
*/
|
||||
static void
|
||||
rpki_relax_group_list(struct rpki_proto *p)
|
||||
remove_empty_cache_groups(struct rpki_proto *p)
|
||||
{
|
||||
struct rpki_cache_group *group, *group_nxt;
|
||||
WALK_LIST_DELSAFE(group, group_nxt, p->group_list)
|
||||
@ -369,32 +402,55 @@ move_cache_into_group(struct rpki_cache *cache)
|
||||
{
|
||||
rpki_remove_cache_from_group(cache);
|
||||
rpki_insert_cache_into_group(cache);
|
||||
rpki_relax_group_list(cache->p);
|
||||
remove_empty_cache_groups(cache->p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start connections to caches in the first (the highest priority) group
|
||||
* and shut down all connections to caches in others groups
|
||||
* Go through the group list ordered by priority.
|
||||
* Open the first CLOSED group or stop opening groups if the processed group state is CONNECTING or ESTABLISHED
|
||||
* Then close all groups with the more unimportant priority
|
||||
*/
|
||||
static int
|
||||
void
|
||||
rpki_relax_groups(struct rpki_proto *p)
|
||||
{
|
||||
RPKI_TRACE(D_EVENTS, p, "rpki_relax_groups START");
|
||||
debug_print_groups(p);
|
||||
|
||||
if (EMPTY_LIST(p->group_list))
|
||||
{
|
||||
RPKI_WARN(p, "No cache in configuration found");
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
bool close_all_next_groups = false;
|
||||
|
||||
struct rpki_cache_group *group;
|
||||
WALK_LIST(group, p->group_list)
|
||||
{
|
||||
if (group == (struct rpki_cache_group *) p->group_list.head)
|
||||
rpki_open_group(p, group);
|
||||
if (!close_all_next_groups)
|
||||
{
|
||||
switch (group->status)
|
||||
{
|
||||
case RTR_MGR_CLOSED:
|
||||
RPKI_TRACE(D_EVENTS, p, "rpki_relax_groups open group(%u)", group->preference);
|
||||
rpki_open_group(group);
|
||||
/* Fall through */
|
||||
case RTR_MGR_CONNECTING:
|
||||
case RTR_MGR_ESTABLISHED:
|
||||
close_all_next_groups = 1;
|
||||
break;
|
||||
|
||||
case RTR_MGR_ERROR:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
rpki_close_group(p, group);
|
||||
rpki_close_group(group);
|
||||
}
|
||||
|
||||
return 1;
|
||||
debug_print_groups(p);
|
||||
RPKI_TRACE(D_EVENTS, p, "rpki_relax_groups END");
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -466,17 +522,7 @@ rpki_reconfigure_proto(struct rpki_proto *p, struct rpki_config *new_cf, struct
|
||||
}
|
||||
}
|
||||
|
||||
struct rpki_cache_group *g;
|
||||
WALK_LIST(g, p->group_list)
|
||||
{
|
||||
DBG("Group(%u)", g->preference);
|
||||
|
||||
struct rpki_cache *c;
|
||||
WALK_LIST(c, g->cache_list)
|
||||
{
|
||||
DBG(" Cache(%s)", get_cache_ident(c));
|
||||
}
|
||||
}
|
||||
debug_print_groups(p);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -28,6 +28,29 @@
|
||||
#define RPKI_DEFAULT_EXPIRE_INTERVAL 1200
|
||||
#define RPKI_DEFAULT_CACHE_PREFERENCE 1 /* The most important priority */
|
||||
|
||||
/*
|
||||
* +-------------------------------------------+
|
||||
* v |
|
||||
* RTR_MGR_CLOSED <--> RTR_MGR_CONNECTING --> RTR_MGR_ESTABLISHED <--> RTR_MGR_ERROR
|
||||
* ^ | ^ |
|
||||
* | +-----------------------------------------+ |
|
||||
* | |
|
||||
* +-----------------------------------------------------------------+
|
||||
*/
|
||||
enum rtr_mgr_status {
|
||||
/* RTR sockets are disconnected */
|
||||
RTR_MGR_CLOSED,
|
||||
|
||||
/* RTR sockets trying to establish a connection. */
|
||||
RTR_MGR_CONNECTING,
|
||||
|
||||
/* All RTR sockets of the group are synchronized with the rtr servers. */
|
||||
RTR_MGR_ESTABLISHED,
|
||||
|
||||
/* Error occured on at least one RTR socket. */
|
||||
RTR_MGR_ERROR,
|
||||
};
|
||||
|
||||
struct rpki_cache_ssh_cfg {
|
||||
char *bird_private_key; /* Filepath to the BIRD server private key */
|
||||
char *cache_public_key; /* Filepath to the public key of cache server, can be file known_hosts */
|
||||
@ -51,6 +74,7 @@ struct rpki_cache {
|
||||
node n;
|
||||
struct rpki_proto *p;
|
||||
struct rpki_cache_cfg *cfg;
|
||||
struct rpki_cache_group *group;
|
||||
struct rtr_socket *rtr_socket; /* RTRlib's socket data structure */
|
||||
sock *sk; /* BIRD's socket data structure */
|
||||
timer *retry_timer; /* Timer for Cache server */
|
||||
@ -63,7 +87,7 @@ struct rpki_cache_group {
|
||||
node n;
|
||||
u8 preference; /* Preference: the most prioritized are the lowest numbers and starts with 1 */
|
||||
list cache_list; /* List of cache servers (struct rpki_cache) * */
|
||||
u8 state; /* RPKI_CACHE_GROUP_STATE_* */
|
||||
enum rtr_mgr_status status;
|
||||
};
|
||||
|
||||
struct rpki_config {
|
||||
@ -84,6 +108,8 @@ void rpki_init_all(void);
|
||||
void rpki_close_connection(struct rpki_cache *cache);
|
||||
int rpki_open_connection(struct rpki_cache *cache);
|
||||
const char *get_cache_ident(struct rpki_cache *cache);
|
||||
void rpki_relax_groups(struct rpki_proto *p);
|
||||
void debug_print_groups(struct rpki_proto *p);
|
||||
|
||||
#define RPKI_LOG(log_level, rpki, msg, args...) \
|
||||
do { \
|
||||
@ -102,23 +128,15 @@ const char *get_cache_ident(struct rpki_cache *cache);
|
||||
#define RPKI_TRACE(level,rpki,msg,args...) \
|
||||
do { \
|
||||
if ((rpki)->p.debug & level) \
|
||||
RPKI_LOG(L_TRACE, rpki, msg, ## args); \
|
||||
RPKI_LOG(L_TRACE, rpki, msg, ## args); \
|
||||
} while(0)
|
||||
|
||||
#define CACHE_TRACE(level,cache,msg,args...) \
|
||||
do { \
|
||||
if ((cache)->p->p.debug & level) \
|
||||
RPKI_LOG(L_TRACE, (cache)->p, "%s: " msg, get_cache_ident(cache), ## args); \
|
||||
RPKI_LOG(L_TRACE, (cache)->p, "%s: " msg, get_cache_ident(cache), ## args); \
|
||||
} while(0)
|
||||
|
||||
#define RPKI_WARN(p, msg, args...) RPKI_LOG(L_WARN, p, msg, ## args);
|
||||
|
||||
#define RPKI_ERROR(p, msg, args...) RPKI_LOG(L_ERR, p, msg, ## args);
|
||||
|
||||
#define RPKI_DIE(p, msg, args...) \
|
||||
do { \
|
||||
RPKI_LOG(L_FATAL, p, msg, ## args); \
|
||||
exit(1); \
|
||||
} while(0)
|
||||
|
||||
#endif /* _BIRD_RPKI_H_ */
|
||||
|
@ -91,6 +91,24 @@ rtr_state_to_str(enum rtr_socket_state state)
|
||||
return rtr_socket_str_states[state];
|
||||
}
|
||||
|
||||
/*
|
||||
* Set group status to @mgr_status if all sockets of caches in the @group are @socket_state
|
||||
*/
|
||||
static void
|
||||
set_group_status_to_if_all_sockets_are(struct rpki_cache_group *group, const enum rtr_mgr_status mgr_status, const enum rtr_socket_state socket_state)
|
||||
{
|
||||
bool do_all_sockets_pass = true;
|
||||
|
||||
struct rpki_cache *cache;
|
||||
WALK_LIST(cache, group->cache_list)
|
||||
{
|
||||
if (cache->rtr_socket->state != socket_state)
|
||||
do_all_sockets_pass = false;
|
||||
}
|
||||
if (do_all_sockets_pass)
|
||||
group->status = mgr_status;
|
||||
}
|
||||
|
||||
void
|
||||
rtr_change_socket_state(struct rtr_socket *rtr_socket, const enum rtr_socket_state new_state)
|
||||
{
|
||||
@ -107,6 +125,9 @@ rtr_change_socket_state(struct rtr_socket *rtr_socket, const enum rtr_socket_sta
|
||||
switch (new_state)
|
||||
{
|
||||
case RTR_CONNECTING:
|
||||
if (old_state == RTR_SHUTDOWN)
|
||||
cache->group->status = RTR_MGR_CONNECTING;
|
||||
|
||||
if (cache->sk == NULL || cache->sk->fd < 0)
|
||||
{
|
||||
if (rpki_open_connection(cache) == TR_SUCCESS)
|
||||
@ -117,7 +138,9 @@ rtr_change_socket_state(struct rtr_socket *rtr_socket, const enum rtr_socket_sta
|
||||
break;
|
||||
|
||||
case RTR_ESTABLISHED:
|
||||
/* Connection is established, socket is waiting for a Serial Notify or expiration of the refresh_interval timer */
|
||||
/* set status of group to RTR_MGR_ESTABLISHED if all caches in the common group are RTR_ESTABLISHED */
|
||||
set_group_status_to_if_all_sockets_are(cache->group, RTR_MGR_ESTABLISHED, RTR_ESTABLISHED);
|
||||
rpki_relax_groups(cache->p);
|
||||
break;
|
||||
|
||||
case RTR_RESET:
|
||||
@ -165,6 +188,8 @@ rtr_change_socket_state(struct rtr_socket *rtr_socket, const enum rtr_socket_sta
|
||||
/* Error on the transport socket occurred. */
|
||||
rpki_close_connection(cache);
|
||||
rtr_schedule_next_retry(cache);
|
||||
cache->group->status = RTR_MGR_ERROR;
|
||||
rpki_relax_groups(cache->p);
|
||||
break;
|
||||
|
||||
case RTR_FAST_RECONNECT:
|
||||
@ -180,6 +205,10 @@ rtr_change_socket_state(struct rtr_socket *rtr_socket, const enum rtr_socket_sta
|
||||
rtr_socket->serial_number = 0;
|
||||
rtr_socket->last_update = 0;
|
||||
pfx_table_src_remove(cache);
|
||||
|
||||
/* set status of group to RTR_MGR_CLOSED if all caches in the common group are RTR_SHUTDOWN */
|
||||
set_group_status_to_if_all_sockets_are(cache->group, RTR_MGR_CLOSED, RTR_SHUTDOWN);
|
||||
rpki_relax_groups(cache->p);
|
||||
break;
|
||||
};
|
||||
}
|
||||
@ -284,6 +313,7 @@ rpki_retry_hook(struct timer *tm)
|
||||
default:
|
||||
CACHE_DBG(cache, "Retry Connecting (%s)", rtr_socket_str_states[rtr_socket->state]);
|
||||
rtr_change_socket_state(rtr_socket, RTR_CONNECTING);
|
||||
debug_print_groups(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -8,13 +8,6 @@
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup mod_rtr_h RTR socket
|
||||
* @brief An RTR socket implements the RPKI-RTR protocol scheme.
|
||||
* @details One rtr_socket communicates with a single RPKI-RTR server.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef RTR_H
|
||||
#define RTR_H
|
||||
#include <time.h>
|
||||
|
@ -34,7 +34,7 @@ int tr_ssh_open(void *socket)
|
||||
const char *err_msg;
|
||||
if((err_msg = load_libssh()) != NULL)
|
||||
{
|
||||
RPKI_ERROR(p, "%s", err_msg);
|
||||
CACHE_TRACE(D_EVENTS, cache, "%s", err_msg);
|
||||
return TR_ERROR;
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,8 @@ const char *tr_tcp_ident(void *socket)
|
||||
static int
|
||||
fulfill_ip_addr(struct tr_tcp_socket *tcp_socket)
|
||||
{
|
||||
struct rpki_proto *p = tcp_socket->cache->p;
|
||||
struct rpki_cache *cache = tcp_socket->cache;
|
||||
struct rpki_proto *p = cache->p;
|
||||
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res;
|
||||
@ -122,7 +123,7 @@ fulfill_ip_addr(struct tr_tcp_socket *tcp_socket)
|
||||
|
||||
if (getaddrinfo(tcp_socket->config.host, port_buf, &hints, &res) != 0)
|
||||
{
|
||||
RPKI_ERROR(p, "getaddrinfo error, %s", tcp_socket, gai_strerror(errno));
|
||||
CACHE_TRACE(D_EVENTS, cache, "getaddrinfo error, %s", gai_strerror(errno));
|
||||
return TR_ERROR;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user