ThrottleController.cpp revision 11b4e9b26fe7b878992162afb39f5a8acfd143ed
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdlib.h> 18#include <errno.h> 19#include <fcntl.h> 20#include <string.h> 21 22#include <sys/socket.h> 23#include <sys/stat.h> 24#include <sys/types.h> 25#include <sys/wait.h> 26 27#include <linux/netlink.h> 28#include <linux/rtnetlink.h> 29#include <linux/pkt_sched.h> 30 31#define LOG_TAG "ThrottleController" 32#include <cutils/log.h> 33 34 35#include "ThrottleController.h" 36 37static char TC_PATH[] = "/system/bin/tc"; 38 39extern "C" int logwrap(int argc, const char **argv, int background); 40extern "C" int ifc_init(void); 41extern "C" int ifc_up(const char *name); 42extern "C" int ifc_down(const char *name); 43 44int ThrottleController::runTcCmd(const char *cmd) { 45 char *buffer; 46 size_t len = strnlen(cmd, 255); 47 int res; 48 49 if (len == 255) { 50 LOGE("tc command too long"); 51 errno = E2BIG; 52 return -1; 53 } 54 55 asprintf(&buffer, "%s %s", TC_PATH, cmd); 56 res = system(buffer); 57 free(buffer); 58 return res; 59} 60 61int ThrottleController::setInterfaceThrottle(const char *iface, int rxKbps, int txKbps) { 62 char cmd[512]; 63 char ifn[65]; 64 int rc; 65 66 memset(ifn, 0, sizeof(ifn)); 67 strncpy(ifn, iface, sizeof(ifn)-1); 68 69 if (txKbps == -1) { 70 reset(ifn); 71 return 0; 72 } 73 74 /* 75 * 76 * Target interface configuration 77 * 78 */ 79 80 /* 81 * Add root qdisc for the interface 82 */ 83 sprintf(cmd, "qdisc add dev %s root handle 1: htb default 1 r2q 1000", ifn); 84 if (runTcCmd(cmd)) { 85 LOGE("Failed to add root qdisc (%s)", strerror(errno)); 86 goto fail; 87 } 88 89 /* 90 * Add our egress throttling class 91 */ 92 sprintf(cmd, "class add dev %s parent 1: classid 1:1 htb rate %dkbit", ifn, txKbps); 93 if (runTcCmd(cmd)) { 94 LOGE("Failed to add egress throttling class (%s)", strerror(errno)); 95 goto fail; 96 } 97 98 /* 99 * Bring up the IFD device 100 */ 101 ifc_init(); 102 if (ifc_up("ifb0")) { 103 LOGE("Failed to up ifb0 (%s)", strerror(errno)); 104 goto fail; 105 } 106 107 /* 108 * Add root qdisc for IFD 109 */ 110 sprintf(cmd, "qdisc add dev ifb0 root handle 1: htb default 1 r2q 1000"); 111 if (runTcCmd(cmd)) { 112 LOGE("Failed to add root ifb qdisc (%s)", strerror(errno)); 113 goto fail; 114 } 115 116 /* 117 * Add our ingress throttling class 118 */ 119 sprintf(cmd, "class add dev ifb0 parent 1: classid 1:1 htb rate %dkbit", rxKbps); 120 if (runTcCmd(cmd)) { 121 LOGE("Failed to add ingress throttling class (%s)", strerror(errno)); 122 goto fail; 123 } 124 125 /* 126 * Add ingress qdisc for pkt redirection 127 */ 128 sprintf(cmd, "qdisc add dev %s ingress", ifn); 129 if (runTcCmd(cmd)) { 130 LOGE("Failed to add ingress qdisc (%s)", strerror(errno)); 131 goto fail; 132 } 133 134 /* 135 * Add filter to link <ifn> -> ifb0 136 */ 137 sprintf(cmd, "filter add dev %s parent ffff: protocol ip prio 10 u32 match " 138 "u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0", ifn); 139 if (runTcCmd(cmd)) { 140 LOGE("Failed to add ifb filter (%s)", strerror(errno)); 141 goto fail; 142 } 143 144 return 0; 145fail: 146 reset(ifn); 147 return -1; 148} 149 150void ThrottleController::reset(const char *iface) { 151 char cmd[128]; 152 153 sprintf(cmd, "qdisc del dev %s root", iface); 154 runTcCmd(cmd); 155 sprintf(cmd, "qdisc del dev %s ingress", iface); 156 runTcCmd(cmd); 157 158 runTcCmd("qdisc del dev ifb0 root"); 159} 160 161int ThrottleController::getInterfaceRxThrottle(const char *iface, int *rx) { 162 *rx = 0; 163 return 0; 164} 165 166int ThrottleController::getInterfaceTxThrottle(const char *iface, int *tx) { 167 *tx = 0; 168 return 0; 169} 170