Commit 3b20722a authored by Maria Matejka's avatar Maria Matejka
Browse files

Table cork: Stop creating updates when there are too many pending.

The corked procedure gets a callback when uncorked. Supported by table
maintenance routines and also BGP.
parent 445eeaf3
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -157,6 +157,7 @@ struct rtable_config {
  btime min_settle_time;		/* Minimum settle time for notifications */
  btime max_settle_time;		/* Maximum settle time for notifications */
  btime export_settle_time;		/* Delay before exports are announced */
  uint cork_limit;			/* Amount of routes to be pending on export to cork imports */
};

typedef struct rtable {
@@ -187,6 +188,9 @@ typedef struct rtable {
  int gc_counter;			/* Number of operations since last GC */
  byte prune_state;			/* Table prune state, 1 -> scheduled, 2-> running */
  byte nhu_state;			/* Next Hop Update state */

  byte cork_active;			/* Congestion control activated */

  struct fib_iterator prune_fit;	/* Rtable prune FIB iterator */
  struct fib_iterator nhu_fit;		/* Next Hop Update FIB iterator */
  struct tbf rl_pipe;			/* Rate limiting token buffer for pipe collisions */
@@ -378,6 +382,8 @@ struct rt_export_hook {
  void (*stopped)(struct rt_export_request *);	/* Stored callback when export is stopped */
};

extern struct event_cork rt_cork;

#define TIS_DOWN	0
#define TIS_UP		1
#define TIS_STOP	2
+22 −1
Original line number Diff line number Diff line
@@ -110,6 +110,7 @@ const char *rt_export_state_name(u8 state)
    return rt_export_state_name_array[state];
}

struct event_cork rt_cork;

/* Like fib_route(), but skips empty net entries */
static inline void *
@@ -1061,7 +1062,13 @@ rte_announce(rtable *tab, net *net, struct rte_storage *new, struct rte_storage
  if (tab->first_export == NULL)
    tab->first_export = rpe;

  if (!tm_active(tab->export_timer))
  if ((tab->first_export->seq + tab->config->cork_limit <= tab->next_export_seq) && !tab->cork_active)
  {
    ev_cork(&rt_cork);
    tab->cork_active = 1;
    tm_start(tab->export_timer, 0);
  }
  else if (!tm_active(tab->export_timer))
    tm_start(tab->export_timer, tab->config->export_settle_time);
}

@@ -2042,6 +2049,7 @@ rt_free(resource *_r)
  DBG("Deleting routing table %s\n", r->name);
  ASSERT_DIE(r->use_count == 0);
  ASSERT_DIE(r->rt_count == 0);
  ASSERT_DIE(!r->cork_active);
  ASSERT_DIE(EMPTY_LIST(r->imports));
  ASSERT_DIE(EMPTY_LIST(r->exports));

@@ -2106,6 +2114,9 @@ rt_setup(pool *pp, struct rtable_config *cf)
  t->hcu_event = ev_new_init(p, rt_update_hostcache, t);
  t->nhu_event = ev_new_init(p, rt_next_hop_update, t);

  t->nhu_event->cork = &rt_cork;
  t->prune_event->cork = &rt_cork;

  t->export_timer = tm_new_init(p, rt_announce_exports, t, 0, 0);
  t->last_rt_change = t->gc_time = current_time();
  t->next_export_seq = 1;
@@ -2128,6 +2139,7 @@ rt_init(void)
  rt_table_pool = rp_new(&root_pool, "Routing tables");
  rte_update_pool = lp_new_default(rt_table_pool);
  init_list(&routing_tables);
  ev_init_cork(&rt_cork, "Route Table Cork");
}

/**
@@ -2420,6 +2432,14 @@ done:;

  if (EMPTY_LIST(tab->pending_exports) && tm_active(tab->export_timer))
    tm_stop(tab->export_timer);

  /* If reduced to at most one export block pending */
  if (tab->cork_active &&
      ((!tab->first_export) || (tab->first_export->seq + 128 > tab->next_export_seq)))
  {
    tab->cork_active = 0;
    ev_uncork(&rt_cork);
  }
}

void
@@ -2699,6 +2719,7 @@ rt_new_table(struct symbol *s, uint addr_type)
  c->gc_min_time = 5;
  c->min_settle_time = 1 S;
  c->max_settle_time = 20 S;
  c->cork_limit = 4 * page_size / sizeof(struct rt_pending_export);
  c->config = new_config;

  add_tail(&new_config->tables, &c->n);
+1 −0
Original line number Diff line number Diff line
@@ -584,6 +584,7 @@ bgp_conn_enter_established_state(struct bgp_conn *conn)
    p->link_addr = p->neigh->iface->llv6->ip;

  conn->sk->fast_rx = 0;
  conn->sk->cork = &rt_cork;

  p->conn = conn;
  p->last_error_class = 0;