Commit 538b879a authored by Maria Matejka's avatar Maria Matejka
Browse files

TMP

parent 94aacc1c
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -99,4 +99,43 @@ extern _Thread_local u64 worker_id;
  node_->_lsp = NULL; \
} while (0)

/* Atomic pointer-based circular buffer.
 * There is 
 *
 * */
#define CIRCULAR_BUFFER_PTR struct { \
  _Atomic u64 acquire, release; \
  _Atomic uint waiting; \
  struct semaphore *sem; \
}

#define CIRCULAR_BUFFER_N(type_, size_, ptrs_) struct { \
  type_ buffer[size_]; \
  CIRCULAR_BUFFER_PTR ptr[ptrs_]; \
}

#define CIRCULAR_BUFFER(type_, size_) CIRCULAR_BUFFER_N(type_, size_, 2)

#define CIRCULAR_BUFFER_PTR_INIT(ptr_, pool_) do { \
  (ptr_)->acquire = (ptr_)->release = ATOMIC_VAR_INIT(0); \
  (ptr_)->waiting = ATOMIC_VAR_INIT(0); \
  (ptr_)->sem = semaphore_new(pool_, 0); \
} while (0)

#define CIRCULAR_BUFFER_INIT(buf_, pool_) do { \
  memset((buf_)->buffer, 0, sizeof((buf_)->buffer)); \
  for (uint i_=0; i_<sizeof((buf_)->ptr) / sizeof((buf_)->ptr[0]); i_++) \
    CIRCULAR_BUFFER_PTR_INIT(&((buf_)->ptr[i_]), pool_); \
} while (0)

#define CIRCULAR_BUFFER_CLEANUP(buf_) do { \
  u64 val = atomic_load(&((buf_)->ptr[0].acquire)); \
  for (uint i_=0; i_<sizeof((buf_)->ptr) / sizeof((buf_)->ptr[0]); i_++) { \
    ASSERT(val == atomic_load(&((buf_)->ptr[i_].acquire))); \
    ASSERT(val == atomic_load(&((buf_)->ptr[i_].release))); \
    ASSERT(0 == atomic_load(&((buf_)->ptr[i_].waiting))); \
    rfree((buf_)->ptr[i_].sem); \
  } \
} while (0)

#endif
+3 −1
Original line number Diff line number Diff line
@@ -168,7 +168,7 @@ proto_add_channel(struct proto *p, struct channel_config *cf)
  c->last_tx_filter_change = current_time();
  c->reloadable = 1;

  INIT_LOCKED_LIST(&c->pending_imports);
  CIRCULAR_BUFFER_INIT(&c->pending_imports, proto_pool);

  CALL(c->channel->init, c, cf);

@@ -186,6 +186,8 @@ proto_remove_channel(struct proto *p, struct channel *c)

  PD(p, "Channel %s removed", c->name);

  CIRCULAR_BUFFER_CLEANUP(&c->pending_imports);

  rem_node(&c->n);
  mb_free(c);
}
+4 −1
Original line number Diff line number Diff line
@@ -496,6 +496,8 @@ struct channel_config {
  u8 in_keep_filtered;			/* Routes rejected in import filter are kept */
};

#define CHANNEL_QUEUE_SIZE	64

struct channel {
  node n;				/* Node in proto->channels */
  node table_node;			/* Node in table->channels */
@@ -535,7 +537,8 @@ struct channel {
  btime last_state_change;		/* Time of last state transition */
  btime last_tx_filter_change;

  LOCKED_LIST(struct rte_update_data) pending_imports;	/* Imports shall be sequenced */
  /* Circular buffer for pending imports */
  CIRCULAR_BUFFER_N(struct rte_update_data, CHANNEL_QUEUE_SIZE, 3) pending_imports;

  struct rtable *in_table;		/* Internal table for received routes */
  struct event *reload_event;		/* Event responsible for reloading from in_table */
+22 −24
Original line number Diff line number Diff line
@@ -147,30 +147,6 @@ struct rtable_config {

/* Route update data that is passed through the filters */

struct rte_update_data {
  LOCKED_LIST_NODE(struct rte_update_data);
  struct task task;
  struct channel *channel;
  const net_addr *net;
  struct rte *rte;
  struct rta *old_rta;
  struct rte_src *src;
  struct linpool *pool;
  _Atomic PACKED enum rte_update_state {
    RUS_PENDING_UPDATE = 0,
    RUS_UPDATING,
    RUS_PENDING_RECALCULATE,
    RUS_RECALCULATING,
  } state;
  PACKED enum rte_update_result {
    RUR_UNKNOWN = 0,
    RUR_WITHDRAW = 1,
    RUR_INVALID = 2,
    RUR_FILTERED = 3,
    RUR_ACCEPTED = 4,
  } result;
};

typedef struct rtable {
  node n;				/* Node in list of all tables */
  struct fib fib;
@@ -307,6 +283,28 @@ static inline int rte_is_filtered(rte *r) { return !!(r->flags & REF_FILTERED);
#define RIC_REJECT	-1		/* Rejected by protocol */
#define RIC_DROP	-2		/* Silently dropped by protocol */

struct rte_update_data {
  struct task task;
  struct channel *channel;
  net_addr_union net;
  struct rte rte;
  struct rta *old_rta;
  struct rte_src *src;
  _Atomic PACKED enum rte_update_state {
    RUS_PENDING_UPDATE = 0,
    RUS_UPDATING,
    RUS_PENDING_RECALCULATE,
    RUS_RECALCULATING,
  } state;
  PACKED enum rte_update_result {
    RUR_UNKNOWN = 0,
    RUR_WITHDRAW = 1,
    RUR_INVALID = 2,
    RUR_FILTERED = 3,
    RUR_ACCEPTED = 4,
  } result;
};

extern list routing_tables;
struct config;

+0 −54
Original line number Diff line number Diff line
@@ -51,58 +51,8 @@
#endif

pool *rt_table_pool;
static pool *rup_pool;
static spinlock rup_spinlock;

#define RUPS_MAX  128

static slab *rte_slab;
static linpool * volatile rte_update_pool[RUPS_MAX] = {};
static volatile uint rups = 0;
static volatile uint rup_total_linpools = 0;
static struct semaphore *rup_sem = NULL;

static inline linpool *rup_get(void) {
  struct linpool *pool;

  /* Wait until some linpool is available */
  semaphore_wait(rup_sem);

  SPIN_LOCK(rup_spinlock);
  if (!rups)
  {
    pool = lp_new_default(rup_pool);
    rup_total_linpools++;
    if (rup_total_linpools > 256)
      bug("");
  }
  else
  {
    /* Get a recycled linpool */
    pool = rte_update_pool[--rups];
  }
  SPIN_UNLOCK(rup_spinlock);

  debug("Linpool state %u (get)\n", rup_total_linpools);
  return pool;
}

static inline void rup_free(linpool *pool) {
  lp_flush(pool);

  SPIN_LOCK(rup_spinlock);
  if (rups == RUPS_MAX) {
    rfree(pool);
    rup_total_linpools--;
  } else {
    /* Keep the linpool for future use */
    rte_update_pool[rups++] = pool;
  }
  SPIN_UNLOCK(rup_spinlock);

  semaphore_post(rup_sem);
  debug("Linpool state %u (free)\n", rup_total_linpools);
}

static inline void rud_state_change(struct rte_update_data *rud, enum rte_update_state from, enum rte_update_state to)
{ 
@@ -1570,10 +1520,6 @@ rte_dispatch_update(struct rte_update_data *rud)
{
  debug("RDU\n");

  /* Get local linpool */
  ASSERT(rud->pool == NULL);
  rud->pool = rup_get();

  /* Check right rud state */
  rud_state_check(rud, RUS_PENDING_UPDATE);