Port the C from `bpf_num_possible_cpus()` over to safe Rust,
with proper error handling and unit tests to ensure that it
is giving the correct answers. Change usages to the new safe
function.
* The JavaScript RingBuffer structure updated correctly.
* Replaced the funnel graph with text - easier to read.
* Discovered that the current "parking_lot" could become unstable
under very heavy load, and only with "fat" LTO. Since it's
no longer recommended (recent change), removed it.
* Replaced the "lazy_static" macro suite with the newly recommended
"once_cell" system. Less code.
* Full source format.
* Update some dependency versions.
Step 1 of the network funnel
* network.json reader now tags throughput entries with their tree
location and parents to whom data should be applied.
* Data flows "up the tree", giving totals all the way up.
* Simple network map page for displaying the data while it's worked
on.
Rather than having lots of "cpu.replace("0x", "").str_radix(...)
calls around, move to a single, unit-tested function in lqos_utils
and use it repeatedly.
* Adds a new Rust program, `lqos_setup`.
* If no /etc/lqos.conf is found, prompts for interfaces and
creates a dual-interface XDP bridge setup.
* If no /opt/libreqos/src/ispConfig.py is found, prompts
for bandwidth and creates one (using the interfaces also)
* Same for ShapedDevices.csv and network.json
* If no webusers are found, prompts to make one.
* Adds build_dbpkg.sh
* Creates a new directory named `dist`
* Builds the Rust components in a portable mode.
* Creates a list of dependencies and DEBIAN directory
with control and postinst files.
* Handles PIP dependencies in postinst
* Calls the new `lqos_setup` program for final
configuration.
* Sets up the daemons in systemd and enables them.
In very brief testing, I had a working XDP bridge with
1 fake user and a total bandwidth limit configured and
working after running:
dpkg -i 1.4-1.dpkg
apt -f install
Could still use some tweaking.
ISSUE #52
* Added file locking commands to the Python/Rust library.
* When LibreQoS.py starts, it checks that /var/run/libreqos.lock
does not exist. If it does, it checks that it contains a PID
and that PID is not still running with a python process.
* If the lock file exists and is valid, execution aborts.
* If the lock file exists and is invalid, it is cleaned.
* Cleans the lock on termination.
ISSUE #209
Replace "anyhow" with "thiserror". Add logging for all errors,
and only allow pass-through for errors that have already been
converted to a local error type and reported.
structure.
* Creates FileWatcher, in lqos_utils.
* Removes "notify" dependency from other crates.
FileWatcher is designed to watch a file. If the file doesn't exist,
then an optional callback is called - and the watcher waits,
periodically checking to see if the file has appeared yet. When the
file appears, another optional callback is executed.
Once the file exists, a `notify` system is started (it uses Linux's
`inotify` system internally) for that file. When the file changes,
the process sleeps briefly and then executes an `on_change` callback.
Further messages are then suppressed for a short period to avoid
duplicates.
All uses of notify have been updated to use this system. Errors are
handled cleanly, per ISSUE #209.
ISSUE #209
Using the inode watcher on a file that doesn't exist fails, and
was previously failing silently! This would result in queue
mappings not updating when LibreQoS.py was executed - even though
the queueingStructure.json file became available.
* Replace "anyhow" with specific errors.
* Track and log each step of the file monitor process for
queueingStructure.json
* If the watcher cannot start because the file doesn't exist,
the watcher loop sleeps for 30 seconds at a time (to keep
load very low) and checks if the file exists yet. If it does,
it loads it and then commences watching.
file descriptor.
* Remove the Tokio timer system.
* Replace with Linux's timer fd system.
* Add a watchdog to alert if we've somehow overrun the timer.
* Queue timing is now provided by Linux "timer file descriptors"
instead of Tokio timers.
* Added an atomic bool to track "we're going faster than we should"
(it's true while executing), skip cycles if we ran out of time and
issue a warning.
* Queue tracking is no longer async, but is locked to its very own
thread.
* Queue watcher is now more verbose about any issues it encounters.
* Queue structures with children will now correctly track all the
children, avoiding the blank queue data issue.
Modern linuxes add fields all the time. On a kernel upgrade we
shouldn't crash just because there's a new json field.
Also there are some further optimizations to represent the kernel
structures themselves. Some fields can overflow which would lead
to some surprizing behaviors in polling the json over time.
FIXME - always check for overflow elsewhere, in packets, overlimits
etc. Could that be a trait?
On systems that support it, `jemallocator` will replace the default
allocator for `lqosd` and `lqos_node_manager`. The Jem allocator
is a LOT more friendly to Rust's preferred vector allocation patterns,
and actually cares about your cache.
Enable "fat" Link-Time Optimization. This slows down compilation a lot,
but results in smaller binaries and permits the LLVM optimizer to
cross crate boundaries when inlining, optimizing tail calls and a
few other optimizations.
The file locking is "smart": it checks to see if a lock is
valid before refusing to run (and updates the lock if
it can run anyway).
The locking mechanism will fail if you manually create
the lock file and dump random data into it that doesn't
readily convert to an i32.
Affects issue #54 and issue #52
* Add a new structure `FileLock` to `lqosd`.
* FileLock first checks /run/lqos/lqosd.lock. If it exists,
it opens it and attempts to read a PID from it. If that PID
is running and the associated name includes "lqosd", the
FileLock returns an error.
* If no lock exists, then a file is created in
/run/lqos/lqosd.lock containing the running PID.
* Includes Drop and signal termination support.