Skip to content
Snippets Groups Projects

qosmngr: make queue number assignment independent on interface name

Merged Maxim Menshikov requested to merge mmenshikov-qosmngr-econet into devel
+ 84
66
@@ -33,10 +33,6 @@
@@ -33,10 +33,6 @@
/* Used as an internal value to query all the queues */
/* Used as an internal value to query all the queues */
#define QOS_QUEUE_ANY -1
#define QOS_QUEUE_ANY -1
/* Used for getting interface indexes for global q_stat array */
#define MIN_INDEX 48
#define MAX_INDEX 57
/* Used for fetching keys from ubus json reqest */
/* Used for fetching keys from ubus json reqest */
#define SEPERATOR 44
#define SEPERATOR 44
#define QUOTE 34
#define QUOTE 34
@@ -45,8 +41,20 @@
@@ -45,8 +41,20 @@
#define PARAM1 "ifname"
#define PARAM1 "ifname"
#define PARAM2 "qid"
#define PARAM2 "qid"
 
/** Container for single interface data (with multiple queues) */
 
typedef struct qos_interface_data {
 
char if_name[IFNAMSIZ]; /**< Cached interface name */
 
int q_count; /**< Cached number of queues */
 
struct qos_stats *q_stat; /**< Cached queue statistics */
 
} qos_interface_data;
 
static int init_flag = 1;
static int init_flag = 1;
static struct qos_stats **q_stat = {0};
 
/** Number of interfaces currently cached by qosmngr */
 
static size_t interface_count = 0;
 
/** Array of interfaces cached by qosmngr */
 
static qos_interface_data *interfaces = NULL;
 
/**
/**
* get_no_queues function for getting number of queues on device by calling uci qos config
* get_no_queues function for getting number of queues on device by calling uci qos config
@@ -93,11 +101,22 @@ done:
@@ -93,11 +101,22 @@ done:
*/
*/
static int get_interface_index(const char *ifname)
static int get_interface_index(const char *ifname)
{
{
int i;
size_t i;
 
size_t len = strlen(ifname);
 
 
for (i = 0; i < interface_count; ++i) {
 
qos_interface_data *cur = &interfaces[i];
 
 
if (strncmp(cur->if_name, ifname, len) == 0) {
 
size_t cur_len = strlen(cur->if_name);
for (i = 0; i < strlen(ifname); i++) {
if (cur_len != len) {
if ((ifname[i] >= MIN_INDEX) && (ifname[i] <= MAX_INDEX)) {
if (sscanf(ifname + len, ".%*d") != 1) {
return atoi(ifname + i);
continue;
 
}
 
}
 
 
return (int)i;
}
}
}
}
@@ -105,84 +124,69 @@ static int get_interface_index(const char *ifname)
@@ -105,84 +124,69 @@ static int get_interface_index(const char *ifname)
}
}
/**
/**
* get_no_ports function for getting number of ports on device by calling uci port config
* init_qstat function for initializing global q_stat structure for sustainable stats
* @param none
* @param none
* retrun integer value 0 on success and -1 on failure
* retrun integer value 0 on success and -1 on failure
*/
*/
static int get_no_ports()
static int init_qstat()
{
{
int ports = 0;
int ret = 0;
 
int index = 0;
 
 
syslog(LOG_ERR, "Initializing global stat structure.\n");
struct uci_package *uci_pkg = NULL;
struct uci_package *uci_pkg = NULL;
struct uci_element *uci_elmnt = NULL;
struct uci_element *uci_elmnt = NULL;
struct uci_context *uci_ctx = uci_alloc_context();
struct uci_context *uci_ctx = uci_alloc_context();
 
interface_count = 0;
 
uci_load(uci_ctx, "ports", &uci_pkg);
uci_load(uci_ctx, "ports", &uci_pkg);
if (!uci_pkg) {
if (!uci_pkg) {
syslog(LOG_ERR, "Failed to load configuration\n");
syslog(LOG_ERR, "Failed to load configuration\n");
ports = -1;
ret = -1;
goto done;
goto done;
}
}
 
interface_count = 0;
 
uci_foreach_element(&uci_pkg->sections, uci_elmnt) {
uci_foreach_element(&uci_pkg->sections, uci_elmnt) {
struct uci_section *uci_sec = uci_to_section(uci_elmnt);
struct uci_section *uci_sec = uci_to_section(uci_elmnt);
if (uci_sec)
if (uci_sec)
ports++;
interface_count++;
}
}
done:
interfaces = (qos_interface_data *)calloc(interface_count,
uci_unload(uci_ctx, uci_pkg);
sizeof(qos_interface_data));
uci_free_context(uci_ctx);
if (interfaces == NULL) {
return ports;
}
/**
* init_qstat function for initializing global q_stat structure for sustainable stats
* @param none
* retrun integer value 0 on success and -1 on failure
*/
static int init_qstat()
{
int ret = 0;
int index = 0;
syslog(LOG_ERR, "Initializing global stat structure.\n");
int ports = get_no_ports();
q_stat = (struct qos_stats **)calloc(ports, sizeof(struct qos_stats *));
if (q_stat == NULL) {
syslog(LOG_ERR, "Initialization failed during memory allocation.\n");
syslog(LOG_ERR, "Initialization failed during memory allocation.\n");
ret = -1;
ret = -1;
return ret;
goto done_unload;
}
struct uci_package *uci_pkg = NULL;
struct uci_element *uci_elmnt = NULL;
struct uci_context *uci_ctx = uci_alloc_context();
uci_load(uci_ctx, "ports", &uci_pkg);
if (!uci_pkg) {
syslog(LOG_ERR, "Failed to load configuration\n");
ret = -1;
goto done;
}
}
uci_foreach_element(&uci_pkg->sections, uci_elmnt) {
uci_foreach_element(&uci_pkg->sections, uci_elmnt) {
struct uci_section *uci_sec = uci_to_section(uci_elmnt);
struct uci_section *uci_sec = uci_to_section(uci_elmnt);
if (uci_sec) {
if (uci_sec) {
struct uci_option *uci_opn = uci_lookup_option(uci_ctx, uci_sec, "ifname");
qos_interface_data *data = &interfaces[index];
index = get_interface_index(uci_opn->v.string);
struct uci_option *uci_opn = uci_lookup_option(uci_ctx, uci_sec, "ifname");
int queues = get_no_queues(uci_opn->v.string);
int queues;
q_stat[index] = (struct qos_stats *)calloc(queues, sizeof(struct qos_stats));
if (q_stat[index] == NULL) {
queues = get_no_queues(uci_opn->v.string);
 
strcpy(data->if_name, uci_opn->v.string);
 
data->q_count = queues;
 
data->q_stat = (struct qos_stats *)calloc(queues,
 
sizeof(struct qos_stats));
 
if (data->q_stat == NULL) {
syslog(LOG_ERR, "Initialization failed during memory allocation.\n");
syslog(LOG_ERR, "Initialization failed during memory allocation.\n");
ret = -1;
ret = -1;
uci_unload(uci_ctx, uci_pkg);
goto done_unload;
goto done;
}
}
 
 
index++;
}
}
}
}
 
done_unload:
uci_unload(uci_ctx, uci_pkg);
uci_unload(uci_ctx, uci_pkg);
done:
done:
uci_free_context(uci_ctx);
uci_free_context(uci_ctx);
@@ -204,6 +208,8 @@ static int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void
@@ -204,6 +208,8 @@ static int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void
int index;
int index;
int ret = 0;
int ret = 0;
int is_read_and_reset;
int is_read_and_reset;
 
qos_interface_data *iface;
 
struct qos_stats *q_stat;
// Initialize global q_stat global struct
// Initialize global q_stat global struct
if (init_flag) {
if (init_flag) {
@@ -222,29 +228,41 @@ static int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void
@@ -222,29 +228,41 @@ static int prepare_stats_blob(struct blob_buf *b, struct qos_stats *stats, void
}
}
index = get_interface_index(ifname);
index = get_interface_index(ifname);
 
if (index < 0 || index >= interface_count) {
 
syslog(LOG_ERR, "Invalid interface index %d (out of %d)", index, interface_count);
 
return -1;
 
}
 
 
iface = &interfaces[index];
 
if (qid < 0 || qid >= iface->q_count) {
 
syslog(LOG_ERR, "Invalid queue index %d (out of %d)", qid, iface->q_count);
 
return -1;
 
}
 
 
q_stat = &iface->q_stat[qid];
/*BCM968 CHIP, stats read from driver is accunulated stats, while in other its read and reset */
/*BCM968 CHIP, stats read from driver is accunulated stats, while in other its read and reset */
if (!is_read_and_reset) {
if (!is_read_and_reset) {
q_stat[index][qid].tx_packets = stats->tx_packets;
q_stat->tx_packets = stats->tx_packets;
q_stat[index][qid].tx_bytes = stats->tx_bytes;
q_stat->tx_bytes = stats->tx_bytes;
q_stat[index][qid].tx_dropped_packets = stats->tx_dropped_packets;
q_stat->tx_dropped_packets = stats->tx_dropped_packets;
q_stat[index][qid].tx_dropped_bytes = stats->tx_dropped_bytes;
q_stat->tx_dropped_bytes = stats->tx_dropped_bytes;
}
}
else {
else {
q_stat[index][qid].tx_packets += stats->tx_packets;
q_stat->tx_packets += stats->tx_packets;
q_stat[index][qid].tx_bytes += stats->tx_bytes;
q_stat->tx_bytes += stats->tx_bytes;
q_stat[index][qid].tx_dropped_packets += stats->tx_dropped_packets;
q_stat->tx_dropped_packets += stats->tx_dropped_packets;
q_stat[index][qid].tx_dropped_bytes += stats->tx_dropped_bytes;
q_stat->tx_dropped_bytes += stats->tx_dropped_bytes;
}
}
dd = blobmsg_open_table(b, "");
dd = blobmsg_open_table(b, "");
blobmsg_add_string(b, "iface", ifname);
blobmsg_add_string(b, "iface", ifname);
blobmsg_add_u32(b, "qid", qid);
blobmsg_add_u32(b, "qid", qid);
blobmsg_add_u32(b, "tx_packets", q_stat[index][qid].tx_packets);
blobmsg_add_u32(b, "tx_packets", q_stat->tx_packets);
blobmsg_add_u32(b, "tx_bytes", q_stat[index][qid].tx_bytes);
blobmsg_add_u32(b, "tx_bytes", q_stat->tx_bytes);
blobmsg_add_u32(b, "tx_dropped_packets", q_stat[index][qid].tx_dropped_packets);
blobmsg_add_u32(b, "tx_dropped_packets", q_stat->tx_dropped_packets);
blobmsg_add_u32(b, "tx_dropped_bytes", q_stat[index][qid].tx_dropped_bytes);
blobmsg_add_u32(b, "tx_dropped_bytes", q_stat->tx_dropped_bytes);
blobmsg_close_table(b, dd);
blobmsg_close_table(b, dd);
Loading