From 219d9b498457b87314e8dec291b899c5324b8f89 Mon Sep 17 00:00:00 2001 From: Daniel Danzberger Date: Wed, 8 Jan 2020 22:35:38 +0100 Subject: [PATCH] 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 --- dmtree/tr181/ip.c | 108 ++++++++++++++---------------------------- dmtree/tr181/usb.c | 55 ++------------------- libbbf_api/dmcommon.c | 84 ++++++++++++++++++++++++-------- libbbf_api/dmcommon.h | 1 + 4 files changed, 105 insertions(+), 143 deletions(-) diff --git a/dmtree/tr181/ip.c b/dmtree/tr181/ip.c index 9bd81e9c..e08ee21b 100644 --- a/dmtree/tr181/ip.c +++ b/dmtree/tr181/ip.c @@ -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"); } diff --git a/dmtree/tr181/usb.c b/dmtree/tr181/usb.c index 8194b27f..a72e94b5 100644 --- a/dmtree/tr181/usb.c +++ b/dmtree/tr181/usb.c @@ -11,8 +11,6 @@ #include "dmentry.h" #include "usb.h" -#include - /* *** 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]; diff --git a/libbbf_api/dmcommon.c b/libbbf_api/dmcommon.c index 9700acfc..5914d5ff 100644 --- a/libbbf_api/dmcommon.c +++ b/libbbf_api/dmcommon.c @@ -31,6 +31,7 @@ #include #include #include +#include #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; +} diff --git a/libbbf_api/dmcommon.h b/libbbf_api/dmcommon.h index 329b2dcf..3826406e 100644 --- a/libbbf_api/dmcommon.h +++ b/libbbf_api/dmcommon.h @@ -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