/*
 * Copyright (c) 2018-2019 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <vnet/tcp/tcp.h>
#include <math.h>

#define beta_cubic 	0.7
#define cubic_c		0.4
#define west_const 	(3 * (1 - beta_cubic) / (1 + beta_cubic))

typedef struct cubic_cfg_
{
  u8 fast_convergence;
} cubic_cfg_t;

static cubic_cfg_t cubic_cfg = {
  .fast_convergence = 1,
};

typedef struct cubic_data_
{
  /** time period (in seconds) needed to increase the current window
   *  size to W_max if there are no further congestion events */
  f64 K;

  /** time (in sec) since the start of current congestion avoidance */
  f64 t_start;

  /** Inflection point of the cubic function (in snd_mss segments) */
  u32 w_max;

} __clib_packed cubic_data_t;

STATIC_ASSERT (sizeof (cubic_data_t) <= TCP_CC_DATA_SZ, "cubic data len");

static inline f64
cubic_time (u32 thread_index)
{
  return transport_time_now (thread_index);
}

/**
 * RFC 8312 Eq. 1
 *
 * CUBIC window increase function. Time and K need to be provided in seconds.
 */
static inline u64
W_cubic (cubic_data_t * cd, f64 t)
{
  f64 diff = t - cd->K;

  /* W_cubic(t) = C*(t-K)^3 + W_max */
  return cubic_c * diff * diff * diff + cd->w_max;
}

/**
 * RFC 8312 Eq. 2
 */
static inline f64
K_cubic (cubic_data_t * cd, u32 wnd)
{
  /* K = cubic_root(W_max*(1-beta_cubic)/C)
   * Because the current window may be less than W_max * beta_cubic because
   * of fast convergence, we pass it as parameter */
  return pow ((f64) (cd->w_max - wnd) / cubic_c, 1 / 3.0);
}

/**
 * RFC 8312 Eq. 4
 *
 * Estimates the window size of AIMD(alpha_aimd, beta_aimd) for
 * alpha_aimd=3*(1-beta_cubic)/(1+beta_cubic) and beta_aimd=beta_cubic.
 * Time (t) and rtt should be provided in seconds
 */
static inline u32
W_est (cubic_data_t * cd, f64 t, f64 rtt)
{
  /* W_est(t) = W_max*beta_cubic+[3*(1-beta_cubic)/(1+beta_cubic)]*(t/RTT) */
  return cd->w_max * beta_cubic + west_const * (t / rtt);
}

static void
cubic_congestion (tcp_connection_t * tc)
{
  cubic_data_t *cd = (cubic_data_t *) tcp_cc_data (tc);
  u32 w_max;

  w_max = tc->cwnd / tc->snd_mss;
  if (cubic_cfg.fast_convergence && w_max < cd->w_max)
    w_max = w_max * ((1.0 + beta_cubic) / 2.0);

  cd->w_max = w_max;
  tc->ssthresh = clib_max (tc->cwnd * beta_cubic, 2 * tc->snd_mss);
}

static void
cubic_recovered (tcp_connection_t * tc)
{
  cubic_data_t *cd = (cubic_data_t *) tcp_cc_data (tc);
  cd->t_start = cubic_time (tc->c_thread_index);
  tc->cwnd = tc->ssthresh;
  cd->K = K_cubic (cd, tc->cwnd / tc->snd_mss);
}

static void
cubic_cwnd_accumulate (tcp_connection_t * tc, u32 thresh, u32 bytes_acked)
{
  /* We just updated the threshold and don't know how large the previous
   * one was. Still, optimistically increase cwnd by one segment and
   * clear the accumulated bytes. */
  if (tc->cwnd_acc_bytes > thresh)
    {
      tc->cwnd += tc->snd_mss;
      tc->cwnd_acc_bytes = 0;
    }

  tcp_cwnd_accumulate (tc, thresh, tc->bytes_acked);
}

static void
cubic_rcv_ack (tcp_connection_t * tc)
{
  cubic_data_t *cd = (cubic_data_t *) tcp_cc_data (tc);
  u64 w_cubic, w_aimd;
  f64 t, rtt_sec;
  u32 thresh;

  /* Constrained by tx fifo, can't grow further */
  if (tc->cwnd >= tc->tx_fifo_size)
    return;

  if (tcp_in_slowstart (tc))
    {
      tc->cwnd += clib_min (tc->snd_mss, tc->bytes_acked);
      return;
    }

  t = cubic_time (tc->c_thread_index) - cd->t_start;
  rtt_sec = clib_min (tc->mrtt_us, (f64) tc->srtt * TCP_TICK);

  w_cubic = W_cubic (cd, t + rtt_sec) * tc->snd_mss;
  w_aimd = (u64) W_est (cd, t, rtt_sec) * tc->snd_mss;
  if (w_cubic < w_aimd)
    {
      cubic_cwnd_accumulate (tc, tc->cwnd, tc->bytes_acked);
    }
  else
    {
      if (w_cubic > tc->cwnd)
	{
	  /* For NewReno and slow start, we increment cwnd based on the
	   * number of bytes acked, not the number of acks received. In
	   * particular, for NewReno we increment the cwnd by 1 snd_mss
	   * only after we accumulate 1 cwnd of acked bytes (RFC 3465).
	   *
	   * For Cubic, as per RFC 8312 we should increment cwnd by
	   * (w_cubic - cwnd)/cwnd for each ack. Instead of using that,
	   * we compute the number of packets that need to be acked
	   * before adding snd_mss to cwnd and compute the threshold
	   */
	  thresh = (tc->snd_mss * tc->cwnd) / (w_cubic - tc->cwnd);

	  /* Make sure we don't increase cwnd more often than every segment */
	  thresh = clib_max (thresh, tc->snd_mss);
	}
      else
	{
	  /* Practically we can't increment so just inflate threshold */
	  thresh = 50 * tc->cwnd;
	}
      cubic_cwnd_accumulate (tc, thresh, tc->bytes_acked);
    }
}

static void
cubic_conn_init (tcp_connection_t * tc)
{
  cubic_data_t *cd = (cubic_data_t *) tcp_cc_data (tc);
  tc->ssthresh = tc->snd_wnd;
  tc->cwnd = tcp_initial_cwnd (tc);
  cd->w_max = 0;
  cd->K = 0;
  cd->t_start = cubic_time (tc->c_thread_index);
}

static uword
cubic_unformat_config (unformat_input_t * input)
{
  if (!input)
    return 0;

  unformat_skip_white_space (input);

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "no-fast-convergence"))
	cubic_cfg.fast_convergence = 0;
      else
	return 0;
    }
  return 1;
}

const static tcp_cc_algorithm_t tcp_cubic = {
  .name = "cubic",
  .unformat_cfg = cubic_unformat_config,
  .congestion = cubic_congestion,
  .recovered = cubic_recovered,
  .rcv_ack = cubic_rcv_ack,
  .rcv_cong_ack = newreno_rcv_cong_ack,
  .init = cubic_conn_init,
};

clib_error_t *
cubic_init (vlib_main_t * vm)
{
  clib_error_t *error = 0;

  tcp_cc_algo_register (TCP_CC_CUBIC, &tcp_cubic);

  return error;
}

VLIB_INIT_FUNCTION (cubic_init);

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
