tr181: ip: Fixes and cleanups

- use sysfs instread of ubus and ifconfig command execution for Inteface stats.
  This reduces uneccessary memory and cpu overhead and speeds up the query time for
  IP.Interface queries by a multiple.

- move redundant code to static functions
- fix rx/tx multicast/broadcast stats can never be obtained from ifconfig
- fix invalid stats for unknownprotopackets.
- fix stats not correclty reported when counters exceed 32bit int values.

Signed-off-by: Daniel Danzberger <daniel@dd-wrt.com>
This commit is contained in:
Daniel Danzberger 2020-01-08 22:35:38 +01:00
parent 8708940709
commit 219d9b4984
4 changed files with 105 additions and 143 deletions

View file

@ -197,6 +197,23 @@ static inline int init_ipv6prefix_args(struct ipv6prefix_args *args, struct uci_
/*************************************************************
* COMMON Functions
**************************************************************/
static int get_ip_iface_sysfs(const struct ip_args *ip, const char *name, char **value)
{
const char *device = get_device(section_name(ip->ip_sec));
if(device[0]) {
char file[256];
char val[64];
snprintf(file, sizeof(file), "/sys/class/net/%s/%s", device, name);
dm_read_sysfs_file(file, val, sizeof(val));
*value = dmstrdup(val);
} else {
*value = "0";
}
return 0;
}
static char *ubus_call_get_value_with_two_objects(char *interface, char *obj1, char *obj2, char *key)
{
json_object *res, *jobj1 = NULL, *jobj2 = NULL;
@ -493,22 +510,7 @@ int set_IPInterface_Reset(char *refparam, struct dmctx *ctx, void *data, char *i
/*#Device.IP.Interface.{i}.MaxMTUSize!UBUS:network.interface/status/interface,@Name/mtu*/
int get_IPInterface_MaxMTUSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
json_object *res, *diag;
char *device= NULL;
dmuci_get_value_by_section_string(((struct ip_args *)data)->ip_sec, "mtu", value);
if(*value[0] == '\0') {
dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(((struct ip_args *)data)->ip_sec), String}}, 1, &res);
DM_ASSERT(res, *value = "");
device = dmjson_get_value(res, 1, "device");
if(device) {
dmubus_call("network.device", "status", UBUS_ARGS{{"name", device, String}}, 1, &diag);
DM_ASSERT(diag, *value = "");
*value = dmjson_get_value(diag, 1, "mtu");
}
return 0;
}
return 0;
return get_ip_iface_sysfs(data, "mtu", value);
}
int set_IPInterface_MaxMTUSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
@ -758,28 +760,31 @@ int set_ipv4_addressing_type(char *refparam, struct dmctx *ctx, void *data, char
int get_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
char linker[64] = "", *proto, *device, *mac;
const struct ip_args *ip = data;
char *section;
dmuci_get_value_by_section_string(((struct ip_args *)data)->ip_sec, "proto", &proto);
dmuci_get_value_by_section_string(ip->ip_sec, "proto", &proto);
if (strstr(proto, "ppp")) {
snprintf(linker, sizeof(linker), "%s", section_name(((struct ip_args *)data)->ip_sec));
adm_entry_get_linker_param(ctx, dm_print_path("%s%cPPP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
goto end;
}
device = get_device(section_name(((struct ip_args *)data)->ip_sec));
section = section_name(ip->ip_sec);
device = get_device(section);
if (device[0] != '\0') {
adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cVLANTermination%c", dmroot, dm_delim, dm_delim, dm_delim), device, value);
if (*value != NULL)
return 0;
}
mac = get_macaddr(section_name(((struct ip_args *)data)->ip_sec));
mac = get_macaddr(section);
if (mac[0] != '\0') {
adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), mac, value);
goto end;
}
end :
end:
if (*value == NULL)
*value = "";
return 0;
@ -1153,126 +1158,84 @@ int set_IPInterfaceIPv6Prefix_ValidLifetime(char *refparam, struct dmctx *ctx, v
/*
* *** Device.IP.Interface.{i}.Stats. ***
*/
static char *get_ip_interface_statistics(char *interface, char *key)
{
json_object *res, *diag;
char *device, *value = "0";
dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface, String}}, 1, &res);
if (!res) return value;
device = dmjson_get_value(res, 1, "device");
if(device[0] != '\0') {
dmubus_call("network.device", "status", UBUS_ARGS{{"name", device, String}}, 1, &diag);
value = dmjson_get_value(diag, 2, "statistics", key);
}
return value;
}
int get_ip_interface_statistics_tx_bytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "tx_bytes");
return 0;
return get_ip_iface_sysfs(data, "statistics/tx_bytes", value);
}
int get_ip_interface_statistics_rx_bytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "rx_bytes");
return 0;
return get_ip_iface_sysfs(data, "statistics/rx_bytes", value);
}
int get_ip_interface_statistics_tx_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "tx_packets");
return 0;
return get_ip_iface_sysfs(data, "statistics/tx_packets", value);
}
int get_ip_interface_statistics_rx_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "rx_packets");
return 0;
return get_ip_iface_sysfs(data, "statistics/rx_packets", value);
}
int get_ip_interface_statistics_tx_errors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "tx_errors");
return 0;
return get_ip_iface_sysfs(data, "statistics/tx_errors", value);
}
int get_ip_interface_statistics_rx_errors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "rx_errors");
return 0;
return get_ip_iface_sysfs(data, "statistics/rx_errors", value);
}
int get_ip_interface_statistics_tx_discardpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "tx_dropped");
return 0;
return get_ip_iface_sysfs(data, "statistics/tx_dropped", value);
}
int get_ip_interface_statistics_rx_discardpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "rx_dropped");
return 0;
return get_ip_iface_sysfs(data, "statistics/rx_dropped", value);
}
int get_ip_interface_statistics_tx_unicastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = "0";
char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
if(device[0] != '\0')
dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "TX", "unicast"));
return 0;
}
int get_ip_interface_statistics_rx_unicastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = "0";
char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
if(device[0] != '\0')
dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "RX", "unicast"));
return 0;
}
int get_ip_interface_statistics_tx_multicastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = "0";
char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
if(device[0] != '\0')
dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "TX", "multicast"));
return 0;
}
int get_ip_interface_statistics_rx_multicastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = "0";
char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
if(device[0] != '\0')
dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "RX", "multicast"));
return 0;
return get_ip_iface_sysfs(data, "statistics/multicast", value);
}
int get_ip_interface_statistics_tx_broadcastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = "0";
char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
if(device[0] != '\0')
dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "TX", "broadcast"));
return 0;
}
int get_ip_interface_statistics_rx_broadcastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = "0";
char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
if(device[0] != '\0')
dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "RX", "broadcast"));
return 0;
}
int get_ip_interface_statistics_rx_unknownprotopackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "rx_over_errors");
*value = "0";
return 0;
}
@ -1327,6 +1290,7 @@ int set_IPInterfaceTWAMPReflector_Enable(char *refparam, struct dmctx *ctx, void
device = dmjson_get_value(res, 1, "device");
dmuci_set_value_by_section((struct uci_section *)data, "device", device);
}
dmuci_set_value_by_section((struct uci_section *)data, "device", get_device(interface));
} else {
dmuci_set_value_by_section((struct uci_section *)data, "enable", "0");
}

View file

@ -11,8 +11,6 @@
#include "dmentry.h"
#include "usb.h"
#include <fcntl.h>
/* *** Device.USB. *** */
DMOBJ tUSBObj[] = {
/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextdynamicobj, nextobj, leaf, linker, bbfdm_type*/
@ -195,55 +193,12 @@ static void init_usb_interface(struct uci_section *dm, char *iface_name, char *i
/*************************************************************
* ENTRY METHOD
*************************************************************/
static inline int char_is_valid(char c)
{
return c > 0x20 && c < 0x7f;
}
static int __read_sysfs_file(const char *file, char *dst, unsigned len)
{
char *content;
int fd;
int rlen;
int i, n;
int rc = 0;
content = alloca(len);
dst[0] = 0;
fd = open(file, O_RDONLY);
if (fd == -1)
return -1;
rlen = read(fd, content, len - 1);
if (rlen == -1) {
rc = -1;
goto out;
}
content[rlen] = 0;
for (i = 0, n = 0; i < rlen; i++) {
if (!char_is_valid(content[i])) {
if (i == 0)
continue;
else
break;
}
dst[n++] = content[i];
}
dst[n] = 0;
out:
close(fd);
return rc;
}
static int read_sysfs_file(const char *file, char **value)
{
char buf[128];
int rc;
rc = __read_sysfs_file(file, buf, sizeof(buf));
rc = dm_read_sysfs_file(file, buf, sizeof(buf));
*value = dmstrdup(buf);
return rc;
@ -262,7 +217,7 @@ static int __read_sysfs(const char *path, const char *name, char *dst, unsigned
char file[256];
snprintf(file, sizeof(file), "%s/%s", path, name);
return __read_sysfs_file(file, dst, len);
return dm_read_sysfs_file(file, dst, len);
}
static int read_sysfs_usb_port(const struct usb_port *port, const char *name, char **value)
@ -432,7 +387,7 @@ int synchronize_usb_devices_with_dmmap_opt_recursively(char *sysfsrep, char *dmm
char deviceClass[16];
snprintf(deviceClassFile, sizeof(deviceClassFile), "%s/%s/bDeviceClass", sysfsrep, ent->d_name);
__read_sysfs_file(deviceClassFile, deviceClass, sizeof(deviceClass));
dm_read_sysfs_file(deviceClassFile, deviceClass, sizeof(deviceClass));
if(strncmp(deviceClass, "09", 2) == 0){
char hubpath[256];
@ -1061,7 +1016,7 @@ int get_USBUSBHostsHost_USBVersion(char *refparam, struct dmctx *ctx, void *data
char buf[16] = { 0, 0 };
snprintf(file, sizeof(file), "%s/bcdDevice", port->folder_path);
__read_sysfs_file(file, buf, sizeof(buf));
dm_read_sysfs_file(file, buf, sizeof(buf));
dmasprintf(value, "%c.%c", buf[1], buf[2]);
}
@ -1082,7 +1037,7 @@ int get_number_devices(char *folderpath, int *nbre)
char deviceClass[16];
snprintf(deviceClassFile, sizeof(deviceClassFile), "%s/%s/bDeviceClass", folderpath, ent->d_name);
__read_sysfs_file(deviceClassFile, deviceClass, sizeof(deviceClass));
dm_read_sysfs_file(deviceClassFile, deviceClass, sizeof(deviceClass));
if(strncmp(deviceClass, "09", 2) == 0){
char hubpath[256];

View file

@ -31,6 +31,7 @@
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <fcntl.h>
#include "dmbbf.h"
#include "dmuci.h"
@ -1412,11 +1413,9 @@ char *get_macaddr(char *interface_name)
char *get_device(char *interface_name)
{
json_object *res;
char *device = "";
dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface_name, String}}, 1, &res);
device = dmjson_get_value(res, 1, "device");
return device;
return dmjson_get_value(res, 1, "device");
}
/*
@ -1520,25 +1519,25 @@ int get_shift_time_shift(char *local_time, char *shift)
int get_stats_from_ifconfig_command(const char *device, char *direction, char *option)
{
char buf[1024], *pch, *pchr, *ret;
int pp, stats = 0;
char buf[1024], *pch, *pchr, *ret;
int pp, r, stats = 0;
pp = dmcmd("ifconfig", 1, device);
if (pp) {
dmcmd_read(pp, buf, 1024);
for(pch = strtok_r(buf, "\n", &pchr); pch != NULL; pch = strtok_r(NULL, "\n", &pchr)) {
if(!strstr(pch, direction))
continue;
ret = strstr(pch, option);
if(ret) {
strtok_r(ret, ":", &ret);
sscanf(ret, "%d", &stats);
break;
}
}
close(pp);
}
return stats;
pp = dmcmd("ifconfig", 1, device);
if (pp) {
r = dmcmd_read(pp, buf, 1024);
for(pch = strtok_r(buf, "\n", &pchr); pch != NULL; pch = strtok_r(NULL, "\n", &pchr)) {
if(!strstr(pch, direction))
continue;
ret = strstr(pch, option);
if(ret) {
strtok_r(ret, ":", &ret);
sscanf(ret, "%d", &stats);
break;
}
}
close(pp);
}
return stats;
}
int command_exec_output_to_array(char *cmd, char **output, int *length)
@ -1620,3 +1619,46 @@ bool match(const char *string, const char *pattern)
if (status != 0) return false;
return true;
}
static inline int char_is_valid(char c)
{
return c > 0x20 && c < 0x7f;
}
int dm_read_sysfs_file(const char *file, char *dst, unsigned len)
{
char *content;
int fd;
int rlen;
int i, n;
int rc = 0;
content = alloca(len);
dst[0] = 0;
fd = open(file, O_RDONLY);
if (fd == -1)
return -1;
rlen = read(fd, content, len - 1);
if (rlen == -1) {
rc = -1;
goto out;
}
content[rlen] = 0;
for (i = 0, n = 0; i < rlen; i++) {
if (!char_is_valid(content[i])) {
if (i == 0)
continue;
else
break;
}
dst[n++] = content[i];
}
dst[n] = 0;
out:
close(fd);
return rc;
}

View file

@ -257,4 +257,5 @@ struct uci_section *is_dmmap_section_exist_eq(char* package, char* section, char
int isfolderexist(char *folderpath);
bool match(const char *string, const char *pattern);
char * dmmap_file_path_get(const char *dmmap_package);
int dm_read_sysfs_file(const char *file, char *dst, unsigned len);
#endif