OSDN Git Service

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