ThrottleController.cpp revision 7e1f476ce965d9bde6e834bbe862faef548b2abb
1a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat/* 2a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat * Copyright (C) 2008 The Android Open Source Project 3a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat * 4a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat * you may not use this file except in compliance with the License. 6a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat * You may obtain a copy of the License at 7a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat * 8a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat * 10a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat * Unless required by applicable law or agreed to in writing, software 11a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat * See the License for the specific language governing permissions and 14a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat * limitations under the License. 15a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat */ 16a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 17a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <stdlib.h> 18a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <errno.h> 19a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <fcntl.h> 20a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 21a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <sys/socket.h> 22a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <sys/stat.h> 23a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <sys/types.h> 24a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <sys/wait.h> 25a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 26a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <linux/netlink.h> 27a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <linux/rtnetlink.h> 28a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <linux/pkt_sched.h> 29a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 30a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#define LOG_TAG "ThrottleController" 31a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <cutils/log.h> 32a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 33a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 34a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include "ThrottleController.h" 35a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 36a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehatstatic char TC_PATH[] = "/system/bin/tc"; 37a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 38a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehatextern "C" int logwrap(int argc, const char **argv, int background); 397e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehatextern "C" int ifc_init(void); 407e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehatextern "C" int ifc_up(const char *name); 417e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehatextern "C" int ifc_down(const char *name); 42a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 43a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehatint ThrottleController::runTcCmd(const char *cmd) { 44a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat char buffer[255]; 45a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 46a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat strncpy(buffer, cmd, sizeof(buffer)-1); 47a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 48a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat const char *args[32]; 49a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat char *next = buffer; 50a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat char *tmp; 51a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 52a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat args[0] = TC_PATH; 53a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat int i = 1; 54a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 55a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat while ((tmp = strsep(&next, " "))) { 56a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat args[i++] = tmp; 57a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat if (i == 32) { 58a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat LOGE("tc argument overflow"); 59a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat errno = E2BIG; 60a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat return -1; 61a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat } 62a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat } 63a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat args[i] = NULL; 64a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 65a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat return logwrap(i, args, 0); 66a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat} 67a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 68a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehatint ThrottleController::setInterfaceThrottle(const char *iface, int rxKbps, int txKbps) { 697e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat char cmd[512]; 707e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat char ifn[65]; 71a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat int rc; 72a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 737e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat memset(ifn, 0, sizeof(ifn)); 747e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat strncpy(ifn, iface, sizeof(ifn)-1); 757e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 76a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat if (txKbps == -1) { 777e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat reset(ifn); 78a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat return 0; 79a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat } 80a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 817e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 827e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * 837e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Target interface configuration 847e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * 857e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 867e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 877e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 887e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Add root qdisc for the interface 897e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 907e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat sprintf(cmd, "qdisc add dev %s root handle 1: cbq avpkt 1000 bandwidth 10mbit",ifn); 917e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (runTcCmd(cmd)) { 927e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat LOGE("Failed to add root qdisc (%s)", strerror(errno)); 937e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 94a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat } 95a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 967e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 977e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Add our egress throttling class 987e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 997e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat sprintf(cmd, "class add dev %s parent 1: classid 1:1 cbq rate %dkbit allot 1500 " 1007e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat "prio 5 bounded isolated", ifn, txKbps); 1017e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (runTcCmd(cmd)) { 1027e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat LOGE("Failed to add egress throttling class (%s)", strerror(errno)); 1037e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 104a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat } 105a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 1067e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 1077e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Add filter for egress matching 1087e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 1097e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat sprintf(cmd, "filter add dev %s parent 1: protocol ip prio 16 u32 match " 1107e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat "ip dst 0.0.0.0/0 flowid 1:1", ifn); 111a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat if (runTcCmd(cmd)) { 1127e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat LOGE("Failed to add egress throttling filter (%s)", strerror(errno)); 1137e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 1147e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat } 1157e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1167e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 1177e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Bring up the IFD device 1187e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 1197e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat ifc_init(); 1207e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (ifc_up("ifb0")) { 1217e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat LOGE("Failed to up ifb0 (%s)", strerror(errno)); 1227e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 1237e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat } 1247e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1257e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 1267e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Add ingress qdisc for pkt redirection 1277e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 1287e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat sprintf(cmd, "qdisc add dev %s ingress", ifn); 1297e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (runTcCmd(cmd)) { 1307e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat LOGE("Failed to add ingress qdisc (%s)", strerror(errno)); 1317e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 1327e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat } 1337e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1347e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 1357e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Add filter to link <ifn> -> ifb0 1367e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 1377e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat sprintf(cmd, "filter add dev %s parent 1: protocol ip prio 10 u32 match " 1387e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat "u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0", ifn); 1397e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (runTcCmd(cmd)) { 1407e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat LOGE("Failed to add ifb filter (%s)", strerror(errno)); 1417e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 1427e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat } 1437e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1447e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 1457e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * 1467e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * IFD configuration 1477e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * 1487e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 1497e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1507e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 1517e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Add root qdisc for the interface 1527e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 1537e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat sprintf(cmd, "qdisc add dev ifb0 root handle 1: cbq avpkt 1000 bandwidth 10mbit"); 1547e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (runTcCmd(cmd)) { 1557e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat LOGE("Failed to add root ifb qdisc (%s)", strerror(errno)); 1567e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 1577e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat } 1587e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1597e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 1607e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Add our ingress throttling class 1617e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 1627e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat sprintf(cmd, "class add dev ifb0 parent 1: classid 1:1 cbq rate %dkbit allot 1500 " 1637e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat "prio 5 bounded isolated", rxKbps); 1647e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (runTcCmd(cmd)) { 1657e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat LOGE("Failed to add ingress throttling class (%s)", strerror(errno)); 1667e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 1677e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat } 1687e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1697e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 1707e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Add filter for ingress matching 1717e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 1727e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat sprintf(cmd, "filter add dev ifb0 parent 1: protocol ip prio 16 u32 match " 1737e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat "ip dst 0.0.0.0/0 flowid 1:1"); 1747e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (runTcCmd(cmd)) { 1757e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat LOGE("Failed to add ingress throttling filter (%s)", strerror(errno)); 1767e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 177a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat } 178a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 179a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat return 0; 1807e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehatfail: 1817e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat reset(ifn); 1827e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat return -1; 183a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat} 184a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 185a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehatvoid ThrottleController::reset(const char *iface) { 1867e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat char cmd[128]; 1877e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1887e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat sprintf(cmd, "qdisc del dev %s root", iface); 1897e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat runTcCmd(cmd); 1907e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat sprintf(cmd, "qdisc del dev %s ingress", iface); 191a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat runTcCmd(cmd); 1927e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1937e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat runTcCmd("qdisc del dev ifb0 root"); 194a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat} 195a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 196a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehatint ThrottleController::getInterfaceRxThrottle(const char *iface, int *rx) { 197a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat *rx = 0; 198a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat return 0; 199a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat} 200a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 201a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehatint ThrottleController::getInterfaceTxThrottle(const char *iface, int *tx) { 202a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat *tx = 0; 203a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat return 0; 204a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat} 205