Add network statistics to ddsrt
Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
parent
f9808c7656
commit
ecb77d481c
6 changed files with 483 additions and 1 deletions
|
@ -147,7 +147,7 @@ list(APPEND sources
|
||||||
# network stack. In order to mix-and-match various compilers, architectures,
|
# network stack. In order to mix-and-match various compilers, architectures,
|
||||||
# operating systems, etc input from the build system is required.
|
# operating systems, etc input from the build system is required.
|
||||||
foreach(feature atomics cdtors environ heap ifaddrs random rusage
|
foreach(feature atomics cdtors environ heap ifaddrs random rusage
|
||||||
sockets string sync threads time md5 process)
|
sockets string sync threads time md5 process netstat)
|
||||||
if(EXISTS "${include_path}/dds/ddsrt/${feature}.h")
|
if(EXISTS "${include_path}/dds/ddsrt/${feature}.h")
|
||||||
list(APPEND headers "${include_path}/dds/ddsrt/${feature}.h")
|
list(APPEND headers "${include_path}/dds/ddsrt/${feature}.h")
|
||||||
file(GLOB_RECURSE
|
file(GLOB_RECURSE
|
||||||
|
|
18
src/ddsrt/cmake/netstat.c
Normal file
18
src/ddsrt/cmake/netstat.c
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||||
|
* v. 1.0 which is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#include "dds/ddsrt/netstat.h"
|
||||||
|
|
||||||
|
#if DDSRT_HAVE_NETSTAT
|
||||||
|
# error "cmake_HAVE_NETSTAT=true"
|
||||||
|
#else
|
||||||
|
# error "cmake_HAVE_NETSTAT=false"
|
||||||
|
#endif
|
73
src/ddsrt/include/dds/ddsrt/netstat.h
Normal file
73
src/ddsrt/include/dds/ddsrt/netstat.h
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2019 ADLINK Technology Limited and others
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||||
|
* v. 1.0 which is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef DDSRT_NETSTAT_H
|
||||||
|
#define DDSRT_NETSTAT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "dds/export.h"
|
||||||
|
#include "dds/ddsrt/retcode.h"
|
||||||
|
|
||||||
|
#if defined (__linux) || defined (__APPLE__) || defined (_WIN32)
|
||||||
|
#define DDSRT_HAVE_NETSTAT (1)
|
||||||
|
#else
|
||||||
|
#define DDSRT_HAVE_NETSTAT (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DDSRT_HAVE_NETSTAT
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ddsrt_netstat {
|
||||||
|
uint64_t ipkt;
|
||||||
|
uint64_t opkt;
|
||||||
|
uint64_t ibytes;
|
||||||
|
uint64_t obytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Platform dependent control structure for network statistics
|
||||||
|
*/
|
||||||
|
struct ddsrt_netstat_control;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prepare for gathering network statistics for specified interface.
|
||||||
|
*/
|
||||||
|
DDS_EXPORT dds_return_t
|
||||||
|
ddsrt_netstat_new (
|
||||||
|
struct ddsrt_netstat_control **control,
|
||||||
|
const char *device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release resources for gathering network statistics.
|
||||||
|
*/
|
||||||
|
DDS_EXPORT dds_return_t
|
||||||
|
ddsrt_netstat_free (
|
||||||
|
struct ddsrt_netstat_control *control);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get network statistics.
|
||||||
|
*/
|
||||||
|
DDS_EXPORT dds_return_t
|
||||||
|
ddsrt_netstat_get (
|
||||||
|
struct ddsrt_netstat_control *control,
|
||||||
|
struct ddsrt_netstat *stats);
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* DDSRT_HAVE_NETSTAT */
|
||||||
|
|
||||||
|
#endif /* DDSRT_NETSTAT_H */
|
130
src/ddsrt/src/netstat/darwin/netstat.c
Normal file
130
src/ddsrt/src/netstat/darwin/netstat.c
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_var.h>
|
||||||
|
#include <net/if_types.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_mib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <dds/ddsrt/heap.h>
|
||||||
|
#include <dds/ddsrt/string.h>
|
||||||
|
#include <dds/ddsrt/netstat.h>
|
||||||
|
|
||||||
|
struct ddsrt_netstat_control {
|
||||||
|
char *name;
|
||||||
|
int cached_row;
|
||||||
|
};
|
||||||
|
|
||||||
|
static dds_return_t ddsrt_netstat_get_int (struct ddsrt_netstat_control *control, struct ddsrt_netstat *stats)
|
||||||
|
{
|
||||||
|
int name[6];
|
||||||
|
size_t len;
|
||||||
|
int count;
|
||||||
|
struct ifmibdata ifmd;
|
||||||
|
|
||||||
|
if (control->cached_row > 0)
|
||||||
|
{
|
||||||
|
name[0] = CTL_NET;
|
||||||
|
name[1] = PF_LINK;
|
||||||
|
name[2] = NETLINK_GENERIC;
|
||||||
|
name[3] = IFMIB_IFDATA;
|
||||||
|
name[4] = control->cached_row;
|
||||||
|
name[5] = IFDATA_GENERAL;
|
||||||
|
len = sizeof (ifmd);
|
||||||
|
if (sysctl (name, 6, &ifmd, &len, NULL, 0) != 0)
|
||||||
|
control->cached_row = 0;
|
||||||
|
else if (strcmp (ifmd.ifmd_name, control->name) != 0)
|
||||||
|
control->cached_row = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (control->cached_row == 0)
|
||||||
|
{
|
||||||
|
name[0] = CTL_NET;
|
||||||
|
name[1] = PF_LINK;
|
||||||
|
name[2] = NETLINK_GENERIC;
|
||||||
|
name[3] = IFMIB_SYSTEM;
|
||||||
|
name[4] = IFMIB_IFCOUNT;
|
||||||
|
len = sizeof (count);
|
||||||
|
if (sysctl (name, 5, &count, &len, NULL, 0) != 0)
|
||||||
|
goto error;
|
||||||
|
for (int row = 1; row <= count; row++)
|
||||||
|
{
|
||||||
|
name[0] = CTL_NET;
|
||||||
|
name[1] = PF_LINK;
|
||||||
|
name[2] = NETLINK_GENERIC;
|
||||||
|
name[3] = IFMIB_IFDATA;
|
||||||
|
name[4] = row;
|
||||||
|
name[5] = IFDATA_GENERAL;
|
||||||
|
len = sizeof (ifmd);
|
||||||
|
if (sysctl (name, 6, &ifmd, &len, NULL, 0) != 0)
|
||||||
|
{
|
||||||
|
if (errno != ENOENT)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else if (strcmp (control->name, ifmd.ifmd_name) == 0)
|
||||||
|
{
|
||||||
|
control->cached_row = row;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (control->cached_row == 0)
|
||||||
|
return DDS_RETCODE_NOT_FOUND;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stats->ipkt = ifmd.ifmd_data.ifi_ipackets;
|
||||||
|
stats->opkt = ifmd.ifmd_data.ifi_opackets;
|
||||||
|
stats->ibytes = ifmd.ifmd_data.ifi_ibytes;
|
||||||
|
stats->obytes = ifmd.ifmd_data.ifi_obytes;
|
||||||
|
return DDS_RETCODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
control->cached_row = -1;
|
||||||
|
return DDS_RETCODE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dds_return_t ddsrt_netstat_new (struct ddsrt_netstat_control **control, const char *device)
|
||||||
|
{
|
||||||
|
struct ddsrt_netstat_control *c = ddsrt_malloc (sizeof (*c));
|
||||||
|
struct ddsrt_netstat dummy;
|
||||||
|
c->name = ddsrt_strdup (device);
|
||||||
|
c->cached_row = 0;
|
||||||
|
if (ddsrt_netstat_get_int (c, &dummy) != DDS_RETCODE_OK)
|
||||||
|
{
|
||||||
|
ddsrt_free (c->name);
|
||||||
|
ddsrt_free (c);
|
||||||
|
*control = NULL;
|
||||||
|
return DDS_RETCODE_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*control = c;
|
||||||
|
return DDS_RETCODE_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dds_return_t ddsrt_netstat_free (struct ddsrt_netstat_control *control)
|
||||||
|
{
|
||||||
|
ddsrt_free (control->name);
|
||||||
|
ddsrt_free (control);
|
||||||
|
return DDS_RETCODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
dds_return_t ddsrt_netstat_get (struct ddsrt_netstat_control *control, struct ddsrt_netstat *stats)
|
||||||
|
{
|
||||||
|
if (control->cached_row < 0)
|
||||||
|
return DDS_RETCODE_ERROR;
|
||||||
|
else
|
||||||
|
return ddsrt_netstat_get_int (control, stats);
|
||||||
|
}
|
146
src/ddsrt/src/netstat/linux/netstat.c
Normal file
146
src/ddsrt/src/netstat/linux/netstat.c
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include <dds/ddsrt/heap.h>
|
||||||
|
#include <dds/ddsrt/string.h>
|
||||||
|
#include <dds/ddsrt/netstat.h>
|
||||||
|
|
||||||
|
struct ddsrt_netstat_control {
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
dds_return_t ddsrt_netstat_get (struct ddsrt_netstat_control *control, struct ddsrt_netstat *stats)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char save[256];
|
||||||
|
int c;
|
||||||
|
size_t np;
|
||||||
|
int field = 0;
|
||||||
|
if ((fp = fopen ("/proc/net/dev", "r")) == NULL)
|
||||||
|
return DDS_RETCODE_ERROR;
|
||||||
|
/* expected format: 2 header lines, then on each line, white space/interface
|
||||||
|
name/colon and then numbers. Received bytes is 1st data field, transmitted
|
||||||
|
bytes is 9th.
|
||||||
|
|
||||||
|
SKIP_HEADER_1 skips up to and including the first newline; then SKIP_TO_EOL
|
||||||
|
skips up to and including the second newline, so the first line that gets
|
||||||
|
interpreted is the third.
|
||||||
|
*/
|
||||||
|
dds_return_t res = DDS_RETCODE_NOT_FOUND;
|
||||||
|
enum { SKIP_HEADER_1, SKIP_WHITE, READ_NAME, SKIP_TO_EOL, READ_SEP, READ_INT } state = SKIP_HEADER_1;
|
||||||
|
np = 0;
|
||||||
|
while (res == DDS_RETCODE_NOT_FOUND && (c = fgetc (fp)) != EOF) {
|
||||||
|
switch (state) {
|
||||||
|
case SKIP_HEADER_1:
|
||||||
|
if (c == '\n') {
|
||||||
|
state = SKIP_TO_EOL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SKIP_WHITE:
|
||||||
|
if (c != ' ' && c != '\t') {
|
||||||
|
save[np++] = (char) c;
|
||||||
|
state = READ_NAME;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case READ_NAME:
|
||||||
|
if (c == ':') {
|
||||||
|
save[np] = 0;
|
||||||
|
np = 0;
|
||||||
|
if (strcmp (save, control->name) != 0)
|
||||||
|
state = SKIP_TO_EOL;
|
||||||
|
else
|
||||||
|
state = READ_SEP;
|
||||||
|
} else if (np < sizeof (save) - 1) {
|
||||||
|
save[np++] = (char) c;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SKIP_TO_EOL:
|
||||||
|
if (c == '\n') {
|
||||||
|
state = SKIP_WHITE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case READ_SEP:
|
||||||
|
if (c == '\n')
|
||||||
|
{
|
||||||
|
/* unexpected end of line */
|
||||||
|
res = DDS_RETCODE_ERROR;
|
||||||
|
}
|
||||||
|
else if (c >= '0' && c <= '9')
|
||||||
|
{
|
||||||
|
field++;
|
||||||
|
save[np++] = (char) c;
|
||||||
|
state = READ_INT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case READ_INT:
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
{
|
||||||
|
if (np == sizeof (save) - 1)
|
||||||
|
{
|
||||||
|
res = DDS_RETCODE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
save[np++] = (char) c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
save[np] = 0;
|
||||||
|
np = 0;
|
||||||
|
if (field == 1 || field == 2 || field == 9 || field == 10)
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
uint64_t val;
|
||||||
|
if (sscanf (save, "%"SCNu64"%n", &val, &pos) != 1 || save[pos] != 0)
|
||||||
|
res = DDS_RETCODE_ERROR;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (field)
|
||||||
|
{
|
||||||
|
case 1: stats->ibytes = val; break;
|
||||||
|
case 2: stats->ipkt = val; break;
|
||||||
|
case 9: stats->obytes = val; break;
|
||||||
|
case 10: stats->opkt = val; res = DDS_RETCODE_OK; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c == '\n' && res != DDS_RETCODE_OK)
|
||||||
|
{
|
||||||
|
/* newline before all expected fields have been read */
|
||||||
|
res = DDS_RETCODE_ERROR;
|
||||||
|
}
|
||||||
|
state = READ_SEP;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose (fp);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
dds_return_t ddsrt_netstat_new (struct ddsrt_netstat_control **control, const char *device)
|
||||||
|
{
|
||||||
|
struct ddsrt_netstat_control *c = ddsrt_malloc (sizeof (*c));
|
||||||
|
struct ddsrt_netstat dummy;
|
||||||
|
c->name = ddsrt_strdup (device);
|
||||||
|
if (ddsrt_netstat_get (c, &dummy) != DDS_RETCODE_OK)
|
||||||
|
{
|
||||||
|
ddsrt_free (c->name);
|
||||||
|
ddsrt_free (c);
|
||||||
|
*control = NULL;
|
||||||
|
return DDS_RETCODE_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*control = c;
|
||||||
|
return DDS_RETCODE_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dds_return_t ddsrt_netstat_free (struct ddsrt_netstat_control *control)
|
||||||
|
{
|
||||||
|
ddsrt_free (control->name);
|
||||||
|
ddsrt_free (control);
|
||||||
|
return DDS_RETCODE_OK;
|
||||||
|
}
|
115
src/ddsrt/src/netstat/windows/netstat.c
Normal file
115
src/ddsrt/src/netstat/windows/netstat.c
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <ws2def.h>
|
||||||
|
#include <ws2ipdef.h>
|
||||||
|
#include <iphlpapi.h>
|
||||||
|
|
||||||
|
#include <dds/ddsrt/heap.h>
|
||||||
|
#include <dds/ddsrt/string.h>
|
||||||
|
#include <dds/ddsrt/netstat.h>
|
||||||
|
|
||||||
|
struct ddsrt_netstat_control {
|
||||||
|
wchar_t *name;
|
||||||
|
bool errored;
|
||||||
|
bool have_index;
|
||||||
|
NET_IFINDEX index;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void copy_data (struct ddsrt_netstat *dst, const MIB_IF_ROW2 *src)
|
||||||
|
{
|
||||||
|
dst->ipkt = src->InUcastPkts + src->InNUcastPkts;
|
||||||
|
dst->opkt = src->OutUcastPkts + src->OutNUcastPkts;
|
||||||
|
dst->ibytes = src->InOctets;
|
||||||
|
dst->obytes = src->OutOctets;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_desired_interface (const struct ddsrt_netstat_control *control, const MIB_IF_ROW2 *info)
|
||||||
|
{
|
||||||
|
return wcscmp (control->name, info->Description) == 0 || wcscmp (control->name, info->Alias) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static dds_return_t ddsrt_netstat_get_int (struct ddsrt_netstat_control *control, struct ddsrt_netstat *stats)
|
||||||
|
{
|
||||||
|
if (control->errored)
|
||||||
|
return DDS_RETCODE_ERROR;
|
||||||
|
|
||||||
|
if (control->have_index)
|
||||||
|
{
|
||||||
|
MIB_IF_ROW2 info;
|
||||||
|
memset (&info, 0, sizeof (info));
|
||||||
|
info.InterfaceIndex = control->index;
|
||||||
|
if (GetIfEntry2 (&info) != NO_ERROR || !is_desired_interface (control, &info))
|
||||||
|
control->have_index = false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
copy_data (stats, &info);
|
||||||
|
return DDS_RETCODE_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MIB_IF_TABLE2 *table;
|
||||||
|
if (GetIfTable2 (&table) != NO_ERROR)
|
||||||
|
goto error;
|
||||||
|
control->have_index = false;
|
||||||
|
for (ULONG row = 0; row < table->NumEntries; row++)
|
||||||
|
{
|
||||||
|
if (is_desired_interface (control, &table->Table[row]))
|
||||||
|
{
|
||||||
|
control->index = table->Table[row].InterfaceIndex;
|
||||||
|
control->have_index = true;
|
||||||
|
copy_data (stats, &table->Table[row]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeMibTable (table);
|
||||||
|
return control->have_index ? DDS_RETCODE_OK : DDS_RETCODE_NOT_FOUND;
|
||||||
|
|
||||||
|
error:
|
||||||
|
control->errored = true;
|
||||||
|
return DDS_RETCODE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dds_return_t ddsrt_netstat_new (struct ddsrt_netstat_control **control, const char *device)
|
||||||
|
{
|
||||||
|
struct ddsrt_netstat_control *c = ddsrt_malloc (sizeof (*c));
|
||||||
|
struct ddsrt_netstat dummy;
|
||||||
|
size_t name_size = strlen (device) + 1;
|
||||||
|
c->name = ddsrt_malloc (name_size * sizeof (*c->name));
|
||||||
|
size_t cnt = 0;
|
||||||
|
mbstowcs_s (&cnt, c->name, name_size, device, _TRUNCATE);
|
||||||
|
c->have_index = false;
|
||||||
|
c->errored = false;
|
||||||
|
c->index = 0;
|
||||||
|
if (ddsrt_netstat_get_int (c, &dummy) != DDS_RETCODE_OK)
|
||||||
|
{
|
||||||
|
ddsrt_free (c->name);
|
||||||
|
ddsrt_free (c);
|
||||||
|
*control = NULL;
|
||||||
|
return DDS_RETCODE_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*control = c;
|
||||||
|
return DDS_RETCODE_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dds_return_t ddsrt_netstat_free (struct ddsrt_netstat_control *control)
|
||||||
|
{
|
||||||
|
ddsrt_free (control->name);
|
||||||
|
ddsrt_free (control);
|
||||||
|
return DDS_RETCODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
dds_return_t ddsrt_netstat_get (struct ddsrt_netstat_control *control, struct ddsrt_netstat *stats)
|
||||||
|
{
|
||||||
|
return ddsrt_netstat_get_int (control, stats);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue