]> git.basschouten.com Git - pithrottler.git/commitdiff
Add ability to limit outbound traffic and change bandwidth sliders to be non-linear.
authorBas Schouten <bas@basschouten.com>
Tue, 7 May 2024 12:11:20 +0000 (13:11 +0100)
committerBas Schouten <bas@basschouten.com>
Tue, 7 May 2024 12:11:20 +0000 (13:11 +0100)
html/index.html
html/pithrottler.css
html/pithrottler.js
pithrottler.js

index ff3a31704e28be77756a9f663186e87b4ed6530f..7758feb9419382f9d10e992fdd41b8fb2d791612 100644 (file)
   <h3>PiThrottler Control</h3>
   <select id="preset" onchange="changePreset();">
   </select>
-  <div class="slidecontainer">
-    Latency<br />
-    <input type="range" min="0" max="1000" style="width:400px;" value="0" class="slider" id="latencyRange" oninput="document.getElementById('latency').innerHTML = this.value;"> <span id="latency">0</span> ms
-  </div>
-  <div class="slidecontainer">
-    Packet Loss<br />
-    <input type="range" min="0" max="95" style="width:400px;" value="0" class="slider" id="plossRange" oninput="document.getElementById('ploss').innerHTML = this.value;"> <span id="ploss">0</span> %
-  </div>
-  <div class="slidecontainer">
-    Throughput Limitation (0 for unlimited)<br />
-    <input type="range" min="0" max="20000" style="width:400px;" value="0" class="slider" id="tpRange" oninput="document.getElementById('tp').innerHTML = this.value;"> <span id="tp">0</span> kb/s
-  </div>
+  <table>
+    <tr><th></th><th>Inbound</th><th>Outbound</th></tr>
+    <tr><td>Latency</td>
+      <td class="slidecontainer">
+        <input type="range" min="0" max="1000" value="0" class="slider" id="latencyinRange" oninput="document.getElementById('latencyin').innerHTML = this.value;"> <span id="latencyin">0</span> ms
+      </td>
+      <td class="slidecontainer">
+        <input type="range" min="0" max="1000" value="0" class="slider" id="latencyoutRange" oninput="document.getElementById('latencyout').innerHTML = this.value;"> <span id="latencyout">0</span> ms
+      </td>
+    </tr>
+    <tr><td>Packet Loss</td>
+      <td class="slidecontainer">
+        <input type="range" min="0" max="95" value="0" class="slider" id="plossinRange" oninput="document.getElementById('plossin').innerHTML = this.value;"> <span id="plossin">0</span> %
+      </td>
+      <td class="slidecontainer">
+        <input type="range" min="0" max="95" value="0" class="slider" id="plossoutRange" oninput="document.getElementById('plossout').innerHTML = this.value;"> <span id="plossout">0</span> %
+      </td>
+    </tr>
+    <tr><td>Throughput Limit (0=unlimited)</td>
+      <td class="slidecontainer">
+        <input type="range" min="0" max="200" value="0" class="slider" id="tpdownRange" oninput="document.getElementById('tpdown').innerHTML = Math.pow(this.value, 2);"> <span id="tpdown">0</span> kb/s
+      </td>
+      <td class="slidecontainer">
+        <input type="range" min="0" max="200" value="0" class="slider" id="tpupRange" oninput="document.getElementById('tpup').innerHTML = Math.pow(this.value, 2);"> <span id="tpup">0</span> kb/s
+      </td>
+    </tr>
+  </table>
+  <br/>
+  <br/>
   <button onclick="saveSettings();">Save Settings</button>
   <button onclick="checkForUpdates();">Check for Updates</button>
   <div id="updateStatus"></div>
index ce0aabefc82dfa7f2cf68d1c4ad8e22e4377cf17..31d89bb2320025c98cbb40969e4d088901b8f8d5 100644 (file)
@@ -8,6 +8,29 @@ body {
   font-family:Arial;
 }
 
+table {
+  margin:auto;
+  text-align:left;
+}
+
+th {
+  text-align:center;
+}
+
+tr {
+  height:30px;
+}
+
+td:first-child {
+  text-align:right;
+}
+
+td {
+  padding-left:5px;
+  padding-right:5px;
+  min-width:270px;
+}
+
 select, button {
   width: 160px;
   height: 30px;
@@ -18,6 +41,10 @@ select, button {
   color: #1c87c9;
 }
 
+.slider {
+  width:180px;
+}
+
 select:hover, button:hover {
   background-color:#303030;
 }
index 4f03904f35e2beeb5cfde8b60039022c33138b3d..5d55a9e5bccca536cfc220b0a7058bf3395454c9 100644 (file)
@@ -1,37 +1,58 @@
 const presets = {
   Unlimited: {
     label: "Unlimited",
-    latency: 0,
-    ploss: 0,
-    throughput: 0
+    latencyin: 0,
+    plossin: 0,
+    throughputdown: 0,
+    latencyout: 0,
+    plossout: 0,
+    throughputup: 0
   },
   F4G: {
     label: "4G Fast",
-    latency: 30,
-    ploss: 0,
-    throughput: 20000
+    latencyin: 30,
+    plossin: 0,
+    throughputdown: 20000,
+    latencyout: 30,
+    plossout: 0,
+    throughputup: 20000
   },
   S4G: {
     label: "4G Slow",
-    latency: 150,
-    ploss: 1,
-    throughput: 10000
+    latencyin: 75,
+    plossin: 1,
+    throughputdown: 10000,
+    latencyout: 75,
+    plossout: 1,
+    throughputup: 10000
   },
   F3G: {
     label: "3G Fast",
-    latency: 110,
-    ploss: 0,
-    throughput: 5000
+    latencyin: 55,
+    plossin: 0,
+    throughputdown: 5000,
+    latencyout: 55,
+    plossout: 0,
+    throughputup: 5000
   },
   S3G: {
     label: "3G Slow",
-    latency: 200,
-    ploss: 3,
-    throughput: 1000
+    latencyin: 100,
+    plossin: 3,
+    throughputdown: 1000,
+    latencyout: 100,
+    plossout: 3,
+    throughputup: 1000
   }
 };
 function saveSettings() {
-  fetch("/set?latency=" + document.getElementById("latencyRange").value + "&ploss=" + document.getElementById("plossRange").value + "&throughput=" + document.getElementById("tpRange").value);
+  fetch("/set?latencyin=" +
+    document.getElementById("latencyinRange").value + "&latencyout=" +
+    document.getElementById("latencyoutRange").value + "&plossin=" +
+    document.getElementById("plossinRange").value + "&plossout=" +
+    document.getElementById("plossoutRange").value + "&throughputdown=" +
+    Math.pow(document.getElementById("tpdownRange").value, 2) + "&throughputup=" +
+    Math.pow(document.getElementById("tpupRange").value, 2));
 }
 
 async function checkForUpdates() {
@@ -61,10 +82,16 @@ function loadPresets() {
 
 function changePreset() {
   var preset = document.getElementById("preset").value;
-  document.getElementById("latencyRange").value = presets[preset].latency;
-  document.getElementById("latency").innerHTML = presets[preset].latency;
-  document.getElementById("plossRange").value = presets[preset].ploss;
-  document.getElementById("ploss").innerHTML = presets[preset].ploss;
-  document.getElementById("tpRange").value = presets[preset].throughput;
-  document.getElementById("tp").innerHTML = presets[preset].throughput;
+  document.getElementById("latencyinRange").value = presets[preset].latencyin;
+  document.getElementById("latencyin").innerHTML = presets[preset].latencyin;
+  document.getElementById("plossinRange").value = presets[preset].plossin;
+  document.getElementById("plossin").innerHTML = presets[preset].plossin;
+  document.getElementById("tpdownRange").value = Math.sqrt(presets[preset].throughputdown);
+  document.getElementById("tpdown").innerHTML = presets[preset].throughputdown;
+  document.getElementById("latencyoutRange").value = presets[preset].latencyout;
+  document.getElementById("latencyout").innerHTML = presets[preset].latencyout;
+  document.getElementById("plossoutRange").value = presets[preset].plossout;
+  document.getElementById("plossout").innerHTML = presets[preset].plossout;
+  document.getElementById("tpupRange").value = Math.sqrt(presets[preset].throughputup);
+  document.getElementById("tpup").innerHTML = presets[preset].throughputup;
 }
\ No newline at end of file
index 0890e13a86b476572b9c4eafde8a66e7028ed392..fcb68e4162670d88121aaf14b5ab1f313404880a 100644 (file)
@@ -41,56 +41,96 @@ const app = (req, res) => {
   if (req.url.startsWith("/set")) {
     let searchParams = new URL("http://localhost:2121" + req.url).searchParams;
 
-    var latency = searchParams.get("latency");
-    var ploss = searchParams.get("ploss");
-    var throughput = searchParams.get("throughput");
-
-    if (!latency) {
-      latency = 0;
+    var latencyin = searchParams.get("latencyin");
+    var latencyout = searchParams.get("latencyout");
+    var plossin = searchParams.get("plossin");
+    var plossout = searchParams.get("plossout");
+    var throughputdown = searchParams.get("throughputdown");
+    var throughputup = searchParams.get("throughputup");
+
+    if (!latencyin) {
+      latencyin = 0;
+    }
+    if (!latencyout) {
+      latencyout = 0;
+    }
+    if (!plossin) {
+      plossin = 0;
     }
-    if (!ploss) {
-      ploss = 0;
+    if (!plossout) {
+      plossout = 0;
     }
-    if (!throughput) {
-      throughput = 0;
+    if (!throughputdown) {
+      throughputdown = 0;
+    }
+    if (!throughputup) {
+      throughputup = 0;
     }
 
     res.statusCode = 200;
     res.setHeader('Content-Type', 'text/plain');
     res.setHeader('Access-Control-Allow-Origin', '*');
-    res.end("Setting parameters, latency: " + latency + " ms, packet loss: " + ploss + "%, Throughput: " + throughput + " kbit/s");
+    res.end("Setting parameters, latency in: " + latencyin + " ms, out: " + latencyout + " ms, packet loss in: " + plossin + "%, out: " + plossout + "%, Throughput in: " + throughputdown + " kbit/s, out: " + throughputup);
 
     exec("sudo tc qdisc del dev wlan0 root");
     exec("sudo tc qdisc del dev wlan0 root");
+    exec("sudo tc qdisc del dev eth0 root");
+
+    let currentParentIn = "root";
+    let currentParentOut = "root";
 
-    if (latency > 0 || ploss > 0) {
+    if (latencyin > 0 || plossin > 0) {
       let command = "sudo tc qdisc add dev wlan0 root handle 30: netem";
 
-      if (latency > 0) {
-        command += " delay " + latency + "ms";
+      if (latencyin > 0) {
+        command += " delay " + latencyin + "ms";
       }
-      if (ploss > 0) {
-        command += " loss " + ploss + "%";
+      if (plossin > 0) {
+        command += " loss " + plossin + "%";
       }
 
       exec(command);
-      console.log("Setting lattency and packet loss");
+      console.log("Setting inbound lattency and packet loss");
+
+      currentParentIn = "parent 30:1";
     }
 
-    if (throughput > 0) {
-      let command = "sudo tc qdisc add dev wlan0 ";
+    if (latencyout > 0 || plossout > 0) {
+      let command = "sudo tc qdisc add dev eth0 root handle 50: netem";
 
-      if (latency > 0 || ploss > 0) {
-        command += "parent 30:1";
-      } else {
-        command += "root";
+      if (latencyout > 0) {
+        command += " delay " + latencyout + "ms";
+      }
+      if (plossout > 0) {
+        command += " loss " + plossout + "%";
       }
 
-      command += " tbf rate " + throughput + "kbit burst 32kbit latency 500ms";
       exec(command);
-      console.log("Setting bandwidth limitation");
+      console.log("Setting outbound latency and packet loss");
+
+      currentParentOut = "parent 50:1";
     }
-    
+
+    if (throughputdown > 0) {
+      let command = "sudo tc qdisc add dev wlan0 " + currentParentIn + " handle 40:";
+
+      currentParentIn = "parent 40:1";
+
+      command += " tbf rate " + throughputdown + "kbit burst 32kbit latency 500ms";
+      exec(command);
+      console.log("Setting down bandwidth limitation");
+    }
+
+    if (throughputup > 0) {
+      let command = "sudo tc qdisc add dev eth0 " + currentParentOut + " handle 60:";
+
+      currentParentOut = "parent 60:1";
+
+      command += " tbf rate " + throughputup + "kbit burst 32kbit latency 500ms";
+      exec(command);
+      console.log("Setting up bandwidth limitation");
+    }
+
     return;
   }