struct ir_ignorelist_s *next;
} ir_ignorelist_t;
+struct qos_stats {
+ struct gnet_stats_basic **bs;
+ struct gnet_stats_queue **qs;
+};
+
static int ir_ignorelist_invert = 1;
static ir_ignorelist_t *ir_ignorelist_head = NULL;
#if HAVE_TCA_STATS2
static int qos_attr_cb(const struct nlattr *attr, void *data) {
- struct gnet_stats_basic **bs = (struct gnet_stats_basic **)data;
+ struct qos_stats *qdisc = (struct qos_stats *)data;
+ struct gnet_stats_basic **bs = qdisc->bs;
+ struct gnet_stats_queue **qs = qdisc->qs;
/* skip unsupported attribute in user-space */
if (mnl_attr_type_valid(attr, TCA_STATS_MAX) < 0)
return MNL_CB_ERROR;
}
*bs = mnl_attr_get_payload(attr);
- return MNL_CB_STOP;
+ return MNL_CB_OK;
+ }
+
+ if (mnl_attr_get_type(attr) == TCA_STATS_QUEUE) {
+ if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(**qs)) < 0) {
+ ERROR("netlink plugin: qos_attr_cb: TCA_STATS_QUEUE mnl_attr_validate2 "
+ "failed.");
+ return MNL_CB_ERROR;
+ }
+ *qs = mnl_attr_get_payload(attr);
+ return MNL_CB_OK;
}
return MNL_CB_OK;
#if HAVE_TCA_STATS2
mnl_attr_for_each(attr, nlh, sizeof(*tm)) {
struct gnet_stats_basic *bs = NULL;
+ struct gnet_stats_queue *qs = NULL;
+ struct qos_stats q_stats;
+ q_stats.bs = &bs;
+ q_stats.qs = &qs;
if (mnl_attr_get_type(attr) != TCA_STATS2)
continue;
return MNL_CB_ERROR;
}
- mnl_attr_parse_nested(attr, qos_attr_cb, &bs);
+ mnl_attr_parse_nested(attr, qos_attr_cb, &q_stats);
- if (bs != NULL) {
+ if (bs != NULL || qs != NULL) {
char type_instance[DATA_MAX_NAME_LEN];
stats_submitted = 1;
ssnprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type,
tc_inst);
- submit_one(dev, "ipt_bytes", type_instance, bs->bytes);
- submit_one(dev, "ipt_packets", type_instance, bs->packets);
+ if (bs != NULL) {
+ submit_one(dev, "ipt_bytes", type_instance, bs->bytes);
+ submit_one(dev, "ipt_packets", type_instance, bs->packets);
+ }
+ if (qs != NULL) {
+ submit_one(dev, "if_tx_errors", type_instance, qs->drops);
+ }
}
break;