-
Notifications
You must be signed in to change notification settings - Fork 26
/
tc.js
125 lines (116 loc) · 2.27 KB
/
tc.js
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
'use strict';
const execa = require('execa');
const sudo = require('./sudo');
async function getDefaultInterface() {
const result = await execa(
"sudo route | grep '^default' | grep -o '[^ ]*$'",
{ shell: true }
);
return result.stdout;
}
async function modProbe() {
try {
await sudo('modprobe', 'ifb');
} catch (e) {
// we are probably in a Docker env
// let us hope that the host is Linux
try {
await sudo('ip', 'link', 'add', 'ifb0', 'type', 'ifb');
} catch (e) {
// If we already setup ifb in a previous run, this will fail
}
}
}
async function setup(defaultInterface) {
await sudo('ip', 'link', 'set', 'dev', 'ifb0', 'up');
await sudo('tc', 'qdisc', 'add', 'dev', defaultInterface, 'ingress');
await sudo(
'tc',
'filter',
'add',
'dev',
defaultInterface,
'parent',
'ffff:',
'protocol',
'ip',
'u32',
'match',
'u32',
'0',
'0',
'flowid',
'1:1',
'action',
'mirred',
'egress',
'redirect',
'dev',
'ifb0'
);
}
async function setLimits(up, down, halfWayRTT, iFace) {
await sudo(
'tc',
'qdisc',
'add',
'dev',
'ifb0',
'root',
'handle',
'1:0',
'netem',
'delay',
`${halfWayRTT}ms`,
'rate',
`${down}kbit`
);
await sudo(
'tc',
'qdisc',
'add',
'dev',
iFace,
'root',
'handle',
'1:0',
'netem',
'delay',
`${halfWayRTT}ms`,
'rate',
`${up}kbit`
);
}
module.exports = {
async start(up, down, rtt) {
const halfWayRTT = rtt / 2;
try {
await this.stop();
} catch (e) {
// ignore
}
const iFace = await getDefaultInterface();
await modProbe();
await setup(iFace);
await setLimits(up, down, halfWayRTT, iFace);
},
async stop() {
const iFace = await getDefaultInterface();
try {
try {
await sudo('tc', 'qdisc', 'del', 'dev', iFace, 'root');
await sudo('tc', 'qdisc', 'del', 'dev', iFace, 'ingress');
} catch (e) {
// make sure we try to remove the ingress
sudo('tc', 'qdisc', 'del', 'dev', iFace, 'ingress');
}
} catch (e) {
// ignore
}
try {
await sudo('tc', 'qdisc', 'del', 'dev', 'ifb0', 'root');
} catch (e) {
// do nada
}
}
};