Hello everyone,
Small update:
I was kindly asked to enhance the
rdevd daemon, so I spent some spare time (between the renovation works in my apartment and other activities), working on the code. The following changes have been made so far in the '
master' branch.
* The multi threading tokio mode was removed (Initially, I planned parallel processing). Now, tokio crate runs in
single threaded mode. This approach allows to simultaneously broadcast the packet to connected clients and perform parsing and command exec. I did not spent much time on measuring the performance of the code, but it seems it is not slower than original
devd(8)(). The
async approach was picked because it reduces the "complications" working with
kqueue(9)() and poll. Even, with small overhead - calling the local scheduler quite often, it is still more convenient because tokio crate does everything.
Since the "tokio" now runs in single threaded mode the memory footprint has decreased:
Code:
PID COMM RESOURCE VALUE
7551 rdevd user time 00:00:00.008964
7551 rdevd system time 00:00:00.017928
7551 rdevd maximum RSS 8648 KB
7551 rdevd integral shared memory 6804 KB
7551 rdevd integral unshared data 12 KB
7551 rdevd integral unshared stack 384 KB
7551 rdevd page reclaims 673
7551 rdevd page faults 0
7551 rdevd swaps 0
7551 rdevd block reads 0
7551 rdevd block writes 3
7551 rdevd messages sent 256
7551 rdevd messages received 10
7551 rdevd signals received 10
7551 rdevd voluntary context switches 850
7551 rdevd involuntary context switches 1
Code:
devd:
PID COMM RESOURCE VALUE
1778 devd user time 00:00:00.007828
1778 devd system time 00:00:00.014259
1778 devd maximum RSS 3680 KB
1778 devd integral shared memory 72 KB
1778 devd integral unshared data 16 KB
1778 devd integral unshared stack 256 KB
1778 devd page reclaims 91
1778 devd page faults 0
1778 devd swaps 0
1778 devd block reads 0
1778 devd block writes 0
1778 devd messages sent 1960
1778 devd messages received 0
1778 devd signals received 0
1778 devd voluntary context switches 428
1778 devd involuntary context switches 0
* The rdevd
daemon's code and
utilities code are now two separate binaries which are linked to librdevd (crate). This allows to reduce the repeated code. Now, the rules can be tested using `rdevdctl`. The '-h' flag prints hints for each sub-command.
* A daemon
self restart functionality was implemented. Now, by receiving
SIG_USR1, daemon should: stop all tokio tasks, exit from async mode (because tokio does not like fork), fork itself, detach from parent and wait until parent quits. Then, it retrieves the exec path from
sysctl(9)()
and calls exec without return. This mode is usefull when it is required to preserve the connections from clients. The daemon will not close the connections. Instead, it will downgrade all connections (UnixSeqpkt and UnixStream) into OwnedFD, remove CLOEXEC flag and serialize this data into the JSON text and store in the environment, so the new process spawned by previous should find the environment variable and restore the FD into UnixSeqpkt or UnixStream and continue. A clients (connected on broadcast) should not notice that rdevd daemon has restarted..
* A syslog-rs crate was updated and received some more features. Some unsafe code was replaced. Rdevd daemon attempts to init the syslog only during async mode (when tokio initialized). A duplicates of sync and async code in base were removed. If daemon's output is
tapped, the syslog-rs (Rust) crate is now capable to write into the local file instead of syslog socket. It creates additional thread which prints output to file.
* A devctl message buffer is now allocated using shared-buffer-rs crate. This crate allows to obtain an (single) exclusive access to inner buffer space and shared access to its content in multiple tasks or threads (one access type at a time!). This allows to avoid
memcpy when it is required to broadcast the same data to clients and to avoid dealing with Arc'ing the buffer. This crate is lock-less and is build using atomics and operations ordering. If CPU does not support ordering
Acquire and
Release operations, it will not work. If buffer is of type "drop in place" it will be de-allocated as soon as there are no base references, read or write active references. If, one day a multitasking will be added (parallel processing of events) this crate can manage allocations of buffers. (The crate was taken from dusty shelf and was not properly tested. A race conditions probably may happen in multi-threading mode, but crossbeam queues are built on the same approach and it works).
* Parsing of the devctl messages no longer modifies the message.
* A VarList is now holds the variables payload in Cow<> (copy-on-write) borrows the reference instead of creating new String.
* A config is now wrapped into Arc and RwLock. This allows to modify rules on the air!
* Each rule is stored with unique ID.
* A remote control socket based on SOCK_SEQPACKET was added which allows to perform the following operations:
1) load rule immediately (a rule must be in format was it is in the file, (not tested)
2) remove rule (by ID, ID is in hex format, but I decided to postpone standartization of both load and remove operations)
3) list rules (all, attach, detach, notify, nomatch)
4) display status (daemon write back the same info as for SIG_INFO)
5) restart
Amount of simultaneous users can be controlled though the program's arguments.
* The clients.rs was re-implemented.
* The remote control socket should be enabled using program's argument flags. See '-h' or rdevd_daemon.in. By default it is turned off.
All changes were poorly tested and now the testing is in process by the interested party. The version in the repository is different from the private version, but all important changes are there.
I have not got the idea behind the executing of the actions through the shell, which was ported directly from the original
devd i.e /bin/sh -c "<cmd>". Why not to execute the binaries directly? But, I have my own vision and plans, so this is up to community.
Since 14.2, if you want to test rdevd, before placing
devd_enabled="NO" you should modify the devd's RC script and comment the line where devctl is disabled in sysctl, otherwise it will not start because it appeared that it is not possible to re-enable
devctl.
One known issue is the message about "Waiting 30s for the default route interface" which appears right after rdevd starts. Probably, this is because the native devd starts earlier or there is a wrong rule ordering in vector or whatever.
I am not planning to support the rdevd code officially. While I am still running FreeBSD instances, me personally and some other people interested in this project, but everything changes so fast and dramatically, that I am afraid that there is a possibility that the tomorrow may not even come.