summaryrefslogtreecommitdiff
path: root/server/BandwidthController.cpp
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2017-02-02 01:34:33 +0900
committerLorenzo Colitti <lorenzo@google.com>2017-02-10 11:40:06 +0900
commitce6748a3f656a206b4e85f48cda949bc152cf741 (patch)
treed9f8f3f1b7ad4d3966fb1fca6ba77dccab775e1b /server/BandwidthController.cpp
parent56c4b1eb7d15e55a4edb88cfc0d190d8817d1353 (diff)
Use iptables pipes when fetching tether counters.
Tested using: adb shell ndc bandwidth gettetherstats adb shell iptables -nvx -L natctrl_tether_counters adb shell ip6tables -nvx -L natctrl_tether_counters Results: 114 0 wlan0 rmnet_data0 272883 2976 8624804 6032 200 0 Tethering stats list completed Chain natctrl_tether_counters (2 references) pkts bytes target prot opt in out source destination 2688 179096 RETURN all -- wlan0 rmnet_data0 0.0.0.0/0 0.0.0.0/0 5713 8351999 RETURN all -- rmnet_data0 wlan0 0.0.0.0/0 0.0.0.0/0 Chain natctrl_tether_counters (1 references) pkts bytes target prot opt in out source destination 288 93787 RETURN all wlan0 rmnet_data0 ::/0 ::/0 319 272805 RETURN all rmnet_data0 wlan0 ::/0 ::/0 Test: manual test described above Test: data usage increases by 10MB when downloading 10MB file Test: netd_unit_test passes Bug: 34873832 Change-Id: I32c4e750a4d3c379074cc13ab1302d51421860d2
Diffstat (limited to 'server/BandwidthController.cpp')
-rw-r--r--server/BandwidthController.cpp46
1 files changed, 20 insertions, 26 deletions
diff --git a/server/BandwidthController.cpp b/server/BandwidthController.cpp
index 3df2309b..c8e8d14c 100644
--- a/server/BandwidthController.cpp
+++ b/server/BandwidthController.cpp
@@ -76,6 +76,11 @@ const int MAX_CMD_LEN = 1024;
const int MAX_IFACENAME_LEN = 64;
const int MAX_IPT_OUTPUT_LINE_LEN = 256;
const std::string NEW_CHAIN_COMMAND = "-N ";
+const std::string GET_TETHER_STATS_COMMAND = android::base::StringPrintf(
+ "*filter\n"
+ "-nvx -L %s\n"
+ "COMMIT\n", NatController::LOCAL_TETHER_COUNTERS_CHAIN);
+
/**
* Some comments about the rules:
@@ -1111,16 +1116,17 @@ void BandwidthController::addStats(TetherStatsList& statsList, const TetherStats
* helps detect complete parsing failure.
*/
int BandwidthController::addForwardChainStats(const TetherStats& filter,
- TetherStatsList& statsList, FILE *fp,
+ TetherStatsList& statsList,
+ const std::string& statsOutput,
std::string &extraProcessingInfo) {
int res;
- char lineBuffer[MAX_IPT_OUTPUT_LINE_LEN];
+ std::string statsLine;
char iface0[MAX_IPT_OUTPUT_LINE_LEN];
char iface1[MAX_IPT_OUTPUT_LINE_LEN];
char rest[MAX_IPT_OUTPUT_LINE_LEN];
TetherStats stats;
- char *buffPtr;
+ const char *buffPtr;
int64_t packets, bytes;
int statsFound = 0;
@@ -1132,7 +1138,10 @@ int BandwidthController::addForwardChainStats(const TetherStats& filter,
stats = filter;
- while (NULL != (buffPtr = fgets(lineBuffer, MAX_IPT_OUTPUT_LINE_LEN, fp))) {
+ std::stringstream stream(statsOutput);
+ while (std::getline(stream, statsLine, '\n')) {
+ buffPtr = statsLine.c_str();
+
/* Clean up, so a failed parse can still print info */
iface0[0] = iface1[0] = rest[0] = packets = bytes = 0;
if (strstr(buffPtr, "0.0.0.0")) {
@@ -1149,6 +1158,7 @@ int BandwidthController::addForwardChainStats(const TetherStats& filter,
ALOGV("parse res=%d iface0=<%s> iface1=<%s> pkts=%" PRId64" bytes=%" PRId64" rest=<%s> orig line=<%s>", res,
iface0, iface1, packets, bytes, rest, buffPtr);
extraProcessingInfo += buffPtr;
+ extraProcessingInfo += "\n";
if (res != 5) {
continue;
@@ -1223,37 +1233,21 @@ char *BandwidthController::TetherStats::getStatsLine(void) const {
return msg;
}
-std::string getTetherStatsCommand(const char *binary) {
- /*
- * Why not use some kind of lib to talk to iptables?
- * Because the only libs are libiptc and libip6tc in iptables, and they are
- * not easy to use. They require the known iptables match modules to be
- * preloaded/linked, and require apparently a lot of wrapper code to get
- * the wanted info.
- */
- return android::base::StringPrintf("%s -nvx -w -L %s", binary,
- NatController::LOCAL_TETHER_COUNTERS_CHAIN);
-}
-
int BandwidthController::getTetherStats(SocketClient *cli, TetherStats& filter,
std::string &extraProcessingInfo) {
int res = 0;
- std::string fullCmd;
- FILE *iptOutput;
TetherStatsList statsList;
- for (const auto binary : {IPTABLES_PATH, IP6TABLES_PATH}) {
- fullCmd = getTetherStatsCommand(binary);
- iptOutput = popenFunction(fullCmd.c_str(), "r");
- if (!iptOutput) {
- ALOGE("Failed to run %s err=%s", fullCmd.c_str(), strerror(errno));
- extraProcessingInfo += "Failed to run iptables.";
+ for (const IptablesTarget target : {V4, V6}) {
+ std::string statsString;
+ res = iptablesRestoreFunction(target, GET_TETHER_STATS_COMMAND, &statsString);
+ if (res != 0) {
+ ALOGE("Failed to run %s err=%d", GET_TETHER_STATS_COMMAND.c_str(), res);
return -1;
}
- res = addForwardChainStats(filter, statsList, iptOutput, extraProcessingInfo);
- pclose(iptOutput);
+ res = addForwardChainStats(filter, statsList, statsString, extraProcessingInfo);
if (res != 0) {
return res;
}