cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/* $Id$ */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** @file
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * NetPerf - Network Performance Benchmark.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Copyright (C) 2010-2014 Oracle Corporation
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * available from http://www.virtualbox.org. This file is free software;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * General Public License (GPL) as published by the Free Software
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * The contents of this file may alternatively be used under the terms
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * of the Common Development and Distribution License Version 1.0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * VirtualBox OSE distribution, in which case the provisions of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * CDDL are applicable instead of those of the GPL.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * You may elect to license modified versions of this file under the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * terms and conditions of either the GPL or the CDDL or both.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*******************************************************************************
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync* Header Files *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync*******************************************************************************/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/asm.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/assert.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/ctype.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/err.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/getopt.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/initterm.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/mem.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/message.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/path.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/param.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/process.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/rand.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/stream.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/string.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/tcp.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/thread.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/test.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/time.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/timer.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*******************************************************************************
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync* Defined Constants And Macros *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync*******************************************************************************/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Default TCP port (update help text if you change this) */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_DEFAULT_PORT 5002
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Default TCP packet size (bytes) */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_DEFAULT_PKT_SIZE_THROUGHPUT 8192
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Default TCP packet size (bytes) */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_DEFAULT_PKT_SIZE_LATENCY 1024
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Maximum packet size possible (bytes). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_MAX_PKT_SIZE _1M
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Minimum packet size possible (bytes). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_MIN_PKT_SIZE sizeof(NETPERFHDR)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Default timeout in (seconds) */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_DEFAULT_TIMEOUT 10
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Maximum timeout possible (seconds). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_MAX_TIMEOUT 3600 /* 1h */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Minimum timeout possible (seconds). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_MIN_TIMEOUT 1
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** The default warmup time (ms). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_DEFAULT_WARMUP 1000 /* 1s */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** The maxium warmup time (ms). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_MAX_WARMUP 60000 /* 60s */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** The minimum warmup time (ms). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_MIN_WARMUP 1000 /* 1s */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** The default cool down time (ms). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_DEFAULT_COOL_DOWN 1000 /* 1s */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** The maxium cool down time (ms). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_MAX_COOL_DOWN 60000 /* 60s */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** The minimum cool down time (ms). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_MIN_COOL_DOWN 1000 /* 1s */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** The length of the length prefix used when submitting parameters and
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * results. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERF_LEN_PREFIX 4
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*******************************************************************************
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync* Structures and Typedefs *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync*******************************************************************************/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynctypedef enum NETPERFPROTO
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFPROTO_INVALID = 0,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFPROTO_TCP
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync //NETPERFPROTO_UDP
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync} NETPERFPROTO;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * What kind of test we're performing.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynctypedef enum NETPERFMODE
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFMODE_INVALID = 0,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Latency of a symmetric packet exchange. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFMODE_LATENCY,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Separate throughput measurements for each direction. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFMODE_THROUGHPUT,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Transmit throughput. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFMODE_THROUGHPUT_XMIT,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Transmit throughput. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFMODE_THROUGHPUT_RECV
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync} NETPERFMODE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Statistics.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynctypedef struct NETPERFSTATS
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t cTx;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t cRx;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t cEchos;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t cErrors;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t cNsElapsed;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync} NETPERFSTATS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Settings & a little bit of state.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynctypedef struct NETPERFPARAMS
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** @name Static settings
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @{ */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** The TCP port number. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uPort;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Client: Use server statistcs. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool fServerStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Server: Quit after the first client. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool fSingleClient;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** @} */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** @name Dynamic settings
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @{ */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Disable send packet coalescing. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool fNoDelay;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Detect broken payloads. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool fCheckData;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** The test mode. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFMODE enmMode;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** The number of seconds to run each of the test steps. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t cSecTimeout;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Number of millisecond to spend warning up before testing. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t cMsWarmup;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Number of millisecond to spend cooling down after the testing. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t cMsCoolDown;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** The packet size. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t cbPacket;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** @} */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** @name State
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @{ */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTSOCKET hSocket;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** @} */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync} NETPERFPARAMS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Packet header used in tests.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Need to indicate when we've timed out and it's time to reverse the roles or
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * stop testing.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynctypedef struct NETPERFHDR
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Magic value (little endian). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t u32Magic;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** State value. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t u32State;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Sequence number (little endian). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t u32Seq;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Reserved, must be zero. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t u32Reserved;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync} NETPERFHDR;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Magic value for NETPERFHDR::u32Magic. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERFHDR_MAGIC UINT32_C(0xfeedf00d)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** @name Packet State (NETPERF::u32Magic)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @{ */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Warm up. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERFHDR_WARMUP UINT32_C(0x0c0ffe01)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** The clock is running. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERFHDR_TESTING UINT32_C(0x0c0ffe02)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Stop the clock but continue the package flow. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERFHDR_COOL_DOWN UINT32_C(0x0c0ffe03)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Done, stop the clock if not done already and reply with results. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define NETPERFHDR_DONE UINT32_C(0x0c0ffe04)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** @} */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*******************************************************************************
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync* Global Variables *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync*******************************************************************************/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Connection start/identifier to make sure other end is NetPerf. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic const char g_ConnectStart[] = "yo! waaazzzzzaaaaup dude?";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Start of parameters proposal made by the client. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic const char g_szStartParams[] = "deal?";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** All okay to start test */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic const char g_szAck[] = "okay!";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Negative. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic const char g_szNegative[] = "nope!";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncAssertCompile(sizeof(g_szAck) == sizeof(g_szNegative));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Start of statistics. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic const char g_szStartStats[] = "dude, stats";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Command line parameters */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic const RTGETOPTDEF g_aCmdOptions[] =
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--server", 's', RTGETOPT_REQ_NOTHING },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--client", 'c', RTGETOPT_REQ_STRING },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--interval", 'i', RTGETOPT_REQ_UINT32 },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--port", 'p', RTGETOPT_REQ_UINT32 },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--len", 'l', RTGETOPT_REQ_UINT32 },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--nodelay", 'N', RTGETOPT_REQ_NOTHING },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--mode", 'm', RTGETOPT_REQ_STRING },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--warmpup", 'w', RTGETOPT_REQ_UINT32 },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--cool-down", 'W', RTGETOPT_REQ_UINT32 },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--server-stats", 'S', RTGETOPT_REQ_NOTHING },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--single-client", '1', RTGETOPT_REQ_NOTHING },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--daemonize", 'd', RTGETOPT_REQ_NOTHING },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--daemonized", 'D', RTGETOPT_REQ_NOTHING },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--check-data", 'C', RTGETOPT_REQ_NOTHING },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--help", 'h', RTGETOPT_REQ_NOTHING } /* for Usage() */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync};
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** The test handle. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTTEST g_hTest;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic void Usage(PRTSTREAM pStrm)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char szExec[RTPATH_MAX];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrmPrintf(pStrm, "usage: %s <-s|-c <host>> [options]\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPathFilename(RTProcGetExecutablePath(szExec, sizeof(szExec))));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrmPrintf(pStrm, "\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrmPrintf(pStrm, "options: \n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (unsigned i = 0; i < RT_ELEMENTS(g_aCmdOptions); i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync const char *pszHelp;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync switch (g_aCmdOptions[i].iShort)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'h':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Displays this help and exit";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 's':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Run in server mode, waiting for clients (default)";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'c':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Run in client mode, connecting to <host>";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'i':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Interval in seconds to run the test (default " RT_XSTR(NETPERF_DEFAULT_TIMEOUT) " s)";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'p':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Server port to listen/connect to (default " RT_XSTR(NETPERF_DEFAULT_PORT) ")";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'l':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Packet size in bytes (defaults to " RT_XSTR(NETPERF_DEFAULT_PKT_SIZE_LATENCY)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync " for latency and " RT_XSTR(NETPERF_DEFAULT_PKT_SIZE_THROUGHPUT) " for throughput)";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'm':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Test mode: latency (default), throughput, throughput-xmit or throughput-recv";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'N':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Set TCP no delay, disabling Nagle's algorithm";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'S':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Report server stats, ignored if server";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case '1':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Stop the server after the first client";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'd':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Daemonize if server, ignored if client";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'D':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync continue; /* internal */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'w':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Warmup time, in milliseconds (default " RT_XSTR(NETPERF_DEFAULT_WARMPUP) " ms)";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'W':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Cool down time, in milliseconds (default " RT_XSTR(NETPERF_DEFAULT_COOL_DOWN) " ms)";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'C':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Check payload data at the receiving end";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync default:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszHelp = "Option undocumented";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char szOpt[256];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrPrintf(szOpt, sizeof(szOpt), "%s, -%c", g_aCmdOptions[i].pszLong, g_aCmdOptions[i].iShort);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrmPrintf(pStrm, " %-20s%s\n", szOpt, pszHelp);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Timer callback employed to set the stop indicator.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * This is used both by the client and server side.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param hTimer The timer, ignored.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pvUser Pointer to the stop variable.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param iTick The tick, ignored.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic void netperfStopTimerCallback(RTTIMERLR hTimer, void *pvUser, uint64_t iTick)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool volatile *pfStop = (bool volatile *)pvUser;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/* RTPrintf("Time's Up!\n");*/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMAtomicWriteBool(pfStop, true);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NOREF(hTimer); NOREF(iTick);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Sends a statistics packet to our peer.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pStats The stats to send.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param hSocket The TCP socket to send them to.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfSendStats(NETPERFSTATS const *pStats, RTSOCKET hSocket)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char szBuf[256 + NETPERF_LEN_PREFIX];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t cch = RTStrPrintf(&szBuf[NETPERF_LEN_PREFIX], sizeof(szBuf) - NETPERF_LEN_PREFIX,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "%s:%llu:%llu:%llu:%llu:%llu",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync g_szStartStats,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pStats->cTx,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pStats->cRx,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pStats->cEchos,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pStats->cErrors,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pStats->cNsElapsed);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrPrintf(szBuf, NETPERF_LEN_PREFIX + 1, "%0*u", NETPERF_LEN_PREFIX, cch);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync szBuf[NETPERF_LEN_PREFIX] = g_szStartStats[0];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert(strlen(szBuf) == cch + NETPERF_LEN_PREFIX);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTTcpWrite(hSocket, szBuf, cch + NETPERF_LEN_PREFIX);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "stats: Failed to send stats: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Wait for ACK.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpRead(hSocket, szBuf, sizeof(g_szAck) - 1, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "stats: failed to write stats: %Rrc\n", szBuf, rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync szBuf[sizeof(g_szAck) - 1] = '\0';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!strcmp(szBuf, g_szNegative))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "stats: client failed to parse them\n", szBuf);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (strcmp(szBuf, g_szAck))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "stats: got '%s' in instead of ack/nack\n", szBuf);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return VINF_SUCCESS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Receives a statistics packet from our peer.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code. Error signalled.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pStats Where to receive the stats.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param hSocket The TCP socket to recevie them from.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfRecvStats(NETPERFSTATS *pStats, RTSOCKET hSocket)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Read the stats message.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* the length prefix */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char szBuf[256 + NETPERF_LEN_PREFIX];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTTcpRead(hSocket, szBuf, NETPERF_LEN_PREFIX, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "stats: failed to read stats prefix: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync szBuf[NETPERF_LEN_PREFIX] = '\0';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t cch;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTStrToUInt32Full(szBuf, 10, &cch);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rc != VINF_SUCCESS)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(RT_SUCCESS(rc) ? -rc : rc, "stats: bad stat length prefix: '%s' - %Rrc\n", szBuf, rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (cch >= sizeof(szBuf))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_BUFFER_OVERFLOW, "stats: too large: %u bytes\n", cch);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* the actual message */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpRead(hSocket, szBuf, cch, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "failed to read stats: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync szBuf[cch] = '\0';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Validate the message header.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( strncmp(szBuf, g_szStartStats, sizeof(g_szStartStats) - 1)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || szBuf[sizeof(g_szStartStats) - 1] != ':')
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_NET_PROTOCOL_ERROR, "stats: invalid packet start: '%s'\n", szBuf);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char *pszCur = &szBuf[sizeof(g_szStartStats)];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Parse it.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync static const char * const s_apszNames[] =
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "cTx", "cRx", "cEchos", "cErrors", "cNsElapsed"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync };
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t *apu64[RT_ELEMENTS(s_apszNames)] =
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync &pStats->cTx,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync &pStats->cRx,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync &pStats->cEchos,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync &pStats->cErrors,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync &pStats->cNsElapsed
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync };
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (unsigned i = 0; i < RT_ELEMENTS(apu64); i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!pszCur)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_PARSE_ERROR, "stats: missing %s\n", s_apszNames[i]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char *pszNext = strchr(pszCur, ':');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pszNext)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *pszNext++ = '\0';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTStrToUInt64Full(pszCur, 10, apu64[i]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rc != VINF_SUCCESS)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(RT_SUCCESS(rc) ? -rc : rc, "stats: bad value for %s: '%s' - %Rrc\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync s_apszNames[i], pszCur, rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszCur = pszNext;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pszCur)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_PARSE_ERROR, "stats: Unparsed data: '%s'\n", pszCur);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Send ACK.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpWrite(hSocket, g_szAck, sizeof(g_szAck) - 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "stats: failed to write ack: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return VINF_SUCCESS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP Throughput: Print the statistics.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pSendStats Send stats.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pRecvStats Receive stats.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param cbPacket Packet size.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic void netperfPrintThroughputStats(NETPERFSTATS const *pSendStats, NETPERFSTATS const *pRecvStats, uint32_t cbPacket)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Packet size", cbPacket, RTTESTUNIT_BYTES);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pSendStats)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync double rdSecElapsed = (double)pSendStats->cNsElapsed / 1000000000.0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Sends", pSendStats->cTx, RTTESTUNIT_PACKETS);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Send Interval", pSendStats->cNsElapsed, RTTESTUNIT_NS);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Send Throughput", (uint64_t)(cbPacket * pSendStats->cTx / rdSecElapsed), RTTESTUNIT_BYTES_PER_SEC);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Send Rate", (uint64_t)(pSendStats->cTx / rdSecElapsed), RTTESTUNIT_PACKETS_PER_SEC);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Send Latency", (uint64_t)(rdSecElapsed / pSendStats->cTx * 1000000000.0), RTTESTUNIT_NS_PER_PACKET);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pRecvStats)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync double rdSecElapsed = (double)pRecvStats->cNsElapsed / 1000000000.0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Receives", pRecvStats->cRx, RTTESTUNIT_PACKETS);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Receive Interval", pRecvStats->cNsElapsed, RTTESTUNIT_NS);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Receive Throughput", (uint64_t)(cbPacket * pRecvStats->cRx / rdSecElapsed), RTTESTUNIT_BYTES_PER_SEC);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Receive Rate", (uint64_t)(pRecvStats->cRx / rdSecElapsed), RTTESTUNIT_PACKETS_PER_SEC);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Receive Latency", (uint64_t)(rdSecElapsed / pRecvStats->cRx * 1000000000.0), RTTESTUNIT_NS_PER_PACKET);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP Throughput: Send data to the other party.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The TCP parameters block.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pBuf The buffer we're using when sending.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pSendStats Where to return the statistics.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfTCPThroughputSend(NETPERFPARAMS const *pParams, NETPERFHDR *pBuf, NETPERFSTATS *pSendStats)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RT_ZERO(*pSendStats);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Create the timer
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTIMERLR hTimer;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool volatile fStop = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTTimerLRCreateEx(&hTimer, 0 /* nsec */, RTTIMER_FLAGS_CPU_ANY, netperfStopTimerCallback, (void *)&fStop);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t u32Seq = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RT_BZERO(pBuf, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pBuf->u32Magic = RT_H2LE_U32_C(NETPERFHDR_MAGIC);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pBuf->u32State = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pBuf->u32Seq = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pBuf->u32Reserved = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Warm up.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pBuf->u32State = RT_H2LE_U32_C(NETPERFHDR_WARMUP);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTimerLRStart(hTimer, pParams->cMsWarmup * UINT64_C(1000000) /* nsec */);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (!fStop)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u32Seq++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pBuf->u32Seq = RT_H2LE_U32(u32Seq);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpWrite(pParams->hSocket, pBuf, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTcpWrite/warmup: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTimerLRStart/warmup: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * The real thing.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pBuf->u32State = RT_H2LE_U32_C(NETPERFHDR_TESTING);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fStop = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTimerLRStart(hTimer, pParams->cSecTimeout * UINT64_C(1000000000) /* nsec */);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t u64StartTS = RTTimeNanoTS();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (!fStop)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u32Seq++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pBuf->u32Seq = RT_H2LE_U32(u32Seq);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpWrite(pParams->hSocket, pBuf, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTcpWrite/testing: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pSendStats->cTx++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pSendStats->cNsElapsed = RTTimeNanoTS() - u64StartTS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTimerLRStart/testing: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Cool down.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pBuf->u32State = RT_H2LE_U32_C(NETPERFHDR_COOL_DOWN);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fStop = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTimerLRStart(hTimer, pParams->cMsCoolDown * UINT64_C(1000000) /* nsec */);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (!fStop)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u32Seq++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pBuf->u32Seq = RT_H2LE_U32(u32Seq);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpWrite(pParams->hSocket, pBuf, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTcpWrite/cool down: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTimerLRStart/testing: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Send DONE packet.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u32Seq++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pBuf->u32Seq = RT_H2LE_U32(u32Seq);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pBuf->u32State = RT_H2LE_U32_C(NETPERFHDR_DONE);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpWrite(pParams->hSocket, pBuf, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTcpWrite/done: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTimerLRDestroy(hTimer);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Failed to create timer object: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP Throughput: Receive data from the other party.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The TCP parameters block.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pBuf The buffer we're using when sending.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pStats Where to return the statistics.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfTCPThroughputRecv(NETPERFPARAMS const *pParams, NETPERFHDR *pBuf, NETPERFSTATS *pStats)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RT_ZERO(*pStats);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t u32Seq = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t cRx = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t u64StartTS = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uState = RT_H2LE_U32_C(NETPERFHDR_WARMUP);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (;;)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpRead(pParams->hSocket, pBuf, pParams->cbPacket, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pStats->cErrors++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTcpRead failed: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_UNLIKELY( pBuf->u32Magic != RT_H2LE_U32_C(NETPERFHDR_MAGIC)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || pBuf->u32Reserved != 0))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pStats->cErrors++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Invalid magic or reserved field value: %#x %#x\n", RT_H2LE_U32(pBuf->u32Magic), RT_H2LE_U32(pBuf->u32Reserved));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = VERR_INVALID_MAGIC;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u32Seq += 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_UNLIKELY(pBuf->u32Seq != RT_H2LE_U32(u32Seq)))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pStats->cErrors++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Out of sequence: got %#x, expected %#x\n", RT_H2LE_U32(pBuf->u32Seq), u32Seq);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = VERR_WRONG_ORDER;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pParams->fCheckData && uState == RT_H2LE_U32_C(NETPERFHDR_TESTING))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync unsigned i = sizeof(NETPERFHDR);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (;i < pParams->cbPacket; ++i)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (((unsigned char *)pBuf)[i])
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (i != pParams->cbPacket)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pStats->cErrors++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Broken payload: at %#x got %#x, expected %#x\n", i, ((unsigned char *)pBuf)[i], 0);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = VERR_NOT_EQUAL;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_LIKELY(pBuf->u32State == uState))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cRx++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Validate and act on switch state.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if ( uState == RT_H2LE_U32_C(NETPERFHDR_WARMUP)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync && pBuf->u32State == RT_H2LE_U32_C(NETPERFHDR_TESTING))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cRx = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u64StartTS = RTTimeNanoTS();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uState = pBuf->u32State;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if ( uState == RT_H2LE_U32_C(NETPERFHDR_TESTING)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync && ( pBuf->u32State == RT_H2LE_U32_C(NETPERFHDR_COOL_DOWN)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || pBuf->u32State == RT_H2LE_U32_C(NETPERFHDR_DONE)) )
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pStats->cNsElapsed = RTTimeNanoTS() - u64StartTS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pStats->cRx = cRx + 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uState = pBuf->u32State;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uState == RT_H2LE_U32_C(NETPERFHDR_DONE))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if ( uState == RT_H2LE_U32_C(NETPERFHDR_COOL_DOWN)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync && pBuf->u32State == RT_H2LE_U32_C(NETPERFHDR_DONE))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uState = pBuf->u32State;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pStats->cErrors++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Protocol error: invalid state transition %#x -> %#x\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RT_LE2H_U32(uState), RT_LE2H_U32(pBuf->u32State));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = VERR_INVALID_MAGIC;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertReturn(uState == RT_H2LE_U32_C(NETPERFHDR_DONE) || RT_FAILURE(rc), VERR_INVALID_STATE);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Prints the statistics for the latency test.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pStats The statistics.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic void netperfPrintLatencyStats(NETPERFSTATS const *pStats, uint32_t cbPacket)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync double rdSecElapsed = (double)pStats->cNsElapsed / 1000000000.0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Transmitted", pStats->cTx, RTTESTUNIT_PACKETS);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Successful echos", pStats->cEchos, RTTESTUNIT_PACKETS);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Errors", pStats->cErrors, RTTESTUNIT_PACKETS);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Interval", pStats->cNsElapsed, RTTESTUNIT_NS);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Packet size", cbPacket, RTTESTUNIT_BYTES);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Average rate", (uint64_t)(pStats->cEchos / rdSecElapsed), RTTESTUNIT_PACKETS_PER_SEC);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Average throughput", (uint64_t)(cbPacket * pStats->cEchos / rdSecElapsed), RTTESTUNIT_BYTES_PER_SEC);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIValue("Average latency", (uint64_t)(rdSecElapsed / pStats->cEchos * 1000000000.0), RTTESTUNIT_NS_PER_ROUND_TRIP);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestISubDone();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * NETPERFMODE -> string.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns readonly string.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param enmMode The mode.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic const char *netperfModeToString(NETPERFMODE enmMode)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync switch (enmMode)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_LATENCY: return "latency";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_THROUGHPUT: return "throughput";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_THROUGHPUT_XMIT: return "throughput-xmit";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_THROUGHPUT_RECV: return "throughput-recv";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync default: AssertFailed(); return "internal-error";
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * String -> NETPERFMODE.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns The corresponding NETPERFMODE, NETPERFMODE_INVALID on failure.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pszMode The mode string.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic NETPERFMODE netperfModeFromString(const char *pszMode)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!strcmp(pszMode, "latency"))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return NETPERFMODE_LATENCY;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( !strcmp(pszMode, "throughput")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(pszMode, "thruput") )
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return NETPERFMODE_THROUGHPUT;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( !strcmp(pszMode, "throughput-xmit")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(pszMode, "thruput-xmit")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(pszMode, "xmit") )
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return NETPERFMODE_THROUGHPUT_XMIT;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( !strcmp(pszMode, "throughput-recv")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(pszMode, "thruput-recv")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(pszMode, "recv") )
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return NETPERFMODE_THROUGHPUT_RECV;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return NETPERFMODE_INVALID;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP Server: Throughput test.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The parameters to use for this test.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfTCPServerDoThroughput(NETPERFPARAMS const *pParams)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Allocate the buffer.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFHDR *pBuf = (NETPERFHDR *)RTMemAllocZ(pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!pBuf)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_NO_MEMORY, "Out of memory");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Receive first, then Send. The reverse of the client.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS RecvStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = netperfTCPThroughputRecv(pParams, pBuf, &RecvStats);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfSendStats(&RecvStats, pParams->hSocket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS SendStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfTCPThroughputSend(pParams, pBuf, &SendStats);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfSendStats(&SendStats, pParams->hSocket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfPrintThroughputStats(&SendStats, &RecvStats, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP Server: Throughput xmit test (receive from client).
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The parameters to use for this test.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfTCPServerDoThroughputXmit(NETPERFPARAMS const *pParams)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Allocate the buffer.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFHDR *pBuf = (NETPERFHDR *)RTMemAllocZ(pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!pBuf)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_NO_MEMORY, "Out of memory");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Receive the transmitted data (reverse of client).
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS RecvStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = netperfTCPThroughputRecv(pParams, pBuf, &RecvStats);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfSendStats(&RecvStats, pParams->hSocket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfPrintThroughputStats(NULL, &RecvStats, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP Server: Throughput recv test (transmit to client).
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The parameters to use for this test.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfTCPServerDoThroughputRecv(NETPERFPARAMS const *pParams)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Allocate the buffer.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFHDR *pBuf = (NETPERFHDR *)RTMemAllocZ(pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!pBuf)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_NO_MEMORY, "Out of memory");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Send data to the client (reverse of client).
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS SendStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = netperfTCPThroughputSend(pParams, pBuf, &SendStats);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfSendStats(&SendStats, pParams->hSocket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfPrintThroughputStats(&SendStats, NULL, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP Server: Latency test.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The parameters to use for this test.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfTCPServerDoLatency(NETPERFPARAMS const *pParams)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFHDR *pBuf = (NETPERFHDR *)RTMemAllocZ(pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!pBuf)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_NO_MEMORY, "Failed to allocated packet buffer of %u bytes.\n", pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Ping pong with client.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uState = RT_H2LE_U32_C(NETPERFHDR_WARMUP);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t u32Seq = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t cTx = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t cRx = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t u64StartTS = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS Stats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RT_ZERO(Stats);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (;;)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpRead(pParams->hSocket, pBuf, pParams->cbPacket, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Failed to read data from client: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Validate the packet
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_UNLIKELY( pBuf->u32Magic != RT_H2LE_U32_C(NETPERFHDR_MAGIC)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || pBuf->u32Reserved != 0))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Invalid magic or reserved field value: %#x %#x\n", RT_H2LE_U32(pBuf->u32Magic), RT_H2LE_U32(pBuf->u32Reserved));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = VERR_INVALID_MAGIC;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u32Seq += 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_UNLIKELY(pBuf->u32Seq != RT_H2LE_U32(u32Seq)))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Out of sequence: got %#x, expected %#x\n", RT_H2LE_U32(pBuf->u32Seq), u32Seq);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = VERR_WRONG_ORDER;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Count the packet if the state remains unchanged.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_LIKELY(pBuf->u32State == uState))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cRx++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Validate and act on the state transition.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if ( uState == RT_H2LE_U32_C(NETPERFHDR_WARMUP)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync && pBuf->u32State == RT_H2LE_U32_C(NETPERFHDR_TESTING))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cRx = cTx = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u64StartTS = RTTimeNanoTS();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uState = pBuf->u32State;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if ( uState == RT_H2LE_U32_C(NETPERFHDR_TESTING)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync && ( pBuf->u32State == RT_H2LE_U32_C(NETPERFHDR_COOL_DOWN)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || pBuf->u32State == RT_H2LE_U32_C(NETPERFHDR_DONE)) )
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Stats.cNsElapsed = RTTimeNanoTS() - u64StartTS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Stats.cEchos = cTx;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Stats.cTx = cTx;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Stats.cRx = cRx;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uState = pBuf->u32State;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uState == RT_H2LE_U32_C(NETPERFHDR_DONE))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if ( uState == RT_H2LE_U32_C(NETPERFHDR_COOL_DOWN)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync && pBuf->u32State == RT_H2LE_U32_C(NETPERFHDR_DONE))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uState = pBuf->u32State;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Protocol error: invalid state transition %#x -> %#x\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RT_LE2H_U32(uState), RT_LE2H_U32(pBuf->u32State));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Write same data back to client.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpWrite(pParams->hSocket, pBuf, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Failed to write data to client: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cTx++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Send stats to client and print them.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uState == RT_H2LE_U32_C(NETPERFHDR_DONE))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfSendStats(&Stats, pParams->hSocket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( uState == RT_H2LE_U32_C(NETPERFHDR_DONE)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || uState == RT_H2LE_U32_C(NETPERFHDR_COOL_DOWN))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfPrintLatencyStats(&Stats, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTMemFree(pBuf);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Parses the parameters the client has sent us.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code. Message has been shown on failure.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The parameter structure to store the parameters
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * in.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pszParams The parameter string sent by the client.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfTCPServerParseParams(NETPERFPARAMS *pParams, char *pszParams)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Set defaults for the dynamic settings.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->fNoDelay = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->enmMode = NETPERFMODE_LATENCY;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->cSecTimeout = NETPERF_DEFAULT_WARMUP;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->cMsCoolDown = NETPERF_DEFAULT_COOL_DOWN;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->cMsWarmup = NETPERF_DEFAULT_WARMUP;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->cbPacket = NETPERF_DEFAULT_PKT_SIZE_LATENCY;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Parse the client parameters.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* first arg: transport type. [mandatory] */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char *pszCur = strchr(pszParams, ':');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!pszCur)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_PARSE_ERROR, "client params: No colon\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char *pszNext = strchr(++pszCur, ':');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pszNext)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *pszNext++ = '\0';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (strcmp(pszCur, "TCP"))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_PARSE_ERROR, "client params: Invalid transport type: \"%s\"\n", pszCur);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszCur = pszNext;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* second arg: mode. [mandatory] */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!pszCur)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_PARSE_ERROR, "client params: Missing test mode\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszNext = strchr(pszCur, ':');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pszNext)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *pszNext++ = '\0';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->enmMode = netperfModeFromString(pszCur);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pParams->enmMode == NETPERFMODE_INVALID)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_PARSE_ERROR, "client params: Invalid test mode: \"%s\"\n", pszCur);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszCur = pszNext;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * The remainder are uint32_t or bool.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync struct
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool fBool;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool fMandatory;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync void *pvValue;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uMin;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uMax;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync const char *pszName;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync } aElements[] =
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { false, true, &pParams->cSecTimeout, NETPERF_MIN_TIMEOUT, NETPERF_MAX_TIMEOUT, "timeout" },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { false, true, &pParams->cbPacket, NETPERF_MIN_PKT_SIZE, NETPERF_MAX_PKT_SIZE, "packet size" },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { false, true, &pParams->cMsWarmup, NETPERF_MIN_WARMUP, NETPERF_MAX_WARMUP, "warmup period" },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { false, true, &pParams->cMsCoolDown, NETPERF_MIN_COOL_DOWN, NETPERF_MAX_COOL_DOWN, "cool down period" },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { true, true, &pParams->fNoDelay, false, true, "no delay" },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync };
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (unsigned i = 0; i < RT_ELEMENTS(aElements); i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!pszCur)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return aElements[i].fMandatory
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ? RTTestIFailedRc(VERR_PARSE_ERROR, "client params: missing %s\n", aElements[i].pszName)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync : VINF_SUCCESS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszNext = strchr(pszCur, ':');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pszNext)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *pszNext++ = '\0';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t u32;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTStrToUInt32Full(pszCur, 10, &u32);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rc != VINF_SUCCESS)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_PARSE_ERROR, "client params: bad %s value \"%s\": %Rrc\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aElements[i].pszName, pszCur, rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( u32 < aElements[i].uMin
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || u32 > aElements[i].uMax)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_PARSE_ERROR, "client params: %s %u s is out of range (%u..%u)\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aElements[i].pszName, u32, aElements[i].uMin, aElements[i].uMax);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (aElements[i].fBool)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *(bool *)aElements[i].pvValue = u32 ? true : false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *(uint32_t *)aElements[i].pvValue = u32;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszCur = pszNext;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Fail if too many elements. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pszCur)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_PARSE_ERROR, "client params: too many elements: \"%s\"\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszCur);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return VINF_SUCCESS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP server callback that handles one client connection.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code. VERR_TCP_SERVER_STOP is special.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param hSocket The client socket.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pvUser Our parameters.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic DECLCALLBACK(int) netperfTCPServerWorker(RTSOCKET hSocket, void *pvUser)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFPARAMS *pParams = (NETPERFPARAMS *)pvUser;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertReturn(pParams, VERR_INVALID_POINTER);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->hSocket = hSocket;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTNETADDR Addr;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTTcpGetPeerAddress(hSocket, &Addr);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIPrintf(RTTESTLVL_ALWAYS, "Client connected from %RTnaddr\n", &Addr);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIPrintf(RTTESTLVL_ALWAYS, "Failed to get client details: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Addr.enmType = RTNETADDRTYPE_INVALID;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Greet the other dude.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpWrite(hSocket, g_ConnectStart, sizeof(g_ConnectStart) - 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "Failed to send connection start Id: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Read connection parameters.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char szBuf[256];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpRead(hSocket, szBuf, NETPERF_LEN_PREFIX, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "Failed to read connection parameters: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync szBuf[NETPERF_LEN_PREFIX] = '\0';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t cchParams;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTStrToUInt32Full(szBuf, 10, &cchParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rc != VINF_SUCCESS)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(RT_SUCCESS(rc) ? VERR_INTERNAL_ERROR : rc,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "Failed to read connection parameters: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (cchParams >= sizeof(szBuf))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_TOO_MUCH_DATA, "parameter packet is too big (%u bytes)\n", cchParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpRead(hSocket, szBuf, cchParams, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "Failed to read connection parameters: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync szBuf[cchParams] = '\0';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (strncmp(szBuf, g_szStartParams, sizeof(g_szStartParams) - 1))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_NET_PROTOCOL_ERROR, "Invalid connection parameters '%s'\n", szBuf);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Parse the parameters and signal whether we've got a deal or not.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfTCPServerParseParams(pParams, szBuf);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc2 = RTTcpWrite(hSocket, g_szNegative, sizeof(g_szNegative) - 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc2))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Failed to send negative ack: %Rrc\n", rc2);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (Addr.enmType != RTNETADDRTYPE_INVALID)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestISubF("%RTnaddr - %s, %u s, %u bytes", &Addr,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfModeToString(pParams->enmMode), pParams->cSecTimeout, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestISubF("Unknown - %s, %u s, %u bytes",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfModeToString(pParams->enmMode), pParams->cSecTimeout, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpSetSendCoalescing(hSocket, !pParams->fNoDelay);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "Failed to apply no-delay option (%RTbool): %Rrc\n", pParams->fNoDelay, rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpWrite(hSocket, g_szAck, sizeof(g_szAck) - 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "Failed to send start test commend to client: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Take action according to our mode.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync switch (pParams->enmMode)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_LATENCY:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfTCPServerDoLatency(pParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_THROUGHPUT:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfTCPServerDoThroughput(pParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_THROUGHPUT_XMIT:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfTCPServerDoThroughputXmit(pParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_THROUGHPUT_RECV:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfTCPServerDoThroughputRecv(pParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_INVALID:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = VERR_INTERNAL_ERROR;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* no default! */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rc == VERR_NO_MEMORY)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return VERR_TCP_SERVER_STOP;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Wait for other clients or quit.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pParams->fSingleClient)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return VERR_TCP_SERVER_STOP;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return VINF_SUCCESS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP server.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The TCP parameter block.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfTCPServer(NETPERFPARAMS *pParams)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Spawn the TCP server thread & listen.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync PRTTCPSERVER pServer;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTTcpServerCreateEx(NULL, pParams->uPort, &pServer);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("Server listening on TCP port %d\n", pParams->uPort);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpServerListen(pServer, netperfTCPServerWorker, pParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTcpServerDestroy(pServer);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("Failed to create TCP server thread: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * The server part.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns Exit code.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param enmProto The protocol.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The parameter block.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE netperfServer(NETPERFPROTO enmProto, NETPERFPARAMS *pParams)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync switch (enmProto)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFPROTO_TCP:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = netperfTCPServer(pParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync default:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Protocol not supported.\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP client: Do the throughput test.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The parameters.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfTCPClientDoThroughput(NETPERFPARAMS *pParams)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Allocate the buffer.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFHDR *pBuf = (NETPERFHDR *)RTMemAllocZ(pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!pBuf)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_NO_MEMORY, "Out of memory");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Send first, then Receive.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS SendStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = netperfTCPThroughputSend(pParams, pBuf, &SendStats);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS SrvSendStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfRecvStats(&SrvSendStats, pParams->hSocket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS RecvStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfTCPThroughputRecv(pParams, pBuf, &RecvStats);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS SrvRecvStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfRecvStats(&SrvRecvStats, pParams->hSocket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pParams->fServerStats)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfPrintThroughputStats(&SrvSendStats, &SrvRecvStats, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfPrintThroughputStats(&SendStats, &RecvStats, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestISubDone();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP client: Do the throughput xmit test.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The parameters.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfTCPClientDoThroughputXmit(NETPERFPARAMS *pParams)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Allocate the buffer.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFHDR *pBuf = (NETPERFHDR *)RTMemAllocZ(pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!pBuf)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_NO_MEMORY, "Out of memory");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Do the job.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS SendStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = netperfTCPThroughputSend(pParams, pBuf, &SendStats);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS SrvSendStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfRecvStats(&SrvSendStats, pParams->hSocket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pParams->fServerStats)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfPrintThroughputStats(&SrvSendStats, NULL, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfPrintThroughputStats(&SendStats, NULL, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestISubDone();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP client: Do the throughput recv test.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The parameters.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfTCPClientDoThroughputRecv(NETPERFPARAMS *pParams)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Allocate the buffer.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFHDR *pBuf = (NETPERFHDR *)RTMemAllocZ(pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!pBuf)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_NO_MEMORY, "Out of memory");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Do the job.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS RecvStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = netperfTCPThroughputRecv(pParams, pBuf, &RecvStats);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS SrvRecvStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfRecvStats(&SrvRecvStats, pParams->hSocket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pParams->fServerStats)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfPrintThroughputStats(NULL, &SrvRecvStats, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfPrintThroughputStats(NULL, &RecvStats, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestISubDone();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP client: Do the latency test.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The parameters.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfTCPClientDoLatency(NETPERFPARAMS *pParams)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Generate a selection of packages before we start, after all we're not
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * benchmarking the random number generator, are we. :-)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync void *pvReadBuf = RTMemAllocZ(pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!pvReadBuf)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_NO_MEMORY, "Out of memory");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t i;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFHDR *apPackets[256];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (i = 0; i < RT_ELEMENTS(apPackets); i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync apPackets[i] = (NETPERFHDR *)RTMemAllocZ(pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!apPackets[i])
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (i-- > 0)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTMemFree(apPackets[i]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_NO_MEMORY, "Out of memory");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTRandBytes(apPackets[i], pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync apPackets[i]->u32Magic = RT_H2LE_U32_C(NETPERFHDR_MAGIC);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync apPackets[i]->u32State = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync apPackets[i]->u32Seq = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync apPackets[i]->u32Reserved = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Create & start a timer to eventually disconnect.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool volatile fStop = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTIMERLR hTimer;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTTimerLRCreateEx(&hTimer, 0 /* nsec */, RTTIMER_FLAGS_CPU_ANY, netperfStopTimerCallback, (void *)&fStop);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t u32Seq = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS Stats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RT_ZERO(Stats);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Warm up.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTimerLRStart(hTimer, pParams->cMsWarmup * UINT64_C(1000000) /* nsec */);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (!fStop)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFHDR *pPacket = apPackets[u32Seq % RT_ELEMENTS(apPackets)];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u32Seq++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pPacket->u32Seq = RT_H2LE_U32(u32Seq);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pPacket->u32State = RT_H2LE_U32_C(NETPERFHDR_WARMUP);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpWrite(pParams->hSocket, pPacket, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTcpWrite/warmup: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpRead(pParams->hSocket, pvReadBuf, pParams->cbPacket, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTcpRead/warmup: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTimerLRStart/warmup: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * The real thing.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fStop = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTimerLRStart(hTimer, pParams->cSecTimeout * UINT64_C(1000000000) /* nsec */);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t u64StartTS = RTTimeNanoTS();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (!fStop)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFHDR *pPacket = apPackets[u32Seq % RT_ELEMENTS(apPackets)];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u32Seq++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pPacket->u32Seq = RT_H2LE_U32(u32Seq);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pPacket->u32State = RT_H2LE_U32_C(NETPERFHDR_TESTING);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpWrite(pParams->hSocket, pPacket, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTcpWrite/testing: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Stats.cTx++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpRead(pParams->hSocket, pvReadBuf, pParams->cbPacket, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTcpRead/testing: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Stats.cRx++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!memcmp(pvReadBuf, pPacket, pParams->cbPacket))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Stats.cEchos++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Stats.cErrors++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Stats.cNsElapsed = RTTimeNanoTS() - u64StartTS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTimerLRStart/testing: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Cool down.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fStop = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTimerLRStart(hTimer, pParams->cMsCoolDown * UINT64_C(1000000) /* nsec */);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (!fStop)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFHDR *pPacket = apPackets[u32Seq % RT_ELEMENTS(apPackets)];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u32Seq++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pPacket->u32Seq = RT_H2LE_U32(u32Seq);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pPacket->u32State = RT_H2LE_U32_C(NETPERFHDR_COOL_DOWN);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpWrite(pParams->hSocket, pPacket, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTcpWrite/warmup: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpRead(pParams->hSocket, pvReadBuf, pParams->cbPacket, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTcpRead/warmup: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTimerLRStart/testing: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Send DONE packet.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u32Seq++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFHDR *pPacket = apPackets[u32Seq % RT_ELEMENTS(apPackets)];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pPacket->u32Seq = RT_H2LE_U32(u32Seq);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pPacket->u32State = RT_H2LE_U32_C(NETPERFHDR_DONE);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpWrite(pParams->hSocket, pPacket, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("RTTcpWrite/done: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Get and print stats.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFSTATS SrvStats;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfRecvStats(&SrvStats, pParams->hSocket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc) && pParams->fServerStats)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfPrintLatencyStats(&SrvStats, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (!pParams->fServerStats)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfPrintLatencyStats(&Stats, pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* clean up*/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTimerLRDestroy(hTimer);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Failed to create timer object: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (i = 0; i < RT_ELEMENTS(apPackets); i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTMemFree(apPackets[i]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * TCP client test driver.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns IPRT status code
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pszServer The server name.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The parameter structure.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int netperfTCPClient(const char *pszServer, NETPERFPARAMS *pParams)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertReturn(pParams, VERR_INVALID_POINTER);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestISubF("TCP - %u s, %u bytes%s", pParams->cSecTimeout,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->cbPacket, pParams->fNoDelay ? ", no delay" : "");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTSOCKET hSocket = NIL_RTSOCKET;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTTcpClientConnect(pszServer, pParams->uPort, &hSocket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "Failed to connect to %s on port %u: %Rrc\n", pszServer, pParams->uPort, rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->hSocket = hSocket;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Disable send coalescing (no-delay).
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pParams->fNoDelay)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpSetSendCoalescing(hSocket, false /*fEnable*/);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "Failed to set no-delay option: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Verify the super secret Start Connect Id to start the connection.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char szBuf[256 + NETPERF_LEN_PREFIX];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RT_ZERO(szBuf);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpRead(hSocket, szBuf, sizeof(g_ConnectStart) - 1, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "Failed to read connection initializer: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (strcmp(szBuf, g_ConnectStart))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_INVALID_MAGIC, "Invalid connection initializer '%s'\n", szBuf);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Send all the dynamic parameters to the server.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * (If the server is newer than the client, it will select default for any
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * missing parameters.)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t cchParams = RTStrPrintf(&szBuf[NETPERF_LEN_PREFIX], sizeof(szBuf) - NETPERF_LEN_PREFIX,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "%s:%s:%s:%u:%u:%u:%u:%u",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync g_szStartParams,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "TCP",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync netperfModeToString(pParams->enmMode),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->cSecTimeout,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->cbPacket,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->cMsWarmup,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->cMsCoolDown,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->fNoDelay);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrPrintf(szBuf, NETPERF_LEN_PREFIX + 1, "%0*u", NETPERF_LEN_PREFIX, cchParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync szBuf[NETPERF_LEN_PREFIX] = g_szStartParams[0];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert(strlen(szBuf) == NETPERF_LEN_PREFIX + cchParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpWrite(hSocket, szBuf, NETPERF_LEN_PREFIX + cchParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "Failed to send connection parameters: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Wait for acknowledgment.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTTcpRead(hSocket, szBuf, sizeof(g_szAck) - 1, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(rc, "Failed to send parameters: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync szBuf[sizeof(g_szAck) - 1] = '\0';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!strcmp(szBuf, g_szNegative))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_NET_PROTOCOL_ERROR, "Server failed to accept packet size of %u bytes.\n", pParams->cbPacket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (strcmp(szBuf, g_szAck))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestIFailedRc(VERR_NET_PROTOCOL_ERROR, "Invalid response from server '%s'\n", szBuf);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Take action according to our mode.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync switch (pParams->enmMode)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_LATENCY:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIPrintf(RTTESTLVL_ALWAYS, "Connected to %s port %u, running the latency test for %u seconds.\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszServer, pParams->uPort, pParams->cSecTimeout);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfTCPClientDoLatency(pParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_THROUGHPUT:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIPrintf(RTTESTLVL_ALWAYS, "Connected to %s port %u, running the throughput test for %u seconds in each direction.\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszServer, pParams->uPort, pParams->cSecTimeout);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfTCPClientDoThroughput(pParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_THROUGHPUT_XMIT:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIPrintf(RTTESTLVL_ALWAYS, "Connected to %s port %u, running the throughput-xmit test for %u seconds.\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszServer, pParams->uPort, pParams->cSecTimeout);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfTCPClientDoThroughputXmit(pParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_THROUGHPUT_RECV:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIPrintf(RTTESTLVL_ALWAYS, "Connected to %s port %u, running the throughput-recv test for %u seconds.\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszServer, pParams->uPort, pParams->cSecTimeout);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfTCPClientDoThroughputRecv(pParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_INVALID:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = VERR_INTERNAL_ERROR;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* no default! */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * The client part.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns Exit code.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param enmProto The protocol.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pParams The parameter block.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE netperfClient(NETPERFPROTO enmProto, const char *pszServer, void *pvUser)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync switch (enmProto)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFPROTO_TCP:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFPARAMS *pParams = (NETPERFPARAMS *)pvUser;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = netperfTCPClient(pszServer, pParams);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pParams->hSocket != NIL_RTSOCKET)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTcpClientClose(pParams->hSocket);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pParams->hSocket = NIL_RTSOCKET;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync default:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestIFailed("Protocol not supported.\n", g_pStdErr);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncint main(int argc, char *argv[])
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Init IPRT and globals.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTTestInitAndCreate("NetPerf", &g_hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rc)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Special case.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (argc < 2)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestFailed(g_hTest, "No arguments given.");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestSummaryAndDestroy(g_hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Default values.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFPROTO enmProtocol = NETPERFPROTO_TCP;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool fServer = true;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool fDaemonize = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool fDaemonized = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool fPacketSizeSet = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync const char *pszServerAddress= NULL;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NETPERFPARAMS Params;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.uPort = NETPERF_DEFAULT_PORT;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.fServerStats = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.fSingleClient = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.fNoDelay = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.fCheckData = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.enmMode = NETPERFMODE_LATENCY;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cSecTimeout = NETPERF_DEFAULT_TIMEOUT;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cMsWarmup = NETPERF_DEFAULT_WARMUP;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cMsCoolDown = NETPERF_DEFAULT_COOL_DOWN;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cbPacket = NETPERF_DEFAULT_PKT_SIZE_LATENCY;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.hSocket = NIL_RTSOCKET;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTGETOPTUNION ValueUnion;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTGETOPTSTATE GetState;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTGetOptInit(&GetState, argc, argv, g_aCmdOptions, RT_ELEMENTS(g_aCmdOptions), 1, 0 /* fFlags */);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while ((rc = RTGetOpt(&GetState, &ValueUnion)))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync switch (rc)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 's':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fServer = true;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'c':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fServer = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pszServerAddress = ValueUnion.psz;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'd':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fDaemonize = true;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'D':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fDaemonized = true;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'i':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cSecTimeout = ValueUnion.u32;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( Params.cSecTimeout < NETPERF_MIN_TIMEOUT
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || Params.cSecTimeout > NETPERF_MAX_TIMEOUT)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestFailed(g_hTest, "Invalid interval %u s, valid range: %u-%u\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cbPacket, NETPERF_MIN_TIMEOUT, NETPERF_MAX_TIMEOUT);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestSummaryAndDestroy(g_hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'l':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cbPacket = ValueUnion.u32;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( Params.cbPacket < NETPERF_MIN_PKT_SIZE
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || Params.cbPacket > NETPERF_MAX_PKT_SIZE)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestFailed(g_hTest, "Invalid packet size %u bytes, valid range: %u-%u\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cbPacket, NETPERF_MIN_PKT_SIZE, NETPERF_MAX_PKT_SIZE);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestSummaryAndDestroy(g_hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fPacketSizeSet = true;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'm':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.enmMode = netperfModeFromString(ValueUnion.psz);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (Params.enmMode == NETPERFMODE_INVALID)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestFailed(g_hTest, "Invalid test mode: \"%s\"\n", ValueUnion.psz);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestSummaryAndDestroy(g_hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!fPacketSizeSet)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync switch (Params.enmMode)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_LATENCY:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cbPacket = NETPERF_DEFAULT_PKT_SIZE_LATENCY;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_THROUGHPUT:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_THROUGHPUT_XMIT:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_THROUGHPUT_RECV:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cbPacket = NETPERF_DEFAULT_PKT_SIZE_THROUGHPUT;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case NETPERFMODE_INVALID:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* no default! */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'p':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.uPort = ValueUnion.u32;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'N':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.fNoDelay = true;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'S':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.fServerStats = true;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case '1':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.fSingleClient = true;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'h':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Usage(g_pStdOut);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTEXITCODE_SUCCESS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'V':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("$Revision$\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTEXITCODE_SUCCESS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'w':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cMsWarmup = ValueUnion.u32;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( Params.cMsWarmup < NETPERF_MIN_WARMUP
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || Params.cMsWarmup > NETPERF_MAX_WARMUP)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestFailed(g_hTest, "invalid warmup time %u ms, valid range: %u-%u\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cMsWarmup, NETPERF_MIN_WARMUP, NETPERF_MAX_WARMUP);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestSummaryAndDestroy(g_hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'W':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cMsCoolDown = ValueUnion.u32;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( Params.cMsCoolDown < NETPERF_MIN_COOL_DOWN
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || Params.cMsCoolDown > NETPERF_MAX_COOL_DOWN)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestFailed(g_hTest, "invalid cool down time %u ms, valid range: %u-%u\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.cMsCoolDown, NETPERF_MIN_COOL_DOWN, NETPERF_MAX_COOL_DOWN);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestSummaryAndDestroy(g_hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'C':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Params.fCheckData = true;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync default:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTGetOptPrintError(rc, &ValueUnion);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Handle the server process daemoniziation.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (fDaemonize && !fDaemonized && fServer)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTProcDaemonize(argv, "--daemonized");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTProcDaemonize failed: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTEXITCODE_SUCCESS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Get down to business.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestBanner(g_hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (fServer)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfServer(enmProtocol, &Params);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (pszServerAddress)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = netperfClient(enmProtocol, pszServerAddress, &Params);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestFailed(g_hTest, "missing server address to connect to\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTEXITCODE rc2 = RTTestSummaryAndDestroy(g_hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc2 != RTEXITCODE_FAILURE ? (RTEXITCODE)rc2 : rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync