static void dump_stat(struct rtnl_link *link, int id)
{
	uint64_t st = rtnl_link_get_stat(link, id);
	char buf[64];

	printf("%s.%s %" PRIu64 "\n", rtnl_link_get_name(link),
	       rtnl_link_stat2str(id, buf, sizeof(buf)), st);
}
Exemple #2
0
static int read_counters(const char *iface, struct sample *stats)
{
	struct rtnl_link *link;
	assert(nl_sock);

	pthread_mutex_lock(&nl_sock_mutex);

	/* iface index zero means use the iface name */
	if (rtnl_link_get_kernel(nl_sock, 0, iface, &link) < 0) {
		syslog(LOG_ERR, "unknown interface/link name: %s\n", iface);
		pthread_mutex_unlock(&nl_sock_mutex);
		return -1;
	}

	/* read and return counter */
	stats->rx_bytes = rtnl_link_get_stat(link, RTNL_LINK_RX_BYTES);
	stats->tx_bytes = rtnl_link_get_stat(link, RTNL_LINK_TX_BYTES);
	stats->rx_packets = rtnl_link_get_stat(link, RTNL_LINK_RX_PACKETS);
	stats->rx_packets += rtnl_link_get_stat(link, RTNL_LINK_RX_COMPRESSED);
	stats->tx_packets = rtnl_link_get_stat(link, RTNL_LINK_TX_PACKETS);
	stats->tx_packets += rtnl_link_get_stat(link, RTNL_LINK_TX_COMPRESSED);
	rtnl_link_put(link);
	pthread_mutex_unlock(&nl_sock_mutex);
	return 0;
}
Exemple #3
0
void print_iface_stats(const char *iface, time_t since, FILE * out, cmd_params_st *params, unsigned have_more)
{
	uint64_t tx, rx;
	char buf1[32], buf2[32];
	time_t diff = time(0) - since;
	int ret;
	struct rtnl_link *rlink = NULL;

	if (iface == NULL || iface[0] == 0)
		return;

	if (open_netlink() < 0)
		return;

	ret = rtnl_link_get_kernel(sock, 0, iface, &rlink);
	if (ret < 0) {
		fprintf(stderr, "nl: cannot find %s\n", iface);
		return;
	}

	rx = rtnl_link_get_stat(rlink, RTNL_LINK_RX_BYTES);
	tx = rtnl_link_get_stat(rlink, RTNL_LINK_TX_BYTES);

	bytes2human(rx, buf1, sizeof(buf1), NULL);
	bytes2human(tx, buf2, sizeof(buf2), NULL);
	if (HAVE_JSON(params)) {
		fprintf(out, "    \"RX\":  \"%"PRIu64"\",\n    \"TX\":  \"%"PRIu64"\",\n", rx, tx);
		fprintf(out, "    \"_RX\":  \"%s\",\n    \"_TX\":  \"%s\",\n", buf1, buf2);
	} else
		fprintf(out, "\tRX: %"PRIu64" (%s)   TX: %"PRIu64" (%s)\n", rx, buf1, tx, buf2);

	value2speed(rx, diff, buf1, sizeof(buf1));
	value2speed(tx, diff, buf2, sizeof(buf2));
	if (HAVE_JSON(params))
		fprintf(out, "    \"Average RX\":  \"%s\",\n    \"Average TX\":  \"%s\"%s\n", buf1, buf2, have_more?",":"");
	else
		fprintf(out, "\tAverage bandwidth RX: %s  TX: %s\n", buf1, buf2);

	return;
}
Exemple #4
0
Result<hashmap<string, uint64_t> > statistics(const string& _link)
{
  Result<Netlink<struct rtnl_link> > link = internal::get(_link);
  if (link.isError()) {
    return Error(link.error());
  } else if (link.isNone()) {
    return None();
  }

  rtnl_link_stat_id_t stats[] = {
    // Statistics related to receiving.
    RTNL_LINK_RX_PACKETS,
    RTNL_LINK_RX_BYTES,
    RTNL_LINK_RX_ERRORS,
    RTNL_LINK_RX_DROPPED,
    RTNL_LINK_RX_COMPRESSED,
    RTNL_LINK_RX_FIFO_ERR,
    RTNL_LINK_RX_LEN_ERR,
    RTNL_LINK_RX_OVER_ERR,
    RTNL_LINK_RX_CRC_ERR,
    RTNL_LINK_RX_FRAME_ERR,
    RTNL_LINK_RX_MISSED_ERR,
    RTNL_LINK_MULTICAST,

    // Statistics related to sending.
    RTNL_LINK_TX_PACKETS,
    RTNL_LINK_TX_BYTES,
    RTNL_LINK_TX_ERRORS,
    RTNL_LINK_TX_DROPPED,
    RTNL_LINK_TX_COMPRESSED,
    RTNL_LINK_TX_FIFO_ERR,
    RTNL_LINK_TX_ABORT_ERR,
    RTNL_LINK_TX_CARRIER_ERR,
    RTNL_LINK_TX_HBEAT_ERR,
    RTNL_LINK_TX_WIN_ERR,
    RTNL_LINK_COLLISIONS,
  };

  hashmap<string, uint64_t> results;

  char buf[32];
  size_t size = sizeof(stats) / sizeof(stats[0]);

  for (size_t i = 0; i < size; i++) {
    rtnl_link_stat2str(stats[i], buf, 32);
    results[buf] = rtnl_link_get_stat(link.get().get(), stats[i]);
  }

  return results;
}
	void LinuxPlatformBackend::update (const QStringList& devices)
	{
		if (!LinkCache_)
			return;

		nl_cache_refill (Rtsock_, LinkCache_);

		for (const auto& devName : devices)
		{
			auto link = rtnl_link_get_by_name (LinkCache_, devName.toLocal8Bit ().constData ());
			if (!link)
			{
				qWarning () << Q_FUNC_INFO
						<< "no link for device"
						<< devName;
				continue;
			}

			auto& info = DevInfos_ [devName];

			info.Traffic_.Down_ = rtnl_link_get_stat (link, RTNL_LINK_RX_BYTES);
			info.Traffic_.Up_ = rtnl_link_get_stat (link, RTNL_LINK_TX_BYTES);
		}
	}
Exemple #6
0
static int
port_stats_iterator(struct nl_msg *msg, void *arg)
{
    of_list_port_stats_entry_t *list = arg;

    struct nlmsghdr *nlh = nlmsg_hdr(msg);
    struct nlattr *attrs[OVS_VPORT_ATTR_MAX+1];
    if (genlmsg_parse(nlh, sizeof(struct ovs_header),
                    attrs, OVS_VPORT_ATTR_MAX,
                    NULL) < 0) {
        abort();
    }
    assert(attrs[OVS_VPORT_ATTR_PORT_NO]);
    assert(attrs[OVS_VPORT_ATTR_STATS]);

    uint32_t port_no = nla_get_u32(attrs[OVS_VPORT_ATTR_PORT_NO]);
    char *ifname = nla_get_string(attrs[OVS_VPORT_ATTR_NAME]);
    uint32_t vport_type = nla_get_u32(attrs[OVS_VPORT_ATTR_TYPE]);
    struct ovs_vport_stats *port_stats = nla_data(attrs[OVS_VPORT_ATTR_STATS]);

    of_port_stats_entry_t entry[1];
    of_port_stats_entry_init(entry, list->version, -1, 1);
    if (of_list_port_stats_entry_append_bind(list, entry) < 0) {
        /* TODO needs fix in indigo core */
        LOG_ERROR("too many port stats replies");
        return NL_STOP;
    }

    of_port_stats_entry_port_no_set(entry, port_no);

    struct rtnl_link *link;
    if ((vport_type == OVS_VPORT_TYPE_NETDEV
        || vport_type == OVS_VPORT_TYPE_INTERNAL)
        && (link = rtnl_link_get_by_name(link_cache, ifname))) {
        /* Get interface stats from NETLINK_ROUTE */
        of_port_stats_entry_rx_packets_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_PACKETS));
        of_port_stats_entry_tx_packets_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_TX_PACKETS));
        of_port_stats_entry_rx_bytes_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_BYTES));
        of_port_stats_entry_tx_bytes_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_TX_BYTES));
        of_port_stats_entry_rx_dropped_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_DROPPED));
        of_port_stats_entry_tx_dropped_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_TX_DROPPED));
        of_port_stats_entry_rx_errors_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_ERRORS));
        of_port_stats_entry_tx_errors_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_TX_ERRORS));
        of_port_stats_entry_rx_frame_err_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_FRAME_ERR));
        of_port_stats_entry_rx_over_err_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_OVER_ERR));
        of_port_stats_entry_rx_crc_err_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_CRC_ERR));
        of_port_stats_entry_collisions_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_COLLISIONS));
        rtnl_link_put(link);
    } else {
        /* Use more limited stats from the datapath */
        of_port_stats_entry_rx_packets_set(entry, port_stats->rx_packets);
        of_port_stats_entry_tx_packets_set(entry, port_stats->tx_packets);
        of_port_stats_entry_rx_bytes_set(entry, port_stats->rx_bytes);
        of_port_stats_entry_tx_bytes_set(entry, port_stats->tx_bytes);
        of_port_stats_entry_rx_dropped_set(entry, port_stats->rx_dropped);
        of_port_stats_entry_tx_dropped_set(entry, port_stats->tx_dropped);
        of_port_stats_entry_rx_errors_set(entry, port_stats->rx_errors);
        of_port_stats_entry_tx_errors_set(entry, port_stats->tx_errors);
        of_port_stats_entry_rx_frame_err_set(entry, 0);
        of_port_stats_entry_rx_over_err_set(entry, 0);
        of_port_stats_entry_rx_crc_err_set(entry, 0);
        of_port_stats_entry_collisions_set(entry, 0);
    }

    return NL_OK;
}
static void __interface_statistics_get(struct nl_object *obj, void *arg)
{
    struct rtnl_link *link = (struct rtnl_link *)obj;
    Dabba__InterfaceStatisticsList *statistics_list = arg;
    Dabba__InterfaceStatistics *statisticsp, **listpp;
    size_t lsize =
        sizeof(*statistics_list->list) * (statistics_list->n_list + 1);

    listpp = realloc(statistics_list->list, lsize);

    if (!listpp)
        return;

    statistics_list->list = listpp;
    statistics_list->list[statistics_list->n_list] =
        malloc(sizeof(*statistics_list->list[statistics_list->n_list]));
    statisticsp = statistics_list->list[statistics_list->n_list];

    if (!statisticsp)
        return;

    dabba__interface_statistics__init(statisticsp);

    statisticsp->id = malloc(sizeof(*statisticsp->id));
    statisticsp->status = malloc(sizeof(*statisticsp->status));

    if (!statisticsp->id || !statisticsp->status) {
        free(statisticsp->status);
        free(statisticsp->id);
        free(statisticsp);
        return;
    }

    dabba__interface_id__init(statisticsp->id);
    dabba__error_code__init(statisticsp->status);

    statisticsp->id->name = rtnl_link_get_name(link);
    statisticsp->rx_byte = rtnl_link_get_stat(link, RTNL_LINK_RX_BYTES);
    statisticsp->rx_packet = rtnl_link_get_stat(link, RTNL_LINK_RX_PACKETS);
    statisticsp->rx_error = rtnl_link_get_stat(link, RTNL_LINK_RX_ERRORS);
    statisticsp->rx_dropped =
        rtnl_link_get_stat(link, RTNL_LINK_RX_DROPPED);
    statisticsp->rx_compressed =
        rtnl_link_get_stat(link, RTNL_LINK_RX_COMPRESSED);
    statisticsp->rx_error_fifo =
        rtnl_link_get_stat(link, RTNL_LINK_RX_FIFO_ERR);
    statisticsp->rx_error_frame =
        rtnl_link_get_stat(link, RTNL_LINK_RX_FRAME_ERR);
    statisticsp->rx_error_crc =
        rtnl_link_get_stat(link, RTNL_LINK_RX_CRC_ERR);
    statisticsp->rx_error_length =
        rtnl_link_get_stat(link, RTNL_LINK_RX_LEN_ERR);
    statisticsp->rx_error_missed =
        rtnl_link_get_stat(link, RTNL_LINK_RX_MISSED_ERR);
    statisticsp->rx_error_over =
        rtnl_link_get_stat(link, RTNL_LINK_RX_OVER_ERR);

    statisticsp->tx_byte = rtnl_link_get_stat(link, RTNL_LINK_TX_BYTES);
    statisticsp->tx_packet = rtnl_link_get_stat(link, RTNL_LINK_TX_PACKETS);
    statisticsp->tx_error = rtnl_link_get_stat(link, RTNL_LINK_TX_ERRORS);
    statisticsp->tx_dropped =
        rtnl_link_get_stat(link, RTNL_LINK_TX_DROPPED);
    statisticsp->tx_compressed =
        rtnl_link_get_stat(link, RTNL_LINK_TX_COMPRESSED);
    statisticsp->tx_error_fifo =
        rtnl_link_get_stat(link, RTNL_LINK_TX_FIFO_ERR);
    statisticsp->tx_error_carrier =
        rtnl_link_get_stat(link, RTNL_LINK_TX_CARRIER_ERR);
    statisticsp->tx_error_heartbeat =
        rtnl_link_get_stat(link, RTNL_LINK_TX_HBEAT_ERR);
    statisticsp->tx_error_window =
        rtnl_link_get_stat(link, RTNL_LINK_TX_WIN_ERR);
    statisticsp->tx_error_aborted =
        rtnl_link_get_stat(link, RTNL_LINK_TX_ABORT_ERR);

    statistics_list->n_list++;
}
Exemple #8
0
static void handle_class(struct nl_object *obj, void *arg)
{
	struct rtnl_tc *tc = (struct rtnl_tc *) obj;
	struct element *e;
	struct rdata *rdata = arg;
	struct rdata ndata = {
		.level = rdata->level + 1,
	};

	if (!(e = handle_tc_obj(tc, "class", rdata)))
		return;

	ndata.parent = e;

	if (!strcmp(rtnl_tc_get_kind(tc), "htb"))
		element_set_txmax(e, rtnl_htb_get_rate((struct rtnl_class *) tc));

	find_classes(rtnl_tc_get_handle(tc), &ndata);
	find_qdiscs(rtnl_tc_get_handle(tc), &ndata);
}

static void find_qdiscs(uint32_t parent, struct rdata *rdata)
{
	struct rtnl_qdisc *filter;

	if (!(filter = rtnl_qdisc_alloc()))
		return;

	rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);

	nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(filter),
				handle_qdisc, rdata);

	rtnl_qdisc_put(filter);
}

static void find_cls(int ifindex, uint32_t parent, struct rdata *rdata)
{
	struct nl_cache *cls_cache;

	if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0)
		return;

	nl_cache_foreach(cls_cache, handle_cls, rdata);

	nl_cache_free(cls_cache);
}

static void find_classes(uint32_t parent, struct rdata *rdata)
{
	struct rtnl_class *filter;

	if (!(filter = rtnl_class_alloc()))
		return;

	rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);

	nl_cache_foreach_filter(class_cache, OBJ_CAST(filter),
				handle_class, rdata);

	rtnl_class_put(filter);
}

static void handle_qdisc(struct nl_object *obj, void *arg)
{
	struct rtnl_tc *tc = (struct rtnl_tc *) obj;
	struct element *e;
	struct rdata *rdata = arg;
	struct rdata ndata = {
		.level = rdata->level + 1,
	};

	if (!(e = handle_tc_obj(tc, "qdisc", rdata)))
		return;

	ndata.parent = e;

	find_cls(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc), &ndata);

	if (rtnl_tc_get_parent(tc) == TC_H_ROOT) {
		find_cls(rtnl_tc_get_ifindex(tc), TC_H_ROOT, &ndata);
		find_classes(TC_H_ROOT, &ndata);
	}

	find_classes(rtnl_tc_get_handle(tc), &ndata);
}

static void handle_tc(struct element *e, struct rtnl_link *link)
{
	struct rtnl_qdisc *qdisc;
	int ifindex = rtnl_link_get_ifindex(link);
	struct rdata rdata = {
		.level = 1,
		.parent = e,
	};

	if (rtnl_class_alloc_cache(sock, ifindex, &class_cache) < 0)
		return;

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT);
	if (qdisc) {
		handle_qdisc(OBJ_CAST(qdisc), &rdata);
		rtnl_qdisc_put(qdisc);
	}

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, 0);
	if (qdisc) {
		handle_qdisc(OBJ_CAST(qdisc), &rdata);
		rtnl_qdisc_put(qdisc);
	}

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_INGRESS);
	if (qdisc) {
		handle_qdisc(OBJ_CAST(qdisc), &rdata);
		rtnl_qdisc_put(qdisc);
	}

	nl_cache_free(class_cache);
}

static void update_link_infos(struct element *e, struct rtnl_link *link)
{
	char buf[64];

	snprintf(buf, sizeof(buf), "%u", rtnl_link_get_mtu(link));
	element_update_info(e, "MTU", buf);

	rtnl_link_flags2str(rtnl_link_get_flags(link), buf, sizeof(buf));
	element_update_info(e, "Flags", buf);

	rtnl_link_operstate2str(rtnl_link_get_operstate(link),
				buf, sizeof(buf));
	element_update_info(e, "Operstate", buf);

	snprintf(buf, sizeof(buf), "%u", rtnl_link_get_ifindex(link));
	element_update_info(e, "IfIndex", buf);

	nl_addr2str(rtnl_link_get_addr(link), buf, sizeof(buf));
	element_update_info(e, "Address", buf);

	nl_addr2str(rtnl_link_get_broadcast(link), buf, sizeof(buf));
	element_update_info(e, "Broadcast", buf);

	rtnl_link_mode2str(rtnl_link_get_linkmode(link),
			   buf, sizeof(buf));
	element_update_info(e, "Mode", buf);

	snprintf(buf, sizeof(buf), "%u", rtnl_link_get_txqlen(link));
	element_update_info(e, "TXQlen", buf);

	nl_af2str(rtnl_link_get_family(link), buf, sizeof(buf));
	element_update_info(e, "Family", buf);

	element_update_info(e, "Alias",
		rtnl_link_get_ifalias(link) ? : "");

	element_update_info(e, "Qdisc",
		rtnl_link_get_qdisc(link) ? : "");

	if (rtnl_link_get_link(link)) {
		snprintf(buf, sizeof(buf), "%u", rtnl_link_get_link(link));
		element_update_info(e, "SlaveOfIndex", buf);
	}
}

static void do_link(struct nl_object *obj, void *arg)
{
	struct rtnl_link *link = (struct rtnl_link *) obj;
	struct element *e, *e_parent = NULL;
	int i, master_ifindex;

	if (!cfg_show_all && !(rtnl_link_get_flags(link) & IFF_UP)) {
		/* FIXME: delete element */
		return;
	}

	/* Check if the interface is a slave of another interface */
	if ((master_ifindex = rtnl_link_get_link(link))) {
		char parent[IFNAMSIZ+1];

		rtnl_link_i2name(link_cache, master_ifindex,
				 parent, sizeof(parent));

		e_parent = element_lookup(grp, parent, master_ifindex, NULL, 0);
	}

	if (!(e = element_lookup(grp, rtnl_link_get_name(link),
				 rtnl_link_get_ifindex(link), e_parent, ELEMENT_CREAT)))
		return;

	if (e->e_flags & ELEMENT_FLAG_CREATED) {
		if (e->e_parent)
			e->e_level = e->e_parent->e_level + 1;

		if (element_set_key_attr(e, "bytes", "packets") ||
		    element_set_usage_attr(e, "bytes"))
			BUG();

		/* FIXME: Update link infos every 1s or so */
		update_link_infos(e, link);

		e->e_flags &= ~ELEMENT_FLAG_CREATED;
	}

	for (i = 0; i < ARRAY_SIZE(link_attrs); i++) {
		struct attr_map *m = &link_attrs[i];
		uint64_t c_rx = 0, c_tx = 0;
		int flags = 0;

		if (m->rxid >= 0) {
			c_rx = rtnl_link_get_stat(link, m->rxid);
			flags |= UPDATE_FLAG_RX;
		}

		if (m->txid >= 0) {
			c_tx = rtnl_link_get_stat(link, m->txid);
			flags |= UPDATE_FLAG_TX;
		}

		attr_update(e, m->attrid, c_rx, c_tx, flags);
	}

	if (!c_notc)
		handle_tc(e, link);

	element_notify_update(e, NULL);
	element_lifesign(e, 1);
}

static void netlink_read(void)
{
	int err;

	if ((err = nl_cache_resync(sock, link_cache, NULL, NULL)) < 0) {
		fprintf(stderr, "Unable to resync link cache: %s\n", nl_geterror(err));
		goto disable;
	}

	if ((err = nl_cache_resync(sock, qdisc_cache, NULL, NULL)) < 0) {
		fprintf(stderr, "Unable to resync qdisc cache: %s\n", nl_geterror(err));
		goto disable;
	}

	nl_cache_foreach(link_cache, do_link, NULL);

	return;

disable:
	netlink_ops.m_flags &= ~BMON_MODULE_ENABLED;
}

static void netlink_shutdown(void)
{
	nl_cache_free(link_cache);
	nl_cache_free(qdisc_cache);
	nl_socket_free(sock);
}