- ip4_address_t v4start, v4end;
- ip6_address_t v6start, v6end;
- int v4set = 0;
- int v6set = 0;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "%U - %U", unformat_ip4_address, &v4start,
- unformat_ip4_address, &v4end))
- v4set = 1;
- else if (unformat (input, "%U", unformat_ip4_address, &v4start))
- {
- memcpy (&v4end, &v4start, sizeof (v4start));
- v4set = 1;
- }
- else if (unformat (input, "%U - %U", unformat_ip6_address, &v6start,
- unformat_ip4_address, &v6end))
- v6set = 1;
- else if (unformat (input, "%U", unformat_ip6_address, &v6start))
- {
- memcpy (&v6end, &v6start, sizeof (v4start));
- v6set = 1;
- }
- else
- break;
- }
-
- if (!v4set && !v6set)
- return clib_error_return (0, "at least one v4 or v6 address required");
-
- if (v4set)
- {
- u32 tmp;
-
- do
- {
- vec_add1 (tm->ip4_src_addresses, v4start);
- tmp = clib_net_to_host_u32 (v4start.as_u32);
- tmp++;
- v4start.as_u32 = clib_host_to_net_u32 (tmp);
- }
- while (clib_host_to_net_u32 (v4start.as_u32) <=
- clib_host_to_net_u32 (v4end.as_u32));
- }
- if (v6set)
- {
- clib_warning ("v6 src address list unimplemented...");
- }
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (tcp_src_address_command, static) =
-{
- .path = "tcp src-address",
- .short_help = "tcp src-address <ip-addr> [- <ip-addr>] add src address range",
- .function = tcp_src_address,
-};
-/* *INDENT-ON* */
-
-static u8 *
-tcp_scoreboard_dump_trace (u8 * s, sack_scoreboard_t * sb)
-{
-#if TCP_SCOREBOARD_TRACE
-
- scoreboard_trace_elt_t *block;
- int i = 0;
-
- if (!sb->trace)
- return s;
-
- s = format (s, "scoreboard trace:");
- vec_foreach (block, sb->trace)
- {
- s = format (s, "{%u, %u, %u, %u, %u}, ", block->start, block->end,
- block->ack, block->snd_una_max, block->group);
- if ((++i % 3) == 0)
- s = format (s, "\n");
- }
- return s;
-#else
- return 0;
-#endif
-}
-
-static clib_error_t *
-tcp_show_scoreboard_trace_fn (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd_arg)
-{
- transport_connection_t *tconn = 0;
- tcp_connection_t *tc;
- u8 *s = 0;
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "%U", unformat_transport_connection, &tconn,
- TRANSPORT_PROTO_TCP))
- ;
- else
- return clib_error_return (0, "unknown input `%U'",
- format_unformat_error, input);
- }
-
- if (!TCP_SCOREBOARD_TRACE)
- {
- vlib_cli_output (vm, "scoreboard tracing not enabled");
- return 0;
- }
-
- tc = tcp_get_connection_from_transport (tconn);
- s = tcp_scoreboard_dump_trace (s, &tc->sack_sb);
- vlib_cli_output (vm, "%v", s);
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (tcp_show_scoreboard_trace_command, static) =
-{
- .path = "show tcp scoreboard trace",
- .short_help = "show tcp scoreboard trace <connection>",
- .function = tcp_show_scoreboard_trace_fn,
-};
-/* *INDENT-ON* */
-
-u8 *
-tcp_scoreboard_replay (u8 * s, tcp_connection_t * tc, u8 verbose)
-{
- int i, trace_len;
- scoreboard_trace_elt_t *trace;
- u32 next_ack, left, group, has_new_ack = 0;
- tcp_connection_t _dummy_tc, *dummy_tc = &_dummy_tc;
- sack_block_t *block;
-
- if (!tc)
- return s;
-
- memset (dummy_tc, 0, sizeof (*dummy_tc));
- tcp_connection_timers_init (dummy_tc);
- scoreboard_init (&dummy_tc->sack_sb);
- dummy_tc->rcv_opts.flags |= TCP_OPTS_FLAG_SACK;
-
-#if TCP_SCOREBOARD_TRACE
- trace = tc->sack_sb.trace;
- trace_len = vec_len (tc->sack_sb.trace);
-#else
- trace = 0;
- trace_len = 0;
-#endif
-
- for (i = 0; i < trace_len; i++)
- {
- if (trace[i].ack != 0)
- {
- dummy_tc->snd_una = trace[i].ack - 1448;
- dummy_tc->snd_una_max = trace[i].ack;
- }
- }
-
- left = 0;
- while (left < trace_len)
- {
- group = trace[left].group;
- vec_reset_length (dummy_tc->rcv_opts.sacks);
- has_new_ack = 0;
- while (trace[left].group == group)
- {
- if (trace[left].ack != 0)
- {
- if (verbose)
- s = format (s, "Adding ack %u, snd_una_max %u, segs: ",
- trace[left].ack, trace[left].snd_una_max);
- dummy_tc->snd_una_max = trace[left].snd_una_max;
- next_ack = trace[left].ack;
- has_new_ack = 1;
- }
- else
- {
- if (verbose)
- s = format (s, "[%u, %u], ", trace[left].start,
- trace[left].end);
- vec_add2 (dummy_tc->rcv_opts.sacks, block, 1);
- block->start = trace[left].start;
- block->end = trace[left].end;
- }
- left++;
- }
-
- /* Push segments */
- tcp_rcv_sacks (dummy_tc, next_ack);
- if (has_new_ack)
- dummy_tc->snd_una = next_ack + dummy_tc->sack_sb.snd_una_adv;