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