blob: 3501f5762296ce8cbad56ca4e98ebd9d2a262060 [file] [log] [blame]
San Mehata1992c92010-04-07 15:21:36 -07001/*
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
21#include <sys/socket.h>
22#include <sys/stat.h>
23#include <sys/types.h>
24#include <sys/wait.h>
25
26#include <linux/netlink.h>
27#include <linux/rtnetlink.h>
28#include <linux/pkt_sched.h>
29
30#define LOG_TAG "ThrottleController"
31#include <cutils/log.h>
32
33
34#include "ThrottleController.h"
35
36static char TC_PATH[] = "/system/bin/tc";
37
38extern "C" int logwrap(int argc, const char **argv, int background);
39
40int ThrottleController::runTcCmd(const char *cmd) {
41 char buffer[255];
42
43 strncpy(buffer, cmd, sizeof(buffer)-1);
44
45 const char *args[32];
46 char *next = buffer;
47 char *tmp;
48
49 args[0] = TC_PATH;
50 int i = 1;
51
52 while ((tmp = strsep(&next, " "))) {
53 args[i++] = tmp;
54 if (i == 32) {
55 LOGE("tc argument overflow");
56 errno = E2BIG;
57 return -1;
58 }
59 }
60 args[i] = NULL;
61
62 return logwrap(i, args, 0);
63}
64
65int ThrottleController::setInterfaceThrottle(const char *iface, int rxKbps, int txKbps) {
66 char *cmd;
67 int rc;
68
69 if (txKbps == -1) {
70 reset(iface);
71 return 0;
72 }
73
74 asprintf(&cmd, "qdisc add dev %s root handle 1: cbq avpkt 1000 bandwidth 10mbit", iface);
75 rc = runTcCmd(cmd);
76 free(cmd);
77 if (rc) {
78 LOGE("Failed to add cbq qdisc (%s)", strerror(errno));
79 reset(iface);
80 return -1;
81 }
82
83 asprintf(&cmd,
84 "class add dev %s parent 1: classid 1:1 cbq rate %dkbit allot 1500 prio 5 bounded isolated",
85 iface, txKbps);
86 rc = runTcCmd(cmd);
87 free(cmd);
88 if (rc) {
89 LOGE("Failed to add class (%s)", strerror(errno));
90 reset(iface);
91 return -1;
92 }
93
94 asprintf(&cmd,
95 "filter add dev %s parent 1: protocol ip prio 16 u32 match ip dst 0.0.0.0/0 flowid 1:1",
96 iface);
97 rc = runTcCmd(cmd);
98 free(cmd);
99 if (runTcCmd(cmd)) {
100 LOGE("Failed to add filter (%s)", strerror(errno));
101 reset(iface);
102 return -1;
103 }
104
105 return 0;
106}
107
108void ThrottleController::reset(const char *iface) {
109 char *cmd;
110 asprintf(&cmd, "qdisc del dev %s root", iface);
111 runTcCmd(cmd);
112 free(cmd);
113}
114
115int ThrottleController::getInterfaceRxThrottle(const char *iface, int *rx) {
116 *rx = 0;
117 return 0;
118}
119
120int ThrottleController::getInterfaceTxThrottle(const char *iface, int *tx) {
121 *tx = 0;
122 return 0;
123}