Commit d438cf1e authored by Andrea Shepard's avatar Andrea Shepard
Browse files

Implement scheduler mechanism to track lists of channels wanting cells or...

Implement scheduler mechanism to track lists of channels wanting cells or writes; doesn't actually drive the cell flow from it yet
parent 1987157d
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -97,8 +97,10 @@
#define LD_HEARTBEAT (1u<<20)
/** Abstract channel_t code */
#define LD_CHANNEL   (1u<<21)
/** Scheduler */
#define LD_SCHED     (1u<<22)
/** Number of logging domains in the code. */
#define N_LOGGING_DOMAINS 22
#define N_LOGGING_DOMAINS 23

/** This log message is not safe to send to a callback-based logger
 * immediately.  Used as a flag, not a log domain. */
+1 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ LIBTOR_OBJECTS = \
  routerlist.obj \
  routerparse.obj \
  routerset.obj \
  scheduler.obj \
  statefile.obj \
  status.obj \
  transports.obj
+19 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include "rephist.h"
#include "router.h"
#include "routerlist.h"
#include "scheduler.h"

/* Cell queue structure */

@@ -788,6 +789,9 @@ channel_free(channel_t *chan)
            "Freeing channel " U64_FORMAT " at %p",
            U64_PRINTF_ARG(chan->global_identifier), chan);

  /* Get this one out of the scheduler */
  scheduler_release_channel(chan);

  /*
   * Get rid of cmux policy before we do anything, so cmux policies don't
   * see channels in weird half-freed states.
@@ -863,6 +867,9 @@ channel_force_free(channel_t *chan)
            "Force-freeing channel " U64_FORMAT " at %p",
            U64_PRINTF_ARG(chan->global_identifier), chan);

  /* Get this one out of the scheduler */
  scheduler_release_channel(chan);

  /*
   * Get rid of cmux policy before we do anything, so cmux policies don't
   * see channels in weird half-freed states.
@@ -1941,6 +1948,18 @@ channel_change_state(channel_t *chan, channel_state_t to_state)
    }
  }

  /*
   * If we're going to a closed/closing state, we don't need scheduling any
   * more; in CHANNEL_STATE_MAINT we can't accept writes.
   */
  if (to_state == CHANNEL_STATE_CLOSING ||
      to_state == CHANNEL_STATE_CLOSED ||
      to_state == CHANNEL_STATE_ERROR) {
    scheduler_release_channel(chan);
  } else if (to_state == CHANNEL_STATE_MAINT) {
    scheduler_channel_doesnt_want_writes(chan);
  }

  /* Tell circuits if we opened and stuff */
  if (to_state == CHANNEL_STATE_OPEN) {
    channel_do_open_actions(chan);
+5 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "relay.h"
#include "router.h"
#include "routerlist.h"
#include "scheduler.h"

/** How many CELL_PADDING cells have we received, ever? */
uint64_t stats_n_padding_cells_processed = 0;
@@ -867,6 +868,10 @@ channel_tls_handle_state_change_on_orconn(channel_tls_t *chan,
     * CHANNEL_STATE_MAINT on this.
     */
    channel_change_state(base_chan, CHANNEL_STATE_OPEN);
    /* We might have just become writeable; check and tell the scheduler */
    if (connection_or_num_cells_writeable(conn) > 0) {
      scheduler_channel_wants_writes(base_chan);
    }
  } else {
    /*
     * Not open, so from CHANNEL_STATE_OPEN we go to CHANNEL_STATE_MAINT,
+37 −0
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@
#include "router.h"
#include "routerlist.h"
#include "ext_orport.h"
#include "scheduler.h"

#ifdef USE_BUFFEREVENTS
#include <event2/bufferevent_ssl.h>
#endif
@@ -595,6 +597,17 @@ connection_or_flushed_some(or_connection_t *conn)
   * high water mark. */
  datalen = connection_get_outbuf_len(TO_CONN(conn));
  if (datalen < OR_CONN_LOWWATER) {
    /* Let the scheduler know */
    scheduler_channel_wants_writes(TLS_CHAN_TO_BASE(conn->chan));

    /*
     * TODO this will be done from the scheduler, so it will
     * need a generic way to ask how many cells a channel can
     * accept and if it still wants writes or not to know how
     * to account for it in the case that it runs out of cells
     * to send first.
     */

    while ((conn->chan) && channel_tls_more_to_flush(conn->chan)) {
      /* Compute how many more cells we want at most */
      n = CEIL_DIV(OR_CONN_HIGHWATER - datalen, cell_network_size);
@@ -616,6 +629,30 @@ connection_or_flushed_some(or_connection_t *conn)
  return 0;
}

/** This is for channeltls.c to ask how many cells we could accept if
 * they were available. */
ssize_t
connection_or_num_cells_writeable(or_connection_t *conn)
{
  size_t datalen, cell_network_size;
  ssize_t n = 0;

  tor_assert(conn);

  /*
   * If we're under the high water mark, we're potentially
   * writeable; note this is different from the calculation above
   * used to trigger when to start writing after we've stopped.
   */
  datalen = connection_get_outbuf_len(TO_CONN(conn));
  if (datalen < OR_CONN_HIGHWATER) {
    cell_network_size = get_cell_network_size(conn->wide_circ_ids);
    n = CEIL_DIV(OR_CONN_HIGHWATER - datalen, cell_network_size);
  }

  return n;
}

/** Connection <b>conn</b> has finished writing and has no bytes left on
 * its outbuf.
 *
Loading