0
0
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:
Pavel Tvrdík 2016-01-06 15:55:29 +01:00
parent a3cc5d7697
commit 27d7aae89f
6 changed files with 136 additions and 48 deletions

View File

@ -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;
}

View File

@ -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 { \
@ -113,12 +139,4 @@ const char *get_cache_ident(struct rpki_cache *cache);
#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_ */

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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;
}