I think he means “order” as in “move around”. A queue may have a different effect based on whether it comes first or second in the list.
There’s no built in way of sorting items, but you could implement one yourself. Once you have the proper sorting order, you can do the moves by looping over the IDs, and call “move” for each. Calling “move” without a second argument puts it at the bottom of the list, so the end result is that your actual list matches the sorted one.
I’m not entirely sure about how the implementation would go though… I mean, because I’m lazy, I’d just use the API to get all queues, extract the IPs and IDs into an array (with the IP as an array key), do the sort with a single function call (present in most languages; certainly in PHP), and then loop over the array, and call “move” with the associated ID.
Considering that queues have masks and interfaces, and that multiple targets may be present in a single queue, this turned out to be a bit more complicated than I thought, but still relatively easy.
Here’s using my API client:
<?php
use PEAR2\Net\RouterOS;
require_once 'PEAR2_Net_RouterOS-1.0.0b5.phar';
$util = new RouterOS\Util($client = new RouterOS\Client('192.168.88.1', 'admin', 'password'));
$util->setMenu('/queue simple');
$queues = $util->getAll(array('.proplist' => '.id,target'))->orderBy(
array(
'target' => function ($a, $b) {
//If the queues compared contain multiple targets, sort based on the first ones
if (strpos($a, ',') !== false) {
$a = explode(',', $a, 1);
$a = $a[0];
}
if (strpos($b, ',') !== false) {
$b = explode(',', $b, 1);
$b = $b[0];
}
//If there are no mask parts, this is an interface queue - sort alphabetically
if (strpos($a, '/') === false && strpos($b, '/') === false) {
return strcmp($a, $b);
}
//If one of the queues is an interface queue, it goes before the IP one
if (strpos($a, '/') === false || strpos($b, '/') === false) {
return strpos($a, '/') === false ? -1 : 1;
}
//Separate the IP/Mask
$a = explode('/', $a, 2);
$b = explode('/', $b, 2);
//Convert to integer representation
$ipA = ip2long($a[0]);
$ipB = ip2long($b[0]);
$maskA = (int)$a[1];
$maskB = (int)$b[1];
//Get network address
$netA = $ipA >> $maskA;
$netB = $ipB >> $maskB;
//Sort based on the network address; Bigger mask = smaller network = later in the list
if ($netA < $netB) {
return 1;
} elseif ($netA > $netB) {
return -1;
} else {//Sort based on the address within the network
$a = ($netA << $maskA) ^ $ipA;
$b = ($netB << $maskB) ^ $ipB;
return $a < $b ? -1 : (int) $a > $b;
}
}
)
);
$moveRequest = new RouterOS\Request('/queue simple move');
foreach ($queues as $queue) {
$client->sendSync($moveRequest->setArgument('numbers', $queue->getProperty('.id')));
}
(Side note: I found a bug with my $util->move() implementation… doesn’t support NULL destination… That’s why I’m using $client for the move part; I’ll be sure to fix this soon, at which point $util->move($queue(‘.id’), null) would be a thing, equivalent of $util->move($queue(‘.id’)) in fact)