Flow 1.0.0
Flow project: Full implementation reference.
options.cpp
Go to the documentation of this file.
1/* Flow
2 * Copyright 2023 Akamai Technologies, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the
5 * "License"); you may not use this file except in
6 * compliance with the License. You may obtain a copy
7 * of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in
12 * writing, software distributed under the License is
13 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14 * CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing
16 * permissions and limitations under the License. */
17
18/// @file
21#include <boost/algorithm/string.hpp>
22
23// Internal macros (#undef at the end of file).
24
25/// @cond
26/* -^- Doxygen, please ignore the following. (Don't want docs generated for temp macro; this is more maintainable
27 * than specifying the macro name to omit it, in Doxygen-config EXCLUDE_SYMBOLS.) */
28
29#define ADD_CONFIG_OPTION(ARG_opt, ARG_desc) \
30 Node_options::add_config_option(opts_desc, #ARG_opt, &target->ARG_opt, defaults_source.ARG_opt, ARG_desc, \
31 printout_only)
32
33// -v- Doxygen, please stop ignoring.
34/// @endcond
35
36namespace flow::net_flow
37{
38
39// Implementations.
40
42 // They definitely need to opt into this.
43 m_st_capture_interrupt_signals_internally(false),
44 /* OS is under no obligation to take this literally and will probably impose its own limit which
45 * may be smaller than this. In Linux 2.6.x I've observed the limit can't go higher than somewhere
46 * between 1MB and 2MB. Anyway, we pick a reasonable value and hope it has some effect. */
47 m_st_low_lvl_max_buf_size(3 * 1024 * 1024),
48 // Let the code pick something reasonable based on platform, hopefully.
49 m_st_timer_min_period(0),
50 // Allow unlimited # of packets per loop iteration for now.
51 m_dyn_max_packets_per_main_loop_iteration(0),
52 // default max_block_size + a SMALL overhead.
53 m_dyn_low_lvl_max_packet_size(1124),
54 // This default is explained in the option description (as of this writing): it's faster.
55 m_dyn_guarantee_one_low_lvl_in_buf_per_socket(true)
56{
57 // Nothing.
58}
59
60template<typename Opt_type>
62 const std::string& opt_id,
63 Opt_type* target_val, const Opt_type& default_val,
64 const char* description, bool printout_only) // Static.
65{
66 using boost::program_options::value;
67 if (printout_only)
68 {
69 opts_desc->add_options()
70 (opt_id_to_str(opt_id).c_str(), value<Opt_type>()->default_value(default_val));
71 }
72 else
73 {
74 opts_desc->add_options()
75 (opt_id_to_str(opt_id).c_str(), value<Opt_type>(target_val)->default_value(default_val),
76 description);
77 }
78}
79
81 Node_options* target,
82 const Node_options& defaults_source,
83 bool printout_only) // Static.
84{
85 ADD_CONFIG_OPTION
87 "If and only if this is true, the Node will detect SIGINT and SIGTERM (or your OS's version thereof); "
88 "upon seeing such a signal, it will fire Node::interrupt_all_waits(), which will interrupt all "
89 "blocking operations, conceptually similarly to POSIX's EINTR. If this is true, the user may register "
90 "their own signal handler(s) (for any purpose whatsoever) using boost::asio::signal_set. However, behavior "
91 "is undefined if the program registers signal handlers via any other API, such as sigaction() or signal(). "
92 "If you need to set up such a non-signal_set signal handler, AND you require EINTR-like behavior, "
93 "then (1) set this option to false; (2) trap SIGINT and SIGTERM yourself; (3) in your handlers for the "
94 "latter, simply call Node::interrupt_all_waits(). Similarly, if you want custom behavior regarding "
95 "Node::interrupt_all_waits(), feel free to call it whenever you want (not necessarily even from a signal "
96 "handler), and set this to false. However, if a typical, common-sense behavior is what you're after -- and "
97 "either don't need additional signal handling or are OK with using signal_set for it -- then setting this to "
98 "true is a good option.");
99 ADD_CONFIG_OPTION
101 "The max size to ask the OS to set our UDP socket's receive buffer to in order to minimize loss "
102 "if we can't process datagrams fast enough. This should be as high as possible while being "
103 "\"acceptable\" in terms of memory. However, the OS will probably have its own limit and may well "
104 "pick a limit that is the minimum of that limit and this value.");
105 ADD_CONFIG_OPTION
107 "A time period such that the boost.asio timer implementation for this platform is able to "
108 "accurately able to schedule events within this time period or greater. If you select 0, the "
109 "code will decide what this value based on the platform, but its logic for this may or may not "
110 "be correct (actually it will probably be correct but possibly too conservative [large], causing "
111 "timer coarseness in mechanisms like packet pacing).");
112 ADD_CONFIG_OPTION
114 "The UDP net-stack may deliver 2 or more datagrams to the Flow Node at the same time. To lower overhead "
115 "and increase efficiency, Flow will process all such datagrams -- and any more that may arrive during this "
116 "processing -- before preparing any resulting outgoing messages, such as acknowledgments or more data packets. "
117 "In high-speed conditions this may result in excessive burstiness of outgoing traffic. This option's value "
118 "places a limit on the number of datagrams to process before constructing and sending any resulting outgoing "
119 "messages to prevent this burstiness. If 0, there is no limit.");
120 ADD_CONFIG_OPTION
122 "Any incoming low-level (UDP) packet will be truncated to this size. This should be well above "
123 "per-socket max-block-size (# of bytes of user payload per DATA packet). There will only be one buffer "
124 "of this size in memory at a time, so no need to be too stingy, but on the other hand certain "
125 "allocation/deallocation behavior may cause performance drops if this unnecessarily large.");
126 ADD_CONFIG_OPTION
128 "This very inside-baseball setting controls the allocation/copy behavior of the UDP receive-deserialize "
129 "operation sequence. When enabled, there is exactly one input buffer large enough to "
130 "hold any one serialized incoming packet; any deserialized data (including DATA and ACK payloads) are "
131 "stored in separately allocated per-packet buffers; and and the input buffer is repeatedly reused "
132 "without reallocation. When disabled, however, at least some packet types (most notably DATA) will "
133 "use the zero-copy principle, having the deserializer take ownership of the input buffer and access pieces "
134 "inside it as post-deserialization values (most notably the DATA payload); in this case the input buffer "
135 "has to be reallocated between UDP reads. As of this writing the former behavior seems to be somewhat "
136 "faster, especially if low-lvl-max-packet-size is unnecessarily large; but arguably the zero-copy behavior "
137 "may become faster if some implementation details related to this change. So this switch seemed worth "
138 "keeping.");
139
141 &target->m_dyn_sock_opts,
142 defaults_source.m_dyn_sock_opts,
143 printout_only);
144} // Node_options::setup_config_parsing_helper()
145
147{
148 // Set up *opts_desc to parse into *this when the caller chooses to. Take defaults from *this.
149 setup_config_parsing_helper(opts_desc, this, *this, false);
150} // Node_options::setup_config_parsing()
151
152std::ostream& operator<<(std::ostream& os, const Node_options& opts)
153{
154 Node_options sink;
155 Node_options::Options_description opts_desc("Per-net_flow::Node option values");
156 Node_options::setup_config_parsing_helper(&opts_desc, &sink, opts, true);
157 return os << opts_desc;
158}
159
160std::string Node_options::opt_id_to_str(const std::string& opt_id) // Static.
161{
162 using boost::algorithm::starts_with;
163 using boost::algorithm::replace_all;
164 using std::string;
165
166 const string STATIC_PREFIX = "m_st_";
167 const string DYNAMIC_PREFIX = "m_dyn_";
168
169 string str = opt_id;
170 if (starts_with(opt_id, STATIC_PREFIX))
171 {
172 str.erase(0, STATIC_PREFIX.size());
173 }
174 else if (starts_with(opt_id, DYNAMIC_PREFIX))
175 {
176 str.erase(0, DYNAMIC_PREFIX.size());
177 }
178
179 replace_all(str, "_", "-");
180
181 return str;
182}
183
185 /* Should be a safe UDP datagram size. @todo Not a totally solid statement... plus it's too low;
186 * increasing to ~1500 increases throughput hugely. Choosing it dynamically is a @todo elsewhere
187 * in the code. */
188 m_st_max_block_size(1024),
189 // Initial value recommended by RFC 6298 is 1 sec but seems too conservative. @todo Decide.
190 m_st_connect_retransmit_period(boost::chrono::milliseconds(125)),
191 // @todo.
192 m_st_connect_retransmit_timeout(boost::chrono::seconds(3)),
193 /* @todo Reconsider. See also to-do in class Node doc header.
194 * WARNING! If you change this, ensure s_st_max_cong_wnd_blocks is still sufficiently small. */
195 m_st_snd_buf_max_size(6 * 1024 * 1024),
196 // @todo Ditto.
197 m_st_rcv_buf_max_size(m_st_snd_buf_max_size),
198 // Disabling flow control is an emergency measure only.
199 m_st_rcv_flow_control_on(true),
200 // Seems reasonable. Should be a few hundred KB typically.
201 m_st_rcv_buf_max_size_slack_percent(10),
202 /* The value 50% is taken from BSD implementation (Stevens/Wright, TCP/IP Illustrated Vol. 2,
203 * 1995), although it's barely discussed there. It does make sense though; it should give the
204 * sender a large window to work with but also leave some time to allow our application layer to
205 * read off more bytes from Receive buffer after advertising the window at this mark. */
206 m_st_rcv_buf_max_size_to_advertise_percent(50),
207 /* This allows for about 2.2 Received_packet struct per maximally large packet in
208 * m_rcv_packets_with_gaps. So it's something like 10-20 bytes per 1k of DATA, or about 2-4%
209 * overhead. So it's conservative in terms of memory use. For any reasonably large max Receive
210 * buffer size, it's also at least 100 packets. If 100 packets arrive numbering higher than
211 * unreceived packet P, it's a VERY good bet P will never arrive. Thus it's also conservative in
212 * terms of loss. Finally, since this formula allows enough space to hold an entire
213 * m_rcv_syn_rcvd_data_q's worth of queued up packets, it won't throw away any queued up
214 * packets in SYN_RCVD state. */
215 m_st_rcv_max_packets_after_unrecvd_packet_ratio_percent(220),
216 // Satisfies RFC 5681 (500 ms max); taken from BSD implementation (Stevens/Wright, TCP/IP Illustrated Vol. 2, 1995).
217 m_st_delayed_ack_timer_period(boost::chrono::milliseconds(200)),
218 // Per RFC 5681.
219 m_st_max_full_blocks_before_ack_send(2),
220 m_st_rexmit_on(true),
221 // @todo Experiment and look at RFCs.
222 m_st_max_rexmissions_per_packet(15),
223 // @todo Experiment. RFC 6298 recommends this value.
224 m_st_init_drop_timeout(boost::chrono::seconds(1)),
225 // @todo Experiment. Choosing less aggressive values for now, except for m_st_drop_all_on_drop_timeout.
226 m_st_drop_packet_exactly_after_drop_timeout(false),
227 // Consistent with RFC 4341, but see discussion where it's used.
228 m_st_drop_all_on_drop_timeout(true),
229 // @todo Experiment. Choosing less aggressive values for now, except for m_st_drop_all_on_drop_timeout.
230 m_st_out_of_order_ack_restarts_drop_timer(true),
231 // @todo Experiment.
232 m_st_snd_pacing_enabled(true),
233 /* Value taken from Linux's westwood.c which was written by the creators of Westwood+ bandwidth
234 * estimation algorithm themselves. 50 msec seems like a reasonable line in the sand between
235 * "small RTT" and "medium RTT." */
236 m_st_snd_bandwidth_est_sample_period_floor(boost::chrono::milliseconds(50)),
237 // Pass in a non-existent strategy ID, which will cause our operator<<() to choose what it considers the default.
238 m_st_cong_ctl_strategy(boost::lexical_cast<Congestion_control_strategy_choice>("none")),
239 // Let code choose initial CWND using RFC 5681 method.
240 m_st_cong_ctl_init_cong_wnd_blocks(0),
241 /* See the constraints in the doc header for this constant. That said, here are the calculations I
242 * used to get 640:
243 *
244 * this option = B * RTT / max-block-size = 100 Mbits/sec * 50 msec * 1/1024 blocks/byte = 100
245 * Mbits/sec * 50 msec * 1/1000 sec/msec * 1/8 Mbytes/Mbits * 1024*1024 bytes/Mbytes / 1024 bytes
246 * = (100*50/1000/8*1024*1024/1024) blocks = 640 blocks. (Note the units cancel out properly.)
247 *
248 * Receive buffer is currently 6 Mbytes. 6 Mbytes / 640 blocks = 6 * 1024 * 1024 / (640 * 1024),
249 * which is a Receive buffer-to-CWND ratio of 9.6s.
250 *
251 * WARNING! If you change this, ensure m_st_max_rcv_buf_size is still sufficiently large. */
252 m_st_cong_ctl_max_cong_wnd_blocks(640),
253 // Per RFC 5681-3.1.
254 m_st_cong_ctl_cong_wnd_on_drop_timeout_blocks(1),
255 // Use RFC 5681 default (0 is special value).
256 m_st_cong_ctl_cong_avoidance_increment_blocks(0),
257 // Use RFC 5681 default (0 is special value).
258 m_st_cong_ctl_classic_wnd_decay_percent(0),
259 // The minimal allowed ceiling by RFC 6298.
260 m_dyn_drop_timeout_ceiling(boost::chrono::seconds(60)),
261 // RFC 6298 recommends this value.
262 m_dyn_drop_timeout_backoff_factor(2),
263 // This shouldn't be too bad. @todo Though it should probably be based off DTO or something....
264 m_dyn_rcv_wnd_recovery_timer_period(boost::chrono::seconds(1)),
265 // Seems OK. After a minute it's probably a lost cause.
266 m_dyn_rcv_wnd_recovery_max_period(boost::chrono::minutes(1))
267{
268 // Nothing.
269}
270
272 Peer_socket_options* target,
273 const Peer_socket_options& defaults_source,
274 bool printout_only) // Static.
275{
276 using std::vector;
277 using std::string;
278 using boost::algorithm::join;
279
280 // Build the comma-separated list of possible string values for enum m_st_cong_ctl_strategy, for help output.
281 vector<string> cong_strategy_ids;
282 Congestion_control_selector::get_ids(&cong_strategy_ids);
283 const string str_cong_strategy_ids = join(cong_strategy_ids, ", ");
284
285 ADD_CONFIG_OPTION
287 "The size of block that we will strive to (and will, assuming at least that many bytes are "
288 "available in Send buffer) pack into each outgoing DATA packet. It is assumed the other side is "
289 "following the same policy (any packets that do not -- i.e., exceed this size -- are dropped). "
290 "This is an important control; the higher it is the better for performance AS LONG AS it's not so "
291 "high it undergoes IP fragmentation (or does that even happen in UDP? if not, even worse -- "
292 "it'll just be dropped and not sent!). The performance impact is major; e.g., assuming no "
293 "fragmentation/dropping, we've seen a ~1500 byte MBS result in 20-30% higher throughput than "
294 "1024 byte MBS. "
295 "Additionally, if using net_flow module with no reliability feature -- i.e., if you want to perform FEC "
296 "or something else outside the Flow protocol -- then it is absolutely essential that EVERY send*() call "
297 "provides a buffer whose size is a multiple of max-block-size. Otherwise packet boundaries "
298 "will not be what you expect, and you will get what seems to be corrupted data at the "
299 "application layer (since our stream-based API has no way of knowing where your message begins "
300 "or ends). Alternatively you can encode message terminators or packet sizes, but since in "
301 "unreliable mode integrity of a given block is guaranteed only if all blocks align with "
302 "max-block-size boundaries, you'll still probably be screwed.");
303 ADD_CONFIG_OPTION
305 "How often to resend SYN or SYN_ACK while SYN_ACK or SYN_ACK_ACK, respectively, has not been received. "
306 "In other words, this controls the pause between retries during the connection opening phase, by either side, "
307 "if the other side is not responding with the appropriate response. "
308 "Examples: \"250 ms\", \"1 s\".");
309 ADD_CONFIG_OPTION
311 "How long from the first SYN or SYN_ACK to allow for connection handshake before aborting connection. "
312 "Examples: \"5500 ms\", \"60 seconds\".");
313 ADD_CONFIG_OPTION
315 "Maximum number of bytes that the Send buffer can hold. This determines how many bytes user can "
316 "send() while peer cannot send over network until send() refuses to take any more bytes. Note "
317 "that any value given will be increased, if necessary, to the nearest multiple of "
318 "max-block-size. This is important to preserve message boundaries when operating in "
319 "unreliable mode (guaranteed max-block-size-sized chunks of data will be sent out in their "
320 "entirety instead of being fragmented).");
321 ADD_CONFIG_OPTION
323 "Maximum number of bytes that the Receive buffer can hold. This determines how many bytes "
324 "can be received in the background by the Node without user doing any receive()s. "
325 "It is also rounded up to to the nearest multiple of max-block-size.");
326 ADD_CONFIG_OPTION
328 "Whether flow control (a/k/a receive window a/k/a rcv_wnd management) is enabled. If this is "
329 "disabled, an infinite rcv_wnd will always be advertised to the sender; so if the Receive buffer "
330 "is exceeded packets are dropped as normal, but the sender will not know it should stop sending "
331 "until Receive buffer space is freed. If this is enabled, we keep the sender informed of how "
332 "much Receive buffer space is available, so it can suspend the flow as necessary.");
333 ADD_CONFIG_OPTION
335 "% of rcv-buf-max-size such that if Receive buffer stores up to (100 + this many) % of "
336 "rcv-buf-max-size bytes, the bytes will still be accepted. In other words, this allows the max "
337 "Receive buffer to hold slightly more than rcv-buf-max-size bytes. However, the current Receive "
338 "buffer capacity advertised to the other side of the connection will be based on the "
339 "non-inflated rcv-buf-max-size. This option provides some protection against the fact that the "
340 "receive window value sent to the other side will lag behind reality somewhat.");
341 ADD_CONFIG_OPTION
343 "% of rcv-buf-max-size that has to be freed, since the last receive window advertisement, via "
344 "user popping data from Receive buffer, before we must send a receive window advertisement. "
345 "Normally we send rcv_wnd to the other side opportunistically in every ACK; but there can be "
346 "situations when there is no packets to acknowledge, and hence we must specifically make a "
347 "packet just to send over rcv_wnd. Typically we should only need to do this if the buffer was "
348 "exceeded and is now significantly freed. This value must be in [1, 100], but anything over 50 "
349 "is probably pushing it.");
350 ADD_CONFIG_OPTION
352 "The limit on the size of Peer_socket::m_rcv_packets_with_gaps, expressed as what percentage the "
353 "maximal size of that structure times max-block-size is of the maximal Receive buffer size. For "
354 "example, if this is 200, then Peer_socket::m_rcv_packets_with_gaps can represent up to roughly "
355 "2x as many full-sized blocks as the Receive buffer can. This should also by far exceed any "
356 "sender congestion window max size to avoid packet loss. m_rcv_packets_with_gaps consists of all packets "
357 "such that at least one packet sequentially preceding them has not yet been received.");
358 ADD_CONFIG_OPTION
360 "The maximum amount of time to delay sending ACK with individual packet's acknowledgment since "
361 "receiving that individual packet. If set to zero duration, any given individual acknowledgment "
362 "is sent within a non-blocking amount of time of its DATA packet being read. Inspired by RFC "
363 "1122-4.2.3.2. Examples: \"200 ms\", \"550200 microseconds\".");
364 ADD_CONFIG_OPTION
366 "If there are at least this many TIMES max-block-size bytes' worth of individual acknowledgments "
367 "to be sent, then the delayed ACK timer is to be short-circuited, and the accumulated "
368 "acknowledgments are to be sent as soon as possible. Inspired by RFC 5681.");
369 ADD_CONFIG_OPTION
371 "Whether to enable reliability via retransmission. If false, a detected lost packet may have "
372 "implications on congestion control (speed at which further data are sent) but will not cause "
373 "that packet to be resent; receiver application code either has to be OK with missing packets or "
374 "must implement its own reliability (e.g., FEC). Packets may also be delivered in an order "
375 "different from the way they were sent. If true, the receiver need not worry about it, as any "
376 "lost packets will be retransmitted with no participation from the application code on either "
377 "side, as in TCP. Also as in TCP, this adds order preservation, so that the stream of bytes sent "
378 "will be exactly equal to the stream of bytes received. Retransmission removes the requirement "
379 "for the very exacting block-based way in which send() and friends must be called. "
380 "This option must have the same value on both sides of the connection, or the server will refuse "
381 "the connection.");
382 ADD_CONFIG_OPTION
384 "If retransmission is enabled and a given packet is retransmitted this many times and has to be "
385 "retransmitted yet again, the connection is reset. Should be positive.");
386 ADD_CONFIG_OPTION
388 "Once socket enters ESTABLISHED state, this is the value for m_snd_drop_timeout before the first RTT "
389 "measurement is made (the first valid acknowledgment arrives). Example: \"2 seconds\".");
390 ADD_CONFIG_OPTION
392 "If true, when scheduling Drop Timer, schedule it for Drop Timeout relative to the send time of "
393 "the earliest In-flight packet at the time. If false, also schedule DTO relative to the time of "
394 "scheduling. The latter is less aggressive and is recommended by RFC 6298.");
395 ADD_CONFIG_OPTION
397 "If true, when the Drop Timer fires, all In-flight packets are to be considered Dropped (and "
398 "thus the timer is to be disabled). If false, only the earliest In-flight packet is to be "
399 "considered Dropped (and thus the timer is to restart). RFC 6298 recommends false. true is more aggressive.");
400 ADD_CONFIG_OPTION
402 "If an In-flight packet is acknowledged, but it is not the earliest In-flight packet (i.e., it's "
403 "an out-of-order acknowledgment), and this is true, the timer is restarted. Otherwise the timer "
404 "continues to run. The former is less aggressive. RFC 6298 wording is ambiguous on what it "
405 "recommends (not clear if cumulative ACK only, or if SACK also qualifies).");
406 ADD_CONFIG_OPTION
408 "When estimating the available send bandwidth, each sample must be compiled over at least this long "
409 "of a time period, even if the SRTT is lower. Normally a sample is collected over at least an SRTT, but "
410 "computing a bandwidth sample over a quite short time period can produce funky results, hence this floor. "
411 "Send bandwidth estimation is used at least for some forms of congestion control.");
412 ADD_CONFIG_OPTION
414 "Enables or disables packet pacing, which attempts to spread out, without sacrificing overall "
415 "send throughput, outgoing low-level packets to prevent loss. If disabled, any packet that is "
416 "allowed by congestion/flow control to be sent over the wire is immediately sent to the UDP "
417 "net-stack; so for example if 200 packets are ready to send and are allowed to be sent, they're sent "
418 "at the same time. If enabled, they will be spread out over a reasonable time period instead. "
419 "Excessive burstiness can lead to major packet drops, so this can really help.");
420 ADD_CONFIG_OPTION
422 (string("The congestion control algorithm to use for the connection or connections. The choices are: [") +
423 str_cong_strategy_ids + "].").c_str());
424 ADD_CONFIG_OPTION
426 "The initial size of the congestion window, given in units of max-block-size-sized blocks. "
427 "The special value 0 means RFC 5681's automatic max-block-size-based computation should "
428 "be used instead.");
429 ADD_CONFIG_OPTION
431 "The constant that determines the CWND limit in congestion_window_at_limit() and "
432 "clamp_congestion_window() (in multiple of max-block-size). When choosing this value, use these "
433 "constraints: "
434 "(1) This limits total outgoing throughput. The throughput B will be <= CWND/RTT, where RTT is "
435 "roughly the RTT of the connection, and CWND == S_MAX_CONG_WND_BLOCKS * max-block-size. "
436 "Therefore, choose B and RTT values and set S_MAX_CONG_WND_BLOCKS = B * RTT / max-block-size "
437 "(B in bytes/second, RTT in seconds). "
438 "(2) Until we implement Receive window, this value should be much (say, 4x) less than the size "
439 "of the Receive buffer, to avoid situations where even a well-behaving user (i.e., user that "
440 "receive()s all data ASAP) cannot keep up with reading data off Receive buffer, forcing "
441 "net_flow to drop large swaths of incoming traffic. If CWND is much smaller than Receive "
442 "buffer size, then this avoids that problem.");
443 ADD_CONFIG_OPTION
445 "On Drop Timeout, set congestion window to this value times max-block-size.");
446 ADD_CONFIG_OPTION
448 "The multiple of max-block-size by which to increment CWND in congestion avoidance mode after receiving "
449 "at least a full CWND's worth of clean acknowledgments. RFC 5681 (classic Reno) mandates this is set to 1, "
450 "but we allow it to be overridden. The special value 0 causes the RFC value to be used.");
451 ADD_CONFIG_OPTION
453 "In classic congestion control, RFC 5681 specified the window should be halved on loss; this "
454 "option allows one to use a customer percentage instead. This should be a value in [1, "
455 "100] to have the window decay to that percentage of its previous value, or 0 to use the RFC "
456 "5681-recommended constant (50).");
457 ADD_CONFIG_OPTION
459 "Whenever the Drop Timer fires, upon the requisite Dropping of packet(s), the DTO (Drop Timeout) "
460 "is set to its current value times this factor, and then the timer is rescheduled accordingly. "
461 "RFC 6298 recommends 2. Another value might be 1 (disable feature). The lower the more "
462 "aggressive.");
463 ADD_CONFIG_OPTION
465 "When the mode triggered by rcv-buf-max-size-to-advertise-percent being exceeded is in effect, "
466 "to counteract the possibility of ACK loss the receive window is periodically advertised "
467 "subsequently -- with the period given by this option -- until either some new data arrive or "
468 "rcv-wnd-recovery-max-period is exceeded. Example: \"5 s\".");
469 ADD_CONFIG_OPTION
471 "Approximate amount of time since the beginning of rcv_wnd recovery due to "
472 "rcv-buf-max-size-to-advertise-percent until we give up and end that phase. Example: \"30 s\".");
473 ADD_CONFIG_OPTION
475 "Ceiling to impose on the Drop Timeout. Example: \"120 s\".");
476} // Peer_socket_options::setup_config_parsing_helper()
477
479{
480 // Set up *opts_desc to parse into *this when the caller chooses to. Take defaults from *this.
481 setup_config_parsing_helper(opts_desc, this, *this, false);
482} // Node_options::setup_config_parsing()
483
484std::ostream& operator<<(std::ostream& os, const Peer_socket_options& opts)
485{
487 Peer_socket_options::Options_description opts_desc("Per-net_flow::Peer_socket option values");
488 Peer_socket_options::setup_config_parsing_helper(&opts_desc, &sink, opts, true);
489 return os << opts_desc;
490}
491
492#undef ADD_CONFIG_OPTION // For cleanliness.
493
494} // namespace flow::net_flow
static void get_ids(std::vector< std::string > *ids)
Returns a list of strings, called IDs, each of which textually represents a distinct Congestion_contr...
Definition: cong_ctl.cpp:115
Flow module containing the API and implementation of the Flow network protocol, a TCP-inspired stream...
Definition: node.cpp:25
std::ostream & operator<<(std::ostream &os, const Congestion_control_selector::Strategy_choice &strategy_choice)
Serializes a Peer_socket_options::Congestion_control_strategy_choice enum to a standard ostream – the...
Definition: cong_ctl.cpp:146
A set of low-level options affecting a single Flow Node, including Peer_socket objects and other obje...
Definition: options.hpp:449
static void setup_config_parsing_helper(Options_description *opts_desc, Node_options *target, const Node_options &defaults_source, bool printout_only)
Loads the full set of boost.program_options config options into the given Options_description,...
Definition: options.cpp:80
void setup_config_parsing(Options_description *opts_desc)
Modifies a boost.program_options options description object to enable subsequent parsing of a command...
Definition: options.cpp:146
Node_options()
Constructs a Node_options with values equal to those used by Node when the Node creator chooses not t...
Definition: options.cpp:41
Peer_socket_options m_dyn_sock_opts
The set of per-Peer_socket options in this per-Node set of options.
Definition: options.hpp:580
size_t m_st_low_lvl_max_buf_size
The max size to ask the OS to set our UDP socket's receive buffer to in order to minimize loss if we ...
Definition: options.hpp:525
size_t m_dyn_low_lvl_max_packet_size
Any incoming low-level (UDP) packet will be truncated to this size.
Definition: options.hpp:553
unsigned int m_dyn_max_packets_per_main_loop_iteration
The UDP net-stack may deliver 2 or more datagrams to the Flow Node at the same time.
Definition: options.hpp:545
static void add_config_option(Options_description *opts_desc, const std::string &opt_id, Opt_type *target_val, const Opt_type &default_val, const char *description, bool printout_only)
A helper that adds a single option to a given Options_description, for use either in printing out the...
Definition: options.cpp:61
static std::string opt_id_to_str(const std::string &opt_id)
Helper that, for a given option m_blah, takes something like "m_blah_blah" and returns the similar mo...
Definition: options.cpp:160
Fine_duration m_st_timer_min_period
A time period such that the boost.asio timer implementation for this platform is able to accurately a...
Definition: options.hpp:534
bool m_dyn_guarantee_one_low_lvl_in_buf_per_socket
This very inside-baseball setting controls the allocation/copy behavior of the UDP receive-deserializ...
Definition: options.hpp:568
bool m_st_capture_interrupt_signals_internally
If and only if this is true, the Node will detect SIGINT and SIGTERM (or your OS's version thereof); ...
Definition: options.hpp:517
Peer_socket_options::Options_description Options_description
Short-hand for boost.program_options config options description. See setup_config_parsing().
Definition: options.hpp:453
A set of low-level options affecting a single Peer_socket.
Definition: options.hpp:36
Fine_duration m_st_init_drop_timeout
Once socket enters ESTABLISHED state, this is the value for Peer_socket::m_snd_drop_timeout until the...
Definition: options.hpp:226
unsigned int m_st_max_rexmissions_per_packet
If retransmission is enabled and a given packet is retransmitted this many times and has to be retran...
Definition: options.hpp:220
size_t m_st_rcv_buf_max_size
Maximum number of bytes that the Receive buffer can hold.
Definition: options.hpp:141
size_t m_st_cong_ctl_max_cong_wnd_blocks
The constant that determines the CWND limit in Congestion_control_classic_data::congestion_window_at_...
Definition: options.hpp:296
Fine_duration m_st_snd_bandwidth_est_sample_period_floor
When estimating the available send bandwidth, each sample must be compiled over at least this long of...
Definition: options.hpp:267
unsigned int m_st_cong_ctl_cong_avoidance_increment_blocks
The multiple of max-block-size by which to increment CWND in congestion avoidance mode after receivin...
Definition: options.hpp:306
size_t m_st_cong_ctl_cong_wnd_on_drop_timeout_blocks
On Drop Timeout, set congestion window to this value times max-block-size.
Definition: options.hpp:299
Fine_duration m_dyn_rcv_wnd_recovery_max_period
Approximate amount of time since the beginning of rcv_wnd recovery due to rcv-buf-max-size-to-adverti...
Definition: options.hpp:339
Congestion_control_strategy_choice
The possible choices for congestion control strategy for the socket.
Definition: options.hpp:63
size_t m_st_cong_ctl_init_cong_wnd_blocks
The initial size of the congestion window, given in units of max-block-size-sized blocks.
Definition: options.hpp:277
bool m_st_drop_packet_exactly_after_drop_timeout
If true, when scheduling Drop Timer, schedule it for Drop Timeout relative to the send time of the ea...
Definition: options.hpp:233
bool m_st_rexmit_on
Whether to enable reliability via retransmission.
Definition: options.hpp:214
size_t m_st_snd_buf_max_size
Maximum number of bytes that the Send buffer can hold.
Definition: options.hpp:134
Fine_duration m_st_connect_retransmit_period
How often to resend SYN or SYN_ACK while SYN_ACK or SYN_ACK_ACK, respectively, has not been received.
Definition: options.hpp:121
unsigned int m_st_rcv_buf_max_size_slack_percent
% of rcv-buf-max-size such that if Receive buffer stores up to (100 + this many) % of rcv-buf-max-siz...
Definition: options.hpp:160
void setup_config_parsing(Options_description *opts_desc)
Analogous to Node_options::setup_config_parsing().
Definition: options.cpp:478
Peer_socket_options()
Constructs a Peer_socket_options with values equal to those used by Node when the Node creator choose...
Definition: options.cpp:184
Fine_duration m_dyn_rcv_wnd_recovery_timer_period
When the mode triggered by rcv-buf-max-size-to-advertise-percent being exceeded is in effect,...
Definition: options.hpp:333
bool m_st_drop_all_on_drop_timeout
If true, when the Drop Timer fires, all In-flight packets are to be considered Dropped (and thus the ...
Definition: options.hpp:240
Fine_duration m_st_connect_retransmit_timeout
How long from the first SYN or SYN_ACK to allow for connection handshake before aborting connection.
Definition: options.hpp:124
Congestion_control_strategy_choice m_st_cong_ctl_strategy
The congestion control algorithm to use for the connection or connections.
Definition: options.hpp:270
static void setup_config_parsing_helper(Options_description *opts_desc, Peer_socket_options *target, const Peer_socket_options &defaults_source, bool printout_only)
Analogous to Node_options::setup_config_parsing_helper().
Definition: options.cpp:271
boost::program_options::options_description Options_description
Short-hand for boost.program_options config options description. See setup_config_parsing().
Definition: options.hpp:40
size_t m_st_max_full_blocks_before_ack_send
If there are at least this many TIMES max-block-size bytes' worth of individual acknowledgments to be...
Definition: options.hpp:198
bool m_st_snd_pacing_enabled
Enables or disables packet pacing, which attempts to spread out, without sacrificing overall send thr...
Definition: options.hpp:258
bool m_st_rcv_flow_control_on
Whether flow control (a/k/a receive window a/k/a rcv_wnd management) is enabled.
Definition: options.hpp:150
Fine_duration m_st_delayed_ack_timer_period
The maximum amount of time to delay sending ACK with individual packet's acknowledgment since receivi...
Definition: options.hpp:191
unsigned int m_dyn_drop_timeout_backoff_factor
Whenever the Drop Timer fires, upon the requisite Dropping of packet(s), the DTO (Drop Timeout) is se...
Definition: options.hpp:325
bool m_st_out_of_order_ack_restarts_drop_timer
If an In-flight packet is acknowledged, but it is not the earliest In-flight packet (i....
Definition: options.hpp:248
size_t m_st_max_block_size
The size of block that we will strive to (and will, assuming at least that many bytes are available i...
Definition: options.hpp:114
unsigned int m_st_cong_ctl_classic_wnd_decay_percent
In classic congestion control, RFC 5681 specifies the window should be halved on loss; this option al...
Definition: options.hpp:314
unsigned int m_st_rcv_buf_max_size_to_advertise_percent
% of rcv-buf-max-size that has to be freed, since the last receive window advertisement,...
Definition: options.hpp:171
unsigned int m_st_rcv_max_packets_after_unrecvd_packet_ratio_percent
The limit on the size of Peer_socket::m_rcv_packets_with_gaps, expressed as what percentage the maxim...
Definition: options.hpp:183
Fine_duration m_dyn_drop_timeout_ceiling
Ceiling to impose on the Drop Timeout.
Definition: options.hpp:317