forked from CyanogenMod/android_system_netd
-
Notifications
You must be signed in to change notification settings - Fork 2
/
ThrottleController.cpp
168 lines (141 loc) · 4.06 KB
/
ThrottleController.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/pkt_sched.h>
#define LOG_TAG "ThrottleController"
#include <cutils/log.h>
#include "ThrottleController.h"
#include "NetdConstants.h"
extern "C" int system_nosh(const char *command);
extern "C" int ifc_init(void);
extern "C" int ifc_up(const char *name);
extern "C" int ifc_down(const char *name);
int ThrottleController::runTcCmd(const char *cmd) {
char *buffer;
size_t len = strnlen(cmd, 255);
int res;
if (len == 255) {
ALOGE("tc command too long");
errno = E2BIG;
return -1;
}
asprintf(&buffer, "%s %s", TC_PATH, cmd);
res = system_nosh(buffer);
free(buffer);
return res;
}
int ThrottleController::setInterfaceThrottle(const char *iface, int rxKbps, int txKbps) {
char cmd[512];
char ifn[65];
int rc;
memset(ifn, 0, sizeof(ifn));
strncpy(ifn, iface, sizeof(ifn)-1);
if (txKbps == -1) {
reset(ifn);
return 0;
}
/*
*
* Target interface configuration
*
*/
/*
* Add root qdisc for the interface
*/
sprintf(cmd, "qdisc add dev %s root handle 1: htb default 1 r2q 1000", ifn);
if (runTcCmd(cmd)) {
ALOGE("Failed to add root qdisc (%s)", strerror(errno));
goto fail;
}
/*
* Add our egress throttling class
*/
sprintf(cmd, "class add dev %s parent 1: classid 1:1 htb rate %dkbit", ifn, txKbps);
if (runTcCmd(cmd)) {
ALOGE("Failed to add egress throttling class (%s)", strerror(errno));
goto fail;
}
/*
* Bring up the IFD device
*/
ifc_init();
if (ifc_up("ifb0")) {
ALOGE("Failed to up ifb0 (%s)", strerror(errno));
goto fail;
}
/*
* Add root qdisc for IFD
*/
sprintf(cmd, "qdisc add dev ifb0 root handle 1: htb default 1 r2q 1000");
if (runTcCmd(cmd)) {
ALOGE("Failed to add root ifb qdisc (%s)", strerror(errno));
goto fail;
}
/*
* Add our ingress throttling class
*/
sprintf(cmd, "class add dev ifb0 parent 1: classid 1:1 htb rate %dkbit", rxKbps);
if (runTcCmd(cmd)) {
ALOGE("Failed to add ingress throttling class (%s)", strerror(errno));
goto fail;
}
/*
* Add ingress qdisc for pkt redirection
*/
sprintf(cmd, "qdisc add dev %s ingress", ifn);
if (runTcCmd(cmd)) {
ALOGE("Failed to add ingress qdisc (%s)", strerror(errno));
goto fail;
}
/*
* Add filter to link <ifn> -> ifb0
*/
sprintf(cmd, "filter add dev %s parent ffff: protocol ip prio 10 u32 match "
"u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0", ifn);
if (runTcCmd(cmd)) {
ALOGE("Failed to add ifb filter (%s)", strerror(errno));
goto fail;
}
return 0;
fail:
reset(ifn);
return -1;
}
void ThrottleController::reset(const char *iface) {
char cmd[128];
sprintf(cmd, "qdisc del dev %s root", iface);
runTcCmd(cmd);
sprintf(cmd, "qdisc del dev %s ingress", iface);
runTcCmd(cmd);
runTcCmd("qdisc del dev ifb0 root");
}
int ThrottleController::getInterfaceRxThrottle(const char *iface, int *rx) {
*rx = 0;
return 0;
}
int ThrottleController::getInterfaceTxThrottle(const char *iface, int *tx) {
*tx = 0;
return 0;
}