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); }
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; }
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; }
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); } }
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++; }
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); }