2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <sys/socket.h>
23 #include <sys/types.h>
26 #include <linux/netlink.h>
27 #include <linux/rtnetlink.h>
28 #include <linux/pkt_sched.h>
30 #define LOG_TAG "ThrottleController"
31 #include <cutils/log.h>
34 #include "ThrottleController.h"
36 static char TC_PATH[] = "/system/bin/tc";
38 extern "C" int logwrap(int argc, const char **argv, int background);
39 extern "C" int ifc_init(void);
40 extern "C" int ifc_up(const char *name);
41 extern "C" int ifc_down(const char *name);
43 int ThrottleController::runTcCmd(const char *cmd) {
46 strncpy(buffer, cmd, sizeof(buffer)-1);
55 while ((tmp = strsep(&next, " "))) {
58 LOGE("tc argument overflow");
65 return logwrap(i, args, 0);
68 int ThrottleController::setInterfaceThrottle(const char *iface, int rxKbps, int txKbps) {
73 memset(ifn, 0, sizeof(ifn));
74 strncpy(ifn, iface, sizeof(ifn)-1);
83 * Target interface configuration
88 * Add root qdisc for the interface
90 sprintf(cmd, "qdisc add dev %s root handle 1: cbq avpkt 1000 bandwidth 10mbit",ifn);
92 LOGE("Failed to add root qdisc (%s)", strerror(errno));
97 * Add our egress throttling class
99 sprintf(cmd, "class add dev %s parent 1: classid 1:1 cbq rate %dkbit allot 1500 "
100 "prio 5 bounded isolated", ifn, txKbps);
102 LOGE("Failed to add egress throttling class (%s)", strerror(errno));
107 * Add filter for egress matching
109 sprintf(cmd, "filter add dev %s parent 1: protocol ip prio 16 u32 match "
110 "ip dst 0.0.0.0/0 flowid 1:1", ifn);
112 LOGE("Failed to add egress throttling filter (%s)", strerror(errno));
117 * Bring up the IFD device
120 if (ifc_up("ifb0")) {
121 LOGE("Failed to up ifb0 (%s)", strerror(errno));
126 * Add ingress qdisc for pkt redirection
128 sprintf(cmd, "qdisc add dev %s ingress", ifn);
130 LOGE("Failed to add ingress qdisc (%s)", strerror(errno));
135 * Add filter to link <ifn> -> ifb0
137 sprintf(cmd, "filter add dev %s parent 1: protocol ip prio 10 u32 match "
138 "u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0", ifn);
140 LOGE("Failed to add ifb filter (%s)", strerror(errno));
151 * Add root qdisc for the interface
153 sprintf(cmd, "qdisc add dev ifb0 root handle 1: cbq avpkt 1000 bandwidth 10mbit");
155 LOGE("Failed to add root ifb qdisc (%s)", strerror(errno));
160 * Add our ingress throttling class
162 sprintf(cmd, "class add dev ifb0 parent 1: classid 1:1 cbq rate %dkbit allot 1500 "
163 "prio 5 bounded isolated", rxKbps);
165 LOGE("Failed to add ingress throttling class (%s)", strerror(errno));
170 * Add filter for ingress matching
172 sprintf(cmd, "filter add dev ifb0 parent 1: protocol ip prio 16 u32 match "
173 "ip dst 0.0.0.0/0 flowid 1:1");
175 LOGE("Failed to add ingress throttling filter (%s)", strerror(errno));
185 void ThrottleController::reset(const char *iface) {
188 sprintf(cmd, "qdisc del dev %s root", iface);
190 sprintf(cmd, "qdisc del dev %s ingress", iface);
193 runTcCmd("qdisc del dev ifb0 root");
196 int ThrottleController::getInterfaceRxThrottle(const char *iface, int *rx) {
201 int ThrottleController::getInterfaceTxThrottle(const char *iface, int *tx) {