ThrottleController.cpp revision 5ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13
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> 20ff2c0d8c13457e43f0d4bf06d3177271aac104c1Olivier Bailly#include <string.h> 21a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 22a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <sys/socket.h> 23a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <sys/stat.h> 24a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <sys/types.h> 25a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <sys/wait.h> 26a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 27a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <linux/netlink.h> 28a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <linux/rtnetlink.h> 29a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <linux/pkt_sched.h> 30a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 31a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#define LOG_TAG "ThrottleController" 32a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include <cutils/log.h> 33a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 34a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 35a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat#include "ThrottleController.h" 36a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 37a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehatstatic char TC_PATH[] = "/system/bin/tc"; 38a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 399e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrallextern "C" int system_nosh(const char *command); 407e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehatextern "C" int ifc_init(void); 417e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehatextern "C" int ifc_up(const char *name); 427e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehatextern "C" int ifc_down(const char *name); 43a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 44a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehatint ThrottleController::runTcCmd(const char *cmd) { 4511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall char *buffer; 4611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall size_t len = strnlen(cmd, 255); 4711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall int res; 4811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall 4911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall if (len == 255) { 505ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("tc command too long"); 5111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall errno = E2BIG; 5211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall return -1; 53a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat } 54a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 5511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall asprintf(&buffer, "%s %s", TC_PATH, cmd); 569e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall res = system_nosh(buffer); 5711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall free(buffer); 5811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall return res; 59a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat} 60a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 61a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehatint ThrottleController::setInterfaceThrottle(const char *iface, int rxKbps, int txKbps) { 627e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat char cmd[512]; 637e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat char ifn[65]; 64a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat int rc; 65a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 667e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat memset(ifn, 0, sizeof(ifn)); 677e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat strncpy(ifn, iface, sizeof(ifn)-1); 687e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 69a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat if (txKbps == -1) { 707e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat reset(ifn); 71a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat return 0; 72a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat } 73a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 747e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 757e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * 767e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Target interface configuration 777e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * 787e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 797e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 807e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 817e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Add root qdisc for the interface 827e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 839d8d728596234e1e49cb1f8267b190bcc2d4b685San Mehat sprintf(cmd, "qdisc add dev %s root handle 1: htb default 1 r2q 1000", ifn); 847e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (runTcCmd(cmd)) { 855ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed to add root qdisc (%s)", strerror(errno)); 867e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 87a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat } 88a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 897e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 907e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Add our egress throttling class 917e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 929d8d728596234e1e49cb1f8267b190bcc2d4b685San Mehat sprintf(cmd, "class add dev %s parent 1: classid 1:1 htb rate %dkbit", ifn, txKbps); 937e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (runTcCmd(cmd)) { 945ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed to add egress throttling class (%s)", strerror(errno)); 957e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 96a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat } 97a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 987e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 997e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat * Bring up the IFD device 1007e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 1017e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat ifc_init(); 1027e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (ifc_up("ifb0")) { 1035ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed to up ifb0 (%s)", strerror(errno)); 1047e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 1057e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat } 1067e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1077e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 1089d8d728596234e1e49cb1f8267b190bcc2d4b685San Mehat * Add root qdisc for IFD 1097e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 1109d8d728596234e1e49cb1f8267b190bcc2d4b685San Mehat sprintf(cmd, "qdisc add dev ifb0 root handle 1: htb default 1 r2q 1000"); 1117e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (runTcCmd(cmd)) { 1125ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed to add root ifb qdisc (%s)", strerror(errno)); 1137e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 1147e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat } 1157e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1167e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 1179d8d728596234e1e49cb1f8267b190bcc2d4b685San Mehat * Add our ingress throttling class 1187e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 1199d8d728596234e1e49cb1f8267b190bcc2d4b685San Mehat sprintf(cmd, "class add dev ifb0 parent 1: classid 1:1 htb rate %dkbit", rxKbps); 1207e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (runTcCmd(cmd)) { 1215ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed to add ingress throttling class (%s)", strerror(errno)); 1227e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 1237e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat } 1247e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1257e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 1269d8d728596234e1e49cb1f8267b190bcc2d4b685San Mehat * Add ingress qdisc for pkt redirection 1277e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 1289d8d728596234e1e49cb1f8267b190bcc2d4b685San Mehat sprintf(cmd, "qdisc add dev %s ingress", ifn); 1297e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (runTcCmd(cmd)) { 1305ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed to add ingress qdisc (%s)", strerror(errno)); 1317e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 1327e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat } 1337e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1347e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat /* 1359d8d728596234e1e49cb1f8267b190bcc2d4b685San Mehat * Add filter to link <ifn> -> ifb0 1367e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat */ 1379d8d728596234e1e49cb1f8267b190bcc2d4b685San Mehat sprintf(cmd, "filter add dev %s parent ffff: protocol ip prio 10 u32 match " 1389d8d728596234e1e49cb1f8267b190bcc2d4b685San Mehat "u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0", ifn); 1397e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat if (runTcCmd(cmd)) { 1405ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed to add ifb filter (%s)", strerror(errno)); 1417e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat goto fail; 142a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat } 143a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 144a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat return 0; 1457e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehatfail: 1467e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat reset(ifn); 1477e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat return -1; 148a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat} 149a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 150a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehatvoid ThrottleController::reset(const char *iface) { 1517e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat char cmd[128]; 1527e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1537e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat sprintf(cmd, "qdisc del dev %s root", iface); 1547e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat runTcCmd(cmd); 1557e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat sprintf(cmd, "qdisc del dev %s ingress", iface); 156a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat runTcCmd(cmd); 1577e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat 1587e1f476ce965d9bde6e834bbe862faef548b2abbSan Mehat runTcCmd("qdisc del dev ifb0 root"); 159a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat} 160a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 161a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehatint ThrottleController::getInterfaceRxThrottle(const char *iface, int *rx) { 162a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat *rx = 0; 163a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat return 0; 164a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat} 165a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat 166a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehatint ThrottleController::getInterfaceTxThrottle(const char *iface, int *tx) { 167a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat *tx = 0; 168a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat return 0; 169a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat} 170