Line data Source code
1 : /* 2 : * Copyright (c) 2017-2019 Cisco and/or its affiliates. 3 : * Licensed under the Apache License, Version 2.0 (the "License"); 4 : * you may not use this file except in compliance with the License. 5 : * You may obtain a copy of the License at: 6 : * 7 : * http://www.apache.org/licenses/LICENSE-2.0 8 : * 9 : * Unless required by applicable law or agreed to in writing, software 10 : * distributed under the License is distributed on an "AS IS" BASIS, 11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : * See the License for the specific language governing permissions and 13 : * limitations under the License. 14 : */ 15 : 16 : #include <vnet/tcp/tcp.h> 17 : #include <vnet/tcp/tcp_inlines.h> 18 : 19 : typedef struct nwreno_cfg_ 20 : { 21 : u32 ssthresh; 22 : } newreno_cfg_t; 23 : 24 : static newreno_cfg_t newreno_cfg = { 25 : .ssthresh = 0x7FFFFFFFU, 26 : }; 27 : 28 : static void 29 0 : newreno_congestion (tcp_connection_t * tc) 30 : { 31 0 : tc->ssthresh = clib_max (tcp_flight_size (tc) / 2, 2 * tc->snd_mss); 32 0 : tc->cwnd = tc->ssthresh; 33 0 : } 34 : 35 : static void 36 0 : newreno_loss (tcp_connection_t * tc) 37 : { 38 0 : tc->cwnd = tcp_loss_wnd (tc); 39 0 : } 40 : 41 : static void 42 0 : newreno_recovered (tcp_connection_t * tc) 43 : { 44 0 : tc->cwnd = tc->ssthresh; 45 0 : } 46 : 47 : static void 48 0 : newreno_rcv_ack (tcp_connection_t * tc, tcp_rate_sample_t * rs) 49 : { 50 0 : if (tcp_in_slowstart (tc)) 51 : { 52 0 : tc->cwnd += clib_min (tc->snd_mss, rs->delivered); 53 : } 54 : else 55 : { 56 : /* tc->cwnd += clib_max ((tc->snd_mss * tc->snd_mss) / tc->cwnd, 1); */ 57 0 : tcp_cwnd_accumulate (tc, tc->cwnd, rs->delivered); 58 : } 59 0 : } 60 : 61 : void 62 0 : newreno_rcv_cong_ack (tcp_connection_t * tc, tcp_cc_ack_t ack_type, 63 : tcp_rate_sample_t * rs) 64 : { 65 : /* With sacks prr controls the data in flight post congestion */ 66 0 : if (PREDICT_TRUE (tcp_opts_sack_permitted (tc))) 67 0 : return; 68 : 69 0 : if (ack_type == TCP_CC_DUPACK) 70 : { 71 0 : tc->cwnd += tc->snd_mss; 72 : } 73 0 : else if (ack_type == TCP_CC_PARTIALACK) 74 : { 75 : /* RFC 6582 Sec. 3.2 76 : * Deflate the congestion window by the amount of new data 77 : * acknowledged by the Cumulative Acknowledgment field. 78 : * If the partial ACK acknowledges at least one SMSS of new data, 79 : * then add back SMSS bytes to the congestion window. This 80 : * artificially inflates the congestion window in order to reflect 81 : * the additional segment that has left the network. This "partial 82 : * window deflation" attempts to ensure that, when fast recovery 83 : * eventually ends, approximately ssthresh amount of data will be 84 : * outstanding in the network. */ 85 0 : tc->cwnd = (tc->cwnd > tc->bytes_acked + tc->snd_mss) ? 86 0 : tc->cwnd - tc->bytes_acked : 87 0 : tc->snd_mss; 88 0 : if (tc->bytes_acked > tc->snd_mss) 89 0 : tc->cwnd += tc->snd_mss; 90 : } 91 : } 92 : 93 : static void 94 0 : newreno_conn_init (tcp_connection_t * tc) 95 : { 96 0 : tc->ssthresh = newreno_cfg.ssthresh; 97 0 : tc->cwnd = tcp_initial_cwnd (tc); 98 0 : } 99 : 100 : static uword 101 0 : newreno_unformat_config (unformat_input_t * input) 102 : { 103 0 : u32 ssthresh = 0x7FFFFFFFU; 104 : 105 0 : if (!input) 106 0 : return 0; 107 : 108 0 : unformat_skip_white_space (input); 109 : 110 0 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 111 : { 112 0 : if (unformat (input, "ssthresh %u", &ssthresh)) 113 0 : newreno_cfg.ssthresh = ssthresh; 114 : else 115 0 : return 0; 116 : } 117 0 : return 1; 118 : } 119 : 120 : const static tcp_cc_algorithm_t tcp_newreno = { 121 : .name = "newreno", 122 : .unformat_cfg = newreno_unformat_config, 123 : .congestion = newreno_congestion, 124 : .loss = newreno_loss, 125 : .recovered = newreno_recovered, 126 : .rcv_ack = newreno_rcv_ack, 127 : .rcv_cong_ack = newreno_rcv_cong_ack, 128 : .init = newreno_conn_init 129 : }; 130 : 131 : clib_error_t * 132 575 : newreno_init (vlib_main_t * vm) 133 : { 134 575 : clib_error_t *error = 0; 135 : 136 575 : tcp_cc_algo_register (TCP_CC_NEWRENO, &tcp_newreno); 137 : 138 575 : return error; 139 : } 140 : 141 58751 : VLIB_INIT_FUNCTION (newreno_init); 142 : 143 : /* 144 : * fd.io coding-style-patch-verification: ON 145 : * 146 : * Local Variables: 147 : * eval: (c-set-style "gnu") 148 : * End: 149 : */