/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you 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.
*/
package io.netty.transport.udt.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Introduce traffic control, such as transfer latency.
* <p>
* requires sudo setup for /sbin/tc under current account
* <p>
* see http://www.davidverhasselt.com/2008/01/27/passwordless-sudo/
*/
public final class TrafficControl {
private static final Logger log = LoggerFactory
.getLogger(TrafficControl.class.getName());
private TrafficControl() {
}
private static final String TC_DELAY = "sudo tc qdisc add dev %s root netem delay %sms limit %s";
private static final String TC_RESET = "sudo tc qdisc del dev %s root";
/**
* verify if traffic control is available
*/
public static boolean isAvailable() {
try {
final int millis = 100;
final int margin = 20;
delay(0);
final long time1 = UnitHelp.ping("localhost");
delay(millis);
final long time2 = UnitHelp.ping("localhost");
delay(0);
final long time3 = UnitHelp.ping("localhost");
return time2 >= time1 + millis - margin
&& time2 >= time3 + millis - margin;
} catch (final Throwable e) {
log.debug("", e);
return false;
}
}
/**
* Introduce round-trip delay on local host
* @param time - delay in milliseconds; use zero to remove delay.
*/
public static void delay(final int time) throws Exception {
if (time < 0) {
throw new IllegalArgumentException("negative latency");
}
final int delay = time / 2;
if (delay == 0) {
UnitHelp.process(String.format(TC_RESET, "lo"));
} else {
/** extend packet buffer queue to avoid packet loss due to latency */
final int limit = 1024 * 1024;
UnitHelp.process(String.format(TC_RESET, "lo"));
UnitHelp.process(String.format(TC_DELAY, "lo", delay, limit));
}
}
}