diff options
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | cbm.cpp | 133 | ||||
-rw-r--r-- | fsbm.c | 202 | ||||
-rw-r--r-- | fsbm.cpp | 133 | ||||
-rw-r--r-- | statistics.cpp | 160 | ||||
-rw-r--r-- | statistics.hpp | 52 |
6 files changed, 207 insertions, 483 deletions
@@ -1,9 +1,9 @@ -CPPC=g++ -CPPFLAGS=-O2 -Wall -Wextra -mtune=native +CC=gcc +CFLAGS=-O2 -Wall -Wextra -mtune=native all: fsbm -fsbm: fsbm.cpp - $(CPPC) fsbm.cpp statistics.cpp -o fsbm $(CPPFLAGS) +fsbm: fsbm.c + $(CC) fsbm.c -o fsbm $(CFLAGS) clean: - @rm fsbm
\ No newline at end of file + @rm fsbm diff --git a/cbm.cpp b/cbm.cpp deleted file mode 100644 index 4668534..0000000 --- a/cbm.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include "config.h" -#include "statistics.hpp" -#include <algorithm> -#include <cstdlib> -#include <cstring> -#include <iomanip> -#include <iostream> -#include <sstream> - -#include <curses.h> -#include <getopt.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <net/if.h> -#include <unistd.h> - -#define PACKAGE "yo" -#define PACKAGE_STRING "yo mamma" - -// Externs -extern int optind, opterr, optopt; - -volatile bool quit = false; - -void endHandler(int signum) { - quit = true; -} - -void formatBandwidth(double bytesPerSecond, bool showBits) { - const char* prefixes[] = { "", "k", "M", "G", "T", "P", "E", "Z", "Y" }; - - // Calculate the value - double value; - const char* unit; - if (showBits){ - value = bytesPerSecond * 8; - unit = "b/s"; - } - else { - value = bytesPerSecond; - unit = "B/s"; - } - - // Choose the prefix - unsigned prefix = 0; - while (prefix < (sizeof(prefixes) / sizeof(const char*)) && value > 1000.) { - value /= 1000.; - ++prefix; - } - - // Format the string - std::cout << std::setprecision(2) << value << " " << prefixes[prefix] << unit; - -} - -int main(int argc, char **argv) { - int retval = EXIT_SUCCESS; - - // parse the command line - int c; - - bool useBits = false; - int interval = 10 * 100000; - - while ((c = getopt (argc, argv, "bi:hv")) != -1) - switch (c) - { - case 'b': - useBits = true; - break; - case 'i': - // Magic numbers? fuck it that's not a magic number, that's a 'real' number. - interval = atoi(optarg) * 100000; - break; - case 'h': - std::cout << "USAGE: fsbm, -b specifies bits, -i sets interval in 10ths of seconds, 1 sec default\n"; - exit(EXIT_SUCCESS); - break; - case 'v': - std::cout << "Version 1\n"; - exit(EXIT_SUCCESS); - break; - case '?': - std::cerr << "bad flag\n"; - break; - default: - exit(EXIT_FAILURE); - } - - // Catch SIGINT - signal(SIGINT, endHandler); - - - - // Create a socket (for ioctls) - int sock = socket(AF_INET, SOCK_DGRAM, 0); - if (!sock) { - std::cerr ("cannot open socket"); - exit(EXIT_FAILURE); - } - - // Initialize curses - - statistics::Reader statisticsReader; - statisticsReader.update(); - while (!quit) { - - // Update the statistics - statisticsReader.update(); - - for (statistics::Reader::Interfaces::const_iterator - interface = statisticsReader.getInterfaces().begin(); - interface != statisticsReader.getInterfaces().end(); - ++interface) { - - std::cout << interface->getName() << " ("; - formatBandwidth(interface->getReceiveSpeed(), useBits); - std::cout << ", "; - formatBandwidth(interface->getTransmitSpeed(), useBits); - std::cout << ")"; - - } - std::cout << "\n"; - usleep(interval); - - - - } - return retval; -} @@ -0,0 +1,202 @@ +#include <getopt.h> +#include <signal.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/time.h> +#include <arpa/inet.h> +#include <net/if.h> +#include <unistd.h> +#include <stdio.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <stddef.h> + +#define PROC_NET_DEV "/proc/net/dev" + +struct iface { + char interface[IFNAMSIZ]; + struct timeval timestamp; + unsigned long long rx_bytes; + unsigned long long tx_bytes; +}; + + +volatile bool q = false; +bool use_bits = false; +struct iface *interfaces = NULL; +size_t no_iface = 0; + +void endHandler(int signum) { + q = true; +} + +void print_bps(double bytesPerSecond) { + const char* prefixes[] = { "", "k", "M", "G", "T", "P", "E", "Z", "Y" }; + + // Calculate the value + double value; + const char* unit; + if(use_bits) { + value = bytesPerSecond * 8; + unit = "b/s"; + } + else { + value = bytesPerSecond; + unit = "B/s"; + } + + // Choose the prefix + unsigned prefix = 0; + while (prefix < (sizeof(prefixes) / sizeof(const char*)) && value > 1000.) { + value /= 1000.; + ++prefix; + } + + // Format the string + printf("%.2f %s%s", value, prefixes[prefix], unit); + +} + +void print_stats() { + // Open /proc/net/dev + FILE *dev = fopen(PROC_NET_DEV, "r"); + if (!dev) { + fprintf(stderr, "cannot open %s - %s\n", PROC_NET_DEV, strerror(errno)); + exit(EXIT_FAILURE); + } + + // Read /proc/dev/net + while (!feof(dev)) { + char buf[512]; + char *name, *statistics_string; + long long unsigned rx_bytes, tx_bytes; + struct timezone unused_timezone; + struct timeval timestamp; + + // Read a line + fgets(buf, sizeof(buf), dev); + + // get timestamp + gettimeofday(×tamp, &unused_timezone); + + // Find the colon separating the name from the statistics + statistics_string = strchr(buf, ':'); + if (!statistics_string) continue; + + // Get a pointer to the statistics + *statistics_string = 0; + ++statistics_string; + + // Remove leading whitespace from the name + name = buf; + ptrdiff_t len = 0; + while (*name == ' ' || *name == '\t') { + ++name; + } + len = name - buf; + + // Parse the statistics, alls well, then get this shit going, otherwise f it. + if (sscanf(statistics_string, "%Lu %*Lu %*Lu %*Lu %*Lu %*Lu %*Lu %*Lu %Lu", + &rx_bytes, &tx_bytes) == 2) { + + size_t i = 0; + bool found = false; + if(interfaces == NULL) { + goto skip; + } + for(i = 0; i < no_iface; i++) { + // if it exists in our interfaces, great. reuse the iface struct + if(strncmp(name, interfaces[i].interface, len) == 0) { + found = true; + break; + } + } + skip: + if(found) { + double timeDelta, rx_speed, tx_speed = 0; + + // print our new speeds + timeDelta = (timestamp.tv_sec - interfaces[i].timestamp.tv_sec) * 1.0 + + (timestamp.tv_usec - interfaces[i].timestamp.tv_usec) * .000001; + + rx_speed = (rx_bytes - interfaces[i].rx_bytes) / timeDelta; + tx_speed = (tx_bytes - interfaces[i].tx_bytes) / timeDelta; + + printf("%s (", interfaces[i].interface); + print_bps(rx_speed); + printf(", "); + print_bps(tx_speed); + printf(")\t"); + + // update our interface + strcpy(interfaces[i].interface, name); + interfaces[i].rx_bytes = rx_bytes; + interfaces[i].timestamp = timestamp; + interfaces[i].tx_bytes = tx_bytes; + } + else { + interfaces = realloc(interfaces, sizeof(struct iface) * (no_iface + 1)); + if(interfaces == NULL) { + fprintf(stderr, "Error: %s\n", strerror(errno)); + exit(1); + } + strcpy(interfaces[no_iface].interface, name); + interfaces[no_iface].rx_bytes = rx_bytes; + interfaces[no_iface].tx_bytes = tx_bytes; + no_iface++; + } + + } + + } + // Close the file + fclose(dev); + +} + +int main(int argc, char **argv) { + + // parse the command line + int c; + + int interval = 10 * 100000; + + while ((c = getopt (argc, argv, "bi:hv")) != -1) + switch (c) + { + case 'b': + use_bits = true; + break; + case 'i': + // Magic numbers? fuck it that's not a magic number, that's a 'real' number. + interval = atoi(optarg) * 100000; + break; + case 'h': + printf("USAGE: fsbm, -b specifies bits, -i sets interval in 10ths of seconds, 1 sec default\n"); + exit(EXIT_SUCCESS); + break; + case 'v': + printf("Version 1\n"); + exit(EXIT_SUCCESS); + break; + case '?': + fprintf(stderr,"bad flag\n"); + break; + default: + exit(EXIT_FAILURE); + } + + // Catch SIGINT + signal(SIGINT, endHandler); + + // populate first. + print_stats(); + while (!q) { + print_stats(); + printf("\n"); + usleep(interval); + } + + return EXIT_SUCCESS; +} diff --git a/fsbm.cpp b/fsbm.cpp deleted file mode 100644 index 1daa239..0000000 --- a/fsbm.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include "config.h" -#include "statistics.hpp" -#include <algorithm> -#include <cstdlib> -#include <cstring> -#include <iomanip> -#include <iostream> -#include <sstream> - -#include <curses.h> -#include <getopt.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <net/if.h> -#include <unistd.h> - -#define PACKAGE "yo" -#define PACKAGE_STRING "yo mamma" - -// Externs -extern int optind, opterr, optopt; - -volatile bool quit = false; - -void endHandler(int signum) { - quit = true; -} - -void formatBandwidth(double bytesPerSecond, bool showBits) { - const char* prefixes[] = { "", "k", "M", "G", "T", "P", "E", "Z", "Y" }; - - // Calculate the value - double value; - const char* unit; - if (showBits){ - value = bytesPerSecond * 8; - unit = "b/s"; - } - else { - value = bytesPerSecond; - unit = "B/s"; - } - - // Choose the prefix - unsigned prefix = 0; - while (prefix < (sizeof(prefixes) / sizeof(const char*)) && value > 1000.) { - value /= 1000.; - ++prefix; - } - - // Format the string - std::cout << std::setprecision(2) << value << " " << prefixes[prefix] << unit; - -} - -int main(int argc, char **argv) { - int retval = EXIT_SUCCESS; - - // parse the command line - int c; - - bool useBits = false; - int interval = 10 * 100000; - - while ((c = getopt (argc, argv, "bi:hv")) != -1) - switch (c) - { - case 'b': - useBits = true; - break; - case 'i': - // Magic numbers? fuck it that's not a magic number, that's a 'real' number. - interval = atoi(optarg) * 100000; - break; - case 'h': - std::cout << "USAGE: fsbm, -b specifies bits, -i sets interval in 10ths of seconds, 1 sec default\n"; - exit(EXIT_SUCCESS); - break; - case 'v': - std::cout << "Version 1\n"; - exit(EXIT_SUCCESS); - break; - case '?': - std::cerr << "bad flag\n"; - break; - default: - exit(EXIT_FAILURE); - } - - // Catch SIGINT - signal(SIGINT, endHandler); - - - - // Create a socket (for ioctls) - int sock = socket(AF_INET, SOCK_DGRAM, 0); - if (!sock) { - std::cerr << "cannot open socket\n"; - exit(EXIT_FAILURE); - } - - // Initialize curses - - statistics::Reader statisticsReader; - statisticsReader.update(); - while (!quit) { - - // Update the statistics - statisticsReader.update(); - - for (statistics::Reader::Interfaces::const_iterator - interface = statisticsReader.getInterfaces().begin(); - interface != statisticsReader.getInterfaces().end(); - ++interface) { - - std::cout << interface->getName() << " ("; - formatBandwidth(interface->getReceiveSpeed(), useBits); - std::cout << ", "; - formatBandwidth(interface->getTransmitSpeed(), useBits); - std::cout << ")"; - - } - std::cout << "\n"; - usleep(interval); - - - - } - return retval; -} diff --git a/statistics.cpp b/statistics.cpp deleted file mode 100644 index 800a4e5..0000000 --- a/statistics.cpp +++ /dev/null @@ -1,160 +0,0 @@ -#include "config.h" -#include "statistics.hpp" -#include <algorithm> -#include <assert.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#include <sys/time.h> - -#include <iostream> -#include <sstream> - -#define PROC_NET_DEV "/proc/net/dev" - -namespace statistics { - -Interface::Interface(const std::string& name) : name_(name), updated_(false) {} - -class InterfaceNameMatchesPredicate { - public: - InterfaceNameMatchesPredicate(const std::string& name) : name_(name) {} - - bool operator() (const Interface& interface) const { - return name_ == interface.getName(); - } - private: - std::string name_; -}; - -class InterfaceNotUpdatedPredicate { - public: - bool operator() (const Interface& interface) const { - return !interface.getUpdated(); - } -}; - -void Interface::update(const Statistics& statistics) { - memcpy(statistics_ + 1, statistics_ + 0, sizeof(Statistics)); - memcpy(statistics_, &statistics, sizeof(Statistics)); - - const Statistics& x0 = statistics_[1]; - const Statistics& x1 = statistics_[0]; - - double timeDelta = - (x1.timestamp.tv_sec - x0.timestamp.tv_sec) * 1. - + (x1.timestamp.tv_usec - x0.timestamp.tv_usec) * .000001; - - receiveSpeed_ = (x1.rx_bytes - x0.rx_bytes) / timeDelta; - transmitSpeed_ = (x1.tx_bytes - x0.tx_bytes) / timeDelta; - - updated_ = true; -} - -void Reader::update() { - // Open /proc/net/dev - FILE *dev = fopen(PROC_NET_DEV, "r"); - if (!dev) { - std::cerr << "cannot open " << PROC_NET_DEV << "\n"; - exit(EXIT_FAILURE); - } - - try { - // Clear the 'updated' flag for all interfaces - for (Interfaces::iterator interface = interfaces_.begin(); - interface != interfaces_.end(); ++interface) - interface->setUpdated(false); - - // Read /proc/dev/net - while (!feof(dev)) { - char buf[500]; - char *name, *statistics_string; - Statistics stats; - struct timezone unused_timezone; - - // Read a line - fgets(buf, sizeof(buf), dev); - gettimeofday(&stats.timestamp, &unused_timezone); - - // Find the colon separating the name from the statistics - statistics_string = strchr(buf, ':'); - if (!statistics_string) continue; - - // Get a pointer to the statistics - *statistics_string = 0; - ++statistics_string; - - // Remove leading whitespace from the name - name = buf; - while (*name == ' ' || *name == '\t') ++name; - - // Parse the statistics - if (sscanf(statistics_string, "%Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu " - "%Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", - &stats.rx_bytes, &stats.rx_packets, - &stats.rx_errs, &stats.rx_drop, - &stats.rx_fifo, &stats.rx_frame, - &stats.rx_compressed, &stats.rx_multicast, - &stats.tx_bytes, &stats.tx_packets, - &stats.tx_errs, &stats.tx_drop, - &stats.tx_fifo, &stats.tx_frame, - &stats.tx_compressed, &stats.tx_multicast) - == 16) { - - // Find the interface with the same name - Interfaces::iterator interface - = std::find_if(interfaces_.begin(), interfaces_.end(), - InterfaceNameMatchesPredicate(name)); - - if (interface == interfaces_.end()) { - // This is a new interface; add it to the list - interfaces_.push_back(Interface(name)); - interface = interfaces_.end(); - --interface; - } - - // Update the interface - interface->update(stats); - } - } - - // Remove all interfaces for which the updated flag was not set - interfaces_.remove_if(InterfaceNotUpdatedPredicate()); - - // Close the file - fclose(dev); - } - catch (...) { - fclose(dev); - throw; - } -} - -void Interface::setUpdated(bool updated) { - updated_ = updated; -} - -bool Interface::getUpdated() const { - return updated_; -} - -const std::string& Interface::getName() const { - return name_; -} - -double Interface::getReceiveSpeed() const { - return receiveSpeed_; -} - -double Interface::getTransmitSpeed() const { - return transmitSpeed_; -} - -const Reader::Interfaces& Reader::getInterfaces() const { - return interfaces_; -} - -} // namespace statistics diff --git a/statistics.hpp b/statistics.hpp deleted file mode 100644 index c916ecb..0000000 --- a/statistics.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef CBM_STATISTICS_H -#define CBM_STATISTICS_H - -#include <list> -#include <string> -#include <sys/time.h> - -namespace statistics { - -struct Statistics { - struct timeval timestamp; - unsigned long long rx_bytes, rx_packets, rx_errs, rx_drop, rx_fifo, - rx_frame, rx_compressed, rx_multicast, - tx_bytes, tx_packets, tx_errs, tx_drop, tx_fifo, - tx_frame, tx_compressed, tx_multicast; -}; - -class Interface { - public: - Interface(const std::string& name); - - const std::string& getName() const; - - void setUpdated(bool updated); - bool getUpdated() const; - - void update(const Statistics& statistics); - - double getReceiveSpeed() const; - double getTransmitSpeed() const; - - private: - std::string name_; - bool updated_; - Statistics statistics_[2]; - double receiveSpeed_, transmitSpeed_; -}; - -class Reader { - public: - void update(); - - typedef std::list<Interface> Interfaces; - const Interfaces& getInterfaces() const; - - private: - Interfaces interfaces_; -}; - -} // namespace statistics - -#endif |