Add network profiling tool from Spearhead and Breakthrough

Profiling can be enabled with `cl_netprofile` and `sv_netprofile`, the overlay can be shown using `cl_netprofileoverlay` and `sv_netprofileoverlay` and the server can dump network profile using the `netprofiledump` command
This commit is contained in:
smallmodel 2024-11-09 21:15:49 +01:00
parent 23a035e2ca
commit 1ef1bad9ae
No known key found for this signature in database
GPG key ID: 9F2D623CEDF08512
14 changed files with 871 additions and 66 deletions

View file

@ -56,6 +56,8 @@ cvar_t *cl_showTimeDelta;
cvar_t *cl_freezeDemo; cvar_t *cl_freezeDemo;
cvar_t *cl_shownet; cvar_t *cl_shownet;
cvar_t *cl_netprofile;
cvar_t *cl_netprofileoverlay;
cvar_t *cl_showSend; cvar_t *cl_showSend;
cvar_t *cl_timedemo; cvar_t *cl_timedemo;
cvar_t *cl_timedemoLog; cvar_t *cl_timedemoLog;
@ -118,6 +120,7 @@ cvar_t *cl_r_fullscreen;
cvar_t *cl_consoleKeys; cvar_t *cl_consoleKeys;
cvar_t *name; cvar_t *name;
cvar_t *cl_rate;
clientActive_t cl; clientActive_t cl;
clientConnection_t clc; clientConnection_t clc;
@ -1057,7 +1060,7 @@ void CL_RequestMotd( void ) {
Info_SetValueForKey( info, "renderer", cls.glconfig.renderer_string ); Info_SetValueForKey( info, "renderer", cls.glconfig.renderer_string );
Info_SetValueForKey( info, "version", com_version->string ); Info_SetValueForKey( info, "version", com_version->string );
NET_OutOfBandPrint( NS_CLIENT, cls.updateServer, "getmotd \"%s\"\n", info ); CL_NET_OutOfBandPrint( cls.updateServer, "getmotd \"%s\"\n", info );
} }
/* /*
@ -1140,7 +1143,7 @@ void CL_RequestAuthorization( void ) {
fs = Cvar_Get ("cl_anonymous", "0", CVAR_INIT|CVAR_SYSTEMINFO ); fs = Cvar_Get ("cl_anonymous", "0", CVAR_INIT|CVAR_SYSTEMINFO );
NET_OutOfBandPrint(NS_CLIENT, cls.authorizeServer, "getKeyAuthorize %i %s", fs->integer, nums ); CL_NET_OutOfBandPrint(cls.authorizeServer, "getKeyAuthorize %i %s", fs->integer, nums );
} }
/* /*
@ -1476,7 +1479,11 @@ void CL_Rcon_f( void ) {
} }
} }
NET_SendPacket (NS_CLIENT, strlen(message)+1, message, to); NET_SendPacket (NS_CLIENT, strlen(message) + 1, message, to);
if (cl_netprofile->integer) {
NetProfileAddPacket(&cls.netprofile.inPackets, strlen(message) + 1, NETPROF_PACKET_MESSAGE);
}
} }
/* /*
@ -1979,12 +1986,12 @@ void CL_CheckForResend( void ) {
// if ( !Sys_IsLANAddress( clc.serverAddress ) ) { // if ( !Sys_IsLANAddress( clc.serverAddress ) ) {
// CL_RequestAuthorization(); // CL_RequestAuthorization();
// } // }
NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "getchallenge"); CL_NET_OutOfBandPrint(clc.serverAddress, "getchallenge");
break; break;
case CA_AUTHORIZING: case CA_AUTHORIZING:
// resend the cd key authorization // resend the cd key authorization
gcd_compute_response(cl_cdkey, Cmd_Argv(1), cls.gcdResponse, CDResponseMethod_REAUTH); gcd_compute_response(cl_cdkey, Cmd_Argv(1), cls.gcdResponse, CDResponseMethod_REAUTH);
NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "authorizeThis %s", cls.gcdResponse); CL_NET_OutOfBandPrint(clc.serverAddress, "authorizeThis %s", cls.gcdResponse);
break; break;
case CA_CHALLENGING: case CA_CHALLENGING:
/* /*
@ -2248,6 +2255,10 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
char *c; char *c;
const char *reason; const char *reason;
if (cl_netprofile->integer) {
NetProfileAddPacket(&cls.netprofile.inPackets, msg->cursize, NETPROF_PACKET_MESSAGE);
}
MSG_BeginReadingOOB( msg ); MSG_BeginReadingOOB( msg );
MSG_ReadLong( msg ); // skip the -1 MSG_ReadLong( msg ); // skip the -1
@ -2331,7 +2342,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
// echo request from server // echo request from server
if ( !Q_stricmp(c, "echo") ) { if ( !Q_stricmp(c, "echo") ) {
NET_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv(1) ); CL_NET_OutOfBandPrint(from, "%s", Cmd_Argv(1) );
return; return;
} }
@ -2339,7 +2350,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
if ( !Q_stricmp(c, "getKey") ) { if ( !Q_stricmp(c, "getKey") ) {
clc.state = CA_AUTHORIZING; clc.state = CA_AUTHORIZING;
gcd_compute_response(cl_cdkey, Cmd_Argv(1), cls.gcdResponse, CDResponseMethod_NEWAUTH); gcd_compute_response(cl_cdkey, Cmd_Argv(1), cls.gcdResponse, CDResponseMethod_NEWAUTH);
NET_OutOfBandPrint(NS_CLIENT, from, "authorizeThis %s", cls.gcdResponse); CL_NET_OutOfBandPrint(from, "authorizeThis %s", cls.gcdResponse);
return; return;
} }
@ -2666,6 +2677,31 @@ void CL_Frame ( int msec ) {
cls.timeScaled = com_timescale->integer != 1; cls.timeScaled = com_timescale->integer != 1;
//
// Added in 2.0: network profiling
//
if (cl_netprofile->integer) {
if (!cls.netprofile.initialized) {
memset(&cls.netprofile, 0, sizeof(cls.netprofile));
cls.netprofile.initialized = qtrue;
}
if (cls.netprofile.rate != cl_rate->integer) {
cls.netprofile.rate = cl_rate->integer;
if (cls.netprofile.rate < 1000) {
cls.netprofile.rate = 1000;
} else if (cls.netprofile.rate > 90000) {
cls.netprofile.rate = 90000;
}
}
cls.netprofile.outPackets.updateTime = Com_Milliseconds();
cls.netprofile.inPackets.updateTime = cls.netprofile.outPackets.updateTime;
} else {
cls.netprofile.initialized = qfalse;
}
// see if we need to update any userinfo // see if we need to update any userinfo
CL_CheckUserinfo(); CL_CheckUserinfo();
@ -3330,6 +3366,8 @@ void CL_Init( void ) {
cl_master = Cvar_Get ("cl_master", MASTER_SERVER_NAME, CVAR_ARCHIVE); cl_master = Cvar_Get ("cl_master", MASTER_SERVER_NAME, CVAR_ARCHIVE);
cl_timeNudge = Cvar_Get ("cl_timeNudge", "0", CVAR_TEMP ); cl_timeNudge = Cvar_Get ("cl_timeNudge", "0", CVAR_TEMP );
cl_shownet = Cvar_Get ("cl_shownet", "0", CVAR_TEMP ); cl_shownet = Cvar_Get ("cl_shownet", "0", CVAR_TEMP );
cl_netprofile = Cvar_Get("cl_netprofile", "0", CVAR_TEMP);
cl_netprofileoverlay = Cvar_Get("cl_netprofileoverlay", "0", CVAR_TEMP);
cl_showSend = Cvar_Get ("cl_showSend", "0", CVAR_TEMP ); cl_showSend = Cvar_Get ("cl_showSend", "0", CVAR_TEMP );
cl_showTimeDelta = Cvar_Get ("cl_showTimeDelta", "0", CVAR_TEMP ); cl_showTimeDelta = Cvar_Get ("cl_showTimeDelta", "0", CVAR_TEMP );
cl_freezeDemo = Cvar_Get ("cl_freezeDemo", "0", CVAR_TEMP ); cl_freezeDemo = Cvar_Get ("cl_freezeDemo", "0", CVAR_TEMP );
@ -3445,7 +3483,7 @@ void CL_Init( void ) {
// userinfo // userinfo
name = Cvar_Get ("name", "UnnamedSoldier", CVAR_USERINFO | CVAR_ARCHIVE ); name = Cvar_Get ("name", "UnnamedSoldier", CVAR_USERINFO | CVAR_ARCHIVE );
Cvar_Get ("rate", "5000", CVAR_USERINFO | CVAR_ARCHIVE ); cl_rate = Cvar_Get ("rate", "5000", CVAR_USERINFO | CVAR_ARCHIVE );
Cvar_Get ("snaps", "20", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("snaps", "20", CVAR_USERINFO | CVAR_ARCHIVE );
Cvar_Get ("password", "", CVAR_USERINFO); Cvar_Get ("password", "", CVAR_USERINFO);
Cvar_Get ("dm_playermodel", "american_army", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("dm_playermodel", "american_army", CVAR_USERINFO | CVAR_ARCHIVE );
@ -3830,7 +3868,7 @@ int CL_ServerStatus( const char *serverAddress, char *serverStatusString, int ma
serverStatus->retrieved = qfalse; serverStatus->retrieved = qfalse;
serverStatus->time = 0; serverStatus->time = 0;
serverStatus->startTime = Com_Milliseconds(); serverStatus->startTime = Com_Milliseconds();
NET_OutOfBandPrint( NS_CLIENT, to, "getstatus" ); CL_NET_OutOfBandPrint(to, "getstatus" );
return qfalse; return qfalse;
} }
} }
@ -3842,7 +3880,7 @@ int CL_ServerStatus( const char *serverAddress, char *serverStatusString, int ma
serverStatus->retrieved = qfalse; serverStatus->retrieved = qfalse;
serverStatus->startTime = Com_Milliseconds(); serverStatus->startTime = Com_Milliseconds();
serverStatus->time = 0; serverStatus->time = 0;
NET_OutOfBandPrint( NS_CLIENT, to, "getstatus" ); CL_NET_OutOfBandPrint(to, "getstatus" );
return qfalse; return qfalse;
} }
return qfalse; return qfalse;
@ -3981,9 +4019,18 @@ void CL_LocalServers_f( void ) {
to.type = NA_BROADCAST; to.type = NA_BROADCAST;
NET_SendPacket( NS_CLIENT, strlen( message ), message, to ); NET_SendPacket( NS_CLIENT, strlen( message ), message, to );
if (cl_netprofile->integer) {
NetProfileAddPacket(&cls.netprofile.inPackets, strlen( message ), NETPROF_PACKET_MESSAGE);
}
// Added in OPM (from ioquake3) // Added in OPM (from ioquake3)
to.type = NA_MULTICAST6; to.type = NA_MULTICAST6;
NET_SendPacket( NS_CLIENT, strlen( message ), message, to ); NET_SendPacket( NS_CLIENT, strlen( message ), message, to );
if (cl_netprofile->integer) {
NetProfileAddPacket(&cls.netprofile.inPackets, strlen(message), NETPROF_PACKET_MESSAGE);
}
} }
} }
} }
@ -4087,7 +4134,7 @@ void CL_GlobalServers_f( void ) {
Q_strcat(command, sizeof(command), Cmd_Argv(i)); Q_strcat(command, sizeof(command), Cmd_Argv(i));
} }
NET_OutOfBandPrint( NS_SERVER, to, "%s", command ); CL_NET_OutOfBandPrint( to, "%s", command );
} }
@ -4307,7 +4354,7 @@ void CL_Ping_f( void ) {
CL_SetServerInfoByAddress(pingptr->adr, NULL, 0); CL_SetServerInfoByAddress(pingptr->adr, NULL, 0);
NET_OutOfBandPrint( NS_CLIENT, to, "\x02getinfo xxx" ); CL_NET_OutOfBandPrint( to, "\x02getinfo xxx" );
} }
/* /*
@ -4477,7 +4524,7 @@ qboolean CL_UpdateVisiblePings_f(int source) {
memcpy(&cl_pinglist[j].adr, &server[i].adr, sizeof(netadr_t)); memcpy(&cl_pinglist[j].adr, &server[i].adr, sizeof(netadr_t));
cl_pinglist[j].start = Sys_Milliseconds(); cl_pinglist[j].start = Sys_Milliseconds();
cl_pinglist[j].time = 0; cl_pinglist[j].time = 0;
NET_OutOfBandPrint( NS_CLIENT, cl_pinglist[j].adr, "getinfo xxx" ); CL_NET_OutOfBandPrint( cl_pinglist[j].adr, "getinfo xxx" );
slots++; slots++;
} }
} }
@ -4565,7 +4612,7 @@ void CL_ServerStatus_f(void) {
return; return;
} }
NET_OutOfBandPrint( NS_CLIENT, *toptr, "getstatus" ); CL_NET_OutOfBandPrint( *toptr, "getstatus" );
serverStatus = CL_GetServerStatus( *toptr ); serverStatus = CL_GetServerStatus( *toptr );
serverStatus->address = *toptr; serverStatus->address = *toptr;

View file

@ -132,7 +132,7 @@ CL_Netchan_TransmitNextFragment
================= =================
*/ */
void CL_Netchan_TransmitNextFragment( netchan_t *chan ) { void CL_Netchan_TransmitNextFragment( netchan_t *chan ) {
Netchan_TransmitNextFragment( chan ); Netchan_TransmitNextFragment( chan, cl_netprofile->integer ? &cls.netprofile.inPackets : NULL );
} }
/* /*
@ -144,7 +144,7 @@ void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg ) {
MSG_WriteByte( msg, clc_EOF ); MSG_WriteByte( msg, clc_EOF );
CL_Netchan_Encode( msg ); CL_Netchan_Encode( msg );
Netchan_Transmit( chan, msg->cursize, msg->data ); Netchan_Transmit( chan, msg->cursize, msg->data, cl_netprofile->integer ? &cls.netprofile.inPackets : NULL );
} }
extern int oldsize; extern int oldsize;
@ -158,10 +158,30 @@ CL_Netchan_Process
qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) { qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) {
int ret; int ret;
ret = Netchan_Process( chan, msg ); ret = Netchan_Process( chan, msg, cl_netprofile->integer ? &cls.netprofile.outPackets : NULL );
if (!ret) if (!ret)
return qfalse; return qfalse;
CL_Netchan_Decode( msg ); CL_Netchan_Decode( msg );
newsize += msg->cursize; newsize += msg->cursize;
return qtrue; return qtrue;
} }
/*
=================
CL_NET_OutOfBandPrint
=================
*/
void CL_NET_OutOfBandPrint(netadr_t adr, const char* format, ...) {
va_list argptr;
char string[MAX_MSGLEN];
va_start(argptr, format);
Q_vsnprintf(string, sizeof(string), format, argptr);
va_end(argptr);
NET_OutOfBandPrint(NS_CLIENT, adr, "%s", string);
if (cl_netprofile->integer) {
NetProfileAddPacket(&cls.netprofile.inPackets, strlen(string), NETPROF_PACKET_MESSAGE);
}
}

View file

@ -3041,14 +3041,14 @@ void CL_PingServers_f(void)
if (!noudp->integer) { if (!noudp->integer) {
adr.type = NA_BROADCAST; adr.type = NA_BROADCAST;
adr.port = BigShort(12203); adr.port = BigShort(12203);
NET_OutOfBandPrint(NS_SERVER, adr, "info %i", 8); CL_NET_OutOfBandPrint(adr, "info %i", 8);
} }
noipx = Cvar_Get("noipx", "0", CVAR_INIT); noipx = Cvar_Get("noipx", "0", CVAR_INIT);
if (!noipx->integer) { if (!noipx->integer) {
adr.type = NA_BROADCAST_IPX; adr.type = NA_BROADCAST_IPX;
adr.port = BigShort(12203); adr.port = BigShort(12203);
NET_OutOfBandPrint(NS_SERVER, adr, "info %i", 8); CL_NET_OutOfBandPrint(adr, "info %i", 8);
} }
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
@ -3063,7 +3063,7 @@ void CL_PingServers_f(void)
adr.port = BigShort(12203); adr.port = BigShort(12203);
} }
NET_OutOfBandPrint(NS_SERVER, adr, "info %i", 8); CL_NET_OutOfBandPrint(adr, "info %i", 8);
} else { } else {
Com_Printf("Bad address: %s\n", adrstring); Com_Printf("Bad address: %s\n", adrstring);
} }

View file

@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cl_ui.h" #include "cl_ui.h"
#include "../qcommon/localization.h" #include "../qcommon/localization.h"
#include "../server/server.h"
CLASS_DECLARATION(UIWidget, View3D, NULL) { CLASS_DECLARATION(UIWidget, View3D, NULL) {
{&W_Activated, &View3D::OnActivate }, {&W_Activated, &View3D::OnActivate },
{&W_Deactivated, &View3D::OnDeactivate}, {&W_Deactivated, &View3D::OnDeactivate},
@ -241,13 +243,262 @@ void View3D::DrawSoundOverlay(void)
setFont("verdana-14"); setFont("verdana-14");
m_font->setColor(UWhite); m_font->setColor(UWhite);
// FIXME: TODO // FIXME: Unimplemented
if (sound_overlay->integer) { if (sound_overlay->integer) {
Com_Printf("sound_overlay isn't supported with OpenAL/SDL right now.\n"); Com_Printf("sound_overlay isn't supported with OpenAL/SDL right now.\n");
Cvar_Set("sound_overlay", "0"); Cvar_Set("sound_overlay", "0");
} }
} }
void DisplayServerNetProfileInfo(UIFont *font, float y, netprofclient_t *netprofile)
{
font->Print(104, y, va("%i", netprofile->inPackets.packetsPerSec));
font->Print(144, y, va("%i", netprofile->outPackets.packetsPerSec));
font->Print(184, y, va("%i", netprofile->inPackets.packetsPerSec + netprofile->outPackets.packetsPerSec));
font->Print(234, y, va("%i", netprofile->inPackets.percentFragmented));
font->Print(264, y, va("%i", netprofile->outPackets.percentFragmented));
font->Print(
294,
y,
va("%i",
(unsigned int)((float)(netprofile->outPackets.numFragmented + netprofile->inPackets.numFragmented)
/ (float)(netprofile->inPackets.totalProcessed + netprofile->outPackets.totalProcessed)
)),
-1,
qfalse
);
font->Print(334, y, va("%i", netprofile->inPackets.percentDropped));
font->Print(364, y, va("%i", netprofile->outPackets.percentDropped));
font->Print(
394,
y,
va("%i",
(unsigned int)((float)(netprofile->outPackets.numDropped + netprofile->inPackets.numDropped)
/ (float)(netprofile->inPackets.totalProcessed + netprofile->outPackets.totalProcessed)
)),
-1,
qfalse
);
font->Print(434, y, va("%i", netprofile->inPackets.percentDropped));
font->Print(464, y, va("%i", netprofile->outPackets.percentDropped));
font->Print(
494,
y,
va("%i",
(unsigned int)((float)(netprofile->outPackets.totalLengthConnectionLess
+ netprofile->inPackets.totalLengthConnectionLess)
/ (float)(netprofile->outPackets.totalSize + netprofile->inPackets.totalSize))),
-1,
qfalse
);
font->Print(534, y, va("%i", netprofile->inPackets.bytesPerSec));
font->Print(594, y, va("%i", netprofile->outPackets.bytesPerSec));
font->Print(654, y, va("%i", netprofile->outPackets.bytesPerSec + netprofile->inPackets.bytesPerSec));
font->Print(714, y, va("%i", netprofile->rate));
}
void DisplayClientNetProfile(UIFont *font, float x, float y, netprofclient_t *netprofile)
{
float columns[5];
float fontHeight;
float columnHeight;
fontHeight = font->getHeight(qfalse);
columns[0] = x + 120;
columns[1] = x + 230;
columns[2] = x + 330;
columns[3] = x + 430;
columns[4] = x + 530;
columnHeight = y;
font->Print(x, y, va("Rate: %i", netprofile->rate));
columnHeight += fontHeight * 1.5;
font->Print(x, columnHeight, "Data Type");
font->Print(columns[0], columnHeight, "Packets per Sec");
font->Print(columns[1], columnHeight, "% Fragmented");
font->Print(columns[2], columnHeight, "% Dropped");
font->Print(columns[3], columnHeight, "% OOB data");
font->Print(columns[4], columnHeight, "Data per Sec");
columnHeight += fontHeight * 0.5;
font->Print(x, columnHeight, "----------");
font->Print(columns[0], columnHeight, "----------");
font->Print(columns[1], columnHeight, "----------");
font->Print(columns[2], columnHeight, "----------");
font->Print(columns[3], columnHeight, "----------");
font->Print(columns[4], columnHeight, "----------");
columnHeight += fontHeight;
font->Print(x, columnHeight, "Data In");
font->Print(columns[0], columnHeight, va("%i", netprofile->outPackets.packetsPerSec));
font->Print(columns[1], columnHeight, va("%i%%", netprofile->outPackets.percentFragmented));
font->Print(columns[2], columnHeight, va("%i%%", netprofile->outPackets.percentDropped));
font->Print(columns[3], columnHeight, va("%i%%", netprofile->outPackets.percentConnectionLess));
font->Print(columns[4], columnHeight, va("%i", netprofile->outPackets.bytesPerSec));
columnHeight += fontHeight;
font->Print(x, columnHeight, "Data Out");
font->Print(columns[0], columnHeight, va("%i", netprofile->inPackets.packetsPerSec));
font->Print(columns[1], columnHeight, va("%i%%", netprofile->inPackets.percentFragmented));
font->Print(columns[2], columnHeight, va("%i%%", netprofile->inPackets.percentDropped));
font->Print(columns[3], columnHeight, va("%i%%", netprofile->inPackets.percentConnectionLess));
font->Print(columns[4], columnHeight, va("%i", netprofile->inPackets.bytesPerSec));
columnHeight += fontHeight;
font->Print(x, columnHeight, "Total Data");
font->Print(
columns[0],
columnHeight,
va("%i", netprofile->inPackets.packetsPerSec + netprofile->outPackets.packetsPerSec)
);
font->Print(
columns[1],
columnHeight,
va("%i%%",
(unsigned int)((float)(netprofile->outPackets.numFragmented + netprofile->inPackets.numFragmented)
/ (float)(netprofile->inPackets.totalProcessed + netprofile->outPackets.totalProcessed)
))
);
font->Print(
columns[2],
columnHeight,
va("%i%%",
(unsigned int)((float)(netprofile->outPackets.numDropped + netprofile->inPackets.numDropped)
/ (double)(netprofile->inPackets.totalProcessed + netprofile->outPackets.totalProcessed
)))
);
font->Print(
columns[3],
columnHeight,
va("%i%%",
(unsigned int)((float)(netprofile->outPackets.totalLengthConnectionLess
+ netprofile->inPackets.totalLengthConnectionLess)
/ (float)(netprofile->outPackets.totalSize + netprofile->inPackets.totalSize)))
);
font->Print(
columns[4],
columnHeight,
va("%i", netprofile->inPackets.bytesPerSec + netprofile->outPackets.bytesPerSec)
);
}
void View3D::DrawNetProfile(void)
{
float fontHeight;
float yOffset;
int i;
if (sv_netprofileoverlay->integer && sv_netprofile->integer && com_sv_running->integer) {
float columnHeight;
float valueHeight;
float separatorHeight;
float categoryHeight;
float currentHeight;
netprofclient_t netproftotal;
setFont("verdana-14");
m_font->setColor(UWhite);
fontHeight = m_font->getHeight(qfalse);
yOffset = sv_netprofileoverlay->integer + 8;
if (svs.netprofile.rate) {
m_font->Print(8, yOffset, va("Server Net Profile Max Rate: %i", svs.netprofile.rate), -1, qfalse);
} else {
m_font->Print(8, yOffset, "Server Net Profile Max Rate: none", -1, qfalse);
}
columnHeight = fontHeight + fontHeight + yOffset;
valueHeight = columnHeight + fontHeight;
separatorHeight = fontHeight * 1.5 + columnHeight;
categoryHeight = fontHeight * 0.5 + columnHeight;
m_font->Print(8, categoryHeight, "Data Source");
m_font->Print(8, separatorHeight, "---------------");
m_font->Print(104, columnHeight, "Packets per Sec");
m_font->Print(104, valueHeight, "In");
m_font->Print(144, valueHeight, "Out");
m_font->Print(184, valueHeight, "Total");
m_font->Print(104, separatorHeight, "---");
m_font->Print(144, separatorHeight, "-----");
m_font->Print(184, separatorHeight, "------");
m_font->Print(234, columnHeight, "% Fragmented");
m_font->Print(234, valueHeight, "In");
m_font->Print(264, valueHeight, "Out");
m_font->Print(294, valueHeight, "Total");
m_font->Print(234, separatorHeight, "---");
m_font->Print(264, separatorHeight, "-----");
m_font->Print(294, separatorHeight, "------");
m_font->Print(334, columnHeight, "% Dropped");
m_font->Print(334, valueHeight, "In");
m_font->Print(364, valueHeight, "Out");
m_font->Print(394, valueHeight, "Total");
m_font->Print(334, separatorHeight, "---");
m_font->Print(364, separatorHeight, "-----");
m_font->Print(394, separatorHeight, "------");
m_font->Print(434, columnHeight, "% OOB Data");
m_font->Print(434, valueHeight, "In");
m_font->Print(464, valueHeight, "Out");
m_font->Print(494, valueHeight, "Total");
m_font->Print(434, separatorHeight, "---");
m_font->Print(464, separatorHeight, "-----");
m_font->Print(494, separatorHeight, "------");
m_font->Print(534, columnHeight, "Data per Sec");
m_font->Print(534, valueHeight, "In");
m_font->Print(594, valueHeight, "Out");
m_font->Print(654, valueHeight, "Total");
m_font->Print(534, separatorHeight, "---");
m_font->Print(594, separatorHeight, "-----");
m_font->Print(654, separatorHeight, "------");
m_font->Print(714, categoryHeight, "Rate");
m_font->Print(714, separatorHeight, "------");
currentHeight = fontHeight * 2.5 + columnHeight;
SV_NET_CalcTotalNetProfile(&netproftotal, qfalse);
m_font->Print(8, columnHeight + fontHeight * 2.5, "Total");
DisplayServerNetProfileInfo(m_font, currentHeight, &netproftotal);
currentHeight += fontHeight * 1.5;
m_font->Print(8, currentHeight, "Clientless");
DisplayServerNetProfileInfo(m_font, currentHeight, &svs.netprofile);
currentHeight += fontHeight;
for (i = 0; i < svs.iNumClients; i++) {
client_t *client = &svs.clients[i];
if (client->state != CS_ACTIVE || !client->gentity) {
continue;
}
if (client->netchan.remoteAddress.type == NA_LOOPBACK) {
m_font->Print(8.0, currentHeight, va("#%i-Loopback", i), -1, 0);
} else {
m_font->Print(8.0, currentHeight, va("Client #%i", i), -1, 0);
}
DisplayServerNetProfileInfo(m_font, currentHeight, &client->netprofile);
currentHeight = currentHeight + fontHeight;
}
} else if (cl_netprofileoverlay->integer && cl_netprofile->integer && com_cl_running->integer) {
setFont("verdana-14");
m_font->setColor(UWhite);
fontHeight = m_font->getHeight(qfalse);
yOffset = cl_netprofileoverlay->integer + 16;
m_font->Print(16, yOffset, "Client Net Profile", -1, qfalse);
NetProfileCalcStats(&cls.netprofile.outPackets, 500);
NetProfileCalcStats(&cls.netprofile.inPackets, 500);
DisplayClientNetProfile(m_font, 16, yOffset + fontHeight * 2, &cls.netprofile);
}
}
void View3D::Draw2D(void) void View3D::Draw2D(void)
{ {
if (!cls.no_menus) { if (!cls.no_menus) {
@ -271,6 +522,7 @@ void View3D::Draw2D(void)
if (!cls.no_menus) { if (!cls.no_menus) {
DrawSoundOverlay(); DrawSoundOverlay();
DrawNetProfile();
DrawSubtitleOverlay(); DrawSubtitleOverlay();
} }
} }

View file

@ -51,6 +51,9 @@ protected:
void OnDeactivate(Event *ev); void OnDeactivate(Event *ev);
void DrawSubtitleOverlay(void); void DrawSubtitleOverlay(void);
// Added in 2.0
void DrawNetProfile(void);
public: public:
View3D(); View3D();

View file

@ -383,8 +383,8 @@ typedef struct {
void* savedCgameState; void* savedCgameState;
size_t savedCgameStateSize; size_t savedCgameStateSize;
char gcdResponse[73]; char gcdResponse[73];
int unknown3_0; // Added in 2.0
int currentRate; netprofclient_t netprofile;
qhandle_t charSetShader; qhandle_t charSetShader;
qhandle_t whiteShader; qhandle_t whiteShader;
qhandle_t consoleShader; qhandle_t consoleShader;
@ -415,6 +415,8 @@ extern cvar_t *cl_connect_timeout;
extern cvar_t *cl_maxpackets; extern cvar_t *cl_maxpackets;
extern cvar_t *cl_packetdup; extern cvar_t *cl_packetdup;
extern cvar_t *cl_shownet; extern cvar_t *cl_shownet;
extern cvar_t *cl_netprofile;
extern cvar_t *cl_netprofileoverlay;
extern cvar_t *cl_showSend; extern cvar_t *cl_showSend;
extern cvar_t *cl_timeNudge; extern cvar_t *cl_timeNudge;
extern cvar_t *cl_showTimeDelta; extern cvar_t *cl_showTimeDelta;
@ -732,6 +734,7 @@ void LAN_SaveServersToCache( void );
void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg); //int length, const byte *data ); void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg); //int length, const byte *data );
void CL_Netchan_TransmitNextFragment( netchan_t *chan ); void CL_Netchan_TransmitNextFragment( netchan_t *chan );
qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ); qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg );
void CL_NET_OutOfBandPrint( netadr_t adr, const char* format, ... );
// //
// cl_avi.c // cl_avi.c

View file

@ -382,7 +382,7 @@ void AuthenticateCallback(int gameid, int localid, int authenticated, char* errm
challenge->cdkeyState = 2; challenge->cdkeyState = 2;
challenge->pingTime = svs.time; challenge->pingTime = svs.time;
NET_OutOfBandPrint(NS_SERVER, challenge->adr, "challengeResponse %i", challenge->challenge); SV_NET_OutOfBandPrint(&svs.netprofile, challenge->adr, "challengeResponse %i", challenge->challenge);
} }
else else
{ {
@ -396,7 +396,7 @@ void AuthenticateCallback(int gameid, int localid, int authenticated, char* errm
Com_Printf("%s failed cdkey authorization\n", buf); Com_Printf("%s failed cdkey authorization\n", buf);
challenge->cdkeyState = 3; challenge->cdkeyState = 3;
// tell the client about the reason // tell the client about the reason
NET_OutOfBandPrint(NS_SERVER, challenge->adr, "droperror\nServer rejected connection:\n%s", errmsg); SV_NET_OutOfBandPrint(&svs.netprofile, challenge->adr, "droperror\nServer rejected connection:\n%s", errmsg);
} }
} }
@ -437,18 +437,18 @@ void SV_GamespyAuthorize(netadr_t from, const char* response)
Com_DPrintf("authorize server timed out\n"); Com_DPrintf("authorize server timed out\n");
challenge->cdkeyState = CDKS_AUTHENTICATED; challenge->cdkeyState = CDKS_AUTHENTICATED;
challenge->pingTime = svs.time; challenge->pingTime = svs.time;
NET_OutOfBandPrint(NS_SERVER, from, "challengeResponse %i", challenge->challenge); SV_NET_OutOfBandPrint(&svs.netprofile, from, "challengeResponse %i", challenge->challenge);
} }
break; break;
case CDKS_AUTHENTICATED: case CDKS_AUTHENTICATED:
NET_OutOfBandPrint(NS_SERVER, from, "challengeResponse %i", challenge->challenge); SV_NET_OutOfBandPrint(&svs.netprofile, from, "challengeResponse %i", challenge->challenge);
break; break;
case CDKS_FAILED: case CDKS_FAILED:
// authentication server told the cdkey was invalid // authentication server told the cdkey was invalid
Com_sprintf(buf, sizeof(buf), "%d.%d.%d.%d", challenge->adr.ip[0], challenge->adr.ip[1], challenge->adr.ip[2], challenge->adr.ip[3]); Com_sprintf(buf, sizeof(buf), "%d.%d.%d.%d", challenge->adr.ip[0], challenge->adr.ip[1], challenge->adr.ip[2], challenge->adr.ip[3]);
Com_Printf("%s failed cdkey authorization\n", buf); Com_Printf("%s failed cdkey authorization\n", buf);
// reject the client // reject the client
NET_OutOfBandPrint(NS_SERVER, from, "droperror\nServer rejected connection:\nInvalid CD Key"); SV_NET_OutOfBandPrint(&svs.netprofile, from, "droperror\nServer rejected connection:\nInvalid CD Key");
break; break;
default: default:
break; break;

View file

@ -99,6 +99,126 @@ void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int
#endif #endif
} }
/*
==============
NetProfileAddPacket
==============
*/
void NetProfileAddPacket(netprofpacketlist_t* list, size_t size, int type)
{
list->index = (list->index + 1) % 64;
list->packets[list->index].updateTime = Com_Milliseconds();
list->packets[list->index].size = size;
list->packets[list->index].flags = type;
}
/*
==============
NetProfileSetPacketFlags
==============
*/
void NetProfileSetPacketFlags(netprofpacketlist_t* list, int flags)
{
list->packets[list->index].flags |= flags;
}
/*
==============
NetProfileCalcStats
==============
*/
void NetProfileCalcStats(netprofpacketlist_t* list, int time)
{
netprofpacket_t* packet;
int i;
float frequency;
if (list->updateTime < time + list->lastCalcTime) {
return;
}
list->lastCalcTime = list->updateTime;
list->lowestUpdateTime = list->updateTime;
list->highestUpdateTime = 0;
list->totalProcessed = 0;
list->totalSize = 0;
list->numFragmented = 0;
list->numDropped = 0;
list->numConnectionLess = 0;
list->totalLengthConnectionLess = 0;
for (i = 0; i < ARRAY_LEN(list->packets); i++) {
packet = &list->packets[i];
if (!packet->size) {
continue;
}
if (list->updateTime > packet->updateTime + 1000) {
packet->size = 0;
continue;
}
if (list->lowestUpdateTime > packet->updateTime) {
list->lowestUpdateTime = packet->updateTime;
}
if (list->highestUpdateTime < packet->updateTime) {
list->highestUpdateTime = packet->updateTime;
}
list->totalProcessed++;
list->totalSize += packet->size;
if (packet->flags & NETPROF_PACKET_FRAGMENTED) {
list->numFragmented++;
}
if (packet->flags & NETPROF_PACKET_DROPPED) {
list->numDropped++;
}
if (packet->flags & NETPROF_PACKET_MESSAGE) {
list->numConnectionLess++;
list->totalLengthConnectionLess += packet->size;
}
}
if (!list->totalProcessed) {
list->packetsPerSec = 0;
list->highestUpdateTime = list->lowestUpdateTime;
list->bytesPerSec = 0;
list->percentFragmented = 0;
list->percentDropped = 0;
list->percentConnectionLess = 0;
return;
}
if (list->lowestUpdateTime == list->highestUpdateTime) {
list->latency = 0.0;
frequency = 1.0;
} else {
list->latency = (list->highestUpdateTime - list->lowestUpdateTime) / 1000.0;
frequency = 1.0 / list->latency;
}
list->packetsPerSec = list->totalProcessed * frequency;
list->bytesPerSec = list->totalSize * frequency;
if (list->numFragmented) {
list->percentFragmented = (float)list->numFragmented / list->totalProcessed * 100.0;
} else {
list->percentFragmented = 0;
}
if (list->numDropped) {
list->percentDropped = (float)list->numDropped / list->totalProcessed * 100.0;
} else {
list->percentDropped = 0;
}
if (list->totalLengthConnectionLess) {
list->percentConnectionLess = (float)list->totalLengthConnectionLess / list->totalSize * 100.0;
}
}
// TTimo: unused, commenting out to make gcc happy // TTimo: unused, commenting out to make gcc happy
#if 0 #if 0
/* /*
@ -192,7 +312,7 @@ Netchan_TransmitNextFragment
Send one fragment of the current message Send one fragment of the current message
================= =================
*/ */
void Netchan_TransmitNextFragment( netchan_t *chan ) { void Netchan_TransmitNextFragment( netchan_t *chan, netprofpacketlist_t *packetlist ) {
msg_t send; msg_t send;
byte send_buf[MAX_PACKETLEN]; byte send_buf[MAX_PACKETLEN];
size_t fragmentLength; size_t fragmentLength;
@ -228,6 +348,10 @@ void Netchan_TransmitNextFragment( netchan_t *chan ) {
, chan->unsentFragmentStart, fragmentLength); , chan->unsentFragmentStart, fragmentLength);
} }
if (packetlist) {
NetProfileAddPacket(packetlist, send.cursize, NETPROF_PACKET_FRAGMENTED);
}
chan->unsentFragmentStart += fragmentLength; chan->unsentFragmentStart += fragmentLength;
// this exit condition is a little tricky, because a packet // this exit condition is a little tricky, because a packet
@ -249,7 +373,7 @@ Sends a message to a connection, fragmenting if necessary
A 0 length will still generate a packet. A 0 length will still generate a packet.
================ ================
*/ */
void Netchan_Transmit( netchan_t *chan, size_t length, const byte *data ) { void Netchan_Transmit( netchan_t *chan, size_t length, const byte *data, netprofpacketlist_t *packetlist ) {
msg_t send; msg_t send;
byte send_buf[MAX_PACKETLEN]; byte send_buf[MAX_PACKETLEN];
@ -265,7 +389,7 @@ void Netchan_Transmit( netchan_t *chan, size_t length, const byte *data ) {
Com_Memcpy( chan->unsentBuffer, data, length ); Com_Memcpy( chan->unsentBuffer, data, length );
// only send the first fragment now // only send the first fragment now
Netchan_TransmitNextFragment( chan ); Netchan_TransmitNextFragment( chan, packetlist );
return; return;
} }
@ -293,6 +417,10 @@ void Netchan_Transmit( netchan_t *chan, size_t length, const byte *data ) {
, chan->outgoingSequence - 1 , chan->outgoingSequence - 1
, chan->incomingSequence ); , chan->incomingSequence );
} }
if (packetlist) {
NetProfileAddPacket(packetlist, send.cursize, 0);
}
} }
/* /*
@ -307,7 +435,7 @@ final fragment of a multi-part message, the entire thing will be
copied out. copied out.
================= =================
*/ */
qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) { qboolean Netchan_Process( netchan_t *chan, msg_t *msg, netprofpacketlist_t *packetlist ) {
int sequence; int sequence;
int qport; int qport;
int fragmentStart, fragmentLength; int fragmentStart, fragmentLength;
@ -357,6 +485,10 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
} }
} }
if (packetlist) {
NetProfileAddPacket(packetlist, msg->cursize, fragmented ? NETPROF_PACKET_FRAGMENTED : 0);
}
// //
// discard out of order or duplicated packets // discard out of order or duplicated packets
// //

View file

@ -299,14 +299,61 @@ typedef struct {
#endif #endif
} netchan_t; } netchan_t;
/*
Packet profiling
*/
#define NETPROF_PACKET_FRAGMENTED 1
#define NETPROF_PACKET_DROPPED 2
#define NETPROF_PACKET_MESSAGE 4
#define NETPROX_MAX_PACKETS 64
typedef struct {
int updateTime;
int size;
int flags;
} netprofpacket_t;
typedef struct {
int updateTime;
int index;
netprofpacket_t packets[NETPROX_MAX_PACKETS];
int lastCalcTime;
int lowestUpdateTime;
int highestUpdateTime;
int totalProcessed;
int totalSize;
int numFragmented;
int numDropped;
int numConnectionLess;
int totalLengthConnectionLess;
int packetsPerSec;
int bytesPerSec;
int percentFragmented;
int percentDropped;
int percentConnectionLess;
float latency;
} netprofpacketlist_t;
typedef struct {
qboolean initialized;
int rate;
netprofpacketlist_t outPackets;
netprofpacketlist_t inPackets;
} netprofclient_t;
void Netchan_Init( int qport ); void Netchan_Init( int qport );
void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int challenge, qboolean compat); void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int challenge, qboolean compat);
void Netchan_Transmit( netchan_t *chan, size_t length, const byte *data ); void Netchan_Transmit( netchan_t *chan, size_t length, const byte *data, netprofpacketlist_t *packetlist );
void Netchan_TransmitNextFragment( netchan_t *chan ); void Netchan_TransmitNextFragment( netchan_t *chan, netprofpacketlist_t *packetlist );
qboolean Netchan_Process( netchan_t *chan, msg_t *msg ); qboolean Netchan_Process( netchan_t *chan, msg_t *msg, netprofpacketlist_t *packetlist );
void NetProfileAddPacket(netprofpacketlist_t* list, size_t size, int flags);
void NetProfileSetPacketFlags(netprofpacketlist_t* list, int flags);
void NetProfileCalcStats(netprofpacketlist_t* list, int time);
/* /*
============================================================== ==============================================================

View file

@ -193,6 +193,8 @@ typedef struct client_s {
int pureAuthentic; int pureAuthentic;
qboolean gotCP; // TTimo - additional flag to distinguish between a bad pure checksum, and no cp command at all qboolean gotCP; // TTimo - additional flag to distinguish between a bad pure checksum, and no cp command at all
netchan_t netchan; netchan_t netchan;
// Added in 2.0
netprofclient_t netprofile;
// TTimo // TTimo
// queuing outgoing fragmented messages to send them properly, without udp packet bursts // queuing outgoing fragmented messages to send them properly, without udp packet bursts
// in case large fragmented messages are stacking up // in case large fragmented messages are stacking up
@ -319,6 +321,8 @@ typedef struct {
#ifndef DEDICATED #ifndef DEDICATED
soundsystemsavegame_t soundSystem; soundsystemsavegame_t soundSystem;
#endif #endif
// Added in 2.0
netprofclient_t netprofile;
} serverStatic_t; } serverStatic_t;
#define SERVER_MAXBANS 1024 #define SERVER_MAXBANS 1024
@ -621,6 +625,10 @@ void SV_Netchan_Transmit( client_t *client, msg_t *msg);
int SV_Netchan_TransmitNextFragment( client_t *client ); int SV_Netchan_TransmitNextFragment( client_t *client );
qboolean SV_Netchan_Process( client_t *client, msg_t *msg ); qboolean SV_Netchan_Process( client_t *client, msg_t *msg );
void SV_Netchan_FreeQueue(client_t *client); void SV_Netchan_FreeQueue(client_t *client);
void SV_NET_OutOfBandPrint(netprofclient_t* netprof, netadr_t adr, const char* format, ...);
void SV_NET_UpdateClientNetProfileInfo(netprofclient_t* netprofile, int rate);
void SV_NET_UpdateAllNetProfileInfo();
void SV_NET_CalcTotalNetProfile(netprofclient_t* netprofile, qboolean server);
// //
// sv_gamespy.c // sv_gamespy.c

View file

@ -502,7 +502,7 @@ static void SV_Ban_f( void ) {
// otherwise send their ip to the authorize server // otherwise send their ip to the authorize server
if ( svs.authorizeAddress.type != NA_BAD ) { if ( svs.authorizeAddress.type != NA_BAD ) {
NET_OutOfBandPrint( NS_SERVER, svs.authorizeAddress, SV_NET_OutOfBandPrint( &svs.netprofile, svs.authorizeAddress,
"banUser %i.%i.%i.%i", cl->netchan.remoteAddress.ip[0], cl->netchan.remoteAddress.ip[1], "banUser %i.%i.%i.%i", cl->netchan.remoteAddress.ip[0], cl->netchan.remoteAddress.ip[1],
cl->netchan.remoteAddress.ip[2], cl->netchan.remoteAddress.ip[3] ); cl->netchan.remoteAddress.ip[2], cl->netchan.remoteAddress.ip[3] );
Com_Printf("%s was banned from coming back\n", cl->name); Com_Printf("%s was banned from coming back\n", cl->name);
@ -556,7 +556,7 @@ static void SV_BanNum_f( void ) {
// otherwise send their ip to the authorize server // otherwise send their ip to the authorize server
if ( svs.authorizeAddress.type != NA_BAD ) { if ( svs.authorizeAddress.type != NA_BAD ) {
NET_OutOfBandPrint( NS_SERVER, svs.authorizeAddress, SV_NET_OutOfBandPrint( &svs.netprofile, svs.authorizeAddress,
"banUser %i.%i.%i.%i", cl->netchan.remoteAddress.ip[0], cl->netchan.remoteAddress.ip[1], "banUser %i.%i.%i.%i", cl->netchan.remoteAddress.ip[0], cl->netchan.remoteAddress.ip[1],
cl->netchan.remoteAddress.ip[2], cl->netchan.remoteAddress.ip[3] ); cl->netchan.remoteAddress.ip[2], cl->netchan.remoteAddress.ip[3] );
Com_Printf("%s was banned from coming back\n", cl->name); Com_Printf("%s was banned from coming back\n", cl->name);
@ -1573,6 +1573,120 @@ void SV_LoadLastGame_f( void )
Cbuf_AddText( va( "loadgame %s\n", Cvar_Get( "g_lastsave", "", 0 )->string ) ); Cbuf_AddText( va( "loadgame %s\n", Cvar_Get( "g_lastsave", "", 0 )->string ) );
} }
/*
=================
SV_NetProfileDump_PrintProf
=================
*/
void SV_NetProfileDump_PrintProf(fileHandle_t file, netprofclient_t* netprofile)
{
size_t totalProcessed;
char buffer[2048];
totalProcessed = netprofile->outPackets.totalProcessed + netprofile->inPackets.totalProcessed;
Com_sprintf(
buffer,
sizeof(buffer),
"%4i %4i %4i | %3i %3i %3i | %3i %3i %3i | %3i %3i %3i | %7i %7i %7i\n",
netprofile->inPackets.packetsPerSec,
netprofile->outPackets.packetsPerSec,
netprofile->outPackets.packetsPerSec + netprofile->inPackets.packetsPerSec,
netprofile->inPackets.percentFragmented,
netprofile->outPackets.percentFragmented,
(unsigned int)((float)(netprofile->outPackets.numFragmented + netprofile->inPackets.numFragmented) / totalProcessed),
netprofile->inPackets.percentDropped,
netprofile->outPackets.percentDropped,
(unsigned int)((float)(netprofile->outPackets.numDropped + netprofile->inPackets.numDropped) / totalProcessed),
netprofile->inPackets.percentDropped,
netprofile->outPackets.percentDropped,
(unsigned int)((float)(netprofile->outPackets.totalLengthConnectionLess + netprofile->inPackets.totalLengthConnectionLess) / (float)(netprofile->outPackets.totalSize + netprofile->inPackets.totalSize)),
netprofile->inPackets.bytesPerSec,
netprofile->outPackets.bytesPerSec,
netprofile->outPackets.bytesPerSec + netprofile->inPackets.bytesPerSec
);
FS_Write(buffer, strlen(buffer), file);
}
/*
=================
SV_NetProfileDump_f
=================
*/
void SV_NetProfileDump_f(void)
{
static fileHandle_t hFile = 0;
client_t *client;
int i;
char buffer[2048];
netprofclient_t netproftotal;
if (!hFile) {
hFile = FS_FOpenTextFileWrite("netprofile.log");
FS_ForceFlush(hFile);
Com_sprintf(buffer, sizeof(buffer), "NetProfile.log\n\n");
FS_Write(buffer, strlen(buffer), hFile);
Com_sprintf(buffer, sizeof(buffer), "Log Format:\n");
FS_Write(buffer, strlen(buffer), hFile);
Com_sprintf(
buffer,
sizeof(buffer),
"Source: Packets per Second In/Out/Total | %%Fragments In/Out/Total | %%Dropped In/Out/Total | %%OOB Data In/Out/Total"
" | Data per Second In/Out/Total\n"
"\n");
FS_Write(buffer, strlen(buffer), hFile);
}
if (!sv_netprofile->integer) {
return;
}
#ifndef DEDICATED
if (!com_cl_running->integer || com_sv_running->integer) {
#else
if (com_sv_running->integer) {
#endif
Com_sprintf(buffer, sizeof(buffer), "------------------\nServer Net Profile\n");
FS_Write(buffer, strlen(buffer), hFile);
SV_NET_CalcTotalNetProfile(&netproftotal, 1);
Com_sprintf(buffer, sizeof(buffer), "Total: ");
FS_Write(buffer, strlen(buffer), hFile);
SV_NetProfileDump_PrintProf(hFile, &netproftotal);
Com_sprintf(buffer, sizeof(buffer), "Clientless: ");
FS_Write(buffer, strlen(buffer), hFile);
SV_NetProfileDump_PrintProf(hFile, &svs.netprofile);
for (i = 0; i < svs.iNumClients; i++) {
client = &svs.clients[i];
if (client->state != CS_ACTIVE || !client->gentity) {
continue;
}
if (client->netchan.remoteAddress.type == NA_LOOPBACK) {
Com_sprintf(buffer, sizeof(buffer), "#%2i-Loopback: ");
} else {
Com_sprintf(buffer, sizeof(buffer), "Client #%2i: ");
}
FS_Write(buffer, strlen(buffer), hFile);
SV_NetProfileDump_PrintProf(hFile, &client->netprofile);
}
}
#ifndef DEDICATED
else if (com_cl_running->integer && cl_netprofile->integer) {
Com_sprintf(buffer, sizeof(buffer), "------------------\nClient Net Profile\n");
FS_Write(buffer, strlen(buffer), hFile);
SV_NetProfileDump_PrintProf(hFile, &cls.netprofile);
}
#endif
}
/* /*
================= =================
SV_ReloadMap_f SV_ReloadMap_f
@ -1730,6 +1844,8 @@ void SV_AddOperatorCommands(void) {
Cmd_AddCommand("difficultyMedium", SV_MediumMode_f); Cmd_AddCommand("difficultyMedium", SV_MediumMode_f);
Cmd_AddCommand("difficultyHard", SV_HardMode_f); Cmd_AddCommand("difficultyHard", SV_HardMode_f);
// Added in 2.0
Cmd_AddCommand("netprofiledump", SV_NetProfileDump_f);
// Added in 2.30 // Added in 2.30
Cmd_AddCommand("reloadmap", SV_ReloadMap_f); Cmd_AddCommand("reloadmap", SV_ReloadMap_f);

View file

@ -89,7 +89,7 @@ void SV_GetChallenge(netadr_t from)
// it's also way more cool this way :) // it's also way more cool this way :)
if ( Sys_IsLANAddress( from ) ) { if ( Sys_IsLANAddress( from ) ) {
challenge->pingTime = svs.time; challenge->pingTime = svs.time;
NET_OutOfBandPrint( NS_SERVER, from, "challengeResponse %i", challenge->challenge ); SV_NET_OutOfBandPrint( &svs.netprofile, from, "challengeResponse %i", challenge->challenge );
return; return;
} }
@ -97,7 +97,7 @@ void SV_GetChallenge(netadr_t from)
// mohaa below 2.0 doesn't handle gamespy key // mohaa below 2.0 doesn't handle gamespy key
// so send the challenge response directly // so send the challenge response directly
challenge->pingTime = svs.time; challenge->pingTime = svs.time;
NET_OutOfBandPrint(NS_SERVER, from, "challengeResponse %i", challenge->challenge); SV_NET_OutOfBandPrint( &svs.netprofile, from, "challengeResponse %i", challenge->challenge);
return; return;
} }
@ -106,12 +106,12 @@ void SV_GetChallenge(netadr_t from)
// however, it could be an useful feature for a far future // however, it could be an useful feature for a far future
// where players could be authenticated // where players could be authenticated
challenge->pingTime = svs.time; challenge->pingTime = svs.time;
NET_OutOfBandPrint(NS_SERVER, from, "challengeResponse %i", challenge->challenge); SV_NET_OutOfBandPrint( &svs.netprofile, from, "challengeResponse %i", challenge->challenge);
return; return;
} }
// check client's cd key // check client's cd key
NET_OutOfBandPrint(NS_SERVER, from, "getKey %s", challenge->gsChallenge); SV_NET_OutOfBandPrint( &svs.netprofile, from, "getKey %s", challenge->gsChallenge);
challenge->pingTime = svs.time; challenge->pingTime = svs.time;
} }
@ -158,21 +158,21 @@ void SV_AuthorizeIpPacket( netadr_t from ) {
if ( !Q_stricmp( s, "demo" ) ) { if ( !Q_stricmp( s, "demo" ) ) {
// they are a demo client trying to connect to a real server // they are a demo client trying to connect to a real server
NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\nServer is not a demo server\n" ); SV_NET_OutOfBandPrint( &svs.netprofile, challengeptr->adr, "print\nServer is not a demo server\n" );
// clear the challenge record so it won't timeout and let them through // clear the challenge record so it won't timeout and let them through
Com_Memset( challengeptr, 0, sizeof( *challengeptr ) ); Com_Memset( challengeptr, 0, sizeof( *challengeptr ) );
return; return;
} }
if ( !Q_stricmp( s, "accept" ) ) { if ( !Q_stricmp( s, "accept" ) ) {
NET_OutOfBandPrint(NS_SERVER, challengeptr->adr, SV_NET_OutOfBandPrint( &svs.netprofile, challengeptr->adr,
"challengeResponse %d %d %d", challengeptr->challenge, challengeptr->clientChallenge, com_protocol->integer); "challengeResponse %d %d %d", challengeptr->challenge, challengeptr->clientChallenge, com_protocol->integer);
return; return;
} }
if ( !Q_stricmp( s, "unknown" ) ) { if ( !Q_stricmp( s, "unknown" ) ) {
if (!r) { if (!r) {
NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\nAwaiting CD key authorization\n" ); SV_NET_OutOfBandPrint( &svs.netprofile, challengeptr->adr, "print\nAwaiting CD key authorization\n" );
} else { } else {
NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\n%s\n", r); SV_NET_OutOfBandPrint( &svs.netprofile, challengeptr->adr, "print\n%s\n", r);
} }
// clear the challenge record so it won't timeout and let them through // clear the challenge record so it won't timeout and let them through
Com_Memset( challengeptr, 0, sizeof( *challengeptr ) ); Com_Memset( challengeptr, 0, sizeof( *challengeptr ) );
@ -181,9 +181,9 @@ void SV_AuthorizeIpPacket( netadr_t from ) {
// authorization failed // authorization failed
if (!r) { if (!r) {
NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\nSomeone is using this CD Key\n" ); SV_NET_OutOfBandPrint( &svs.netprofile, challengeptr->adr, "print\nSomeone is using this CD Key\n" );
} else { } else {
NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\n%s\n", r ); SV_NET_OutOfBandPrint( &svs.netprofile, challengeptr->adr, "print\n%s\n", r );
} }
// clear the challenge record so it won't timeout and let them through // clear the challenge record so it won't timeout and let them through
@ -317,7 +317,7 @@ void SV_DirectConnect( netadr_t from ) {
// Check whether this client is banned. // Check whether this client is banned.
if(SV_IsBanned(&from, qfalse)) if(SV_IsBanned(&from, qfalse))
{ {
NET_OutOfBandPrint(NS_SERVER, from, "droperror\nYou are banned from this server.\n"); SV_NET_OutOfBandPrint( &svs.netprofile, from, "droperror\nYou are banned from this server.\n");
return; return;
} }
@ -330,7 +330,7 @@ void SV_DirectConnect( netadr_t from ) {
// Added in 2.30 // Added in 2.30
// Only allow breakthrough clients when targeting mohaab // Only allow breakthrough clients when targeting mohaab
if (strcmp(clientType, "Breakthrough")) { if (strcmp(clientType, "Breakthrough")) {
NET_OutOfBandPrint(NS_SERVER, from, "droperror\nRequires Medal of Honor Allied Assault Breakthrough\n"); SV_NET_OutOfBandPrint( &svs.netprofile, from, "droperror\nRequires Medal of Honor Allied Assault Breakthrough\n");
Com_DPrintf(" rejected connect - only Breakthrough clients allowed.\n"); Com_DPrintf(" rejected connect - only Breakthrough clients allowed.\n");
return; return;
} }
@ -346,7 +346,7 @@ void SV_DirectConnect( netadr_t from ) {
{ {
if(version != com_protocol->integer) if(version != com_protocol->integer)
{ {
NET_OutOfBandPrint(NS_SERVER, from, "droperror\nServer uses protocol version %i " SV_NET_OutOfBandPrint( &svs.netprofile, from, "droperror\nServer uses protocol version %i "
"(yours is %i).\n", com_protocol->integer, version); "(yours is %i).\n", com_protocol->integer, version);
Com_DPrintf(" rejected connect from version %i\n", version); Com_DPrintf(" rejected connect from version %i\n", version);
return; return;
@ -379,7 +379,7 @@ void SV_DirectConnect( netadr_t from ) {
else else
ip = (char *)NET_AdrToString( from ); ip = (char *)NET_AdrToString( from );
if( ( strlen( ip ) + strlen( userinfo ) + 4 ) >= MAX_INFO_STRING ) { if( ( strlen( ip ) + strlen( userinfo ) + 4 ) >= MAX_INFO_STRING ) {
NET_OutOfBandPrint( NS_SERVER, from, SV_NET_OutOfBandPrint( &svs.netprofile, from,
"droperror\nUserinfo string length exceeded. " "droperror\nUserinfo string length exceeded. "
"Try removing setu cvars from your config.\n" ); "Try removing setu cvars from your config.\n" );
return; return;
@ -403,7 +403,7 @@ void SV_DirectConnect( netadr_t from ) {
if (i == MAX_CHALLENGES) if (i == MAX_CHALLENGES)
{ {
NET_OutOfBandPrint( NS_SERVER, from, "print\nNo or bad challenge for your address.\n" ); SV_NET_OutOfBandPrint( &svs.netprofile, from, "print\nNo or bad challenge for your address.\n" );
return; return;
} }
@ -420,13 +420,13 @@ void SV_DirectConnect( netadr_t from ) {
// never reject a LAN client based on ping // never reject a LAN client based on ping
if ( !Sys_IsLANAddress( from ) ) { if ( !Sys_IsLANAddress( from ) ) {
if ( sv_minPing->value && ping < sv_minPing->value ) { if ( sv_minPing->value && ping < sv_minPing->value ) {
NET_OutOfBandPrint( NS_SERVER, from, "print\nServer is for high pings only\n" ); SV_NET_OutOfBandPrint( &svs.netprofile, from, "print\nServer is for high pings only\n" );
Com_DPrintf ("Client %i rejected on a too low ping\n", i); Com_DPrintf ("Client %i rejected on a too low ping\n", i);
challengeptr->wasrefused = qtrue; challengeptr->wasrefused = qtrue;
return; return;
} }
if ( sv_maxPing->value && ping > sv_maxPing->value ) { if ( sv_maxPing->value && ping > sv_maxPing->value ) {
NET_OutOfBandPrint( NS_SERVER, from, "print\nServer is for low pings only\n" ); SV_NET_OutOfBandPrint( &svs.netprofile, from, "print\nServer is for low pings only\n" );
Com_DPrintf ("Client %i rejected on a too high ping\n", i); Com_DPrintf ("Client %i rejected on a too high ping\n", i);
challengeptr->wasrefused = qtrue; challengeptr->wasrefused = qtrue;
return; return;
@ -509,7 +509,7 @@ void SV_DirectConnect( netadr_t from ) {
} }
} }
else { else {
NET_OutOfBandPrint( NS_SERVER, from, "droperror\nServer is full.\n" ); SV_NET_OutOfBandPrint( &svs.netprofile, from, "droperror\nServer is full.\n" );
Com_DPrintf ("Rejected a connection.\n"); Com_DPrintf ("Rejected a connection.\n");
return; return;
} }
@ -548,7 +548,7 @@ gotnewcl:
// get the game a chance to reject this connection or modify the userinfo // get the game a chance to reject this connection or modify the userinfo
denied = ge->ClientConnect( clientNum, qtrue, qfalse ); denied = ge->ClientConnect( clientNum, qtrue, qfalse );
if ( denied ) { if ( denied ) {
NET_OutOfBandPrint( NS_SERVER, from, "droperror\n%s\n", denied ); SV_NET_OutOfBandPrint( &svs.netprofile, from, "droperror\n%s\n", denied );
Com_DPrintf ( "Game rejected a connection: %s.\n", denied ); Com_DPrintf ( "Game rejected a connection: %s.\n", denied );
return; return;
} }
@ -560,8 +560,12 @@ gotnewcl:
SV_UserinfoChanged( newcl ); SV_UserinfoChanged( newcl );
if (sv_netprofile->integer) {
SV_NET_UpdateClientNetProfileInfo(&newcl->netprofile, newcl->rate);
}
// send the connect packet to the client // send the connect packet to the client
NET_OutOfBandPrint(NS_SERVER, from, "connectResponse %d", challenge); SV_NET_OutOfBandPrint( &svs.netprofile, from, "connectResponse %d", challenge);
Com_DPrintf( "Going from CS_FREE to CS_CONNECTED for %s\n", newcl->name ); Com_DPrintf( "Going from CS_FREE to CS_CONNECTED for %s\n", newcl->name );

View file

@ -530,7 +530,7 @@ void SVC_Status( netadr_t from ) {
} }
} }
NET_OutOfBandPrint( NS_SERVER, from, "statusResponse\n%s\n%s", infostring, status ); SV_NET_OutOfBandPrint( &svs.netprofile, from, "statusResponse\n%s\n%s", infostring, status );
} }
/* /*
@ -618,7 +618,7 @@ void SVC_Info( netadr_t from ) {
Info_SetValueForKey(infostring, "gamever", com_target_version->string); Info_SetValueForKey(infostring, "gamever", com_target_version->string);
Info_SetValueForKey(infostring, "serverType", va("%i", com_target_game->integer)); Info_SetValueForKey(infostring, "serverType", va("%i", com_target_game->integer));
NET_OutOfBandPrint( NS_SERVER, from, "infoResponse\n%s", infostring ); SV_NET_OutOfBandPrint( &svs.netprofile, from, "infoResponse\n%s", infostring );
} }
/* /*
@ -628,7 +628,7 @@ SVC_FlushRedirect
================ ================
*/ */
static void SV_FlushRedirect( char *outputbuf ) { static void SV_FlushRedirect( char *outputbuf ) {
NET_OutOfBandPrint( NS_SERVER, svs.redirectAddress, "print\n%s", outputbuf ); SV_NET_OutOfBandPrint( &svs.netprofile, svs.redirectAddress, "print\n%s", outputbuf );
} }
/* /*
@ -720,6 +720,10 @@ void SV_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
char *s; char *s;
char *c; char *c;
if (sv_netprofile->integer) {
NetProfileAddPacket(&svs.netprofile.inPackets, msg->cursize, NETPROF_PACKET_MESSAGE);
}
MSG_BeginReadingOOB( msg ); MSG_BeginReadingOOB( msg );
MSG_ReadLong( msg ); // skip the -1 marker MSG_ReadLong( msg ); // skip the -1 marker
@ -818,7 +822,7 @@ void SV_PacketEvent( netadr_t from, msg_t *msg ) {
// if we received a sequenced packet from an address we don't recognize, // if we received a sequenced packet from an address we don't recognize,
// send an out of band disconnect packet to it // send an out of band disconnect packet to it
NET_OutOfBandPrint( NS_SERVER, from, "disconnect" ); SV_NET_OutOfBandPrint( &svs.netprofile, from, "disconnect" );
} }
@ -1023,6 +1027,8 @@ void SV_Frame( int msec ) {
return; return;
} }
SV_NET_UpdateAllNetProfileInfo();
// allow pause if only the local client is connected // allow pause if only the local client is connected
if ( SV_CheckPaused() ) { if ( SV_CheckPaused() ) {
return; return;

View file

@ -169,7 +169,7 @@ void SV_Netchan_TransmitNextInQueue(client_t *client)
SV_Netchan_Encode(client, &netbuf->msg, netbuf->clientCommandString); SV_Netchan_Encode(client, &netbuf->msg, netbuf->clientCommandString);
#endif #endif
Netchan_Transmit(&client->netchan, netbuf->msg.cursize, netbuf->msg.data); Netchan_Transmit(&client->netchan, netbuf->msg.cursize, netbuf->msg.data, sv_netprofile->integer ? &client->netprofile.outPackets : NULL);
// pop from queue // pop from queue
client->netchan_start_queue = netbuf->next; client->netchan_start_queue = netbuf->next;
@ -197,7 +197,7 @@ int SV_Netchan_TransmitNextFragment(client_t *client)
{ {
if(client->netchan.unsentFragments) if(client->netchan.unsentFragments)
{ {
Netchan_TransmitNextFragment(&client->netchan); Netchan_TransmitNextFragment(&client->netchan, sv_netprofile->integer ? &client->netprofile.outPackets : NULL);
return SV_RateMsec(client); return SV_RateMsec(client);
} }
else if(client->netchan_start_queue) else if(client->netchan_start_queue)
@ -250,7 +250,7 @@ void SV_Netchan_Transmit( client_t *client, msg_t *msg)
if(client->compat) if(client->compat)
SV_Netchan_Encode(client, msg, client->lastClientCommandString); SV_Netchan_Encode(client, msg, client->lastClientCommandString);
#endif #endif
Netchan_Transmit( &client->netchan, msg->cursize, msg->data ); Netchan_Transmit(&client->netchan, msg->cursize, msg->data, sv_netprofile->integer ? &client->netprofile.outPackets : NULL);
} }
} }
@ -261,7 +261,7 @@ Netchan_SV_Process
*/ */
qboolean SV_Netchan_Process( client_t *client, msg_t *msg ) { qboolean SV_Netchan_Process( client_t *client, msg_t *msg ) {
int ret; int ret;
ret = Netchan_Process( &client->netchan, msg ); ret = Netchan_Process( &client->netchan, msg, sv_netprofile->integer ? &client->netprofile.inPackets : NULL );
if (!ret) if (!ret)
return qfalse; return qfalse;
@ -273,3 +273,170 @@ qboolean SV_Netchan_Process( client_t *client, msg_t *msg ) {
return qtrue; return qtrue;
} }
/*
=================
SV_NET_OutOfBandPrint
=================
*/
void SV_NET_OutOfBandPrint(netprofclient_t* netprof, netadr_t adr, const char* format, ...) {
va_list argptr;
char string[MAX_MSGLEN];
va_start(argptr, format);
Q_vsnprintf(string, sizeof(string), format, argptr);
va_end(argptr);
NET_OutOfBandPrint(NS_SERVER, adr, "%s", string);
if (sv_netprofile->integer && netprof) {
NetProfileAddPacket(&netprof->outPackets, strlen(string), NETPROF_PACKET_MESSAGE);
}
}
/*
=================
SV_NET_UpdateClientNetProfileInfo
=================
*/
void SV_NET_UpdateClientNetProfileInfo(netprofclient_t* netprofile, int rate) {
int time;
if (!netprofile->initialized) {
memset(netprofile, 0, sizeof(*netprofile));
netprofile->initialized = qtrue;
}
if (netprofile->rate != rate) {
netprofile->rate = rate;
}
// set the update time
time = Com_Milliseconds();
netprofile->outPackets.updateTime = time;
netprofile->inPackets.updateTime = time;
}
/*
=================
SV_NET_UpdateAllNetProfileInfo
=================
*/
void SV_NET_UpdateAllNetProfileInfo() {
client_t *client;
int i;
if (!sv_netprofile->integer) {
//
// Clear all netprofile fields
//
svs.netprofile.initialized = qfalse;
for (i = 0; i < svs.iNumClients; i++) {
svs.clients[i].netprofile.initialized = qfalse;
}
return;
}
SV_NET_UpdateClientNetProfileInfo(&svs.netprofile, sv_maxRate->integer);
for (i = 0; i < svs.iNumClients; i++) {
client = &svs.clients[i];
if (client->state != CS_ACTIVE || !client->gentity) {
client->netprofile.initialized = qfalse;
continue;
}
SV_NET_UpdateClientNetProfileInfo(&client->netprofile, client->rate);
}
}
/*
=================
SV_NET_CalcTotalNetProfile
=================
*/
void SV_NET_CalcTotalNetProfile(netprofclient_t* netprofile, qboolean server) {
client_t *client;
int i;
int numValidClients;
numValidClients = 0;
memset(netprofile, 0, sizeof(*netprofile));
if (server) {
NetProfileCalcStats(&svs.netprofile.outPackets, 0);
NetProfileCalcStats(&svs.netprofile.inPackets, 0);
} else {
NetProfileCalcStats(&svs.netprofile.outPackets, 500);
NetProfileCalcStats(&svs.netprofile.inPackets, 500);
}
for (i = 0; i < svs.iNumClients; i++) {
client = &svs.clients[i];
if (client->state != CS_ACTIVE || !client->gentity) {
client->netprofile.initialized = qfalse;
continue;
}
if (server) {
NetProfileCalcStats(&client->netprofile.outPackets, 0);
NetProfileCalcStats(&client->netprofile.inPackets, 0);
} else {
NetProfileCalcStats(&client->netprofile.outPackets, 500);
NetProfileCalcStats(&client->netprofile.inPackets, 500);
}
numValidClients++;
netprofile->rate += client->netprofile.rate;
netprofile->outPackets.totalSize += client->netprofile.outPackets.totalSize;
netprofile->outPackets.bytesPerSec += client->netprofile.outPackets.bytesPerSec;
netprofile->outPackets.numDropped += client->netprofile.outPackets.numDropped;
netprofile->outPackets.percentDropped += client->netprofile.outPackets.percentDropped;
netprofile->outPackets.percentFragmented += client->netprofile.outPackets.percentFragmented;
netprofile->outPackets.numFragmented += client->netprofile.outPackets.numFragmented;
netprofile->outPackets.totalLengthConnectionLess += client->netprofile.outPackets.totalLengthConnectionLess;
netprofile->outPackets.percentConnectionLess += client->netprofile.outPackets.percentConnectionLess;
netprofile->outPackets.totalProcessed += client->netprofile.outPackets.totalProcessed;
netprofile->outPackets.packetsPerSec += client->netprofile.outPackets.packetsPerSec;
netprofile->inPackets.totalSize += client->netprofile.inPackets.totalSize;
netprofile->inPackets.bytesPerSec += client->netprofile.inPackets.bytesPerSec;
netprofile->inPackets.numDropped += client->netprofile.inPackets.numDropped;
netprofile->inPackets.percentDropped += client->netprofile.inPackets.percentDropped;
netprofile->inPackets.percentFragmented += client->netprofile.inPackets.percentFragmented;
netprofile->inPackets.numFragmented += client->netprofile.inPackets.numFragmented;
netprofile->inPackets.totalLengthConnectionLess += client->netprofile.inPackets.totalLengthConnectionLess;
netprofile->inPackets.percentConnectionLess += client->netprofile.inPackets.percentConnectionLess;
netprofile->inPackets.totalProcessed += client->netprofile.inPackets.totalProcessed;
netprofile->inPackets.packetsPerSec += client->netprofile.inPackets.packetsPerSec;
}
if (numValidClients && netprofile->rate) {
netprofile->rate /= numValidClients;
}
netprofile->outPackets.totalSize += svs.netprofile.outPackets.totalSize;
netprofile->outPackets.bytesPerSec += svs.netprofile.outPackets.bytesPerSec;
netprofile->outPackets.numDropped += svs.netprofile.outPackets.numDropped;
netprofile->outPackets.percentDropped += svs.netprofile.outPackets.percentDropped;
netprofile->outPackets.percentFragmented += svs.netprofile.outPackets.percentFragmented;
netprofile->outPackets.numFragmented += svs.netprofile.outPackets.numFragmented;
netprofile->outPackets.totalLengthConnectionLess += svs.netprofile.outPackets.totalLengthConnectionLess;
netprofile->outPackets.percentConnectionLess += svs.netprofile.outPackets.percentConnectionLess;
netprofile->outPackets.totalProcessed += svs.netprofile.outPackets.totalProcessed;
netprofile->outPackets.packetsPerSec += svs.netprofile.outPackets.packetsPerSec;
netprofile->inPackets.totalSize += svs.netprofile.inPackets.totalSize;
netprofile->inPackets.bytesPerSec += svs.netprofile.inPackets.bytesPerSec;
netprofile->inPackets.numDropped += svs.netprofile.inPackets.numDropped;
netprofile->inPackets.percentDropped += svs.netprofile.inPackets.percentDropped;
netprofile->inPackets.percentFragmented += svs.netprofile.inPackets.percentFragmented;
netprofile->inPackets.numFragmented += svs.netprofile.inPackets.numFragmented;
netprofile->inPackets.totalLengthConnectionLess += svs.netprofile.inPackets.totalLengthConnectionLess;
netprofile->inPackets.percentConnectionLess += svs.netprofile.inPackets.percentConnectionLess;
netprofile->inPackets.totalProcessed += svs.netprofile.inPackets.totalProcessed;
netprofile->inPackets.packetsPerSec += svs.netprofile.inPackets.packetsPerSec;
}