OSDN Git Service

Reconcile with gingerbread-release
[android-x86/system-netd.git] / ThrottleController.cpp
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
37 static char TC_PATH[] = "/system/bin/tc";
38
39 extern "C" int logwrap(int argc, const char **argv, int background);
40 extern "C" int ifc_init(void);
41 extern "C" int ifc_up(const char *name);
42 extern "C" int ifc_down(const char *name);
43
44 int 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
69 int 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;
153 fail:
154     reset(ifn);
155     return -1;
156 }
157
158 void 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
169 int ThrottleController::getInterfaceRxThrottle(const char *iface, int *rx) {
170     *rx = 0;
171     return 0;
172 }
173
174 int ThrottleController::getInterfaceTxThrottle(const char *iface, int *tx) {
175     *tx = 0;
176     return 0;
177 }