ThrottleController.cpp revision ff2c0d8c13457e43f0d4bf06d3177271aac104c1
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[255]; 46 47 strncpy(buffer, cmd, sizeof(buffer)-1); 48 49 const char *args[32]; 50 char *next = buffer; 51 char *tmp; 52 53 args[0] = TC_PATH; 54 int i = 1; 55 56 while ((tmp = strsep(&next, " "))) { 57 args[i++] = tmp; 58 if (i == 32) { 59 LOGE("tc argument overflow"); 60 errno = E2BIG; 61 return -1; 62 } 63 } 64 args[i] = NULL; 65 66 return logwrap(i, args, 0); 67} 68 69int ThrottleController::setInterfaceThrottle(const char *iface, int rxKbps, int txKbps) { 70 char cmd[512]; 71 char ifn[65]; 72 int rc; 73 74 memset(ifn, 0, sizeof(ifn)); 75 strncpy(ifn, iface, sizeof(ifn)-1); 76 77 if (txKbps == -1) { 78 reset(ifn); 79 return 0; 80 } 81 82 /* 83 * 84 * Target interface configuration 85 * 86 */ 87 88 /* 89 * Add root qdisc for the interface 90 */ 91 sprintf(cmd, "qdisc add dev %s root handle 1: htb default 1 r2q 1000", ifn); 92 if (runTcCmd(cmd)) { 93 LOGE("Failed to add root qdisc (%s)", strerror(errno)); 94 goto fail; 95 } 96 97 /* 98 * Add our egress throttling class 99 */ 100 sprintf(cmd, "class add dev %s parent 1: classid 1:1 htb rate %dkbit", ifn, txKbps); 101 if (runTcCmd(cmd)) { 102 LOGE("Failed to add egress throttling class (%s)", strerror(errno)); 103 goto fail; 104 } 105 106 /* 107 * Bring up the IFD device 108 */ 109 ifc_init(); 110 if (ifc_up("ifb0")) { 111 LOGE("Failed to up ifb0 (%s)", strerror(errno)); 112 goto fail; 113 } 114 115 /* 116 * Add root qdisc for IFD 117 */ 118 sprintf(cmd, "qdisc add dev ifb0 root handle 1: htb default 1 r2q 1000"); 119 if (runTcCmd(cmd)) { 120 LOGE("Failed to add root ifb qdisc (%s)", strerror(errno)); 121 goto fail; 122 } 123 124 /* 125 * Add our ingress throttling class 126 */ 127 sprintf(cmd, "class add dev ifb0 parent 1: classid 1:1 htb rate %dkbit", rxKbps); 128 if (runTcCmd(cmd)) { 129 LOGE("Failed to add ingress throttling class (%s)", strerror(errno)); 130 goto fail; 131 } 132 133 /* 134 * Add ingress qdisc for pkt redirection 135 */ 136 sprintf(cmd, "qdisc add dev %s ingress", ifn); 137 if (runTcCmd(cmd)) { 138 LOGE("Failed to add ingress qdisc (%s)", strerror(errno)); 139 goto fail; 140 } 141 142 /* 143 * Add filter to link <ifn> -> ifb0 144 */ 145 sprintf(cmd, "filter add dev %s parent ffff: protocol ip prio 10 u32 match " 146 "u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0", ifn); 147 if (runTcCmd(cmd)) { 148 LOGE("Failed to add ifb filter (%s)", strerror(errno)); 149 goto fail; 150 } 151 152 return 0; 153fail: 154 reset(ifn); 155 return -1; 156} 157 158void ThrottleController::reset(const char *iface) { 159 char cmd[128]; 160 161 sprintf(cmd, "qdisc del dev %s root", iface); 162 runTcCmd(cmd); 163 sprintf(cmd, "qdisc del dev %s ingress", iface); 164 runTcCmd(cmd); 165 166 runTcCmd("qdisc del dev ifb0 root"); 167} 168 169int ThrottleController::getInterfaceRxThrottle(const char *iface, int *rx) { 170 *rx = 0; 171 return 0; 172} 173 174int ThrottleController::getInterfaceTxThrottle(const char *iface, int *tx) { 175 *tx = 0; 176 return 0; 177} 178