Procd trigger types documentation

The procd helper functions (/lib/functions/procd.sh) offer a range of triggers and yet finding documentation about them eludes my DDG-foo.

Dumping the procd service repository (ubus -v call service list '{"verbose": true}'|grep -A5 trigger) also yields little information beyond leveraging the config.change trigger (which begs the question - what other config events are available?)

Thank-you in advance for any links.

Do you mean hotplug events?

I’m thinking the OP is looking for pretty well none existent documentation for these multiple procd_add_*_trigger() helpers

Procd Triggers

_procd_open_trigger() {
let '_procd_trigger_open = _procd_trigger_open + 1'
[ "$_procd_trigger_open" -gt 1 ] && return
json_add_array "triggers"
_procd_close_trigger() {
let '_procd_trigger_open = _procd_trigger_open - 1'
[ "$_procd_trigger_open" -lt 1 ] || return
json_select triggers
_procd_add_interface_trigger() {
_procd_add_reload_interface_trigger() {
_procd_open_trigger
_procd_add_interface_trigger "interface.*" $1 /etc/init.d/$name reload
_procd_close_trigger
_procd_add_data_trigger() {
_procd_add_reload_data_trigger() {
_procd_open_trigger
_procd_add_data_trigger $1 /etc/init.d/$name reload
_procd_close_trigger
_procd_add_config_trigger() {
_procd_add_mount_trigger() {
_procd_add_action_mount_trigger() {
_procd_open_trigger
_procd_add_mount_trigger mount.add $action "$mountpoints"
_procd_close_trigger
_procd_add_restart_mount_trigger() {
_procd_add_action_mount_trigger restart "$@"
_procd_add_reload_mount_trigger() {
_procd_add_action_mount_trigger reload "$@"
_procd_add_raw_trigger() {
_procd_add_reload_trigger() {
_procd_open_trigger
_procd_add_config_trigger "config.change" "$file" /etc/init.d/$name reload
_procd_close_trigger
procd_add_raw_trigger
procd_add_config_trigger
procd_add_interface_trigger
procd_add_mount_trigger
procd_add_reload_trigger
procd_add_reload_data_trigger
procd_add_reload_interface_trigger
procd_add_action_mount_trigger
procd_add_reload_mount_trigger
procd_add_restart_mount_trigger
procd_open_trigger
procd_close_trigger \

Square one.

1 Like

I have found this in my search

The hotplug framework offers the possibility to ‘unmask’ events that trigger a script (under the supervision of procd), my answer is ‘no’. The request concerns scripts that are destined for /etc/initd

1 Like

Right in one (but BTDT).

Time to read the C source?

@dave14305 - check, to you

The article offers generalities and little more.

Time to read the C code?

Likely. I’m not the guy. I got by with https://github.com/search?q=repo%3Aopenwrt%2Fpackages+procd_add_&type=code and head -41 /lib/functions/procd.sh .

1 Like

In ancient email thread, I believe on infradead.org, between ‘dirk’ and ‘jo’, ‘jo’ explained that the procd interface trigger ‘interface.*’ is equivalent to listening for ‘interface.down’ + ‘interface.up’ events.

After replacing ‘interface.*’ with ‘interface.down’ and adding a second trigger for ‘interface.up’,

"triggers": [
		[
				"interface.up",
				[
						"if",
						[
								"eq",
								"interface",
								"lan"
						],
						[
								"run_script",
								"/etc/init.d/https-dns-proxy",
								"reload",
								"up"
						]
				],
				1000
		],
		[
				"interface.down",
				[
						"if",
						[
								"eq",
								"interface",
								"lan"
						],
						[
								"run_script",
								"/etc/init.d/https-dns-proxy",
								"stop",
								"down"
						]
				],
				1000
		],

procd does invoke the ‘interface.down’ trigger when the interface is set down (root@pWPW10-1:~# ubus -v call network.interface.lan down) but not on ‘interface.up’ events (root@pWPW10-1:~# ubus -v call network.interface.lan up).

This is confirmed by monitoring the ubus ‘invoke’ method - root@pWPW10-1:~# ubus -m invoke monitor >/tmp/lan_events.txt.

root@pWPW10-1:~# grep -e http /tmp/lan_events.txt
<- 03d05ccd #8ac6a30f invoke: {"objid":-1966693617,"method":"delete","data":{"name":"https-dns-proxy","instance":"down"}}
-> 820aa895 #03d05ccd invoke: {"objid":-1966693617,"method":"delete","data":{"name":"https-dns-proxy","instance":"down"},"user":"root","group":"root"}

ubus id invoking procd {“objid”:1,
} for both events -

<- 8639c9da #00000001         invoke: {"objid":1,"method":"send","data":{"id":"network.interface","data":{"action":"ifdown","interface":"lan"}}}
-> 820aa895 #8639c9da         invoke: {"objid":1116470396,"method":"interface.down","data":{"interface":"lan","up":false,"pending":false,"available":true,"autostart":false,"dynamic":false,"proto":"dhcp","device":"br-lan","data":{"dhcpserver":"192.168.2.249","hostname":"pWPW10-1","leasetime":14400}},"no_reply":true,"user":"root","group":"root"}

<- 8639c9da #00000001         invoke: {"objid":1,"method":"send","data":{"id":"network.interface","data":{"action":"ifdown","interface":"lan"}}}
-> 820aa895 #8639c9da         invoke: {"objid":1116470396,"method":"interface.down","data":{"interface":"lan","up":false,"pending":false,"available":true,"autostart":false,"dynamic":false,"proto":"dhcp","device":"br-lan","data":{"dhcpserver":"192.168.2.249","hostname":"pWPW10-1","leasetime":14400}},"no_reply":true,"user":"root","group":"root"}

<- 30e4e364 #00000001         invoke: {"objid":1,"method":"register","data":{"object":1225318724,"pattern":"ubus.object.add"}}
<- 1077c4ad #67703481         invoke: {"objid":1735406721,"method":"config_set","data":{"config":
,"phy":"phy0","radio":-1,"num_global_macaddr":1,"macaddr_base":"","defer":true}}

<- cafea0f7 #00000001         invoke: {"objid":1,"method":"register","data":{"object":541236989,"pattern":"ubus.object.add"}}
<- 672ac31e #67703481         invoke: {"objid":1735406721,"method":"config_set","data":{"config":
,"phy":"phy1","radio":-1,"num_global_macaddr":1,"macaddr_base":"","defer":true}}

<- 2a66c1d2 #00000001         invoke: {"objid":1,"method":"register","data":{"object":-583809852,"pattern":"ubus.object.add"}}
<- e9823bd4 #67703481         invoke: {"objid":1735406721,"method":"config_set","data":{"config":
,"phy":"phy1","radio":-1,"num_global_macaddr":1,"macaddr_base":"","defer":true}}

<- 8639c9da #00000001         invoke: {"objid":1,"method":"send","data":{"id":"network.interface","data":{"action":"ifup","interface":"lan"}}}
-> 820aa895 #8639c9da         invoke: {"objid":1116470396,"method":"interface.update","data":{"interface":"lan","up":true,"pending":false,"available":true,"autostart":true,"dynamic":false,"uptime":0,"l3_device":"br-lan","proto":"dhcp","device":"br-lan","updated":["addresses","routes","data"],"metric":0,"dns_metric":0,"delegation":false,"ipv4-address":[{"address":"192.168.2.31","mask":24}],"ipv6-address":
,"ipv6-prefix":
,"ipv6-prefix-assignment":
,"route":[{"target":"0.0.0.0","mask":0,"nexthop":"192.168.2.254","source":"192.168.2.31/32"}],"dns-server":["192.168.2.249"],"dns-search":["wpw10.lan"],"neighbors":
,"inactive":{"ipv4-address":
,"ipv6-address":
,"route":
,"dns-server":
,"dns-search":
,"neighbors":
},"data":{"dhcpserver":"192.168.2.249","hostname":"pWPW10-1","leasetime":14400}},"no_reply":true,"user":"root","group":"root"}
<- 11ca811c #00000001         invoke: {"objid":1,"method":"register","data":{"object":353147778,"pattern":"ubus.object.add"}}
<- 8b716252 #d62d142e         invoke: {"objid":-701688786,"method":"config_set","data":{"phy":"phy1","radio":-1,"config":"/var/run/hostapd-phy1.conf","prev_config":"/var/run/hostapd-phy1.conf.prev"}}

<- 68bc0640 #00000001         invoke: {"objid":1,"method":"register","data":{"object":96395886,"pattern":"ubus.object.add"}}
<- bece1239 #67703481         invoke: {"objid":1735406721,"method":"phy_status","data":{"phy":"phy1","radio":-1}}

<- 264335de #00000001         invoke: {"objid":1,"method":"register","data":{"object":1032773891,"pattern":"ubus.object.add"}}
<- 2e5d0475 #d62d142e         invoke: {"objid":-701688786,"method":"config_set","data":{"phy":"phy0","radio":-1,"config":"/var/run/hostapd-phy0.conf","prev_config":"/var/run/hostapd-phy0.conf.prev"}}

but procd does not trigger its listeners.

Where / what is the appropriate channel / method for reporting this behaviour?

1 Like

Create an issue on https://github.com/openwrt/openwrt

Given the paucity of documentation, much experimentation was conducted.
Thus, the network topology 'scenario' is -

  • several OWRT-based routers operating in AP-mode (no WAN interfaces)
  • one AP servicing IPV4 DHCP requests via DNSMASQ
  • vDSL modem servicing IPV6 DHCP requests
  • package https-dns-proxy (HDP) installed in all APs
  • implemented 'load balancing' functionality in HDP (IPV6 link local addresses of all APs are programmatically added to the DNSMASQ list of upstream DNSes)

NOTES:

  1. the function network_find_wan() selects the first (or second in the case of the network_find_wan6()) value from an ordered list of interfaces in an up state
  2. in the absence of a WAN(6) interface (AP-mode), the function call returns a LAN interface
  3. upon booting OWRT, a LAN interface is (almost) immediately available, an up event posted and soon set to a down state to facilitate its addition to any L3 BRIDGE interface that may (almost always) be configured (far earlier than the launching of an init.d (HDP) script and it setting a procd_add_interface_trigger() for any up events)
  4. no / slow WAN (or delayed LAN) interface availability is managed with a catchall procd_add_raw_trigger() function in the (HDP) init.d script service_triggers() function for any network interface that appears in ubus, notified by netifd, in the 'up' state and returns to procd
  5. netifd sets interfaces associated with an L3 device to their up state and posts interface.update events to ubus (not interface.up events)
  6. 'subscribing' to ubus traffic associated with the LAN interface (for HDP), an interface.update event was observed when 'state cycling' the LAN interface
  7. adding a call to procd_add_interface_trigger() for interface.update and launching a call to HDP's init.d reload() function (internally calling stop_service() and start_service()) eliminates the classic network interface race condition