Commit 27d7aae8 authored by Pavel Tvrdík's avatar Pavel Tvrdík
Browse files

RPKI: Add the basis for manager

parent a3cc5d76
Loading
Loading
Loading
Loading
+72 −26
Original line number Diff line number Diff line
@@ -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;
}
+29 −11
Original line number Diff line number Diff line
@@ -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_ */
+31 −1
Original line number Diff line number Diff line
@@ -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;
  }
}
+0 −7
Original line number Diff line number Diff line
@@ -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>
+1 −1
Original line number Diff line number Diff line
@@ -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;
  }

Loading