Compare commits

..

157 Commits

Author SHA1 Message Date
jaspreetsachdev
a70dda4a8e Merge pull request #453 from Telecominfraproject/main
Merge Main to release/v2.6.0
2022-06-09 15:43:49 -04:00
John Crispin
a01f1add81 ipq807x: disable Q14 image generation
Fixes: WIFI-7570
Signed-off-by: John Crispin <john@phrozen.org>
2022-06-09 14:06:39 +02:00
Felix Fietkau
57849591d7 ipq807x: backport act_mirred changes
Fixes: WIFI-7838
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2022-06-09 14:06:25 +02:00
John Crispin
b4a09e7167 ucentral-schema: update to latest HEAD
96324e2 fix a typo inside the state handler

Fixes: WIFI-7838
Signed-off-by: John Crispin <john@phrozen.org>
2022-06-09 14:05:34 +02:00
John Crispin
96bb8b1372 ucentral-schema: update to latest HEAD
6974baa add data model support for wireguard overlay networks

Fixes: WIFI-7571
Signed-off-by: John Crispin <john@phrozen.org>
2022-06-09 14:05:24 +02:00
John Crispin
99ea9da785 ipq807x: add kmod-wireguard backport package
Fixes: WIFI-7571
Signed-off-by: John Crispin <john@phrozen.org>
2022-06-09 14:05:00 +02:00
John Crispin
bfe7fadfc5 ucentral-schema: update to latest HEAD
Signed-off-by: John Crispin <john@phrozen.org>
2022-06-09 14:04:04 +02:00
John Crispin
ad1dcc4f45 radius-gw-proxy: fix compile error on gcc5
Fixes: WIFI-7570
Signed-off-by: John Crispin <john@phrozen.org>
2022-06-09 14:03:53 +02:00
John Crispin
f371c789d0 ipq807x: revert all 11.5 changes
Fixes: WIFI-7570
Signed-off-by: John Crispin <john@phrozen.org>
2022-06-09 14:03:42 +02:00
John Crispin
386eca1f65 wifi-ax: revert all ath11.5 changes
Fixes: WIFI-7570
Signed-off-by: John Crispin <john@phrozen.org>
2022-06-09 14:03:05 +02:00
John Crispin
8b9047952d ipq807x: make USB work on wallys-dr6018 and disable sdhci
Fixes: WIFI-9306
Signed-off-by: John Crispin <john@phrozen.org>
2022-06-09 14:01:49 +02:00
John Crispin
5a105ef06e hostapd: make psk2-radius work on wifi-5 devices
Signed-off-by: John Crispin <john@phrozen.org>
2022-06-09 13:59:43 +02:00
John Crispin
c60dc1e045 wifi-ax: disable encap offloading in WDS / STA mode
Fixes: WIFI-9305
Signed-off-by: John Crispin <john@phrozen.org>
2022-06-09 13:58:06 +02:00
John Crispin
1e1bd19429 ucentral-schema: update to latest HEAD
bfa2647 make sure that vxlan tunnels endup inside a bridge

Fixes: WIFI-9121
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-30 08:26:51 +02:00
John Crispin
cfe07f6e15 ipq807x: backport the skb->cb fix from upstream
This was causing sporadic proxy_arp failures.

Fixes: WIFI-7154
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-30 06:03:02 +02:00
John Crispin
a64039db20 mac80211-qca: properly rebase a patch
The patch had a line skew due to a bad rebase.

Fixes: WIFI-7570
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-29 18:11:58 +02:00
John Crispin
7f81ddb8cc ucentral-schema: update to latest HEAD
27f451b add script command handler

Fixes: WIFI-9120
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-29 18:11:58 +02:00
John Crispin
3c0d495334 ucode: package the uloop library
Fixes: WIFI-9120
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-29 17:33:14 +02:00
John Crispin
38a7c54cce ucentral-client: update to latest HEAD
a4671bb fix an error reported by CI
a82c3f0 add handling for the "script" command

Fixes: WIFI-9120
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-29 17:31:00 +02:00
Jianhui Zhao
1aead07444 ath11k-wifi: update GL-AXT1800 BDF
Fixes: WIFI-8042
Signed-off-by: Jianhui Zhao <jianhui.zhao@gl-inet.com>
2022-05-29 10:31:54 +02:00
John Crispin
d2f44cbb12 ucentral-schema: update to latest HEAD
d1c7ab8 add ip-collide handler

Fixes: WIFI-7830
Fixes: WIFI-7989
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-29 10:30:45 +02:00
John Crispin
43d7ca31d6 wifi-ax/mac80211: make the 11.4 ath11k work inside the v5.4 kernel
Fixes: WIFI-7570
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-27 10:05:52 +02:00
John Crispin
0985c573b0 ipq807x: fix MAC assign on cig-wf19* units
The mtd offset changed in the v5.4 kernel causing MAC lookup to fail.

Fixes: WIFI-7997
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-27 07:34:07 +02:00
John Crispin
d9ed861c1d ipq807x: add support for wallytech dr6018(-v4)
Fixes: WIFI-7570
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-26 16:20:34 +02:00
John Crispin
8ef9989147 ipq807x: fix a null pointer crash in ip_tunnel
Fixes: WIFI-7571
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-26 09:51:07 +02:00
John Crispin
7d5eab4bf3 libnl-tine: update to latest HEAD
Fixes: WIFI-7571
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-26 09:50:34 +02:00
John Crispin
5e03e04bbd unetd: add wireshark overlay service
Fixes: WIFI-7571
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-26 09:30:11 +02:00
John Crispin
6fabaeca53 kernel-headers: make sure that the QSDK v5.4 kernel has access to the wireshark headers
Fixes: WIFI-7571
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-26 09:28:59 +02:00
John Crispin
be4ca445f5 netifd: update to latest HEAD
Fixes: WIFI-7571
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-26 09:28:36 +02:00
John Crispin
e99c8b27e1 libubox: update to latest HEAD
Fixes: WIFI-7571
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-26 09:28:11 +02:00
John Crispin
e9055b4f08 ucentral-schema: update to latest HEAD
6d83248 add missing radsec features

Fixes: WIFI-7077
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-26 09:13:23 +02:00
John Crispin
cfcafb676b ipq807x: backport the wireguard patches from the generic folder
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-24 17:28:11 +02:00
GL.iNet-Xinfa.Deng
899b4d6bfd ipq807x: fix gl-ax1800 switch button high active level
The active status of the switch button in the DTS configuration
is the opposite of that marked on the product housing.

The switch button should be activated at high GPIO level.

Fixes: WIFI-8042
Signed-off-by: GL.iNet-Xinfa.Deng <xinfa.deng@gl-inet.com>
2022-05-24 15:07:19 +02:00
John Crispin
2003632ddb ucentral-schema: update to latest HEAD
db15ed7 third-party services were not getting shut down properly

Fixes: WIFI-6907
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-24 14:05:14 +02:00
John Crispin
d4a14106b7 radius_gw_proxy: add support for a radius/gateway proxy
This will allow the AP to send radius requests via the websocket
to the gateway for routing to the correct AAA.

Fixes: WIFI-7328
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-24 14:05:14 +02:00
John Crispin
85af9d7e0b ipq807x: add motorola q14 support
Fixes: WIFI-8040
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-24 14:05:06 +02:00
John Crispin
d4442efbfe ipq807x: disable bluetooth on eap102
this causes units to take several minutes if the nrf8 chip has not been flashed yet

Signed-off-by: John Crispin <john@phrozen.org>
2022-05-20 15:37:10 +02:00
John Crispin
3a26ae2695 ipq807x: re-add patches that got lost during the v5.4 update
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-20 15:36:42 +02:00
John Crispin
09af596e85 ipq807x: fix the lan port on EAP102
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-20 15:36:20 +02:00
John Crispin
5985187316 .github: remove wallys cypress from CI until bootloop on v5.4 is resolved
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-20 12:12:22 +02:00
John Crispin
33ac83a309 wifi-ax: enable fils_discovery and multiple_ssid by default on 6g band
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-20 11:29:36 +02:00
John Crispin
921c1b553d ipq807x: enable ethernet LEDs on wf196
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-20 11:29:11 +02:00
Jianhui Zhao
d160507230 ipq807x: fix dts for gl-ax1800
Signed-off-by: Jianhui Zhao <jianhui.zhao@gl-inet.com>
2022-05-19 13:16:26 +02:00
Jianhui Zhao
7368620fd2 ipq807x: bump glinet ax1800/axt1800 to ath11.5/v5.4
Signed-off-by: Jianhui Zhao <jianhui.zhao@gl-inet.com>
2022-05-19 11:21:21 +02:00
John Crispin
a910e297a3 ucentral-schema: update to latest HEAD
7ead16a add device serial as an additional TLV inside radius requests

Signed-off-by: John Crispin <john@phrozen.org>
2022-05-18 13:02:32 +02:00
John Crispin
f819bb8753 wifi-ax: update hostapd to latest 11.5-cs
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-18 10:59:06 +02:00
John Crispin
cc0d4bded2 ipq807x: bump wf194c4 to ath11.5/v5.4
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:33 +02:00
Felix Fietkau
e3b2b7f232 ipq807x: enable threaded napi on ethernet
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2022-05-17 07:45:32 +02:00
Felix Fietkau
c8dde50eba ath11k: enable threaded napi support
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2022-05-17 07:45:32 +02:00
Felix Fietkau
3c355f96eb ipq807x: backport threaded NAPI support
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2022-05-17 07:45:32 +02:00
John Crispin
93dd24ef6e qca-nss-fw: update maple firmware
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:32 +02:00
John Crispin
107bc8ef65 ucentral-schema: update to latest HEAD
a18efc1 add psk2-radius support

Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:32 +02:00
John Crispin
9a8278afcc hostapd: add psk2-radius support
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:32 +02:00
John Crispin
1c48765913 ipq807x: add the diagchar module
This is required for FTM to correctly work

Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:32 +02:00
John Crispin
c6a45184fd ipq807x: fix buildsystem for ath11.5-csu
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:32 +02:00
John Crispin
18d5b8cba7 batman-adv: drop v4.4 backport
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:32 +02:00
John Crispin
65c08ade18 ath11k-wifi: update to ath11.5-cs
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:32 +02:00
John Crispin
3f6fee91e9 ath11k-firmware: update to ath11.5-cs
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:32 +02:00
John Crispin
d29c4e49b3 mac80211-qsdk: update to ath11.5-cs
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:32 +02:00
John Crispin
f162000749 qca-thermald-10.4: drop legacy package
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:32 +02:00
John Crispin
c804333bc0 kmod-sched-cake: drop legacy v4.4 backport
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:32 +02:00
John Crispin
449795db97 ipq807x: update to ath11.5-cs
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:31 +02:00
John Crispin
af92a2c7aa qca-nss-clients: update to ath11.5-cs
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-12 14:31:52 +02:00
John Crispin
b68affdf6a qca-nss-dp: update to ath11.5-cs
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-12 14:31:33 +02:00
John Crispin
7a95f9ac2d qca-nss-drv: update to ath11.5-cs
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-12 14:31:16 +02:00
John Crispin
8b5d9d84de qca-ssdk-shell: update to ath11.5-cs
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-12 14:30:59 +02:00
John Crispin
93d93c7708 qsdk-ssdk: update to ath11.5-cs
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-12 14:30:21 +02:00
John Crispin
b35232ab4a wifi-ax: enable fils_discovery and multiple_ssid by default on 6g band
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-12 11:51:06 +02:00
John Crispin
770a2bdd36 wifi-ax: add ftm package as default selection
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-12 11:46:21 +02:00
John Crispin
9650f8eaa8 iwinfo: fix 6e channel calculation
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-12 11:45:30 +02:00
John Crispin
63ab76bb30 ucentral-schema: add various 6e fixes
ba2bc69 fix wifi 6e channel calculation

Signed-off-by: John Crispin <john@phrozen.org>
2022-05-12 11:39:58 +02:00
John Crispin
fcb21ca0b6 ucentral-schema: add a sample wifi 6e config file
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-06 12:44:35 +02:00
John Crispin
d6d5422152 ipq40xx: add indio UM510/550AC support
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-06 09:08:59 +02:00
John Crispin
5b970a3f12 .github: add Indio UM-305ax to the CI job
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-05 10:38:59 +02:00
Matthew Hagan
a4a7c1f9f3 usteer: uchannel.uc: check host_info exists
If another host has not set a status, for example when autochannel is
disabled, it will not show host_info when remote_hosts is called. This
fix adds a check for this condition.

Signed-off-by: Matthew Hagan <mnhagan88@gmail.com>
2022-05-05 09:50:35 +02:00
John Crispin
5cbac23e3f ramips: disable switch/bridge offload
This is breaking win10 laptops when vlan_filtering is enabled

Signed-off-by: John Crispin <john@phrozen.org>
2022-05-04 17:09:53 +02:00
John Crispin
172c0d3690 bpf.mk: backport a fix that unbreaks bpf compile on armv7
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-03 07:44:34 +02:00
John Crispin
535f41d58b hostapd: fix phy level max-assoc settings
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-02 08:47:12 +02:00
John Crispin
2be18091a4 proxy_arp: backport skb->cb fix from upstream kernel
this caused proxy_arp to misbehave

Signed-off-by: John Crispin <john@phrozen.org>
2022-04-26 12:24:51 +02:00
John Crispin
73f42e3c6f ipq807x: enable dual boot on HFCL ION4X*
Signed-off-by: John Crispin <john@phrozen.org>
2022-04-26 07:59:41 +02:00
John Crispin
cff778d8ca treewide: update ucode to work with latest interpreter
Signed-off-by: John Crispin <john@phrozen.org>
2022-04-26 07:59:41 +02:00
John Crispin
94d4498a2d ucode: update to latest HEAD
Signed-off-by: John Crispin <john@phrozen.org>
2022-04-26 07:59:41 +02:00
John Crispin
eb0ab17f58 ipq807x: enable dual boot on EdgeCore devices
Signed-off-by: John Crispin <john@phrozen.org>
2022-04-21 11:18:58 +02:00
John Crispin
1ab99d50b2 certificates: add support for finding certificates on dual boot devices
Signed-off-by: John Crispin <john@phrozen.org>
2022-04-21 11:18:58 +02:00
Johann Hoffmann
dfeddc0d89 x86: add CI workflows
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-04-21 11:18:58 +02:00
Johann Hoffmann
efde86be9d x86: add vm images
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-04-21 11:18:58 +02:00
John Crispin
739e8c12fb ramips: fix actiontect web7200 wifi macs
Signed-off-by: John Crispin <john@phrozen.org>
2022-04-21 11:18:58 +02:00
John Crispin
3fdbbff9f7 ucentral-schema: update to latest HEAD
4829132 properly honour mac addresses that are inside board.json
ba9a2ee various 6G improvements
0a05052 interface: fix wan side STA-only interfaces

Signed-off-by: John Crispin <john@phrozen.org>
2022-04-21 11:18:58 +02:00
Sohail Ahmad
0a56755bef ramips: Support for Indio UM-305AX AP
Signed-off-by: Sohail Ahmad <sohail@indionetworks.com>
2022-04-21 11:18:58 +02:00
John Crispin
c35290772d ipq40xx: add certificate partition to cig-wf610
Signed-off-by: John Crispin <john@phrozen.org>
2022-04-19 10:28:15 +02:00
John Crispin
cedcbcbc2b ratelimit: fix ratelimit for multiple bss
The function looking up the rate was leaking a local variable into the global space

Signed-off-by: John Crispin <john@phrozen.org>
2022-04-19 07:40:58 +02:00
Stijn Tintel
9de96deca8 usteer: rename uptime to executed in uchannel.uc state
The uptime value in the uchannel state contains the uptime at the time
the script was last executed. This is a rather confusing name, and
possibly this is what lead to WIFI-7613. Rename it to executed to avoid
confusion in the future.

Keep the original name in the usteerd node status, as it is unclear what
impact this has, and could lead to breakage elsewhere.

Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
2022-04-19 06:35:42 +02:00
Stijn Tintel
19dbb1d5e3 usteer: fix uchannel.uc script
Once the uchannel.uc script sets its status to waiting, it becomes
defunct. The next invocation of the script will compare uptime to
state.uptime, and if the difference is less than 12h, it will change
state.uptime to the current uptime and return. As the script runs every
5 minutes, the difference will always be less than 12h.

Fix this by comparing uptime against state.changed rather than
state.uptime.

Fixes: WIFI-7613
Fixes: 670bc9d2e2 ("ucentral: development update")
Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
2022-04-19 06:35:42 +02:00
Stijn Tintel
83b6ccf562 usteer: fix init script
The uchannel instance of the usteer init script contains a typo, causing
the following error when autochannel is enabled:

/etc/rc.common: line 147: procd_close_instancea: not found

Fixes: WIFI-7577
Fixes: c467a62af3 ("usteer: update to latest HEAD")
Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
2022-04-19 06:35:12 +02:00
Owen Anderson
ea86593835 profiles: Fixed typo in cig_wf610d profile name
Signed-off-by: Owen Anderson <owen.anderson@netexperience.com>
2022-04-19 06:33:24 +02:00
John Crispin
36b5478005 ipq807x: fix dwc3 module dependency
Signed-off-by: John Crispin <john@phrozen.org>
2022-04-06 08:54:20 +02:00
John Crispin
1ad19297c1 ipq807x: factory images for wf196 were generated with a bad page size
Signed-off-by: John Crispin <john@phrozen.org>
2022-04-06 08:53:20 +02:00
John Crispin
f5357f7854 ath11k: add ath11k-fwtest support
Signed-off-by: John Crispin <john@phrozen.org>
2022-04-05 17:21:55 +02:00
Johann Hoffmann
8a3140b89b Add dummy workflow to test workflow modifications in PR branch
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-04-05 15:13:54 +02:00
John Crispin
16e0724ace ramips: fix actiontec web7200 dual boot
Signed-off-by: John Crispin <john@phrozen.org>
2022-04-04 16:09:55 +02:00
wenij
17ff9eecf5 ipq807x: cybertan eww622 usb xchi driver not work
Signed-off-by: wenij <wenij.chang@cybertan.com.tw>
2022-04-04 10:54:46 +02:00
wenij
4b870f978c ipq807x: Cybertan EWW622-A1 get mac address from nand devinfo partition.
Signed-off-by: wenij <wenij.chang@cybertan.com.tw>
2022-04-04 10:53:10 +02:00
John Crispin
8b83365961 ucentral-schema: update to latest HEAD
7015feb improve wifi reload

Signed-off-by: John Crispin <john@phrozen.org>
2022-04-04 06:54:06 +02:00
John Crispin
c6ebb5537a ucentral-schema: update to latest HEAD
e12bc03 revert hostapd restart hack as the root cause of the channel issue was found

Signed-off-by: John Crispin <john@phrozen.org>
2022-04-01 14:15:50 +02:00
John Crispin
6ebe189d71 ramips: fix uboot-env-tools mtd offset
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-31 13:41:16 +02:00
John Crispin
98b56551d5 mac80211: automatically restart wifi if bringup failed
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-31 10:58:50 +02:00
John Crispin
606e27e256 wifi: fix channel select when using ACS
there were several small issues that caused ACS to leave the radio in a bad state
during sanity runs.

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-31 10:58:45 +02:00
John Crispin
94fe14b9f9 ucentral-schema: update to latest HEAD
4cff999 add a 5s delay on config re-apply to give wifi time to restart

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-30 16:46:43 +02:00
John Crispin
58388f84b6 ipq40xx: add status led support on udaya board
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-29 13:44:54 +02:00
John Crispin
79ea04af49 ipq807x: re-add accidentially deleted config-default
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-29 13:22:38 +02:00
John Crispin
396e2bd06c ucentral-client: cleanup health parameter
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-29 07:29:12 +02:00
John Crispin
1a484c7f39 protobuf: drop legacy out of tree package
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-28 15:12:04 +02:00
John Crispin
e6b1030991 ucentral-schema: update to latest HEAD
9ac9f7e health: add a 75s delay when applying a new config

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-25 16:08:34 +01:00
John Crispin
6e32e68302 ucentral-client: update to latest HEAD
6cb4485 drop healthcheck from the client and move it to its own service

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-25 16:08:34 +01:00
John Crispin
0f13f7f5cd ipq40xx: add support for udaya a5 id2
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-25 16:08:34 +01:00
John Crispin
2ac4f9ef1d ucentral-schema: update to latest HEAD
fb6db0f force hapd restart upon cfg apply
ee0a8a4 broadband username was not getting applied correctly

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-24 15:59:34 +01:00
wenij
f1a75c25f9 ipq807x: Cybertan EWW622-A1 LED fixes
Signed-off-by: wenij <wenij.chang@cybertan.com.tw>
2022-03-24 15:59:34 +01:00
John Crispin
ff8d70753d ucentral-event: update to latest HEAD
24b7fb3 use async invoke when sending events

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-23 12:09:25 +01:00
John Crispin
caea6baecd certificates: create ubivolume with LEBs instead of MiB
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-23 11:51:32 +01:00
John Crispin
2e914c9b35 ipq807x: use CIG mac address hack on wf196
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-23 11:50:34 +01:00
Jianhui Zhao
da65d7e06f ipq807x: add initial support for GL.iNet AXT1800
Hardware:
* SoC: Qcom IPQ6000
* RAM: DDR3L 512MB
* Flash: 128MB Nand
* Ethernet: 3x GbE
* WLAN: 2x2 2.4GHz 600Mbps + 2x2 5GHz 1200Mbps (builtin + builtin)
* LEDS: 1x white, 1x blue
* Buttons: 1x switch, 1x reset
* USB: 1x 3.0(Type-A)
* SD: 1x microSD
* PWM Fan
* Power: 12VDC, 2A
* UART (4-pin, 2.54 mm pitch) pad on PCB
* JTAG (8-pin, 2.54 mm pitch) pad on PCB

Installation: upgrade "openwrt-ipq807x-glinet_ax1800-squashfs-sysupgrade.tar" directly.

Signed-off-by: Jianhui Zhao <jianhui.zhao@gl-inet.com>
2022-03-22 08:19:50 +01:00
Sohail Ahmad
d18eef480c ipq40xx: add Support for Indio's UM-325AC AP
Changes made in OpenWrt supported targets to Include Indio's UM-325AC AP which is an indoor WiFi5 AP based on ipq4019 chipset.

Signed-off-by: Sohail Ahmad <sohail@indionetworks.com>
2022-03-22 08:04:40 +01:00
John Crispin
f3532c66e5 ucentral-client: update to latest HEAD
63eddd2 send the original size when using compress_64

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-21 09:44:32 +01:00
Felix Fietkau
9678b1d6a5 ipq807x: backport clsact support
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2022-03-21 09:00:35 +01:00
John Crispin
379a4e2382 ucentral-schema: update to latest HEAD
fb537b9 enhance healthcheck to provide verbose error messages
2b65900 sysinfo: add helper tool to monitor memory consumption per service/instance

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-21 08:44:43 +01:00
John Crispin
edb33cd560 ucentral-schema: update to latest HEAD
5865d5a fix detection of pci radios

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-17 16:11:55 +01:00
John Crispin
2ff425ddeb ucentral-schema: update to latest HEAD
6dbd602 fix gre bridges
611af3d fix vxlan bridges

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-17 10:22:28 +01:00
John Crispin
7d016ac27f ucentral-schema: update to latest HEAD
d97a35c do not allow roaming for none, psk and wpa

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-15 18:49:51 +01:00
John Crispin
9790377dec ath11k-wifi: update cig wf196 BDF files
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-15 17:25:25 +01:00
John Crispin
597c547101 ipq807x: fix vmalloc on wf196
the built in wifi failed to start

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-15 16:24:33 +01:00
John Crispin
73b2645027 ucentral-schema: update to latest HEAD
9dfff17 fix include paths of the new wifi module

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-15 10:37:02 +01:00
John Crispin
8d58387d15 ucentral-schema: update to latest HEAD
ef7649f fix channel 140
302c5bf drop dependency on ucentral-wifi

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-14 17:19:07 +01:00
John Crispin
54dac4d348 ucode: update to latest HEAD
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-14 17:17:59 +01:00
John Crispin
a0880ed0f1 edgecore: disable dual boot on eap10x/ecw5211
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-11 16:28:41 +01:00
John Crispin
ed6d683980 ramips: add bmtv2 and nbnm support
this fixes the nand issue on the actiontec web7200

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-11 14:57:54 +01:00
John Crispin
4c72c6a35a ucentral-wifi: update to latest HEAD
aa9c3ee set the AP bssid inside the assoc list

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-11 07:59:34 +01:00
Sven Eckelmann
125d56866e batman-adv: Merge bugfixes from 2022.0
* allow netlink usage in unprivileged containers
* mcast: don't send link-local multicast to mcast routers

Origin: upstream, https://git.openwrt.org/?p=feed/routing.git;a=commit;h=9e2383e9b42087d5a3892366bed8b6bb4f868fe3
Signed-off-by: Sven Eckelmann <sven@narfation.org>
2022-03-10 15:10:05 +01:00
Hendrik Borghorst
a70a767ec0 batman-adv: Prevent use from libc headers to not build with BIG_ENDIAN
Commit 97d35a552ec5b6ddf7923dd2f9a8eb973526acea of musl introduced the
macros __LITTLE_ENDIAN and __BIG_ENDIAN in alltypes.h. These are pulled
into the compilation of batman-adv. This has the side effect that the
function is_multicast_ether_addr of etherdevice.h in Linux kernel is
compiled as the big endian version and so fails to work properly on
little endian devices.

This commits prevents pulling in header files of musl libc similar to
OpenWRT commit 9ac47ee46918c45b91f4e4d1fa76b1e26b9d57fe

Origin: upstream, https://git.openwrt.org/?p=feed/routing.git;a=commit;h=47436b04fd32cf3b6e6b46c25cb9c1fff3a995fd
Signed-off-by: Hendrik Borghorst <hendrikborghorst@gmail.com>
(cherry picked from commit 523821c1959cb288b55b7fcc8761c83f6ff48c4d)
Signed-off-by: Sven Eckelmann <sven@narfation.org>
2022-03-10 15:10:05 +01:00
Sven Eckelmann
b8a6764207 batman-adv: Merge bugfixes from 2021.4
* fix error handling during interface initialization

Origin: upstream, https://git.openwrt.org/?p=feed/routing.git;a=commit;h=6d10a01dfa68eb5e25b84b33e33aefd312f46f4d
Signed-off-by: Sven Eckelmann <sven@narfation.org>
2022-03-10 15:10:05 +01:00
Sven Eckelmann
98c9fcfd5d batman-adv: Refresh patches with quilt
The test builds are now requiring quilt refreshed patches instead of git
patches. Otherwise the build check will not even try to build something.

Origin: upstream, https://git.openwrt.org/?p=feed/routing.git;a=commit;h=e294a224640e03791a101a9302dbf72b06efab80
Signed-off-by: Sven Eckelmann <sven@narfation.org>
2022-03-10 15:10:05 +01:00
Sven Eckelmann
eac5504fec batman-adv: Merge bugfixes from 2021.2
* Avoid WARN_ON timing related checks

Origin: upstream, https://git.openwrt.org/?p=feed/routing.git;a=commit;h=519ef4ad29a8e53c1763df1553d386e3abf6206d
Signed-off-by: Sven Eckelmann <sven@narfation.org>
2022-03-10 15:10:05 +01:00
Piotr Dymacz
c2c75b67eb ipq807x: add initial support for YunCore AX840
This adds initial support for the YunCore AX840, an IPQ6010 based
802.11ax ceiling AP.

Specifications:

- Qualcomm IPQ6010
- 1 GB of RAM (DDR3)
- 8 MB of serial flash (SPI NOR)
- 256 MB of parallel flash (NAND)
- 2x2 2.4 GHz WiFi (IPQ6010)
- 2x2 5 GHz WiFi (IPQ6010)
- 2x IPEX/U.FL antenna connectors
- 4x 3 dBi dual-band antennas
- 2x 1 Gbps Ethernet (QCA8075) with 802.3at PoE input support
- 1x RGB LED
- 1x push-button (reset)
- DC jack for main power input (12 V)
- UART (4-pin, 2.54 mm pitch) header on PCB

Flash instruction under stock QSDK image:

  sysupgrade -n openwrt-ipq807x-yuncore_ax840-squashfs-nand-factory.bin

Flash instruction under U-Boot:

  tftpb 0x44000000 openwrt-ipq807x-yuncore_ax840-squashfs-nand-factory.ubi
  flash rootfs
  reset

Signed-off-by: Piotr Dymacz <pepe2k@gmail.com>
2022-03-10 14:50:37 +01:00
John Crispin
ef3eacefa7 ath11k-wifi: update WF188n BDF
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-10 08:21:58 +01:00
John Crispin
ef7481596a qosify: update to latest HEAD
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-10 08:18:47 +01:00
Paul Spooren
6f4e00aa46 README: fix linksys_ea8300 example
The profile is no longer called just `ea8300`.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2022-03-10 07:59:59 +01:00
Jianhui Zhao
be65578a7f profile: add gl-ax1800 support
Because we have an another similar device named gl-axt1800,
so we put the common functions in a dtsi file. And we'll
submit a PR for gl-axt1800 soon.

Hardware:
* SoC: Qcom IPQ6000
* RAM: DDR3L 512MB
* Flash: 128MB Nand
* Ethernet: 5x GbE
* WLAN: 2x2 2.4GHz 600Mbps + 2x2 5GHz 1200Mbps (builtin + builtin)
* LEDS: 1x white, 1x blue
* Buttons: 1x switch, 1x reset
* USB: 1x 3.0(Type-A)
* Power: 12VDC, 1.5A

Installation:
* from qsdk to openwifi:
upgrade "openwrt-ipq807x-glinet_ax1800-squashfs-nand-factory.bin" via web ui
without keep config.
* upgrade "openwrt-ipq807x-glinet_ax1800-squashfs-sysupgrade.tar" if you are already in openwifi.

Signed-off-by: Jianhui Zhao <jianhui.zhao@gl-inet.com>
2022-03-10 07:59:21 +01:00
John Crispin
20d4bd0c7d ucentral-schema: fix online-check
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-10 07:52:13 +01:00
John Crispin
531f4eb811 ucentral-schema: update to latest HEAD
4532c47 fix downstream bridges with no eth ports
04edaef ntp: open firewall port if ntpd is enabled
bf11105 fix led-active restart
c95667a a failed apply should return the error code 2
72e225e capabilities: add label_macaddr to capabilities

Signed-off-by: John Crispin <john@phrozen.org>
2022-03-10 07:52:13 +01:00
John Crispin
3b0dae7189 ucentral-schema: update to latest HEAD
72e225e capabilities: add label_macaddr to capabilities
f09f2b2 state: improve link metric, add ssid location
5586b93 unit: improve password generation
959a40d system: add sysinfo / resource consumption reporting
cdfb209 state: fix link state reporting

Fixes: WIFI-7210
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-03 17:12:31 +01:00
John Crispin
79395593ba ipq807x: add support for label_macaddr
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-03 17:09:21 +01:00
John Crispin
61248b98e0 ucentral-schema: set executable bit for wifi_max_user.uc
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-02 16:02:18 +01:00
Felix Fietkau
72b5abb72a ath10k: enable threaded napi support
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2022-03-02 15:45:08 +01:00
Felix Fietkau
673a029a02 ipq807x: enable threaded napi on ethernet
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2022-03-02 15:45:08 +01:00
Felix Fietkau
7efb85180f ipq807x: backport threaded napi support
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2022-03-02 15:45:08 +01:00
Felix Fietkau
f95eadaa8f ipq807x: backport kbuild fix to avoid spurious rebuilds
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2022-03-02 15:45:08 +01:00
Felix Fietkau
6f6b40a94f toolchain/gcc: fix building gcc 5.5 on newer systems
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2022-03-02 15:45:08 +01:00
John Crispin
d84982f161 ath11k: fix WDS when encap offload is enabled
Signed-off-by: John Crispin <john@phrozen.org>
2022-03-02 15:45:08 +01:00
175 changed files with 21727 additions and 3539 deletions

View File

@@ -0,0 +1,39 @@
name: Create AMI from firmware image in S3 bucket
inputs:
firmware_image_name:
description: Name of the firmware image
required: true
firmware_image_s3_bucket:
description: Name of the S3 bucket where the image resides
required: true
runs:
using: "composite"
steps:
- name: Import snapshot based on firmware image
id: import_snapshot
shell: bash
run: |
echo ::set-output name=import_task_id::$(aws ec2 import-snapshot --description '${{ inputs.firmware_image_name }}' --disk-container 'Format=raw,UserBucket={S3Bucket=${{ inputs.firmware_image_s3_bucket }},S3Key=${{ inputs.firmware_image_name }}}' | jq -r '.ImportTaskId')
- name: Wait for import task to complete and get snapshot ID
id: get_snapshot_id
shell: bash
run: |
IMPORT_TASK_STATUS=""
while [[ $IMPORT_TASK_STATUS != 'completed' ]]; do
IMPORT_TASK_STATUS=$(aws ec2 describe-import-snapshot-tasks --import-task-ids ${{ steps.import_snapshot.outputs.import_task_id }} | jq -r '.ImportSnapshotTasks[].SnapshotTaskDetail.Status')
echo "Import task status is $IMPORT_TASK_STATUS, waiting for completion."
done
echo ::set-output name=id::$(aws ec2 describe-import-snapshot-tasks --import-task-ids ${{ steps.import_snapshot.outputs.import_task_id }} | jq -r '.ImportSnapshotTasks[].SnapshotTaskDetail.SnapshotId')
- name: Tag snapshot with image name
shell: bash
run: |
aws ec2 create-tags --resources ${{ steps.get_snapshot_id.outputs.id }} --tags 'Key=Name,Value=${{ inputs.firmware_image_name }}'
- name: Register AMI based on snapshot
shell: bash
run: |
aws ec2 register-image --name '${{ inputs.firmware_image_name }}' --root-device-name /dev/xvda --block-device-mappings 'DeviceName=/dev/xvda,Ebs={SnapshotId=${{ steps.get_snapshot_id.outputs.id }}}'

View File

@@ -1,5 +1,13 @@
name: Build OpenWrt/uCentral images
env:
AWS_DEFAULT_OUTPUT: json
AWS_DEFAULT_REGION: us-east-1
AWS_S3_BUCKET_NAME: ucentral-ap-firmware
AWS_ACCOUNT_ID: ${{ secrets.UCENTRAL_S3_ACCOUNT_ID }}
AWS_ACCESS_KEY_ID: ${{ secrets.UCENTRAL_S3_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.UCENTRAL_S3_ACCESS_KEY_SECRET }}
on:
push:
branches: [ main, next, staging-* ]
@@ -8,10 +16,12 @@ on:
jobs:
build:
runs-on: ubuntu-latest
outputs:
x64_vm_image_name: ${{ steps.package_and_upload_image.outputs.x64_vm_image_name }}
strategy:
fail-fast: false
matrix:
target: ['actiontec_web7200', 'cig_wf188n', 'cig_wf194c', 'cig_wf194c4', 'cig_wf196', 'cig_wf160d', 'cig_wf808', 'cybertan_eww622-a1', 'edgecore_eap101', 'edgecore_eap102', 'edgecore_eap104', 'edgecore_ecs4100-12ph', 'edgecore_ecw5211', 'edgecore_ecw5410', 'edgecore_oap100', 'edgecore_ssw2ac2600', 'edgecore_spw2ac1200', 'edgecore_spw2ac1200-lan-poe', 'hfcl_ion4', 'hfcl_ion4xe', 'hfcl_ion4xi', 'indio_um-305ac', 'linksys_ea6350-v4', 'linksys_e8450-ubi', 'linksys_ea8300', 'tp-link_ec420-g1', 'tplink_ex227', 'tplink_ex228', 'tplink_ex447', 'wallys_dr40x9', 'wallys_dr6018', 'wallys_dr6018_v4' ]
target: ['actiontec_web7200', 'cig_wf188n', 'cig_wf194c', 'cig_wf194c4', 'cig_wf196', 'cig_wf610d', 'cig_wf808', 'cybertan_eww622-a1', 'edgecore_eap101', 'edgecore_eap102', 'edgecore_eap104', 'edgecore_ecs4100-12ph', 'edgecore_ecw5211', 'edgecore_ecw5410', 'edgecore_oap100', 'edgecore_ssw2ac2600', 'edgecore_spw2ac1200', 'edgecore_spw2ac1200-lan-poe', 'hfcl_ion4', 'hfcl_ion4xe', 'hfcl_ion4xi', 'indio_um-305ac', 'indio_um-305ax', 'indio_um-325ac', 'indio_um-510ac-v3', 'indio_um-550ac', 'linksys_ea6350-v4', 'linksys_e8450-ubi', 'linksys_ea8300', 'tp-link_ec420-g1', 'tplink_ex227', 'tplink_ex228', 'tplink_ex447', 'udaya_a5-id2', 'wallys_dr40x9', 'x64_vm' ]
steps:
- uses: actions/checkout@v2
@@ -24,17 +34,12 @@ jobs:
make -j TARGET=${{ matrix.target }}
- name: Package and upload image for ${{ matrix.target }}
id: package_and_upload_image
env:
GH_BUILD_USERNAME: ${{ secrets.GH_BUILD_USERNAME }}
GH_BUILD_PASSWORD: ${{ secrets.GH_BUILD_PASSWORD }}
ARTIFACTORY_USERNAME: cicd-indoor-main
ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
AWS_S3_BUCKET_NAME: ucentral-ap-firmware
AWS_DEFAULT_OUTPUT: json
AWS_DEFAULT_REGION: us-east-1
AWS_ACCOUNT_ID: ${{ secrets.UCENTRAL_S3_ACCOUNT_ID }}
AWS_ACCESS_KEY_ID: ${{ secrets.UCENTRAL_S3_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.UCENTRAL_S3_ACCESS_KEY_SECRET }}
run: |
LOWERCASE_TARGET=`echo ${{ matrix.target }} | tr '[:upper:]' '[:lower:]'`
HASH=$(git rev-parse --short HEAD)
@@ -66,6 +71,10 @@ jobs:
[ -f openwrt/tmp/image-file ] && aws s3 cp --acl public-read --content-type "application/json" "latest-upgrade.json" "s3://$AWS_S3_BUCKET_NAME/$JSON_NAME"
[ -f openwrt/tmp/image-file ] && aws s3api put-object-tagging --bucket "$AWS_S3_BUCKET_NAME" --key "$JSON_NAME" --tagging "{\"TagSet\":[{\"Key\":\"release\",\"Value\":\"$IS_RELEASE\"}]}"
if [ ${{ matrix.target }} == 'x64_vm' ]; then
echo ::set-output name=x64_vm_image_name::"$(echo $IMG_NAME)"
fi
trigger-testing:
runs-on: ubuntu-latest
needs: build
@@ -78,3 +87,16 @@ jobs:
repository: Telecominfraproject/wlan-testing
event-type: new-ap-release
client-payload: '{"ref": "${GITHUB_REF#refs/tags/}", "sha": "${{ github.sha }}"}'
create-x64_vm-ami:
runs-on: ubuntu-latest
needs: build
if: startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v2
- name: Use create-ami-from-image composite action
uses: ./.github/actions/create-ami-from-image
with:
firmware_image_name: ${{ needs.build.outputs.x64_vm_image_name }}
firmware_image_s3_bucket: ${{ env.AWS_S3_BUCKET_NAME }}

88
.github/workflows/x64_vm-build-test.yml vendored Normal file
View File

@@ -0,0 +1,88 @@
name: Test x64_vm build and AMI creation
env:
AWS_DEFAULT_OUTPUT: json
AWS_DEFAULT_REGION: us-east-1
AWS_S3_BUCKET_NAME: ucentral-ap-firmware
AWS_ACCOUNT_ID: ${{ secrets.UCENTRAL_S3_ACCOUNT_ID }}
AWS_ACCESS_KEY_ID: ${{ secrets.UCENTRAL_S3_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.UCENTRAL_S3_ACCESS_KEY_SECRET }}
on:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
outputs:
x64_vm_image_name: ${{ steps.package_and_upload_image.outputs.x64_vm_image_name }}
strategy:
fail-fast: false
matrix:
target: ['x64_vm']
steps:
- uses: actions/checkout@v2
- name: Build image for ${{ matrix.target }}
id: build
run: |
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
make -j TARGET=${{ matrix.target }}
- name: Package and upload image for ${{ matrix.target }}
id: package_and_upload_image
env:
GH_BUILD_USERNAME: ${{ secrets.GH_BUILD_USERNAME }}
GH_BUILD_PASSWORD: ${{ secrets.GH_BUILD_PASSWORD }}
ARTIFACTORY_USERNAME: cicd-indoor-main
ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
run: |
LOWERCASE_TARGET=`echo ${{ matrix.target }} | tr '[:upper:]' '[:lower:]'`
HASH=$(git rev-parse --short HEAD)
if [[ ${GITHUB_REF} == "refs/heads/"* ]]
then
REF=$(echo ${GITHUB_REF#refs/heads/} | tr '/' '-')
IS_RELEASE="false"
else
REF=$(echo ${GITHUB_REF#refs/tags/} | tr '/' '-')
IS_RELEASE="true"
fi
BASENAME="$(date +%Y%m%d)-$LOWERCASE_TARGET-$REF-$HASH"
TAR_NAME="$BASENAME.tar.gz"
IMG_NAME="$BASENAME-upgrade.bin";
JSON_NAME="$BASENAME.json";
tar cfz "$TAR_NAME" -C openwrt/bin/targets/ .
curl -s -u $GH_BUILD_USERNAME:$GH_BUILD_PASSWORD -T "$TAR_NAME" "https://tip.jfrog.io/artifactory/tip-wlan-ap-firmware/uCentral/$LOWERCASE_TARGET/"$TAR_NAME""
IMG_NAME="$BASENAME-upgrade.bin";
TIP_VERSION="$(grep DISTRIB_TIP= openwrt/tmp/openwrt_release | cut -d\' -f2)"
echo -e "{\n\t\"image\":\""${IMG_NAME}"\",\n\t\"revision\": \""${TIP_VERSION}"\",\n\t\"timestamp\":\""$(date +%s)"\",\n\t\"compatible\": \""${LOWERCASE_TARGET}"\"\n}" > latest-upgrade.json
[ -f openwrt/tmp/image-file ] && curl -s -u $GH_BUILD_USERNAME:$GH_BUILD_PASSWORD -T "openwrt/$(cat openwrt/tmp/image-file)" "https://tip.jfrog.io/artifactory/tip-wlan-ap-firmware/uCentral/$LOWERCASE_TARGET/"$IMG_NAME""
[ -f openwrt/tmp/image-file ] && curl -s -u $GH_BUILD_USERNAME:$GH_BUILD_PASSWORD -T "latest-upgrade.json" "https://tip.jfrog.io/artifactory/tip-wlan-ap-firmware/uCentral/$LOWERCASE_TARGET/latest-upgrade.json"
[ -f openwrt/tmp/image-file ] && aws s3 cp --acl public-read --content-type "application/octet-stream" "openwrt/$(cat openwrt/tmp/image-file)" "s3://$AWS_S3_BUCKET_NAME/$IMG_NAME"
[ -f openwrt/tmp/image-file ] && aws s3api put-object-tagging --bucket "$AWS_S3_BUCKET_NAME" --key "$IMG_NAME" --tagging "{\"TagSet\":[{\"Key\":\"release\",\"Value\":\"$IS_RELEASE\"}]}"
[ -f openwrt/tmp/image-file ] && aws s3 cp --acl public-read --content-type "application/json" "latest-upgrade.json" "s3://$AWS_S3_BUCKET_NAME/$JSON_NAME"
[ -f openwrt/tmp/image-file ] && aws s3api put-object-tagging --bucket "$AWS_S3_BUCKET_NAME" --key "$JSON_NAME" --tagging "{\"TagSet\":[{\"Key\":\"release\",\"Value\":\"$IS_RELEASE\"}]}"
if [[ ${{ matrix.target }} == 'x64_vm' ]]; then
echo ::set-output name=x64_vm_image_name::"$(echo $IMG_NAME)"
fi
create-x64_vm-ami:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v2
with:
ref: WIFI-7206-add-workflow-to-build-virtual-ap-image
- name: Use create-ami-from-image composite action
uses: ./.github/actions/create-ami-from-image
with:
firmware_image_name: ${{ needs.build.outputs.x64_vm_image_name }}
firmware_image_s3_bucket: ${{ env.AWS_S3_BUCKET_NAME }}

View File

@@ -12,7 +12,7 @@ First we need to clone and setup our tree. This will result in an openwrt/.
Next we need to select the profile and base package selection. This setup will install the feeds, packages and generate the .config file.
```
cd openwrt
./scripts/gen_config.py ea8300
./scripts/gen_config.py linksys_ea8300
```
Finally we can build the tree.
```

View File

@@ -39,6 +39,10 @@ hfcl,ion4xe)
ucidef_set_led_wlan "wlan5g" "WLAN5G" "blue:wifi5" "phy0tpt"
ucidef_set_led_wlan "wlan2g" "WLAN2G" "blue:wifi2" "phy1tpt"
;;
glinet,ax1800|\
glinet,axt1800)
ucidef_set_led_netdev "wan" "WAN" "blue:wan" "eth0" "tx rx link"
;;
esac
board_config_flush

View File

@@ -32,11 +32,14 @@ qcom_setup_interfaces()
cig,wf194c4|\
edgecore,eap106|\
qcom,ipq5018-mp03.3|\
yuncore,ax840|\
motorola,q14|\
sercomm,wallaby)
ucidef_set_interface_lan "eth0"
ucidef_set_interface_wan "eth1"
;;
edgecore,eap101)
edgecore,eap101|\
glinet,axt1800)
ucidef_set_interface_lan "eth1 eth2"
ucidef_set_interface_wan "eth0"
;;
@@ -52,7 +55,8 @@ qcom_setup_interfaces()
ucidef_set_interface_lan "eth0 eth1 eth2 eth3"
ucidef_set_interface_wan "eth4"
;;
wallys,dr6018-v4)
wallys,dr6018-v4|\
glinet,ax1800)
ucidef_set_interface_lan "eth1 eth2 eth3 eth4"
ucidef_set_interface_wan "eth0"
;;
@@ -73,7 +77,8 @@ qcom_setup_macs()
case $board in
cig,wf194c|\
cig,wf194c4)
cig,wf194c4|\
cig,wf196)
mac=$(grep BaseMacAddress= /dev/mtd14 | cut -dx -f2)
wan_mac=$(macaddr_canonicalize $mac)
lan_mac=$(macaddr_add "$wan_mac" 1)
@@ -81,6 +86,15 @@ qcom_setup_macs()
ucidef_set_network_device_mac eth1 $wan_mac
ucidef_set_label_macaddr $wan_mac
;;
cybertan,eww622-a1)
mac=$(grep -i -m 1 mac_addr_base= /dev/`cat /proc/mtd | grep devinfo | cut -d: -f1` | cut -d= -f2)
[ -z "$mac"] && mac="00:11:22:33:44:55"
wan_mac=$(macaddr_canonicalize $mac)
lan_mac=$(macaddr_add "$wan_mac" 1)
ucidef_set_network_device_mac eth0 $wan_mac
ucidef_set_network_device_mac eth1 $lan_mac
ucidef_set_label_macaddr $wan_mac
;;
*)
wan_mac=$(cat /sys/class/net/eth0/address)
lan_mac=$(macaddr_add "$wan_mac" 1)
@@ -88,6 +102,7 @@ qcom_setup_macs()
esac
[ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac
[ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac
[ -n "$wan_mac" ] && ucidef_set_label_macaddr "$wan_mac"
}
board_config_update

View File

@@ -81,6 +81,7 @@ case "$FIRMWARE" in
qcom,ipq807x-hk14|\
tplink,ex227|\
tplink,ex447|\
yuncore,ax840|\
sercomm,wallaby)
caldata_extract "0:ART" 0x1000 0x20000
;;
@@ -96,7 +97,8 @@ case "$FIRMWARE" in
wallys,dr6018|\
wallys,dr6018-v4|\
qcom,ipq6018-cp01|\
xiaomi,ax1800)
xiaomi,ax1800|\
glinet,ax1800)
caldata_extract "0:ART" 0x1000 0x20000
;;
esac
@@ -105,13 +107,22 @@ ath11k/IPQ5018/hw1.0/caldata.bin)
case "$board" in
cybertan,eww622-a1|\
edgecore,eap104|\
motorola,q14|\
qcom,ipq5018-mp03.1)
caldata_extract "0:ART" 0x1000 0x20000
;;
esac
;;
ath11k/qcn6122/hw1.0/caldata_1.bin)
case "$board" in
motorola,q14)
caldata_extract "0:ART" 0x26800 0x20000
;;
esac
;;
ath11k/qcn6122/hw1.0/caldata_2.bin)
case "$board" in
motorola,q14|\
edgecore,eap104)
caldata_extract "0:ART" 0x4c000 0x20000
;;

View File

@@ -19,4 +19,12 @@ boot() {
ssdk_sh debug phy set 8 0x4004c441 0x8
;;
esac
case "$(board_name)" in
cig,wf196)
# setup the leds
ssdk_sh debug phy set 0 0x401ec431 0xc00f
ssdk_sh debug phy set 0 0x401ec430 0x806f
;;
esac
}

View File

@@ -4,8 +4,14 @@ START=99
boot() {
case "$(board_name)" in
hfcl,ion4xe|\
hfcl,ion4xi)
fw_setenv boot_count 0
;;
edgecore,eap101|\
edgecore,eap102)
avail=$(fw_printenv -n upgrade_available)
[ ${avail} -eq 0 ] && fw_setenv upgrade_available 1
fw_setenv bootcount 0
;;
esac

View File

@@ -1,5 +1,8 @@
. /lib/functions/system.sh
RAMFS_COPY_BIN='fw_printenv fw_setenv'
RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock'
qca_do_upgrade() {
local tar_file="$1"
@@ -16,6 +19,50 @@ qca_do_upgrade() {
fi
}
find_mmc_part() {
local DEVNAME PARTNAME
if grep -q "$1" /proc/mtd; then
echo "" && return 0
fi
for DEVNAME in /sys/block/mmcblk*/mmcblk*p*; do
PARTNAME=$(grep PARTNAME ${DEVNAME}/uevent | cut -f2 -d'=')
[ "$PARTNAME" = "$1" ] && echo "/dev/$(basename $DEVNAME)" && return 0
done
}
do_flash_emmc() {
local tar_file=$1
local emmcblock=$(find_mmc_part $2)
local board_dir=$3
local part=$4
[ -z "$emmcblock" ] && {
echo failed to find $2
return
}
echo erase $4
dd if=/dev/zero of=${emmcblock}
echo flash $4
tar Oxf $tar_file ${board_dir}/$part | dd of=${emmcblock}
}
emmc_do_upgrade() {
local tar_file="$1"
local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$')
board_dir=${board_dir%/}
do_flash_emmc $tar_file '0:HLOS' $board_dir kernel
do_flash_emmc $tar_file 'rootfs' $board_dir root
local emmcblock="$(find_mmc_part "rootfs_data")"
if [ -e "$emmcblock" ]; then
mkfs.ext4 "$emmcblock"
fi
}
platform_check_image() {
local magic_long="$(get_magic_long "$1")"
board=$(board_name)
@@ -26,6 +73,8 @@ platform_check_image() {
cig,wf194c4|\
cig,wf196|\
cybertan,eww622-a1|\
glinet,ax1800|\
glinet,axt1800|\
wallys,dr6018|\
wallys,dr6018-v4|\
edgecore,eap101|\
@@ -36,6 +85,8 @@ platform_check_image() {
hfcl,ion4xe|\
tplink,ex227|\
tplink,ex447|\
yuncore,ax840|\
motorola,q14|\
qcom,ipq6018-cp01|\
qcom,ipq807x-hk01|\
qcom,ipq807x-hk14|\
@@ -56,30 +107,58 @@ platform_do_upgrade() {
cig,wf188)
qca_do_upgrade $1
;;
motorola,q14)
emmc_do_upgrade $1
;;
cig,wf188n|\
cig,wf194c|\
cig,wf194c4|\
cig,wf196|\
cybertan,eww622-a1|\
edgecore,eap104|\
hfcl,ion4xi|\
hfcl,ion4xe|\
glinet,ax1800|\
glinet,axt1800|\
qcom,ipq6018-cp01|\
qcom,ipq807x-hk01|\
qcom,ipq807x-hk14|\
qcom,ipq5018-mp03.3|\
wallys,dr6018|\
wallys,dr6018-v4|\
yuncore,ax840|\
tplink,ex447|\
tplink,ex227)
nand_upgrade_tar "$1"
;;
edgecore,eap106|\
edgecore,eap102|\
edgecore,eap101)
hfcl,ion4xi|\
hfcl,ion4xe)
if grep -q rootfs_1 /proc/cmdline; then
CI_UBIPART="rootfs"
fw_setenv primary 0 || exit 1
else
CI_UBIPART="rootfs_1"
fw_setenv primary 1 || exit 1
fi
nand_upgrade_tar "$1"
;;
edgecore,eap106)
CI_UBIPART="rootfs1"
[ "$(find_mtd_chardev rootfs)" ] && CI_UBIPART="rootfs"
nand_upgrade_tar "$1"
;;
edgecore,eap101|\
edgecore,eap102)
if [ "$(find_mtd_chardev rootfs)" ]; then
CI_UBIPART="rootfs"
else
if grep -q rootfs1 /proc/cmdline; then
CI_UBIPART="rootfs2"
fw_setenv active 2 || exit 1
else
CI_UBIPART="rootfs1"
fw_setenv active 1 || exit 1
fi
fi
nand_upgrade_tar "$1"
;;
esac
}

View File

@@ -0,0 +1,18 @@
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "../../../arm64/boot/dts/qcom/qcom-ipq6018-gl-ax1800.dts"
#include "qcom-ipq6018.dtsi"

View File

@@ -0,0 +1,18 @@
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "../../../arm64/boot/dts/qcom/qcom-ipq6018-gl-axt1800.dts"
#include "qcom-ipq6018.dtsi"

View File

@@ -0,0 +1,18 @@
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "../../../arm64/boot/dts/qcom/qcom-ipq6018-yuncore-ax840.dts"
#include "qcom-ipq6018.dtsi"

View File

@@ -32,6 +32,10 @@
serial1 = &blsp1_uart2;
ethernet0 = "/soc/dp1";
ethernet1 = "/soc/dp2";
led-boot = &led_sys;
led-failsafe = &led_sys;
led-running = &led_sys;
led-upgrade = &led_sys;
};
chosen {
@@ -708,32 +712,20 @@
pinctrl-0 = <&leds_pins>;
pinctrl-names = "default";
led@1 {
led_sys: led@1 {
label = "sys:blue";
gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; /* GPIO_1 */
/* default-state="on"; */
linux,default-trigger = "timer";
active-delay = <700>;
inactive-delay = <700>;
default-state="on";
};
led@35 {
label = "sys:green";
gpios = <&tlmm 35 GPIO_ACTIVE_HIGH>; /* GPIO_35 */
default-state="off";
/* linux,default-trigger = "timer";
active-delay = <700>;
inactive-delay = <700>;
default-state="on"; */
};
led@31 {
label = "sys:red";
gpios = <&tlmm 31 GPIO_ACTIVE_HIGH>; /* GPIO_31 */
default-state="off";
/* linux,default-trigger = "timer";
active-delay = <700>;
inactive-delay = <700>;
default-state="on"; */
};
};
};

View File

@@ -0,0 +1,78 @@
/dts-v1/;
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "qcom-ipq6018-gl-ax1800.dtsi"
/ {
model = "GL Technologies, Inc. AX1800";
compatible = "glinet,ax1800", "qcom,ipq6018-cp03", "qcom,ipq6018";
aliases {
ethernet3 = "/soc/dp4";
ethernet4 = "/soc/dp5";
};
};
&mdio0 {
phy3: ethernet-phy@3 {
reg = <3>;
};
phy4: ethernet-phy@4 {
reg = <4>;
};
};
&ess0 {
switch_lan_bmp = <0x3c>; /* lan port bitmap */
qcom,port_phyinfo {
port@3 {
port_id = <4>;
phy_address = <3>;
};
port@4 {
port_id = <5>;
phy_address = <4>;
};
};
};
&soc {
dp4 {
device_type = "network";
compatible = "qcom,nss-dp";
qcom,id = <4>;
reg = <0x3a001600 0x200>;
qcom,mactype = <0>;
local-mac-address = [000000000000];
qcom,link-poll = <1>;
qcom,phy-mdio-addr = <3>;
phy-mode = "sgmii";
};
dp5 {
device_type = "network";
compatible = "qcom,nss-dp";
qcom,id = <5>;
reg = <0x3a001800 0x200>;
qcom,mactype = <0>;
local-mac-address = [000000000000];
qcom,link-poll = <1>;
qcom,phy-mdio-addr = <4>;
phy-mode = "sgmii";
};
};

View File

@@ -0,0 +1,364 @@
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "qcom-ipq6018.dtsi"
#include <dt-bindings/input/input.h>
/ {
#address-cells = <0x2>;
#size-cells = <0x2>;
interrupt-parent = <&intc>;
qcom,msm-id = <0x1A5 0x0>;
aliases {
ethernet0 = "/soc/dp1";
ethernet1 = "/soc/dp2";
ethernet2 = "/soc/dp3";
led-boot = &led_run;
led-failsafe = &led_run;
led-running = &led_run;
led-upgrade = &led_run;
};
chosen {
bootargs = "console=ttyMSM0,115200,n8 rw init=/init";
bootargs-append = " swiotlb=1 coherent_pool=2M";
};
};
&tlmm {
uart_pins: uart_pins {
mux {
pins = "gpio44", "gpio45";
function = "blsp2_uart";
drive-strength = <8>;
bias-pull-down;
};
};
qpic_pins: qpic_pins {
data_0 {
pins = "gpio15";
function = "qpic_pad0";
drive-strength = <8>;
bias-pull-down;
};
data_1 {
pins = "gpio12";
function = "qpic_pad1";
drive-strength = <8>;
bias-pull-down;
};
data_2 {
pins = "gpio13";
function = "qpic_pad2";
drive-strength = <8>;
bias-pull-down;
};
data_3 {
pins = "gpio14";
function = "qpic_pad3";
drive-strength = <8>;
bias-pull-down;
};
data_4 {
pins = "gpio5";
function = "qpic_pad4";
drive-strength = <8>;
bias-pull-down;
};
data_5 {
pins = "gpio6";
function = "qpic_pad5";
drive-strength = <8>;
bias-pull-down;
};
data_6 {
pins = "gpio7";
function = "qpic_pad6";
drive-strength = <8>;
bias-pull-down;
};
data_7 {
pins = "gpio8";
function = "qpic_pad7";
drive-strength = <8>;
bias-pull-down;
};
qpic_pad {
pins = "gpio1", "gpio3", "gpio4",
"gpio10", "gpio11", "gpio17";
function = "qpic_pad";
drive-strength = <8>;
bias-pull-down;
};
};
button_pins: button_pins {
switch_button {
pins = "gpio9";
function = "gpio";
drive-strength = <8>;
bias-pull-up;
};
reset_button {
pins = "gpio18";
function = "gpio";
drive-strength = <8>;
bias-pull-up;
};
};
mdio_pins: mdio_pinmux {
mux_0 {
pins = "gpio64";
function = "mdc";
drive-strength = <8>;
bias-pull-up;
};
mux_1 {
pins = "gpio65";
function = "mdio";
drive-strength = <8>;
bias-pull-up;
};
mux_2 {
pins = "gpio74";
function = "gpio";
bias-pull-up;
};
};
leds_pins: leds_pins {
white {
pins = "gpio35";
function = "gpio";
drive-strength = <8>;
bias-pull-down;
};
blue {
pins = "gpio37";
function = "gpio";
drive-strength = <8>;
bias-pull-down;
};
};
usb_pins: usb_pins {
usb_pwr {
pins = "gpio0";
function = "gpio";
bias-pull-up;
output-high;
};
};
};
&soc {
mdio0: mdio@90000 {
pinctrl-0 = <&mdio_pins>;
pinctrl-names = "default";
phy-reset-gpio = <&tlmm 74 GPIO_ACTIVE_HIGH>;
status = "ok";
phy0: ethernet-phy@0 {
reg = <0>;
};
phy1: ethernet-phy@1 {
reg = <1>;
};
phy2: ethernet-phy@2 {
reg = <2>;
};
};
ess0: ess-switch@3a000000 {
switch_cpu_bmp = <0x1>; /* cpu port bitmap */
switch_lan_bmp = <0x0c>; /* lan port bitmap */
switch_wan_bmp = <0x02>; /* wan port bitmap */
switch_inner_bmp = <0xc0>; /*inner port bitmap*/
switch_mac_mode = <0x0>; /* mac mode for uniphy instance0*/
switch_mac_mode1 = <0xff>; /* mac mode for uniphy instance1*/
switch_mac_mode2 = <0xff>; /* mac mode for uniphy instance2*/
qcom,port_phyinfo {
port@0 {
port_id = <1>;
phy_address = <0>;
};
port@1 {
port_id = <2>;
phy_address = <1>;
};
port@2 {
port_id = <3>;
phy_address = <2>;
};
};
};
dp1 {
device_type = "network";
compatible = "qcom,nss-dp";
qcom,id = <1>;
reg = <0x3a001000 0x200>;
qcom,mactype = <0>;
local-mac-address = [000000000000];
qcom,link-poll = <1>;
qcom,phy-mdio-addr = <0>;
phy-mode = "sgmii";
};
dp2 {
device_type = "network";
compatible = "qcom,nss-dp";
qcom,id = <2>;
reg = <0x3a001200 0x200>;
qcom,mactype = <0>;
local-mac-address = [000000000000];
qcom,link-poll = <1>;
qcom,phy-mdio-addr = <1>;
phy-mode = "sgmii";
};
dp3 {
device_type = "network";
compatible = "qcom,nss-dp";
qcom,id = <3>;
reg = <0x3a001400 0x200>;
qcom,mactype = <0>;
local-mac-address = [000000000000];
qcom,link-poll = <1>;
qcom,phy-mdio-addr = <2>;
phy-mode = "sgmii";
};
leds {
compatible = "gpio-leds";
pinctrl-0 = <&leds_pins>;
pinctrl-names = "default";
led_run: led@35 {
label = "white:sys";
gpios = <&tlmm 35 GPIO_ACTIVE_HIGH>;
default-state = "on";
};
led@37 {
label = "blue:wan";
gpios = <&tlmm 37 GPIO_ACTIVE_HIGH>;
default-state = "on";
};
};
gpio_keys {
compatible = "gpio-keys";
pinctrl-0 = <&button_pins>;
pinctrl-names = "default";
switch {
label = "switch";
linux,code = <KEY_WPS_BUTTON>;
gpios = <&tlmm 9 GPIO_ACTIVE_LOW>;
linux,input-type = <1>;
debounce-interval = <60>;
};
reset {
label = "reset";
linux,code = <KEY_RESTART>;
gpios = <&tlmm 18 GPIO_ACTIVE_LOW>;
linux,input-type = <1>;
debounce-interval = <60>;
};
};
};
&blsp1_uart3 {
pinctrl-0 = <&uart_pins>;
pinctrl-names = "default";
status = "ok";
};
&qpic_bam {
status = "ok";
};
&nand {
pinctrl-0 = <&qpic_pins>;
pinctrl-names = "default";
status = "ok";
};
&ssphy_0 {
status = "ok";
};
&qusb_phy_0 {
status = "ok";
};
&usb3 {
pinctrl-0 = <&usb_pins>;
pinctrl-names = "default";
status = "ok";
};
&nss_crypto {
status = "ok";
};
&q6_region {
reg = <0x0 0x4ab00000 0x0 0x05500000>;
};
&CPU0 {
operating-points = <
/* kHz uV (fixed) */
864000 1100000
1056000 1100000
1200000 1100000
>;
clock-latency = <200000>;
};
&CPU1 {
operating-points = <
/* kHz uV (fixed) */
864000 1100000
1056000 1100000
1200000 1100000
>;
clock-latency = <200000>;
};
&CPU2 {
operating-points = <
/* kHz uV (fixed) */
864000 1100000
1056000 1100000
1200000 1100000
>;
clock-latency = <200000>;
};
&CPU3 {
operating-points = <
/* kHz uV (fixed) */
864000 1100000
1056000 1100000
1200000 1100000
>;
clock-latency = <200000>;
};

View File

@@ -0,0 +1,94 @@
/dts-v1/;
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "qcom-ipq6018-gl-ax1800.dtsi"
/ {
model = "GL Technologies, Inc. AXT1800";
compatible = "glinet,axt1800", "qcom,ipq6018-cp03", "qcom,ipq6018";
aliases {
sdhc0 = &sdhc_2;
};
};
&tlmm {
sd_pins: sd_pins {
sd {
pins = "gpio62";
function = "sd_card";
bias-pull-up;
};
ldo {
pins = "gpio66";
function = "gpio";
bias-pull-up;
};
};
pwm_pins: pwm_pinmux {
pwm {
pins = "gpio30";
function = "pwm13";
drive-strength = <8>;
};
};
fan_pins: fan_pins {
pwr {
pins = "gpio29";
function = "gpio";
bias-pull-up;
output-high;
};
speed {
pins = "gpio31";
function = "gpio";
drive-strength = <8>;
bias-pull-down;
};
};
};
&soc {
pwm:pwm {
#pwm-cells = <2>;
pinctrl-0 = <&pwm_pins>;
pinctrl-names = "default";
used-pwm-indices = <0>, <1>, <0>, <0>;
status = "ok";
};
pwm-fan {
compatible = "pwm-fan";
pinctrl-0 = <&fan_pins>;
pinctrl-names = "default";
cooling-min-state = <0>;
cooling-max-state = <3>;
#cooling-cells = <2>;
pwms = <&pwm 1 255>;
cooling-levels = <0 150 200 255>;
};
};
&sdhc_2 {
pinctrl-0 = <&sd_pins>;
pinctrl-names = "default";
cd-gpios = <&tlmm 62 1>;
sd-ldo-gpios = <&tlmm 66 1>;
status = "ok";
};

View File

@@ -0,0 +1,343 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/dts-v1/;
#include "qcom-ipq6018.dtsi"
#include "qcom-ipq6018-rpm-regulator.dtsi"
#include "qcom-ipq6018-cpr-regulator.dtsi"
#include "qcom-ipq6018-cp-cpu.dtsi"
#include <dt-bindings/input/input.h>
#include <dt-bindings/gpio/gpio.h>
/ {
model = "YunCore AX840";
compatible = "yuncore,ax840", "qcom,ipq6018-cp03", "qcom,ipq6018";
#address-cells = <0x2>;
#size-cells = <0x2>;
interrupt-parent = <&intc>;
aliases {
/* Aliases as required by u-boot to patch MAC addresses */
ethernet0 = "/soc/dp2";
ethernet1 = "/soc/dp1";
serial0 = &blsp1_uart3;
serial1 = &blsp1_uart2;
led-boot = &led_system;
led-failsafe = &led_system;
led-running = &led_system;
led-upgrade = &led_system;
};
chosen {
bootargs = "console=ttyMSM0,115200,n8 rw init=/init";
bootargs-append = " swiotlb=1 coherent_pool=2M";
};
reserved-memory {
tzapp:tzapp@49B00000 { /* TZAPPS */
no-map;
reg = <0x0 0x49B00000 0x0 0x00600000>;
};
};
};
&tlmm {
uart_pins: uart_pins {
mux {
pins = "gpio44", "gpio45";
function = "blsp2_uart";
drive-strength = <8>;
bias-pull-down;
};
};
spi_0_pins: spi_0_pins {
mux {
pins = "gpio38", "gpio39", "gpio40", "gpio41";
function = "blsp0_spi";
drive-strength = <8>;
bias-pull-down;
};
};
qpic_pins: qpic_pins {
data_0 {
pins = "gpio15";
function = "qpic_pad0";
drive-strength = <8>;
bias-pull-down;
};
data_1 {
pins = "gpio12";
function = "qpic_pad1";
drive-strength = <8>;
bias-pull-down;
};
data_2 {
pins = "gpio13";
function = "qpic_pad2";
drive-strength = <8>;
bias-pull-down;
};
data_3 {
pins = "gpio14";
function = "qpic_pad3";
drive-strength = <8>;
bias-pull-down;
};
data_4 {
pins = "gpio5";
function = "qpic_pad4";
drive-strength = <8>;
bias-pull-down;
};
data_5 {
pins = "gpio6";
function = "qpic_pad5";
drive-strength = <8>;
bias-pull-down;
};
data_6 {
pins = "gpio7";
function = "qpic_pad6";
drive-strength = <8>;
bias-pull-down;
};
data_7 {
pins = "gpio8";
function = "qpic_pad7";
drive-strength = <8>;
bias-pull-down;
};
qpic_pad {
pins = "gpio1", "gpio3", "gpio4",
"gpio10", "gpio11", "gpio17";
function = "qpic_pad";
drive-strength = <8>;
bias-pull-down;
};
};
button_pins: button_pins {
rst_button {
pins = "gpio19";
function = "gpio";
drive-strength = <8>;
bias-pull-up;
};
};
mdio_pins: mdio_pinmux {
mux_0 {
pins = "gpio64";
function = "mdc";
drive-strength = <8>;
bias-pull-up;
};
mux_1 {
pins = "gpio65";
function = "mdio";
drive-strength = <8>;
bias-pull-up;
};
mux_2 {
pins = "gpio75";
function = "gpio";
bias-pull-up;
};
};
leds_pins: leds_pins {
led_blue {
pins = "gpio35";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
led_green {
pins = "gpio37";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
led_red {
pins = "gpio32";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
};
};
&soc {
mdio: mdio@90000 {
status = "ok";
pinctrl-0 = <&mdio_pins>;
pinctrl-names = "default";
phy-reset-gpio = <&tlmm 75 0>;
ethernet-phy@0 {
reg = <0x03>;
};
ethernet-phy@1 {
reg = <0x04>;
};
};
ess-switch@3a000000 {
switch_cpu_bmp = <0x01>; /* cpu port bitmap */
switch_lan_bmp = <0x10>; /* lan port bitmap */
switch_wan_bmp = <0x20>; /* wan port bitmap */
switch_inner_bmp = <0x80>; /*inner port bitmap*/
switch_mac_mode = <0x00>; /* mac mode for uniphy instance0*/
switch_mac_mode1 = <0xff>; /* mac mode for uniphy instance1*/
switch_mac_mode2 = <0xff>; /* mac mode for uniphy instance2*/
qcom,port_phyinfo {
port@3 {
port_id = <0x04>;
phy_address = <0x03>;
};
port@4 {
port_id = <0x05>;
phy_address = <0x04>;
};
};
};
dp1 {
device_type = "network";
compatible = "qcom,nss-dp";
qcom,id = <0x05>;
reg = <0x3a001800 0x200>;
qcom,mactype = <0x00>;
local-mac-address = [00 00 00 00 00 00];
qcom,link-poll = <0x01>;
qcom,phy-mdio-addr = <0x04>;
phy-mode = "sgmii";
};
dp2 {
device_type = "network";
compatible = "qcom,nss-dp";
qcom,id = <0x04>;
reg = <0x3a001600 0x200>;
qcom,mactype = <0x00>;
local-mac-address = [00 00 00 00 00 00];
qcom,link-poll = <0x01>;
qcom,phy-mdio-addr = <0x03>;
phy-mode = "sgmii";
};
gpio_keys {
compatible = "gpio-keys";
pinctrl-0 = <&button_pins>;
pinctrl-names = "default";
reset {
label = "reset";
linux,code = <KEY_RESTART>;
gpios = <&tlmm 19 GPIO_ACTIVE_LOW>;
linux,input-type = <1>;
debounce-interval = <60>;
};
};
leds {
compatible = "gpio-leds";
pinctrl-0 = <&leds_pins>;
pinctrl-names = "default";
led_system: system {
label = "ax860:green:system";
gpio = <&tlmm 37 GPIO_ACTIVE_HIGH>;
};
wlan2g {
label = "ax860:blue:wlan2g";
gpio = <&tlmm 35 GPIO_ACTIVE_HIGH>;
};
wlan5g {
label = "ax860:red:wlan5g";
gpio = <&tlmm 32 GPIO_ACTIVE_HIGH>;
};
};
};
&blsp1_uart3 {
pinctrl-0 = <&uart_pins>;
pinctrl-names = "default";
status = "ok";
};
&spi_0 {
pinctrl-0 = <&spi_0_pins>;
pinctrl-names = "default";
cs-select = <0>;
status = "ok";
m25p80@0 {
#address-cells = <1>;
#size-cells = <1>;
reg = <0>;
compatible = "n25q128a11";
linux,modalias = "m25p80", "n25q128a11";
spi-max-frequency = <50000000>;
use-default-sizes;
};
};
&qpic_bam {
status = "ok";
};
&nand {
pinctrl-0 = <&qpic_pins>;
pinctrl-names = "default";
status = "ok";
};
&nss_crypto {
status = "ok";
};
&cpu0_opp_table {
compatible = "operating-points-v2";
opp-shared;
opp03 {
opp-hz = /bits/ 64 <1200000000>;
opp-microvolt = <3>;
clock-latency-ns = <200000>;
};
/delete-node/ opp04;
/delete-node/ opp05;
/delete-node/ opp06;
};
&qseecom {
mem-start = <0x49B00000>;
mem-size = <0x600000>;
status = "ok";
};

View File

@@ -51,7 +51,7 @@
#ifdef __IPQ_MEM_PROFILE_256_MB__
bootargs-append = " swiotlb=1";
#else
bootargs-append = " swiotlb=1 coherent_pool=2M";
bootargs-append = " swiotlb=1 coherent_pool=2M vmalloc=600M";
#endif
};

View File

@@ -18,6 +18,17 @@ define Device/edgecore_eap104
endef
TARGET_DEVICES += edgecore_eap104
define Device/motorola_q14
DEVICE_TITLE := Motorola Q14
DEVICE_DTS := qcom-ipq5018-q14
SUPPORTED_DEVICES := motorola,q14
DEVICE_PACKAGES := ath11k-wifi-motorola-q14 ath11k-firmware-ipq50xx-spruce ath11k-firmware-qcn6122
DEVICE_DTS_CONFIG := config@mp03.5-c1
IMAGES := sysupgrade.tar mmc-factory.bin
IMAGE/mmc-factory.bin := append-ubi | qsdk-ipq-factory-mmc
endef
#TARGET_DEVICES += motorola_q14
define Device/qcom_mp03_1
DEVICE_TITLE := Qualcomm Maple 03.1
DEVICE_DTS := qcom-ipq5018-mp03.1

View File

@@ -1,16 +1,5 @@
KERNEL_LOADADDR := 0x41008000
define Device/cig_wf188
DEVICE_TITLE := Cigtech WF-188
DEVICE_DTS := qcom-ipq6018-cig-wf188
DEVICE_DTS_CONFIG := config@cp03-c1
SUPPORTED_DEVICES := cig,wf188
IMAGES := sysupgrade.tar
IMAGE/sysupgrade.tar/squashfs := append-rootfs | pad-rootfs | sysupgrade-tar rootfs=$$$$@ | append-metadata
DEVICE_PACKAGES := ath11k-wifi-cig-wf188 uboot-env
endef
TARGET_DEVICES += cig_wf188
define Device/cig_wf188n
DEVICE_TITLE := Cigtech WF-188n
DEVICE_DTS := qcom-ipq6018-cig-wf188n
@@ -43,7 +32,7 @@ define Device/edgecore_eap101
DEVICE_DTS := qcom-ipq6018-edgecore-eap101
DEVICE_DTS_CONFIG := config@cp01-c1
SUPPORTED_DEVICES := edgecore,eap101
DEVICE_PACKAGES := ath11k-wifi-edgecore-eap101 uboot-envtools
DEVICE_PACKAGES := ath11k-wifi-edgecore-eap101 uboot-envtools -kmod-usb-dwc3-of-simple kmod-usb-dwc3-qcom kmod-usb3 kmod-usb2
endef
TARGET_DEVICES += edgecore_eap101
@@ -52,7 +41,7 @@ define Device/wallys_dr6018
DEVICE_DTS := qcom-ipq6018-wallys-dr6018
DEVICE_DTS_CONFIG := config@cp01-c4
SUPPORTED_DEVICES := wallys,dr6018
DEVICE_PACKAGES := ath11k-wifi-wallys-dr6018 uboot-envtools
DEVICE_PACKAGES := ath11k-wifi-wallys-dr6018 uboot-envtools -kmod-usb-dwc3-of-simple kmod-usb-dwc3-qcom kmod-usb3 kmod-usb2
endef
TARGET_DEVICES += wallys_dr6018
@@ -72,3 +61,30 @@ define Device/qcom_cp01_c1
DEVICE_PACKAGES := ath11k-wifi-qcom-ipq6018
endef
TARGET_DEVICES += qcom_cp01_c1
define Device/glinet_ax1800
DEVICE_TITLE := GL-iNet AX1800
DEVICE_DTS := qcom-ipq6018-gl-ax1800
SUPPORTED_DEVICES := glinet,ax1800
DEVICE_DTS_CONFIG := config@cp03-c1
DEVICE_PACKAGES := ath11k-wifi-gl-ax1800 -kmod-usb-dwc3-of-simple kmod-usb-dwc3-qcom kmod-usb3
endef
TARGET_DEVICES += glinet_ax1800
define Device/glinet_axt1800
DEVICE_TITLE := GL-iNet AXT1800
DEVICE_DTS := qcom-ipq6018-gl-axt1800
SUPPORTED_DEVICES := glinet,axt1800
DEVICE_DTS_CONFIG := config@cp03-c1
DEVICE_PACKAGES := ath11k-wifi-gl-axt1800 -kmod-usb-dwc3-of-simple kmod-usb-dwc3-qcom kmod-usb3
endef
TARGET_DEVICES += glinet_axt1800
define Device/yuncore_ax840
DEVICE_TITLE := YunCore AX840
DEVICE_DTS := qcom-ipq6018-yuncore-ax840
DEVICE_DTS_CONFIG := config@cp03-c1
SUPPORTED_DEVICES := yuncore,ax840
DEVICE_PACKAGES := ath11k-wifi-yuncore-ax840 uboot-env
endef
TARGET_DEVICES += yuncore_ax840

View File

@@ -41,6 +41,8 @@ define Device/cig_wf196
DEVICE_DTS := qcom-ipq807x-wf196
DEVICE_DTS_CONFIG=config@hk14
SUPPORTED_DEVICES := cig,wf196
BLOCKSIZE := 256k
PAGESIZE := 4096
DEVICE_PACKAGES := ath11k-wifi-cig-wf196 aq-fw-download uboot-envtools kmod-usb3 kmod-usb2 \
ath11k-firmware-qcn9000 ath11k-wifi-cig-wf196_6g
endef

View File

@@ -111,3 +111,22 @@ define KernelPackage/diag-char/description
endef
$(eval $(call KernelPackage,diag-char))
define KernelPackage/usb-dwc3-qcom
TITLE:=DWC3 Qualcomm USB driver
DEPENDS:=@(!LINUX_4_14) @TARGET_ipq807x +kmod-usb-dwc3
KCONFIG:= CONFIG_USB_DWC3_QCOM
FILES:= $(LINUX_DIR)/drivers/usb/dwc3/dwc3-qcom.ko \
$(LINUX_DIR)/drivers/usb/dwc3/dbm.ko
AUTOLOAD:=$(call AutoLoad,53,dwc3-qcom dbm,1)
$(call AddDepends/usb)
endef
define KernelPackage/usb-dwc3-qcom/description
Some Qualcomm SoCs use DesignWare Core IP for USB2/3 functionality.
This driver also handles Qscratch wrapper which is needed for
peripheral mode support.
endef
$(eval $(call KernelPackage,usb-dwc3-qcom))

View File

@@ -0,0 +1,25 @@
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -96,10 +96,10 @@ obj-dirs := $(addprefix $(obj)/,$(obj-di
# Note: Files that end up in two or more modules are compiled without the
# KBUILD_MODNAME definition. The reason is that any made-up name would
# differ in different configs.
-name-fix = $(subst $(comma),_,$(subst -,_,$1))
-basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
+name-fix = $(squote)$(quote)$(subst $(comma),_,$(subst -,_,$1))$(quote)$(squote)
+basename_flags = -DKBUILD_BASENAME=$(call name-fix,$(basetarget))
modname_flags = $(if $(filter 1,$(words $(modname))),\
- -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
+ -DKBUILD_MODNAME=$(call name-fix,$(modname)))
orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
$(ccflags-y) $(CFLAGS_$(basetarget).o)
@@ -155,7 +155,7 @@ endif
c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(__c_flags) $(modkern_cflags) \
- -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
+ $(basename_flags) $(modname_flags)
a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(__a_flags) $(modkern_aflags)

View File

@@ -0,0 +1,36 @@
From fd65e5a95d08389444e8591a20538b3edece0e15 Mon Sep 17 00:00:00 2001
From: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Date: Fri, 31 Jul 2020 19:26:16 +0300
Subject: [PATCH] net: bridge: clear bridge's private skb space on xmit
We need to clear all of the bridge private skb variables as they can be
stale due to the packet being recirculated through the stack and then
transmitted through the bridge device. Similar memset is already done on
bridge's input. We've seen cases where proxyarp_replied was 1 on routed
multicast packets transmitted through the bridge to ports with neigh
suppress which were getting dropped. Same thing can in theory happen with
the port isolation bit as well.
Fixes: 821f1b21cabb ("bridge: add new BR_NEIGH_SUPPRESS port flag to suppress arp and nd flood")
Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/bridge/br_device.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 8c7b78f8bc23..9a2fb4aa1a10 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -36,6 +36,8 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
const unsigned char *dest;
u16 vid = 0;
+ memset(skb->cb, 0, sizeof(struct br_input_skb_cb));
+
rcu_read_lock();
nf_ops = rcu_dereference(nf_br_ops);
if (nf_ops && nf_ops->br_dev_xmit_hook(skb)) {
--
2.25.1

View File

@@ -0,0 +1,88 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Mon, 8 Feb 2021 11:34:08 -0800
Subject: [PATCH] net: extract napi poll functionality to __napi_poll()
This commit introduces a new function __napi_poll() which does the main
logic of the existing napi_poll() function, and will be called by other
functions in later commits.
This idea and implementation is done by Felix Fietkau <nbd@nbd.name> and
is proposed as part of the patch to move napi work to work_queue
context.
This commit by itself is a code restructure.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Wei Wang <weiwan@google.com>
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6322,15 +6322,10 @@ void netif_napi_del(struct napi_struct *
}
EXPORT_SYMBOL(netif_napi_del);
-static int napi_poll(struct napi_struct *n, struct list_head *repoll)
+static int __napi_poll(struct napi_struct *n, bool *repoll)
{
- void *have;
int work, weight;
- list_del_init(&n->poll_list);
-
- have = netpoll_poll_lock(n);
-
weight = n->weight;
/* This NAPI_STATE_SCHED test is for avoiding a race
@@ -6348,7 +6343,7 @@ static int napi_poll(struct napi_struct
WARN_ON_ONCE(work > weight);
if (likely(work < weight))
- goto out_unlock;
+ return work;
/* Drivers must not modify the NAPI state if they
* consume the entire weight. In such cases this code
@@ -6357,7 +6352,7 @@ static int napi_poll(struct napi_struct
*/
if (unlikely(napi_disable_pending(n))) {
napi_complete(n);
- goto out_unlock;
+ return work;
}
if (n->gro_bitmask) {
@@ -6375,12 +6370,29 @@ static int napi_poll(struct napi_struct
if (unlikely(!list_empty(&n->poll_list))) {
pr_warn_once("%s: Budget exhausted after napi rescheduled\n",
n->dev ? n->dev->name : "backlog");
- goto out_unlock;
+ return work;
}
- list_add_tail(&n->poll_list, repoll);
+ *repoll = true;
+
+ return work;
+}
+
+static int napi_poll(struct napi_struct *n, struct list_head *repoll)
+{
+ bool do_repoll = false;
+ void *have;
+ int work;
+
+ list_del_init(&n->poll_list);
+
+ have = netpoll_poll_lock(n);
+
+ work = __napi_poll(n, &do_repoll);
+
+ if (do_repoll)
+ list_add_tail(&n->poll_list, repoll);
-out_unlock:
netpoll_poll_unlock(have);
return work;

View File

@@ -0,0 +1,245 @@
From: Wei Wang <weiwan@google.com>
Date: Mon, 8 Feb 2021 11:34:09 -0800
Subject: [PATCH] net: implement threaded-able napi poll loop support
This patch allows running each napi poll loop inside its own
kernel thread.
The kthread is created during netif_napi_add() if dev->threaded
is set. And threaded mode is enabled in napi_enable(). We will
provide a way to set dev->threaded and enable threaded mode
without a device up/down in the following patch.
Once that threaded mode is enabled and the kthread is
started, napi_schedule() will wake-up such thread instead
of scheduling the softirq.
The threaded poll loop behaves quite likely the net_rx_action,
but it does not have to manipulate local irqs and uses
an explicit scheduling point based on netdev_budget.
Co-developed-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Co-developed-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Wei Wang <weiwan@google.com>
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -319,6 +319,7 @@ struct napi_struct {
struct list_head dev_list;
struct hlist_node napi_hash_node;
unsigned int napi_id;
+ struct task_struct *thread;
};
enum {
@@ -326,6 +327,7 @@ enum {
NAPI_STATE_DISABLE, /* Disable pending */
NAPI_STATE_NPSVC, /* Netpoll - don't dequeue from poll_list */
NAPI_STATE_HASHED, /* In NAPI hash */
+ NAPI_STATE_THREADED, /* The poll is performed inside its own thread*/
};
enum gro_result {
@@ -501,13 +503,7 @@ void napi_disable(struct napi_struct *n)
* Resume NAPI from being scheduled on this context.
* Must be paired with napi_disable.
*/
-static inline void napi_enable(struct napi_struct *n)
-{
- BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state));
- smp_mb__before_atomic();
- clear_bit(NAPI_STATE_SCHED, &n->state);
- clear_bit(NAPI_STATE_NPSVC, &n->state);
-}
+void napi_enable(struct napi_struct *n);
/**
* napi_synchronize - wait until NAPI is not running
@@ -1573,6 +1569,8 @@ enum netdev_priv_flags_ext {
* switch driver and used to set the phys state of the
* switch port.
*
+ * @threaded: napi threaded mode is enabled
+ *
* FIXME: cleanup struct net_device such that network protocol info
* moves out.
*/
@@ -1852,6 +1850,7 @@ struct net_device {
struct phy_device *phydev;
struct lock_class_key *qdisc_tx_busylock;
bool proto_down;
+ unsigned threaded:1;
};
#define to_net_dev(d) container_of(d, struct net_device, dev)
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -94,6 +94,7 @@
#include <linux/ethtool.h>
#include <linux/notifier.h>
#include <linux/skbuff.h>
+#include <linux/kthread.h>
#include <net/net_namespace.h>
#include <net/sock.h>
#include <linux/rtnetlink.h>
@@ -1304,6 +1305,27 @@ void netdev_notify_peers(struct net_devi
}
EXPORT_SYMBOL(netdev_notify_peers);
+static int napi_threaded_poll(void *data);
+
+static int napi_kthread_create(struct napi_struct *n)
+{
+ int err = 0;
+
+ /* Create and wake up the kthread once to put it in
+ * TASK_INTERRUPTIBLE mode to avoid the blocked task
+ * warning and work with loadavg.
+ */
+ n->thread = kthread_run(napi_threaded_poll, n, "napi/%s-%d",
+ n->dev->name, n->napi_id);
+ if (IS_ERR(n->thread)) {
+ err = PTR_ERR(n->thread);
+ pr_err("kthread_run failed with err %d\n", err);
+ n->thread = NULL;
+ }
+
+ return err;
+}
+
static int __dev_open(struct net_device *dev)
{
const struct net_device_ops *ops = dev->netdev_ops;
@@ -3248,6 +3270,21 @@ int weight_p __read_mostly = 64;
static inline void ____napi_schedule(struct softnet_data *sd,
struct napi_struct *napi)
{
+ struct task_struct *thread;
+
+ if (test_bit(NAPI_STATE_THREADED, &napi->state)) {
+ /* Paired with smp_mb__before_atomic() in
+ * napi_enable(). Use READ_ONCE() to guarantee
+ * a complete read on napi->thread. Only call
+ * wake_up_process() when it's not NULL.
+ */
+ thread = READ_ONCE(napi->thread);
+ if (thread) {
+ wake_up_process(thread);
+ return;
+ }
+ }
+
list_add_tail(&napi->poll_list, &sd->poll_list);
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
}
@@ -4828,9 +4865,33 @@ void netif_napi_add(struct net_device *d
napi->poll_owner = -1;
#endif
set_bit(NAPI_STATE_SCHED, &napi->state);
+ /* Create kthread for this napi if dev->threaded is set.
+ * Clear dev->threaded if kthread creation failed so that
+ * threaded mode will not be enabled in napi_enable().
+ */
+ if (dev->threaded && napi_kthread_create(napi))
+ dev->threaded = 0;
}
EXPORT_SYMBOL(netif_napi_add);
+/**
+ * napi_enable - enable NAPI scheduling
+ * @n: NAPI context
+ *
+ * Resume NAPI from being scheduled on this context.
+ * Must be paired with napi_disable.
+ */
+void napi_enable(struct napi_struct *n)
+{
+ BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state));
+ smp_mb__before_atomic();
+ clear_bit(NAPI_STATE_SCHED, &n->state);
+ clear_bit(NAPI_STATE_NPSVC, &n->state);
+ if (n->dev->threaded && n->thread)
+ set_bit(NAPI_STATE_THREADED, &n->state);
+}
+EXPORT_SYMBOL(napi_enable);
+
void napi_disable(struct napi_struct *n)
{
might_sleep();
@@ -4844,6 +4905,7 @@ void napi_disable(struct napi_struct *n)
hrtimer_cancel(&n->timer);
clear_bit(NAPI_STATE_DISABLE, &n->state);
+ clear_bit(NAPI_STATE_THREADED, &n->state);
}
EXPORT_SYMBOL(napi_disable);
@@ -4855,6 +4917,11 @@ void netif_napi_del(struct napi_struct *
kfree_skb_list(napi->gro_list);
napi->gro_list = NULL;
napi->gro_count = 0;
+
+ if (napi->thread) {
+ kthread_stop(napi->thread);
+ napi->thread = NULL;
+ }
}
EXPORT_SYMBOL(netif_napi_del);
@@ -4940,6 +5007,50 @@ static int napi_poll(struct napi_struct
return work;
}
+static int napi_thread_wait(struct napi_struct *napi)
+{
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ while (!kthread_should_stop() && !napi_disable_pending(napi)) {
+ if (test_bit(NAPI_STATE_SCHED, &napi->state)) {
+ WARN_ON(!list_empty(&napi->poll_list));
+ __set_current_state(TASK_RUNNING);
+ return 0;
+ }
+
+ schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
+ }
+ __set_current_state(TASK_RUNNING);
+ return -1;
+}
+
+static int napi_threaded_poll(void *data)
+{
+ struct napi_struct *napi = data;
+ void *have;
+
+ while (!napi_thread_wait(napi)) {
+ for (;;) {
+ bool repoll = false;
+
+ local_bh_disable();
+
+ have = netpoll_poll_lock(napi);
+ __napi_poll(napi, &repoll);
+ netpoll_poll_unlock(have);
+
+ local_bh_enable();
+
+ if (!repoll)
+ break;
+
+ cond_resched();
+ }
+ }
+ return 0;
+}
+
static void net_rx_action(struct softirq_action *h)
{
struct softnet_data *sd = this_cpu_ptr(&softnet_data);

View File

@@ -0,0 +1,156 @@
From: Wei Wang <weiwan@google.com>
Date: Mon, 8 Feb 2021 11:34:10 -0800
Subject: [PATCH] net: add sysfs attribute to control napi threaded mode
This patch adds a new sysfs attribute to the network device class.
Said attribute provides a per-device control to enable/disable the
threaded mode for all the napi instances of the given network device,
without the need for a device up/down.
User sets it to 1 or 0 to enable or disable threaded mode.
Note: when switching between threaded and the current softirq based mode
for a napi instance, it will not immediately take effect if the napi is
currently being polled. The mode switch will happen for the next time
napi_schedule() is called.
Co-developed-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Co-developed-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Wei Wang <weiwan@google.com>
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -496,6 +496,8 @@ void napi_hash_del(struct napi_struct *n
*/
void napi_disable(struct napi_struct *n);
+int dev_set_threaded(struct net_device *dev, bool threaded);
+
/**
* napi_enable - enable NAPI scheduling
* @n: napi context
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3274,8 +3274,9 @@ static inline void ____napi_schedule(str
if (test_bit(NAPI_STATE_THREADED, &napi->state)) {
/* Paired with smp_mb__before_atomic() in
- * napi_enable(). Use READ_ONCE() to guarantee
- * a complete read on napi->thread. Only call
+ * napi_enable()/dev_set_threaded().
+ * Use READ_ONCE() to guarantee a complete
+ * read on napi->thread. Only call
* wake_up_process() when it's not NULL.
*/
thread = READ_ONCE(napi->thread);
@@ -4844,6 +4845,49 @@ static enum hrtimer_restart napi_watchdo
return HRTIMER_NORESTART;
}
+int dev_set_threaded(struct net_device *dev, bool threaded)
+{
+ struct napi_struct *napi;
+ int err = 0;
+
+ if (dev->threaded == threaded)
+ return 0;
+
+ if (threaded) {
+ list_for_each_entry(napi, &dev->napi_list, dev_list) {
+ if (!napi->thread) {
+ err = napi_kthread_create(napi);
+ if (err) {
+ threaded = false;
+ break;
+ }
+ }
+ }
+ }
+
+ dev->threaded = threaded;
+
+ /* Make sure kthread is created before THREADED bit
+ * is set.
+ */
+ smp_mb__before_atomic();
+
+ /* Setting/unsetting threaded mode on a napi might not immediately
+ * take effect, if the current napi instance is actively being
+ * polled. In this case, the switch between threaded mode and
+ * softirq mode will happen in the next round of napi_schedule().
+ * This should not cause hiccups/stalls to the live traffic.
+ */
+ list_for_each_entry(napi, &dev->napi_list, dev_list) {
+ if (threaded)
+ set_bit(NAPI_STATE_THREADED, &napi->state);
+ else
+ clear_bit(NAPI_STATE_THREADED, &napi->state);
+ }
+
+ return err;
+}
+
void netif_napi_add(struct net_device *dev, struct napi_struct *napi,
int (*poll)(struct napi_struct *, int), int weight)
{
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -486,6 +486,45 @@ static ssize_t phys_switch_id_show(struc
}
static DEVICE_ATTR_RO(phys_switch_id);
+static ssize_t threaded_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct net_device *netdev = to_net_dev(dev);
+ ssize_t ret = -EINVAL;
+
+ if (!rtnl_trylock())
+ return restart_syscall();
+
+ if (dev_isalive(netdev))
+ ret = sprintf(buf, fmt_dec, netdev->threaded);
+
+ rtnl_unlock();
+ return ret;
+}
+
+static int modify_napi_threaded(struct net_device *dev, unsigned long val)
+{
+ int ret;
+
+ if (list_empty(&dev->napi_list))
+ return -EOPNOTSUPP;
+
+ if (val != 0 && val != 1)
+ return -EOPNOTSUPP;
+
+ ret = dev_set_threaded(dev, val);
+
+ return ret;
+}
+
+static ssize_t threaded_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ return netdev_store(dev, attr, buf, len, modify_napi_threaded);
+}
+static DEVICE_ATTR_RW(threaded);
+
static struct attribute *net_class_attrs[] = {
&dev_attr_netdev_group.attr,
&dev_attr_type.attr,
@@ -514,6 +553,7 @@ static struct attribute *net_class_attrs
&dev_attr_phys_port_name.attr,
&dev_attr_phys_switch_id.attr,
&dev_attr_proto_down.attr,
+ &dev_attr_threaded.attr,
NULL,
};
ATTRIBUTE_GROUPS(net_class);

View File

@@ -0,0 +1,118 @@
From: Wei Wang <weiwan@google.com>
Date: Mon, 1 Mar 2021 17:21:13 -0800
Subject: [PATCH] net: fix race between napi kthread mode and busy poll
Currently, napi_thread_wait() checks for NAPI_STATE_SCHED bit to
determine if the kthread owns this napi and could call napi->poll() on
it. However, if socket busy poll is enabled, it is possible that the
busy poll thread grabs this SCHED bit (after the previous napi->poll()
invokes napi_complete_done() and clears SCHED bit) and tries to poll
on the same napi. napi_disable() could grab the SCHED bit as well.
This patch tries to fix this race by adding a new bit
NAPI_STATE_SCHED_THREADED in napi->state. This bit gets set in
____napi_schedule() if the threaded mode is enabled, and gets cleared
in napi_complete_done(), and we only poll the napi in kthread if this
bit is set. This helps distinguish the ownership of the napi between
kthread and other scenarios and fixes the race issue.
Fixes: 29863d41bb6e ("net: implement threaded-able napi poll loop support")
Reported-by: Martin Zaharinov <micron10@gmail.com>
Suggested-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Wei Wang <weiwan@google.com>
Cc: Alexander Duyck <alexanderduyck@fb.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -328,6 +328,7 @@ enum {
NAPI_STATE_NPSVC, /* Netpoll - don't dequeue from poll_list */
NAPI_STATE_HASHED, /* In NAPI hash */
NAPI_STATE_THREADED, /* The poll is performed inside its own thread*/
+ NAPI_STATE_SCHED_THREADED, /* Napi is currently scheduled in threaded mode */
};
enum gro_result {
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3281,6 +3281,8 @@ static inline void ____napi_schedule(str
*/
thread = READ_ONCE(napi->thread);
if (thread) {
+ if (thread->state != TASK_INTERRUPTIBLE)
+ set_bit(NAPI_STATE_SCHED_THREADED, &napi->state);
wake_up_process(thread);
return;
}
@@ -4745,12 +4747,14 @@ void __napi_complete(struct napi_struct
list_del_init(&n->poll_list);
smp_mb__before_atomic();
clear_bit(NAPI_STATE_SCHED, &n->state);
+ clear_bit(NAPI_STATE_SCHED_THREADED, &n->state);
}
EXPORT_SYMBOL(__napi_complete);
void napi_complete_done(struct napi_struct *n, int work_done)
{
unsigned long flags;
+ unsigned long val, new;
/*
* don't let napi dequeue from the cpu poll list
@@ -4771,14 +4775,19 @@ void napi_complete_done(struct napi_stru
else
napi_gro_flush(n, false);
}
- if (likely(list_empty(&n->poll_list))) {
- WARN_ON_ONCE(!test_and_clear_bit(NAPI_STATE_SCHED, &n->state));
- } else {
- /* If n->poll_list is not empty, we need to mask irqs */
- local_irq_save(flags);
- __napi_complete(n);
- local_irq_restore(flags);
- }
+
+ /* If n->poll_list is not empty, we need to mask irqs */
+ local_irq_save(flags);
+ list_del_init(&n->poll_list);
+ local_irq_restore(flags);
+
+ do {
+ val = READ_ONCE(n->state);
+
+ WARN_ON_ONCE(!(val & BIT(NAPI_STATE_SCHED)));
+ new = val & ~(BIT(NAPI_STATE_SCHED) |
+ BIT(NAPI_STATE_SCHED_THREADED));
+ } while (cmpxchg(&n->state, val, new) != val);
}
EXPORT_SYMBOL(napi_complete_done);
@@ -5053,16 +5062,25 @@ static int napi_poll(struct napi_struct
static int napi_thread_wait(struct napi_struct *napi)
{
+ bool woken = false;
+
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop() && !napi_disable_pending(napi)) {
- if (test_bit(NAPI_STATE_SCHED, &napi->state)) {
+ /* Testing SCHED_THREADED bit here to make sure the current
+ * kthread owns this napi and could poll on this napi.
+ * Testing SCHED bit is not enough because SCHED bit might be
+ * set by some other busy poll thread or by napi_disable().
+ */
+ if (test_bit(NAPI_STATE_SCHED_THREADED, &napi->state) || woken) {
WARN_ON(!list_empty(&napi->poll_list));
__set_current_state(TASK_RUNNING);
return 0;
}
schedule();
+ /* woken being true indicates this thread owns this napi. */
+ woken = true;
set_current_state(TASK_INTERRUPTIBLE);
}
__set_current_state(TASK_RUNNING);

View File

@@ -0,0 +1,53 @@
From: Paolo Abeni <pabeni@redhat.com>
Date: Fri, 9 Apr 2021 17:24:17 +0200
Subject: [PATCH] net: fix hangup on napi_disable for threaded napi
napi_disable() is subject to an hangup, when the threaded
mode is enabled and the napi is under heavy traffic.
If the relevant napi has been scheduled and the napi_disable()
kicks in before the next napi_threaded_wait() completes - so
that the latter quits due to the napi_disable_pending() condition,
the existing code leaves the NAPI_STATE_SCHED bit set and the
napi_disable() loop waiting for such bit will hang.
This patch addresses the issue by dropping the NAPI_STATE_DISABLE
bit test in napi_thread_wait(). The later napi_threaded_poll()
iteration will take care of clearing the NAPI_STATE_SCHED.
This also addresses a related problem reported by Jakub:
before this patch a napi_disable()/napi_enable() pair killed
the napi thread, effectively disabling the threaded mode.
On the patched kernel napi_disable() simply stops scheduling
the relevant thread.
v1 -> v2:
- let the main napi_thread_poll() loop clear the SCHED bit
Reported-by: Jakub Kicinski <kuba@kernel.org>
Fixes: 29863d41bb6e ("net: implement threaded-able napi poll loop support")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/883923fa22745a9589e8610962b7dc59df09fb1f.1617981844.git.pabeni@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5066,7 +5066,7 @@ static int napi_thread_wait(struct napi_
set_current_state(TASK_INTERRUPTIBLE);
- while (!kthread_should_stop() && !napi_disable_pending(napi)) {
+ while (!kthread_should_stop()) {
/* Testing SCHED_THREADED bit here to make sure the current
* kthread owns this napi and could poll on this napi.
* Testing SCHED bit is not enough because SCHED bit might be
@@ -5084,6 +5084,7 @@ static int napi_thread_wait(struct napi_
set_current_state(TASK_INTERRUPTIBLE);
}
__set_current_state(TASK_RUNNING);
+
return -1;
}

View File

@@ -0,0 +1,439 @@
From: Daniel Borkmann <daniel@iogearbox.net>
Date: Thu, 7 Jan 2016 22:29:47 +0100
Subject: [PATCH] net, sched: add clsact qdisc
This work adds a generalization of the ingress qdisc as a qdisc holding
only classifiers. The clsact qdisc works on ingress, but also on egress.
In both cases, it's execution happens without taking the qdisc lock, and
the main difference for the egress part compared to prior version of [1]
is that this can be applied with _any_ underlying real egress qdisc (also
classless ones).
Besides solving the use-case of [1], that is, allowing for more programmability
on assigning skb->priority for the mqprio case that is supported by most
popular 10G+ NICs, it also opens up a lot more flexibility for other tc
applications. The main work on classification can already be done at clsact
egress time if the use-case allows and state stored for later retrieval
f.e. again in skb->priority with major/minors (which is checked by most
classful qdiscs before consulting tc_classify()) and/or in other skb fields
like skb->tc_index for some light-weight post-processing to get to the
eventual classid in case of a classful qdisc. Another use case is that
the clsact egress part allows to have a central egress counterpart to
the ingress classifiers, so that classifiers can easily share state (e.g.
in cls_bpf via eBPF maps) for ingress and egress.
Currently, default setups like mq + pfifo_fast would require for this to
use, for example, prio qdisc instead (to get a tc_classify() run) and to
duplicate the egress classifier for each queue. With clsact, it allows
for leaving the setup as is, it can additionally assign skb->priority to
put the skb in one of pfifo_fast's bands and it can share state with maps.
Moreover, we can access the skb's dst entry (f.e. to retrieve tclassid)
w/o the need to perform a skb_dst_force() to hold on to it any longer. In
lwt case, we can also use this facility to setup dst metadata via cls_bpf
(bpf_skb_set_tunnel_key()) without needing a real egress qdisc just for
that (case of IFF_NO_QUEUE devices, for example).
The realization can be done without any changes to the scheduler core
framework. All it takes is that we have two a-priori defined minors/child
classes, where we can mux between ingress and egress classifier list
(dev->ingress_cl_list and dev->egress_cl_list, latter stored close to
dev->_tx to avoid extra cacheline miss for moderate loads). The egress
part is a bit similar modelled to handle_ing() and patched to a noop in
case the functionality is not used. Both handlers are now called
sch_handle_ingress() and sch_handle_egress(), code sharing among the two
doesn't seem practical as there are various minor differences in both
paths, so that making them conditional in a single handler would rather
slow things down.
Full compatibility to ingress qdisc is provided as well. Since both
piggyback on TC_H_CLSACT, only one of them (ingress/clsact) can exist
per netdevice, and thus ingress qdisc specific behaviour can be retained
for user space. This means, either a user does 'tc qdisc add dev foo ingress'
and configures ingress qdisc as usual, or the 'tc qdisc add dev foo clsact'
alternative, where both, ingress and egress classifier can be configured
as in the below example. ingress qdisc supports attaching classifier to any
minor number whereas clsact has two fixed minors for muxing between the
lists, therefore to not break user space setups, they are better done as
two separate qdiscs.
I decided to extend the sch_ingress module with clsact functionality so
that commonly used code can be reused, the module is being aliased with
sch_clsact so that it can be auto-loaded properly. Alternative would have been
to add a flag when initializing ingress to alter its behaviour plus aliasing
to a different name (as it's more than just ingress). However, the first would
end up, based on the flag, choosing the new/old behaviour by calling different
function implementations to handle each anyway, the latter would require to
register ingress qdisc once again under different alias. So, this really begs
to provide a minimal, cleaner approach to have Qdisc_ops and Qdisc_class_ops
by its own that share callbacks used by both.
Example, adding qdisc:
# tc qdisc add dev foo clsact
# tc qdisc show dev foo
qdisc mq 0: root
qdisc pfifo_fast 0: parent :1 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: parent :2 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: parent :3 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: parent :4 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc clsact ffff: parent ffff:fff1
Adding filters (deleting, etc works analogous by specifying ingress/egress):
# tc filter add dev foo ingress bpf da obj bar.o sec ingress
# tc filter add dev foo egress bpf da obj bar.o sec egress
# tc filter show dev foo ingress
filter protocol all pref 49152 bpf
filter protocol all pref 49152 bpf handle 0x1 bar.o:[ingress] direct-action
# tc filter show dev foo egress
filter protocol all pref 49152 bpf
filter protocol all pref 49152 bpf handle 0x1 bar.o:[egress] direct-action
A 'tc filter show dev foo' or 'tc filter show dev foo parent ffff:' will
show an empty list for clsact. Either using the parent names (ingress/egress)
or specifying the full major/minor will then show the related filter lists.
Prior work on a mqprio prequeue() facility [1] was done mainly by John Fastabend.
[1] http://patchwork.ozlabs.org/patch/512949/
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1770,7 +1770,9 @@ struct net_device {
#ifdef CONFIG_XPS
struct xps_dev_maps __rcu *xps_maps;
#endif
-
+#ifdef CONFIG_NET_CLS_ACT
+ struct tcf_proto __rcu *egress_cl_list;
+#endif
#ifdef CONFIG_NET_SWITCHDEV
u32 offload_fwd_mark;
#endif
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -84,6 +84,11 @@ void net_inc_ingress_queue(void);
void net_dec_ingress_queue(void);
#endif
+#ifdef CONFIG_NET_EGRESS
+void net_inc_egress_queue(void);
+void net_dec_egress_queue(void);
+#endif
+
extern void rtnetlink_init(void);
extern void __rtnl_unlock(void);
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -72,6 +72,10 @@ struct tc_estimator {
#define TC_H_UNSPEC (0U)
#define TC_H_ROOT (0xFFFFFFFFU)
#define TC_H_INGRESS (0xFFFFFFF1U)
+#define TC_H_CLSACT TC_H_INGRESS
+
+#define TC_H_MIN_INGRESS 0xFFF2U
+#define TC_H_MIN_EGRESS 0xFFF3U
/* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */
enum tc_link_layer {
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1697,6 +1697,22 @@ void net_dec_ingress_queue(void)
EXPORT_SYMBOL_GPL(net_dec_ingress_queue);
#endif
+#ifdef CONFIG_NET_EGRESS
+static struct static_key egress_needed __read_mostly;
+
+void net_inc_egress_queue(void)
+{
+ static_key_slow_inc(&egress_needed);
+}
+EXPORT_SYMBOL_GPL(net_inc_egress_queue);
+
+void net_dec_egress_queue(void)
+{
+ static_key_slow_dec(&egress_needed);
+}
+EXPORT_SYMBOL_GPL(net_dec_egress_queue);
+#endif
+
static struct static_key netstamp_needed __read_mostly;
#ifdef HAVE_JUMP_LABEL
static atomic_t netstamp_needed_deferred;
@@ -2936,7 +2952,6 @@ static inline int __dev_xmit_skb(struct
bool contended;
int rc;
- qdisc_pkt_len_init(skb);
qdisc_calculate_pkt_len(skb, q);
/*
* Heuristic to force contended enqueues to serialize on a
@@ -3028,6 +3043,49 @@ int dev_loopback_xmit(struct net *net, s
}
EXPORT_SYMBOL(dev_loopback_xmit);
+#ifdef CONFIG_NET_EGRESS
+static struct sk_buff *
+sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
+{
+ struct tcf_proto *cl = rcu_dereference_bh(dev->egress_cl_list);
+ struct tcf_result cl_res;
+
+ if (!cl)
+ return skb;
+
+ /* skb->tc_verd and qdisc_skb_cb(skb)->pkt_len were already set
+ * earlier by the caller.
+ */
+ qdisc_bstats_cpu_update(cl->q, skb);
+
+ switch (tc_classify(skb, cl, &cl_res, false)) {
+ case TC_ACT_OK:
+ case TC_ACT_RECLASSIFY:
+ skb->tc_index = TC_H_MIN(cl_res.classid);
+ break;
+ case TC_ACT_SHOT:
+ qdisc_qstats_cpu_drop(cl->q);
+ *ret = NET_XMIT_DROP;
+ goto drop;
+ case TC_ACT_STOLEN:
+ case TC_ACT_QUEUED:
+ *ret = NET_XMIT_SUCCESS;
+drop:
+ kfree_skb(skb);
+ return NULL;
+ case TC_ACT_REDIRECT:
+ /* No need to push/pop skb's mac_header here on egress! */
+ skb_do_redirect(skb);
+ *ret = NET_XMIT_SUCCESS;
+ return NULL;
+ default:
+ break;
+ }
+
+ return skb;
+}
+#endif /* CONFIG_NET_EGRESS */
+
static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
{
#ifdef CONFIG_XPS
@@ -3152,6 +3210,17 @@ static int __dev_queue_xmit(struct sk_bu
skb_update_prio(skb);
+ qdisc_pkt_len_init(skb);
+#ifdef CONFIG_NET_CLS_ACT
+ skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS);
+# ifdef CONFIG_NET_EGRESS
+ if (static_key_false(&egress_needed)) {
+ skb = sch_handle_egress(skb, &rc, dev);
+ if (!skb)
+ goto out;
+ }
+# endif
+#endif
/* If device/qdisc don't need skb->dst, release it right now while
* its hot in this cpu cache.
*/
@@ -3173,9 +3242,6 @@ static int __dev_queue_xmit(struct sk_bu
txq = netdev_pick_tx(dev, skb, accel_priv);
q = rcu_dereference_bh(txq->qdisc);
-#ifdef CONFIG_NET_CLS_ACT
- skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS);
-#endif
trace_net_dev_queue(skb);
if (q->enqueue) {
rc = __dev_xmit_skb(skb, q, dev, txq);
@@ -3750,9 +3816,9 @@ int (*br_fdb_test_addr_hook)(struct net_
EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook);
#endif
-static inline struct sk_buff *handle_ing(struct sk_buff *skb,
- struct packet_type **pt_prev,
- int *ret, struct net_device *orig_dev)
+static inline struct sk_buff *
+sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
+ struct net_device *orig_dev)
{
#ifdef CONFIG_NET_CLS_ACT
struct tcf_proto *cl = rcu_dereference_bh(skb->dev->ingress_cl_list);
@@ -3974,7 +4040,7 @@ another_round:
skip_taps:
#ifdef CONFIG_NET_INGRESS
if (static_key_false(&ingress_needed)) {
- skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
+ skb = sch_handle_ingress(skb, &pt_prev, &ret, orig_dev);
if (!skb)
goto out;
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -54,6 +54,9 @@ config COMPAT_NETLINK_MESSAGES
config NET_INGRESS
bool
+config NET_EGRESS
+ bool
+
menu "Networking options"
source "net/packet/Kconfig"
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -291,7 +291,7 @@ static int cls_bpf_prog_from_efd(struct
prog->bpf_name = name;
prog->filter = fp;
- if (fp->dst_needed)
+ if (fp->dst_needed && !(tp->q->flags & TCQ_F_INGRESS))
netif_keep_dst(qdisc_dev(tp->q));
return 0;
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -342,15 +342,21 @@ config NET_SCH_PIE
If unsure, say N.
config NET_SCH_INGRESS
- tristate "Ingress Qdisc"
+ tristate "Ingress/classifier-action Qdisc"
depends on NET_CLS_ACT
select NET_INGRESS
+ select NET_EGRESS
---help---
- Say Y here if you want to use classifiers for incoming packets.
+ Say Y here if you want to use classifiers for incoming and/or outgoing
+ packets. This qdisc doesn't do anything else besides running classifiers,
+ which can also have actions attached to them. In case of outgoing packets,
+ classifiers that this qdisc holds are executed in the transmit path
+ before real enqueuing to an egress qdisc happens.
+
If unsure, say Y.
- To compile this code as a module, choose M here: the
- module will be called sch_ingress.
+ To compile this code as a module, choose M here: the module will be
+ called sch_ingress with alias of sch_clsact.
config NET_SCH_PLUG
tristate "Plug network traffic until release (PLUG)"
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -1,4 +1,5 @@
-/* net/sched/sch_ingress.c - Ingress qdisc
+/* net/sched/sch_ingress.c - Ingress and clsact qdisc
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -98,17 +99,100 @@ static struct Qdisc_ops ingress_qdisc_op
.owner = THIS_MODULE,
};
+static unsigned long clsact_get(struct Qdisc *sch, u32 classid)
+{
+ switch (TC_H_MIN(classid)) {
+ case TC_H_MIN(TC_H_MIN_INGRESS):
+ case TC_H_MIN(TC_H_MIN_EGRESS):
+ return TC_H_MIN(classid);
+ default:
+ return 0;
+ }
+}
+
+static unsigned long clsact_bind_filter(struct Qdisc *sch,
+ unsigned long parent, u32 classid)
+{
+ return clsact_get(sch, classid);
+}
+
+static struct tcf_proto __rcu **clsact_find_tcf(struct Qdisc *sch,
+ unsigned long cl)
+{
+ struct net_device *dev = qdisc_dev(sch);
+
+ switch (cl) {
+ case TC_H_MIN(TC_H_MIN_INGRESS):
+ return &dev->ingress_cl_list;
+ case TC_H_MIN(TC_H_MIN_EGRESS):
+ return &dev->egress_cl_list;
+ default:
+ return NULL;
+ }
+}
+
+static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
+{
+ net_inc_ingress_queue();
+ net_inc_egress_queue();
+
+ sch->flags |= TCQ_F_CPUSTATS;
+
+ return 0;
+}
+
+static void clsact_destroy(struct Qdisc *sch)
+{
+ struct net_device *dev = qdisc_dev(sch);
+
+ tcf_destroy_chain(&dev->ingress_cl_list);
+ tcf_destroy_chain(&dev->egress_cl_list);
+
+ net_dec_ingress_queue();
+ net_dec_egress_queue();
+}
+
+static const struct Qdisc_class_ops clsact_class_ops = {
+ .leaf = ingress_leaf,
+ .get = clsact_get,
+ .put = ingress_put,
+ .walk = ingress_walk,
+ .tcf_chain = clsact_find_tcf,
+ .bind_tcf = clsact_bind_filter,
+ .unbind_tcf = ingress_put,
+};
+
+static struct Qdisc_ops clsact_qdisc_ops __read_mostly = {
+ .cl_ops = &clsact_class_ops,
+ .id = "clsact",
+ .init = clsact_init,
+ .destroy = clsact_destroy,
+ .dump = ingress_dump,
+ .owner = THIS_MODULE,
+};
+
static int __init ingress_module_init(void)
{
- return register_qdisc(&ingress_qdisc_ops);
+ int ret;
+
+ ret = register_qdisc(&ingress_qdisc_ops);
+ if (!ret) {
+ ret = register_qdisc(&clsact_qdisc_ops);
+ if (ret)
+ unregister_qdisc(&ingress_qdisc_ops);
+ }
+
+ return ret;
}
static void __exit ingress_module_exit(void)
{
unregister_qdisc(&ingress_qdisc_ops);
+ unregister_qdisc(&clsact_qdisc_ops);
}
module_init(ingress_module_init);
module_exit(ingress_module_exit);
+MODULE_ALIAS("sch_clsact");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,75 @@
From: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Date: Thu, 13 Oct 2016 09:06:41 +0300
Subject: [PATCH] net/sched: act_mirred: Rename tcfm_ok_push to
tcfm_mac_header_xmit and make it a bool
'tcfm_ok_push' specifies whether a mac_len sized push is needed upon
egress to the target device (if action is performed at ingress).
Rename it to 'tcfm_mac_header_xmit' as this is actually an attribute of
the target device (and use a bool instead of int).
This allows to decouple the attribute from the action to be taken.
Signed-off-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
--- a/include/net/tc_act/tc_mirred.h
+++ b/include/net/tc_act/tc_mirred.h
@@ -7,7 +7,7 @@ struct tcf_mirred {
struct tcf_common common;
int tcfm_eaction;
int tcfm_ifindex;
- int tcfm_ok_push;
+ bool tcfm_mac_header_xmit;
struct net_device __rcu *tcfm_dev;
struct list_head tcfm_list;
};
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -55,10 +55,11 @@ static int tcf_mirred_init(struct net *n
int bind)
{
struct nlattr *tb[TCA_MIRRED_MAX + 1];
+ bool mac_header_xmit = false;
struct tc_mirred *parm;
struct tcf_mirred *m;
struct net_device *dev;
- int ret, ok_push = 0;
+ int ret;
if (nla == NULL)
return -EINVAL;
@@ -86,10 +87,10 @@ static int tcf_mirred_init(struct net *n
case ARPHRD_IPGRE:
case ARPHRD_VOID:
case ARPHRD_NONE:
- ok_push = 0;
+ mac_header_xmit = false;
break;
default:
- ok_push = 1;
+ mac_header_xmit = true;
break;
}
} else {
@@ -123,7 +124,7 @@ static int tcf_mirred_init(struct net *n
dev_put(rcu_dereference_protected(m->tcfm_dev, 1));
dev_hold(dev);
rcu_assign_pointer(m->tcfm_dev, dev);
- m->tcfm_ok_push = ok_push;
+ m->tcfm_mac_header_xmit = mac_header_xmit;
}
if (ret == ACT_P_CREATED) {
@@ -169,7 +170,7 @@ static int tcf_mirred(struct sk_buff *sk
goto out;
if (!(at & AT_EGRESS)) {
- if (m->tcfm_ok_push)
+ if (m->tcfm_mac_header_xmit)
skb_push_rcsum(skb2, skb->mac_len);
}

View File

@@ -0,0 +1,36 @@
From: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Date: Thu, 13 Oct 2016 09:06:42 +0300
Subject: [PATCH] net/sched: act_mirred: Refactor detection whether dev needs
xmit at mac header
Move detection logic that tests whether device expects skb data to point
at mac_header upon xmit into a function.
Signed-off-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -80,19 +80,7 @@ static int tcf_mirred_init(struct net *n
dev = __dev_get_by_index(net, parm->ifindex);
if (dev == NULL)
return -ENODEV;
- switch (dev->type) {
- case ARPHRD_TUNNEL:
- case ARPHRD_TUNNEL6:
- case ARPHRD_SIT:
- case ARPHRD_IPGRE:
- case ARPHRD_VOID:
- case ARPHRD_NONE:
- mac_header_xmit = false;
- break;
- default:
- mac_header_xmit = true;
- break;
- }
+ mac_header_xmit = dev_is_mac_header_xmit(dev);
} else {
dev = NULL;
}

View File

@@ -0,0 +1,125 @@
From: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Date: Thu, 13 Oct 2016 09:06:44 +0300
Subject: [PATCH] net/sched: act_mirred: Implement ingress actions
Up until now, 'action mirred' supported only egress actions (either
TCA_EGRESS_REDIR or TCA_EGRESS_MIRROR).
This patch implements the corresponding ingress actions
TCA_INGRESS_REDIR and TCA_INGRESS_MIRROR.
This allows attaching filters whose target is to hand matching skbs into
the rx processing of a specified device.
Signed-off-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Cong Wang <xiyou.wangcong@gmail.com>
Tested-by: Jamal Hadi Salim <jhs@mojatatu.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -33,6 +33,25 @@
static LIST_HEAD(mirred_list);
static DEFINE_SPINLOCK(mirred_list_lock);
+static bool tcf_mirred_is_act_redirect(int action)
+{
+ return action == TCA_EGRESS_REDIR || action == TCA_INGRESS_REDIR;
+}
+
+static u32 tcf_mirred_act_direction(int action)
+{
+ switch (action) {
+ case TCA_EGRESS_REDIR:
+ case TCA_EGRESS_MIRROR:
+ return AT_EGRESS;
+ case TCA_INGRESS_REDIR:
+ case TCA_INGRESS_MIRROR:
+ return AT_INGRESS;
+ default:
+ BUG();
+ }
+}
+
static void tcf_mirred_release(struct tc_action *a, int bind)
{
struct tcf_mirred *m = to_mirred(a);
@@ -72,6 +91,8 @@ static int tcf_mirred_init(struct net *n
switch (parm->eaction) {
case TCA_EGRESS_MIRROR:
case TCA_EGRESS_REDIR:
+ case TCA_INGRESS_REDIR:
+ case TCA_INGRESS_MIRROR:
break;
default:
return -EINVAL;
@@ -129,9 +150,12 @@ static int tcf_mirred(struct sk_buff *sk
struct tcf_result *res)
{
struct tcf_mirred *m = a->priv;
+ bool m_mac_header_xmit;
struct net_device *dev;
struct sk_buff *skb2;
- int retval, err;
+ int retval, err = 0;
+ int m_eaction;
+ int mac_len;
u32 at;
tcf_lastuse_update(&m->tcf_tm);
@@ -139,6 +163,8 @@ static int tcf_mirred(struct sk_buff *sk
bstats_cpu_update(this_cpu_ptr(m->common.cpu_bstats), skb);
rcu_read_lock();
+ m_mac_header_xmit = READ_ONCE(m->tcfm_mac_header_xmit);
+ m_eaction = READ_ONCE(m->tcfm_eaction);
retval = READ_ONCE(m->tcf_action);
dev = rcu_dereference(m->tcfm_dev);
if (unlikely(!dev)) {
@@ -157,24 +183,37 @@ static int tcf_mirred(struct sk_buff *sk
if (!skb2)
goto out;
- if (!(at & AT_EGRESS)) {
- if (m->tcfm_mac_header_xmit)
+ /* If action's target direction differs than filter's direction,
+ * and devices expect a mac header on xmit, then mac push/pull is
+ * needed.
+ */
+ if (at != tcf_mirred_act_direction(m_eaction) && m_mac_header_xmit) {
+ if (at & AT_EGRESS) {
+ /* caught at egress, act ingress: pull mac */
+ mac_len = skb_network_header(skb) - skb_mac_header(skb);
+ skb_pull_rcsum(skb2, mac_len);
+ } else {
+ /* caught at ingress, act egress: push mac */
skb_push_rcsum(skb2, skb->mac_len);
+ }
}
/* mirror is always swallowed */
- if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
+ if (tcf_mirred_is_act_redirect(m_eaction))
skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at);
skb2->skb_iif = skb->dev->ifindex;
skb2->dev = dev;
skb_sender_cpu_clear(skb2);
- err = dev_queue_xmit(skb2);
+ if (tcf_mirred_act_direction(m_eaction) & AT_EGRESS)
+ err = dev_queue_xmit(skb2);
+ else
+ err = netif_receive_skb(skb2);
if (err) {
out:
qstats_overlimit_inc(this_cpu_ptr(m->common.cpu_qstats));
- if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
+ if (tcf_mirred_is_act_redirect(m_eaction))
retval = TC_ACT_SHOT;
}
rcu_read_unlock();

View File

@@ -1,67 +0,0 @@
#
# Copyright (C) 2011 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=libprotobuf-c
PKG_VERSION:=1.3.1
PKG_RELEASE:=2
PKG_SOURCE:=protobuf-c-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/protobuf-c/protobuf-c/releases/download/v$(PKG_VERSION)
PKG_HASH:=51472d3a191d6d7b425e32b612e477c06f73fe23e07f6a6a839b11808e9d2267
PKG_BUILD_DIR:=$(BUILD_DIR)/protobuf-c-$(PKG_VERSION)
HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/protobuf-c-$(PKG_VERSION)
PKG_MAINTAINER:=Rosen Penev <rosenp@gmail.com>
PKG_LICENSE:=BSD-2c
PKG_BUILD_DEPENDS:=protobuf-c/host
HOST_BUILD_DEPENDS:=protobuf/host
PKG_INSTALL:=1
PKG_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/host-build.mk
define Package/libprotobuf-c
TITLE:=Protocol Buffers library
SECTION:=libs
CATEGORY:=Libraries
URL:=https://github.com/protobuf-c/protobuf-c
endef
define Package/libprotobuf-c/description
Runtime library to use Google Protocol Buffers from C applications.
Protocol Buffers are a way of encoding structured data in an efficient yet
extensible format. Google uses Protocol Buffers for almost all of its
internal RPC protocols and file formats.
endef
CONFIGURE_ARGS += \
--enable-shared \
--enable-static \
--disable-protoc
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include/
$(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libprotobuf-c.{a,la,so*} $(1)/usr/lib/
$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/* $(1)/usr/lib/pkgconfig/
endef
define Package/libprotobuf-c/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libprotobuf-c.so.* $(1)/usr/lib/
endef
$(eval $(call BuildPackage,libprotobuf-c))
$(eval $(call HostBuild))

View File

@@ -1,13 +0,0 @@
Index: protobuf-c-1.3.1/t/generated-code2/cxx-generate-packed-data.cc
===================================================================
--- protobuf-c-1.3.1.orig/t/generated-code2/cxx-generate-packed-data.cc
+++ protobuf-c-1.3.1/t/generated-code2/cxx-generate-packed-data.cc
@@ -998,7 +998,7 @@ static void dump_test_packed_repeated_en
static void dump_test_unknown_fields (void)
{
EmptyMess mess;
- const google::protobuf::Message::Reflection *reflection = mess.GetReflection();
+ const google::protobuf::Reflection *reflection = mess.GetReflection();
google::protobuf::UnknownFieldSet *fs = reflection->MutableUnknownFields(&mess);
#if GOOGLE_PROTOBUF_VERSION >= 2001000

View File

@@ -1,110 +0,0 @@
#
# Copyright (C) 2007-2015 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=protobuf
PKG_VERSION:=3.7.1
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-cpp-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/google/protobuf/releases/download/v$(PKG_VERSION)
PKG_HASH:=97f6cdaa0724d5a8cd3375d5f5cf4bd253d5ad5291154f533ed0d94a9d501ef3
PKG_LICENSE:=BSD-3-Clause
PKG_LICENSE_FILES:=LICENSE
PKG_CPE_ID:=cpe:/a:google:protobuf
PKG_BUILD_DEPENDS:=protobuf/host
PKG_BUILD_PARALLEL:=1
PKG_INSTALL:=1
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/host-build.mk
define Package/protobuf/Default
SECTION:=libs
CATEGORY:=Libraries
TITLE:=A structured data encoding library
URL:=https://github.com/google/protobuf
DEPENDS:=+zlib +libpthread +libatomic +libstdcpp
MAINTAINER:=Ken Keys <kkeys@caida.org>
endef
define Package/protobuf
$(call Package/protobuf/Default)
DEPENDS+=+protobuf-lite
endef
define Package/protobuf-lite
$(call Package/protobuf/Default)
endef
define Package/protobuf/description/Default
Protocol Buffers are a way of encoding structured data in an efficient
yet extensible format. Google uses Protocol Buffers for almost all
of its internal RPC protocols and file formats.
endef
define Package/protobuf/description
$(call Package/protobuf/description/Default)
This package provides the libprotoc, libprotobuf, and libprotobuf-lite
libraries. For a much smaller protobuf package, see "protobuf-lite".
endef
define Package/protobuf-lite/description
$(call Package/protobuf/description/Default)
This package provides the libprotobuf-lite library.
endef
EXTRA_CPPFLAGS+=-std=c++11
CONFIGURE_ARGS += --with-protoc=$(STAGING_DIR_HOSTPKG)/bin/protoc
define Build/InstallDev
$(INSTALL_DIR) \
$(1)/usr/lib \
$(1)/usr/include
$(CP) \
$(PKG_INSTALL_DIR)/usr/include/* \
$(1)/usr/include/
$(CP) \
$(PKG_INSTALL_DIR)/usr/lib/* \
$(1)/usr/lib/
endef
define Package/protobuf-lite/install
$(INSTALL_DIR) \
$(1)/usr/lib
$(CP) \
$(PKG_INSTALL_DIR)/usr/lib/libprotobuf-lite.so* \
$(1)/usr/lib/
endef
define Package/protobuf/install
$(INSTALL_DIR) \
$(1)/usr/lib
$(CP) \
$(PKG_INSTALL_DIR)/usr/lib/libprotoc.so* \
$(1)/usr/lib/
$(CP) \
$(PKG_INSTALL_DIR)/usr/lib/libprotobuf.so* \
$(1)/usr/lib/
endef
$(eval $(call BuildPackage,protobuf))
$(eval $(call BuildPackage,protobuf-lite))
$(eval $(call HostBuild))

View File

@@ -0,0 +1,11 @@
--- a/nss_hal/nss_hal.c
+++ b/nss_hal/nss_hal.c
@@ -306,6 +306,8 @@ int nss_hal_probe(struct platform_device
* Initialize the dummy netdevice.
*/
init_dummy_netdev(&nss_ctx->napi_ndev);
+ strcpy(nss_ctx->napi_ndev.name, "nss");
+ nss_ctx->napi_ndev.threaded = 1;
for (i = 0; i < npd->num_irq; i++) {
err = nss_hal_register_irq(nss_ctx, npd, &nss_ctx->napi_ndev, i);

View File

@@ -0,0 +1,55 @@
#
# Copyright (C) 2016-2019 Jason A. Donenfeld <Jason@zx2c4.com>
# Copyright (C) 2016 Baptiste Jonglez <openwrt@bitsofnetworks.org>
# Copyright (C) 2016-2017 Dan Luedtke <mail@danrl.com>
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=wireguard-backport
PKG_VERSION:=1.0.20211208
PKG_RELEASE:=1
PKG_SOURCE:=wireguard-linux-compat-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://git.zx2c4.com/wireguard-linux-compat/snapshot/
PKG_HASH:=c0e607138a17daac656f508d8e63ea3737b5221fa5d9288191ddeb099f5a3b92
PKG_LICENSE:=GPL-2.0
PKG_LICENSE_FILES:=COPYING
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/wireguard-linux-compat-$(PKG_VERSION)
PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0
# WireGuard's makefile needs this to know where to build the kernel module
export KERNELDIR:=$(LINUX_DIR)
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/kernel-defaults.mk
include $(INCLUDE_DIR)/package-defaults.mk
define Build/Compile
$(MAKE) $(KERNEL_MAKEOPTS) M="$(PKG_BUILD_DIR)/src" modules
endef
define KernelPackage/wireguard-backport
SECTION:=kernel
CATEGORY:=Kernel modules
SUBMENU:=Network Support
TITLE:=WireGuard kernel module
DEPENDS:=+IPV6:kmod-udptunnel6 +kmod-udptunnel4
FILES:= $(PKG_BUILD_DIR)/src/wireguard.$(LINUX_KMOD_SUFFIX)
AUTOLOAD:=$(call AutoProbe,wireguard)
endef
define KernelPackage/wireguard-backport/description
$(call Package/wireguard/Default/description)
This package provides the kernel module for WireGuard.
endef
$(eval $(call KernelPackage,wireguard-backport))

View File

@@ -0,0 +1,29 @@
Index: wireguard-linux-compat-1.0.20211208/src/compat/compat.h
===================================================================
--- wireguard-linux-compat-1.0.20211208.orig/src/compat/compat.h
+++ wireguard-linux-compat-1.0.20211208/src/compat/compat.h
@@ -11,6 +11,8 @@
#include <linux/types.h>
#include <generated/utsrelease.h>
+#define fallthrough
+
#ifdef RHEL_MAJOR
#if RHEL_MAJOR == 7
#define ISRHEL7
@@ -686,15 +688,6 @@ struct __compat_dummy_container { char d
#define genl_dump_check_consistent(a, b) genl_dump_check_consistent(a, b, &genl_family)
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) && !defined(ISRHEL7)
-static inline void *skb_put_data(struct sk_buff *skb, const void *data, unsigned int len)
-{
- void *tmp = skb_put(skb, len);
- memcpy(tmp, data, len);
- return tmp;
-}
-#endif
-
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) && !defined(ISRHEL7)
#define napi_complete_done(n, work_done) napi_complete(n)
#endif

View File

@@ -2,6 +2,17 @@
START=80
copy_certificates() {
[ -f /certificates/dev-id ] || return
cp /certificates/*.pem /etc/ucentral/
cp /certificates/dev-id /etc/ucentral/
chown root.network /etc/ucentral/*.pem
chmod 0440 root.network /etc/ucentral/*.pem
chmod 0400 /etc/ucentral/dev-id
exit 0
}
boot() {
[ -f /etc/ucentral/dev-id ] && return
. /lib/functions.sh
@@ -17,11 +28,49 @@ boot() {
[ -e /dev/ubi1 ] && mount -t ubifs ubi1:certificates /certificates
fi
fi
[ -f /certificates/dev-id ] && {
cp /certificates/*.pem /etc/ucentral/
cp /certificates/dev-id /etc/ucentral/
chown root.network /etc/ucentral/*.pem
chmod 0440 root.network /etc/ucentral/*.pem
chmod 0400 /etc/ucentral/dev-id
}
copy_certificates
# if we get here no valid certificates were found
. /lib/functions.sh
local PART_NAME
case "$(board_name)" in
actiontec,web7200)
if grep -q bootselect=0 /proc/cmdline; then
PART_NAME=firmware2
else
PART_NAME=firmware1
fi
;;
edgecore,ecw5211|\
edgecore,eap101|\
edgecore,eap102)
if grep -q rootfs1 /proc/cmdline; then
PART_NAME=rootfs2
else
PART_NAME=rootfs1
fi
;;
hfcl,ion4xi|\
hfcl,ion4xe)
if grep -q rootfs_1 /proc/cmdline; then
PART_NAME=rootfs
else
PART_NAME=rootfs_1
fi
;;
*)
return 1
;;
esac
local MTD=$(find_mtd_index $PART_NAME)
[ -z "$MTD" ] && return 1
ubiattach -m $MTD -d 3
[ -e /dev/ubi3 ] && mount -t ubifs ubi3:certificates /certificates
copy_certificates
}

View File

@@ -8,7 +8,7 @@ generate_certificate_volume() {
ubinfo /dev/ubi0 -N certificates > /dev/null
[ $? -eq 0 ] || {
ubirsvol /dev/ubi0 -N rootfs_data -s 20MiB
ubimkvol /dev/ubi0 -N certificates -s 2MiB
ubimkvol /dev/ubi0 -N certificates -S 20
}
}

View File

@@ -8,13 +8,13 @@ PROG=/usr/bin/ucode
start_service() {
[ -f /etc/ucentral/capabilities.json ] || {
mkdir -p /etc/ucentral/
ucode -m ubus -E board=/etc/board.json /usr/share/ucentral/capabilities.uc > /etc/ucentral/capabilities.json
/usr/share/ucentral/capabilities.uc
}
/usr/share/ucentral/ucentral.uc /etc/ucentral/ucentral.cfg.0000000001 > /dev/null
procd_open_instance
procd_set_param command "$PROG" -m uci -m fs -i /usr/share/ucentral/firstcontact.uc
procd_set_param command "$PROG" -l uci -l fs /usr/share/ucentral/firstcontact.uc
procd_set_param respawn 1 10 0
procd_close_instance
}

View File

@@ -1,4 +1,3 @@
{%
let devid;
let fd = fs.open("/etc/ucentral/dev-id", "r");
if (!fd) {
@@ -62,4 +61,3 @@ system("/etc/init.d/firstcontact disable");
system("reload_config");
system("/etc/init.d/ucentral start");
system("/etc/init.d/firstcontact stop");
%}

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2008-2012 OpenWrt.org
# Copyright (C) 2021 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
@@ -9,26 +9,31 @@ include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=qosify
PKG_RELEASE:=1
PKG_SOURCE_URL=$(PROJECT_GIT)/project/qosify.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2022-03-06
PKG_SOURCE_VERSION:=f13b67c9a786567df240a8f3f608e2724ddaadba
PKG_MIRROR_HASH:=3d8629e711e46a6be79a46a6394165fd1761687f24b8ed954dc4f16f177cd90f
PKG_RELEASE:=$(AUTORELEASE)
PKG_LICENSE:=GPL-2.0
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_BUILD_DEPENDS:=bpf-headers
PKG_FLAGS:=nonshared
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
include $(INCLUDE_DIR)/bpf.mk
include $(INCLUDE_DIR)/nls.mk
define Package/qosify
SECTION:=kernel
CATEGORY:=Kernel modules
SUBMENU:=Network Support
TITLE:=QoS classifier eBPF module
DEPENDS:=+libbpf +libubox +libubus +kmod-sched-cake +tc-full
PKGFLAGS+=nonshared
SECTION:=utils
CATEGORY:=Base system
TITLE:=A simple QoS solution based eBPF + CAKE
DEPENDS:=+libbpf +libubox +libubus +kmod-sched-cake +kmod-sched-bpf +kmod-ifb +tc-full $(BPF_DEPENDS)
endef
BPF_DOC = $(wildcard $(patsubst %,$(BPF_HEADERS_DIR)/scripts/%.py,bpf_doc bpf_helpers_doc))
define Build/Compile
$(call CompileBPF,$(PKG_BUILD_DIR)/qosify-bpf.c)
$(Build/Compile/Default)
@@ -36,17 +41,28 @@ endef
define Package/qosify/conffiles
/etc/config/qosify
/etc/qosify-defaults.conf
/etc/qosify/00-defaults.conf
endef
define Package/qosify/install
$(INSTALL_DIR) $(1)/lib/bpf $(1)/usr/sbin $(1)/etc/init.d $(1)/etc/config $(1)/etc/hotplug.d/net
$(INSTALL_DIR) \
$(1)/lib/bpf \
$(1)/usr/sbin \
$(1)/etc/init.d \
$(1)/etc/config \
$(1)/etc/qosify \
$(1)/etc/hotplug.d/net \
$(1)/etc/hotplug.d/iface
$(INSTALL_DATA) $(PKG_BUILD_DIR)/qosify-bpf.o $(1)/lib/bpf
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qosify $(1)/usr/sbin/
$(INSTALL_BIN) \
$(PKG_INSTALL_DIR)/usr/bin/qosify \
./files/qosify-status \
$(1)/usr/sbin/
$(INSTALL_BIN) ./files/qosify.init $(1)/etc/init.d/qosify
$(INSTALL_DATA) ./files/qosify-defaults.conf $(1)/etc/qosify-defaults.conf
$(INSTALL_DATA) ./files/qosify-defaults.conf $(1)/etc/qosify/00-defaults.conf
$(INSTALL_DATA) ./files/qosify.conf $(1)/etc/config/qosify
$(INSTALL_DATA) ./files/qosify.hotplug $(1)/etc/hotplug.d/net/10-qosify
$(INSTALL_DATA) ./files/qosify.hotplug $(1)/etc/hotplug.d/iface/10-qosify
endef
$(eval $(call BuildPackage,qosify))

View File

@@ -1,17 +1,17 @@
# DNS
tcp:53 CS5
tcp:5353 CS5
udp:53 CS5
udp:5353 CS5
tcp:53 voice
tcp:5353 voice
udp:53 voice
udp:5353 voice
# NTP
udp:123 CS6
udp:123 voice
# SSH
tcp:22 +CS4
tcp:22 +video
# HTTP/QUIC
tcp:80 +CS3
tcp:443 +CS3
udp:80 +CS3
udp:443 +CS3
tcp:80 +besteffort
tcp:443 +besteffort
udp:80 +besteffort
udp:443 +besteffort

View File

@@ -0,0 +1,70 @@
#!/bin/sh
. /usr/share/libubox/jshn.sh
dev_status() {
tc -s qdisc sh dev "$1" root
echo
}
common_status() {
json_get_vars ifname ingress egress
[ -n "$ifname" ] || return
[ "$egress" -gt 0 ] && {
echo "egress status:"
dev_status "$ifname"
}
[ "$ingress" -gt 0 ] && {
echo "ingress status:"
dev_status "$(printf %.16s "ifb-$ifname")"
}
}
is_active() {
json_get_vars active
[ "${active:-0}" -gt 0 ]
}
device_status() {
local name="$2"
json_select "$name"
if is_active; then
status="active"
else
status="not found"
fi
echo "===== device $name: $status ====="
is_active && common_status
json_select ..
}
interface_status() {
local name="$2"
json_select "$name"
if is_active; then
status="active"
elif ubus -S -t 0 wait_for "network.interface.$name"; then
status="down"
else
status="not found"
fi
echo "===== interface $name: $status ====="
is_active && common_status
json_select ..
}
json_load "$(ubus call qosify status)"
json_for_each_item device_status devices
json_for_each_item interface_status interfaces

View File

@@ -1,24 +1,42 @@
config defaults
list defaults /etc/qosify-defaults.conf
option dscp_prio CS5
option dscp_icmp CS6
option dscp_bulk CS0
option dscp_default_udp CS4
option bulk_trigger_timeout 5
option bulk_trigger_pps 100
list defaults /etc/qosify/*.conf
option dscp_prio video
option dscp_icmp +besteffort
option dscp_default_udp besteffort
option prio_max_avg_pkt_len 500
config class besteffort
option ingress CS0
option egress CS0
config class bulk
option ingress LE
option egress LE
config class video
option ingress AF41
option egress AF41
config class voice
option ingress CS6
option egress CS6
option bulk_trigger_pps 100
option bulk_trigger_timeout 5
option dscp_bulk CS0
config interface wan
option name wan
option disabled 1
option bandwidth_up 100mbit
option bandwidth_down 100mbit
option overhead_type none
# defaults:
option ingress 1
option egress 1
option mode diffserv4
option nat 1
option host_isolate 1
option autorate_ingress 1
option autorate_ingress 0
option ingress_options ""
option egress_options ""
option options ""

View File

@@ -1,5 +1,5 @@
#!/bin/sh /etc/rc.common
# Copyright (c) 2014 OpenWrt.org
# Copyright (c) 2021 OpenWrt.org
START=19
@@ -15,6 +15,16 @@ add_option() {
[ -n "$val" ] && json_add_$type "$name" "$val"
}
add_flow_config() {
local cfg="$1"
add_option string dscp_prio
add_option string dscp_bulk
add_option int bulk_trigger_timeout
add_option int bulk_trigger_pps
add_option int prio_max_avg_pkt_len
}
add_defaults() {
cfg="$1"
@@ -27,15 +37,11 @@ add_defaults() {
done
json_close_array
add_flow_config "$cfg"
add_option int timeout
add_option string dscp_prio
add_option string dscp_bulk
add_option string dscp_icmp
add_option string dscp_default_udp
add_option string dscp_default_tcp
add_option int bulk_trigger_timeout
add_option int bulk_trigger_pps
add_option int prio_max_avg_pkt_len
}
add_interface() {
@@ -61,15 +67,70 @@ add_interface() {
add_option boolean ingress
add_option boolean egress
add_option string mode
add_option boolean nat
add_option boolean host_isolate
add_option boolean autorate_ingress
add_option string ingress_options
add_option string egress_options
add_option string options
config_get user_options "$cfg" options
config_get otype "$cfg" overhead_type
options=
case "$otype" in
none);;
manual)
config_get overhead "$cfg" overhead
[ -n "$overhead" ] && append options "overhead $overhead"
config_get encap "$cfg" overhead_encap
[ -n "$encap" ] && append options "$encap"
;;
conservative|\
pppoa-vcmux|\
pppoa-llc|\
pppoe-vcmux|\
pppoe-llcsnap|\
bridged-vcmux|\
bridged-llcsnap|\
ipoa-vcmux|\
ipoa-llcsnap|\
pppoe-ptm|\
bridged-ptm|\
docsis|\
ethernet)
append options "$otype"
;;
esac
config_get mpu "$cfg" overhead_mpu
[ -n "$mpu" ] && append options "mpu $mpu"
config_get ovlan "$cfg" overhead_vlan
[ "${ovlan:-0}" -ge 2 ] && append options "ether-vlan"
[ "${ovlan:-0}" -ge 1 ] && append options "ether-vlan"
[ -n "$user_options" ] && append options "$user_options"
[ -n "$options" ] && json_add_string options "$options"
json_close_object
}
add_class() {
local cfg="$1"
config_get value "$cfg" value
config_get ingress "$cfg" ingress
config_get egress "$cfg" egress
json_add_object "$cfg"
json_add_string ingress "${ingress:-$value}"
json_add_string egress "${egress:-$value}"
add_flow_config "$cfg"
json_close_object
}
reload_service() {
json_init
@@ -81,6 +142,11 @@ reload_service() {
config_foreach add_interface interface
json_close_object
json_add_object classes
config_foreach add_class class
config_foreach add_class alias
json_close_object
json_add_object devices
config_foreach add_interface device
json_close_object

View File

@@ -1,15 +0,0 @@
cmake_minimum_required(VERSION 3.10)
PROJECT(qosify C)
ADD_DEFINITIONS(-Os -Wall -Wno-unknown-warning-option -Wno-array-bounds -Wno-format-truncation -Werror --std=gnu99)
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
find_library(bpf NAMES bpf)
ADD_EXECUTABLE(qosify main.c loader.c map.c ubus.c interface.c)
TARGET_LINK_LIBRARIES(qosify ${bpf} ubox ubus)
INSTALL(TARGETS qosify
RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
)

View File

@@ -1,112 +0,0 @@
QoSify is simple daemon for setting up and managing CAKE along with a custom
eBPF based classifier that sets DSCP fields of packets.
It supports the following features:
- simple TCP/UDP port based mapping
- IP address based mapping
- priority boosting based on average packet size
- bulk flow detection based on number of packets per second
- dynamically add IP entries with timeout
- dns regex entries and ubus api for providing dns lookup results
It can be configured via ubus call qosify config.
This call supports the following parameters:
- "reset": BOOL
Reset the config to defaults instead of only updating supplied values
- "files": ARRAY of STRING
List of files with port/IP/host mappings
- "timeout": INT32
Default timeout for dynamically added entries
- "dscp_default_udp": STRING
Default DSCP value for UDP packets
- "dscp_default_tcp": STRING
Default DSCP value for TCP packets
- "dscp_prio": STRING
DSCP value for priority-marked packets
- "dscp_bulk": STRING
DSCP value for bulk-marked packets
- "dscp_icmp": STRING
DSCP value for ICMP packets
- "bulk_trigger_pps": INT32
Number of packets per second to trigger bulk flow detection
- "bulk_trigger_timeout": INT32
Time below bulk_trigger_pps threshold until a bulk flow mark is removed
- "prio_max_avg_pkt_len": INT32
Maximum average packet length for marking a flow as priority
- "interfaces": TABLE of TABLE
netifd interfaces to enable QoS on
- "devices": TABLE of TABLE
netdevs to enable QoS on
interface/device properties:
- "bandwidth_up": STRING
Uplink bandwidth (same format as tc)
- "bandwidth_down": STRING
Downlink bandwidth (same format as tc)
- "ingress": BOOL
Enable ingress shaping
- "egress": BOOL
Enable egress shaping
- "mode": STRING
CAKE diffserv mode
- "nat": BOOL
Enable CAKE NAT host detection via conntrack
- "host_isolate": BOOL
Enable CAKE host isolation
- "autorate_ingress": BOOL
Enable CAKE automatic rate estimation for ingress
- "ingress_options": STRING
CAKE ingress options
- "egress_options": STRING
CAKE egress options
- "options": STRING
CAKE options for ingress + egress
Mapping file syntax:
Each line has two whitespace separated fields, match and dscp
match is one of:
- tcp:<port>[-<endport>]
TCP single port, or range from <port> to <endport>
- udp:<port>[-<endport>]
UDP single port, or range from <port> to <endport>
- <ipaddr>
IPv4 address, e.g. 1.1.1.1
- <ipv6addr>
IPv6 address, e.g. ff01::1
- dns:<regex>
POSIX.2 extended regular expression for matching hostnames
Only works, if dns lookups are passed to qosify via the add_dns_host ubus call.
dscp can be a raw value, or a codepoint like CS0
Adding a + in front of the value tells qosify to only override the DSCP value if it is zero
Planned features:
- Integration with dnsmasq to support hostname pattern based DSCP marking
- Support for LAN host based priority

View File

@@ -1,563 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <net/if_arp.h>
#include <net/if.h>
#include <unistd.h>
#include <errno.h>
#include <libubox/vlist.h>
#include <libubox/avl-cmp.h>
#include <libubox/uloop.h>
#include "qosify.h"
static void interface_update_cb(struct vlist_tree *tree,
struct vlist_node *node_new,
struct vlist_node *node_old);
static VLIST_TREE(devices, avl_strcmp, interface_update_cb, true, false);
static VLIST_TREE(interfaces, avl_strcmp, interface_update_cb, true, false);
static int socket_fd;
#define APPEND(_buf, _ofs, _format, ...) _ofs += snprintf(_buf + _ofs, sizeof(_buf) - _ofs, _format, ##__VA_ARGS__)
struct qosify_iface_config {
struct blob_attr *data;
bool ingress;
bool egress;
bool nat;
bool host_isolate;
bool autorate_ingress;
const char *bandwidth_up;
const char *bandwidth_down;
const char *mode;
const char *common_opts;
const char *ingress_opts;
const char *egress_opts;
};
struct qosify_iface {
struct vlist_node node;
char ifname[IFNAMSIZ];
bool active;
bool device;
struct blob_attr *config_data;
struct qosify_iface_config config;
};
enum {
IFACE_ATTR_BW_UP,
IFACE_ATTR_BW_DOWN,
IFACE_ATTR_INGRESS,
IFACE_ATTR_EGRESS,
IFACE_ATTR_MODE,
IFACE_ATTR_NAT,
IFACE_ATTR_HOST_ISOLATE,
IFACE_ATTR_AUTORATE_IN,
IFACE_ATTR_INGRESS_OPTS,
IFACE_ATTR_EGRESS_OPTS,
IFACE_ATTR_OPTS,
__IFACE_ATTR_MAX
};
static inline const char *qosify_iface_name(struct qosify_iface *iface)
{
return iface->node.avl.key;
}
static void
iface_config_parse(struct blob_attr *attr, struct blob_attr **tb)
{
static const struct blobmsg_policy policy[__IFACE_ATTR_MAX] = {
[IFACE_ATTR_BW_UP] = { "bandwidth_up", BLOBMSG_TYPE_STRING },
[IFACE_ATTR_BW_DOWN] = { "bandwidth_down", BLOBMSG_TYPE_STRING },
[IFACE_ATTR_INGRESS] = { "ingress", BLOBMSG_TYPE_BOOL },
[IFACE_ATTR_EGRESS] = { "egress", BLOBMSG_TYPE_BOOL },
[IFACE_ATTR_MODE] = { "mode", BLOBMSG_TYPE_STRING },
[IFACE_ATTR_NAT] = { "nat", BLOBMSG_TYPE_BOOL },
[IFACE_ATTR_HOST_ISOLATE] = { "host_isolate", BLOBMSG_TYPE_BOOL },
[IFACE_ATTR_AUTORATE_IN] = { "autorate_ingress", BLOBMSG_TYPE_BOOL },
[IFACE_ATTR_INGRESS_OPTS] = { "ingress_options", BLOBMSG_TYPE_STRING },
[IFACE_ATTR_EGRESS_OPTS] = { "egress_options", BLOBMSG_TYPE_STRING },
[IFACE_ATTR_OPTS] = { "options", BLOBMSG_TYPE_STRING },
};
blobmsg_parse(policy, __IFACE_ATTR_MAX, tb, blobmsg_data(attr), blobmsg_len(attr));
}
static bool
iface_config_equal(struct qosify_iface *if1, struct qosify_iface *if2)
{
struct blob_attr *tb1[__IFACE_ATTR_MAX], *tb2[__IFACE_ATTR_MAX];
int i;
iface_config_parse(if1->config_data, tb1);
iface_config_parse(if2->config_data, tb2);
for (i = 0; i < __IFACE_ATTR_MAX; i++) {
if (!!tb1[i] != !!tb2[i])
return false;
if (!tb1[i])
continue;
if (blob_raw_len(tb1[i]) != blob_raw_len(tb2[i]))
return false;
if (memcmp(tb1[i], tb2[i], blob_raw_len(tb1[i])) != 0)
return false;
}
return true;
}
static const char *check_str(struct blob_attr *attr)
{
const char *str = blobmsg_get_string(attr);
if (strchr(str, '\''))
return NULL;
return str;
}
static void
iface_config_set(struct qosify_iface *iface, struct blob_attr *attr)
{
struct qosify_iface_config *cfg = &iface->config;
struct blob_attr *tb[__IFACE_ATTR_MAX];
struct blob_attr *cur;
iface_config_parse(attr, tb);
memset(cfg, 0, sizeof(*cfg));
/* defaults */
cfg->mode = "diffserv4";
cfg->ingress = true;
cfg->egress = true;
cfg->host_isolate = true;
cfg->autorate_ingress = true;
cfg->nat = !iface->device;
if ((cur = tb[IFACE_ATTR_BW_UP]) != NULL)
cfg->bandwidth_up = check_str(cur);
if ((cur = tb[IFACE_ATTR_BW_DOWN]) != NULL)
cfg->bandwidth_down = check_str(cur);
if ((cur = tb[IFACE_ATTR_MODE]) != NULL)
cfg->mode = check_str(cur);
if ((cur = tb[IFACE_ATTR_OPTS]) != NULL)
cfg->common_opts = check_str(cur);
if ((cur = tb[IFACE_ATTR_EGRESS_OPTS]) != NULL)
cfg->egress_opts = check_str(cur);
if ((cur = tb[IFACE_ATTR_INGRESS_OPTS]) != NULL)
cfg->ingress_opts = check_str(cur);
if ((cur = tb[IFACE_ATTR_INGRESS]) != NULL)
cfg->ingress = blobmsg_get_bool(cur);
if ((cur = tb[IFACE_ATTR_EGRESS]) != NULL)
cfg->egress = blobmsg_get_bool(cur);
if ((cur = tb[IFACE_ATTR_NAT]) != NULL)
cfg->nat = blobmsg_get_bool(cur);
if ((cur = tb[IFACE_ATTR_HOST_ISOLATE]) != NULL)
cfg->host_isolate = blobmsg_get_bool(cur);
if ((cur = tb[IFACE_ATTR_AUTORATE_IN]) != NULL)
cfg->autorate_ingress = blobmsg_get_bool(cur);
}
static const char *
interface_ifb_name(struct qosify_iface *iface)
{
static char ifname[IFNAMSIZ + 1] = "ifb-";
int len = strlen(iface->ifname);
if (len + 4 < IFNAMSIZ) {
snprintf(ifname + 4, IFNAMSIZ - 4, "%s", iface->ifname);
return ifname;
}
ifname[4] = iface->ifname[0];
ifname[5] = iface->ifname[1];
snprintf(ifname + 6, IFNAMSIZ - 6, "%s", iface->ifname + len - (IFNAMSIZ + 6) - 1);
return ifname;
}
static int run_cmd(char *cmd, bool ignore)
{
char *argv[] = { "sh", "-c", cmd, NULL };
bool first = true;
int status = -1;
char buf[512];
int fds[2];
FILE *f;
int pid;
if (pipe(fds))
return -1;
pid = fork();
if (!pid) {
close(fds[0]);
if (fds[1] != STDOUT_FILENO)
dup2(fds[1], STDOUT_FILENO);
if (fds[1] != STDERR_FILENO)
dup2(fds[1], STDERR_FILENO);
if (fds[1] > STDERR_FILENO)
close(fds[1]);
execv("/bin/sh", argv);
exit(1);
}
if (pid < 0)
return -1;
close(fds[1]);
f = fdopen(fds[0], "r");
if (!f) {
close(fds[0]);
goto out;
}
while (fgets(buf, sizeof(buf), f) != NULL) {
if (!strlen(buf))
break;
if (ignore)
continue;
if (first) {
ULOG_WARN("Command: %s\n", cmd);
first = false;
}
ULOG_WARN("%s%s", buf, strchr(buf, '\n') ? "" : "\n");
}
fclose(f);
out:
while (waitpid(pid, &status, 0) < 0)
if (errno != EINTR)
break;
return status;
}
static int
prepare_tc_cmd(char *buf, int len, const char *type, const char *cmd,
const char *dev, const char *extra)
{
return snprintf(buf, len, "tc %s %s dev '%s' %s", type, cmd, dev, extra);
}
static int
cmd_del_qdisc(const char *ifname, const char *type)
{
char buf[64];
prepare_tc_cmd(buf, sizeof(buf), "qdisc", "del", ifname, type);
return run_cmd(buf, true);
}
static int
cmd_add_qdisc(struct qosify_iface *iface, const char *ifname, bool egress, bool eth)
{
struct qosify_iface_config *cfg = &iface->config;
const char *bw = egress ? cfg->bandwidth_up : cfg->bandwidth_down;
const char *dir_opts = egress ? cfg->egress_opts : cfg->ingress_opts;
char buf[512];
int ofs;
cmd_del_qdisc(ifname, "root");
ofs = prepare_tc_cmd(buf, sizeof(buf), "qdisc", "add", ifname, "root handle 1: cake");
if (bw)
APPEND(buf, ofs, " bandwidth %s", bw);
APPEND(buf, ofs, " %s %sgress", cfg->mode, egress ? "e" : "in");
if (cfg->host_isolate)
APPEND(buf, ofs, " %snat dual-%shost",
cfg->nat ? "" : "no",
egress ? "src" : "dst");
else
APPEND(buf, ofs, " flows");
APPEND(buf, ofs, " %s %s",
cfg->common_opts ? cfg->common_opts : "",
dir_opts ? dir_opts : "");
run_cmd(buf, false);
ofs = prepare_tc_cmd(buf, sizeof(buf), "filter", "add", ifname, "parent 1: bpf");
APPEND(buf, ofs, " object-pinned /sys/fs/bpf/qosify_%sgress_%s verbose direct-action",
egress ? "e" : "in",
eth ? "eth" : "ip");
return run_cmd(buf, false);
}
static int
cmd_del_ingress(struct qosify_iface *iface)
{
char buf[256];
cmd_del_qdisc(iface->ifname, "handle ffff: ingress");
snprintf(buf, sizeof(buf), "ip link del '%s'", interface_ifb_name(iface));
return run_cmd(buf, true);
}
static int
cmd_add_ingress(struct qosify_iface *iface, bool eth)
{
const char *ifbdev = interface_ifb_name(iface);
char buf[256];
int ofs;
cmd_del_ingress(iface);
ofs = prepare_tc_cmd(buf, sizeof(buf), "qdisc", "add", iface->ifname, " handle ffff: ingress");
run_cmd(buf, false);
snprintf(buf, sizeof(buf), "ip link add '%s' type ifb", ifbdev);
run_cmd(buf, false);
cmd_add_qdisc(iface, ifbdev, false, eth);
snprintf(buf, sizeof(buf), "ip link set dev '%s' up", ifbdev);
run_cmd(buf, false);
ofs = prepare_tc_cmd(buf, sizeof(buf), "filter", "add", iface->ifname, " parent ffff:");
APPEND(buf, ofs, " protocol all prio 10 u32 match u32 0 0 "
"flowid 1:1 action mirred egress redirect dev '%s'", ifbdev);
return run_cmd(buf, false);
}
static void
interface_start(struct qosify_iface *iface)
{
struct ifreq ifr = {};
bool eth;
if (!iface->ifname[0] || iface->active)
return;
ULOG_INFO("start interface %s\n", iface->ifname);
strncpy(ifr.ifr_name, iface->ifname, sizeof(ifr.ifr_name));
if (ioctl(socket_fd, SIOCGIFHWADDR, &ifr) < 0) {
ULOG_ERR("ioctl(SIOCGIFHWADDR, %s) failed: %s\n", iface->ifname, strerror(errno));
return;
}
eth = ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER;
if (iface->config.egress)
cmd_add_qdisc(iface, iface->ifname, true, eth);
if (iface->config.ingress)
cmd_add_ingress(iface, eth);
iface->active = true;
}
static void
interface_stop(struct qosify_iface *iface)
{
if (!iface->ifname[0] || !iface->active)
return;
ULOG_INFO("stop interface %s\n", iface->ifname);
iface->active = false;
if (iface->config.egress)
cmd_del_qdisc(iface->ifname, "root");
if (iface->config.ingress)
cmd_del_ingress(iface);
}
static void
interface_set_config(struct qosify_iface *iface, struct blob_attr *config)
{
iface->config_data = blob_memdup(config);
iface_config_set(iface, iface->config_data);
interface_start(iface);
}
static void
interface_update_cb(struct vlist_tree *tree,
struct vlist_node *node_new, struct vlist_node *node_old)
{
struct qosify_iface *if_new = NULL, *if_old = NULL;
if (node_new)
if_new = container_of(node_new, struct qosify_iface, node);
if (node_old)
if_old = container_of(node_old, struct qosify_iface, node);
if (if_new && if_old) {
if (!iface_config_equal(if_old, if_new)) {
interface_stop(if_old);
free(if_old->config_data);
interface_set_config(if_old, if_new->config_data);
}
free(if_new);
return;
}
if (if_old) {
interface_stop(if_old);
free(if_old->config_data);
free(if_old);
}
if (if_new)
interface_set_config(if_new, if_new->config_data);
}
static void
interface_create(struct blob_attr *attr, bool device)
{
struct qosify_iface *iface;
const char *name = blobmsg_name(attr);
int name_len = strlen(name);
char *name_buf;
if (strchr(name, '\''))
return;
if (name_len >= IFNAMSIZ)
return;
if (blobmsg_type(attr) != BLOBMSG_TYPE_TABLE)
return;
iface = calloc_a(sizeof(*iface), &name_buf, name_len + 1);
strcpy(name_buf, blobmsg_name(attr));
iface->config_data = attr;
iface->device = device;
vlist_add(device ? &devices : &interfaces, &iface->node, name_buf);
}
void qosify_iface_config_update(struct blob_attr *ifaces, struct blob_attr *devs)
{
struct blob_attr *cur;
int rem;
vlist_update(&devices);
blobmsg_for_each_attr(cur, devs, rem)
interface_create(cur, true);
vlist_flush(&devices);
vlist_update(&interfaces);
blobmsg_for_each_attr(cur, ifaces, rem)
interface_create(cur, false);
vlist_flush(&interfaces);
}
static void
qosify_iface_check_device(struct qosify_iface *iface)
{
const char *name = qosify_iface_name(iface);
int ifindex;
ifindex = if_nametoindex(name);
if (!ifindex) {
interface_stop(iface);
iface->ifname[0] = 0;
} else {
snprintf(iface->ifname, sizeof(iface->ifname), "%s", name);
interface_start(iface);
}
}
static void
qosify_iface_check_interface(struct qosify_iface *iface)
{
const char *name = qosify_iface_name(iface);
char ifname[IFNAMSIZ];
if (qosify_ubus_check_interface(name, ifname, sizeof(ifname)) == 0) {
snprintf(iface->ifname, sizeof(iface->ifname), "%s", ifname);
interface_start(iface);
} else {
interface_stop(iface);
iface->ifname[0] = 0;
}
}
static void qos_iface_check_cb(struct uloop_timeout *t)
{
struct qosify_iface *iface;
vlist_for_each_element(&devices, iface, node)
qosify_iface_check_device(iface);
vlist_for_each_element(&interfaces, iface, node)
qosify_iface_check_interface(iface);
}
void qosify_iface_check(void)
{
static struct uloop_timeout timer = {
.cb = qos_iface_check_cb,
};
uloop_timeout_set(&timer, 10);
}
void qosify_iface_status(struct blob_buf *b)
{
struct qosify_iface *iface;
void *c, *i;
c = blobmsg_open_table(b, "devices");
vlist_for_each_element(&devices, iface, node) {
i = blobmsg_open_table(b, qosify_iface_name(iface));
blobmsg_add_u8(b, "active", iface->active);
blobmsg_close_table(b, i);
}
blobmsg_close_table(b, c);
c = blobmsg_open_table(b, "interfaces");
vlist_for_each_element(&interfaces, iface, node) {
i = blobmsg_open_table(b, qosify_iface_name(iface));
blobmsg_add_u8(b, "active", iface->active);
if (iface->ifname)
blobmsg_add_string(b, "ifname", iface->ifname);
blobmsg_close_table(b, i);
}
blobmsg_close_table(b, c);
}
int qosify_iface_init(void)
{
socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (socket < 0)
return -1;
return 0;
}
void qosify_iface_stop(void)
{
struct qosify_iface *iface;
vlist_for_each_element(&interfaces, iface, node)
interface_stop(iface);
vlist_for_each_element(&devices, iface, node)
interface_stop(iface);
}

View File

@@ -1,121 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
*/
#include <sys/resource.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <glob.h>
#include <unistd.h>
#include "qosify.h"
static int qosify_bpf_pr(enum libbpf_print_level level, const char *format,
va_list args)
{
return vfprintf(stderr, format, args);
}
static void qosify_init_env(void)
{
struct rlimit limit = {
.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY,
};
setrlimit(RLIMIT_MEMLOCK, &limit);
}
static void qosify_fill_rodata(struct bpf_object *obj, uint32_t flags)
{
struct bpf_map *map = NULL;
while ((map = bpf_map__next(map, obj)) != NULL) {
if (!strstr(bpf_map__name(map), ".rodata"))
continue;
bpf_map__set_initial_value(map, &flags, sizeof(flags));
}
}
static int
qosify_create_program(const char *suffix, uint32_t flags)
{
DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts,
.pin_root_path = CLASSIFY_DATA_PATH,
);
struct bpf_program *prog;
struct bpf_object *obj;
char path[256];
int err;
snprintf(path, sizeof(path), CLASSIFY_PIN_PATH "_" "%s", suffix);
obj = bpf_object__open_file(CLASSIFY_PROG_PATH, &opts);
err = libbpf_get_error(obj);
if (err) {
perror("bpf_object__open_file");
return -1;
}
prog = bpf_object__find_program_by_title(obj, "classifier");
if (!prog) {
fprintf(stderr, "Can't find classifier prog\n");
return -1;
}
bpf_program__set_type(prog, BPF_PROG_TYPE_SCHED_CLS);
qosify_fill_rodata(obj, flags);
err = bpf_object__load(obj);
if (err) {
perror("bpf_object__load");
return -1;
}
libbpf_set_print(NULL);
unlink(path);
err = bpf_program__pin(prog, path);
if (err) {
fprintf(stderr, "Failed to pin program to %s: %s\n",
path, strerror(-err));
}
bpf_object__close(obj);
return 0;
}
int qosify_loader_init(void)
{
static const struct {
const char *suffix;
uint32_t flags;
} progs[] = {
{ "egress_eth", 0 },
{ "egress_ip", QOSIFY_IP_ONLY },
{ "ingress_eth", QOSIFY_INGRESS },
{ "ingress_ip", QOSIFY_INGRESS | QOSIFY_IP_ONLY },
};
glob_t g;
int i;
if (glob(CLASSIFY_DATA_PATH "/*", 0, NULL, &g) == 0) {
for (i = 0; i < g.gl_pathc; i++)
unlink(g.gl_pathv[i]);
}
libbpf_set_print(qosify_bpf_pr);
qosify_init_env();
for (i = 0; i < ARRAY_SIZE(progs); i++) {
if (qosify_create_program(progs[i].suffix, progs[i].flags))
return -1;
}
return 0;
}

View File

@@ -1,72 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
*/
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <libubox/uloop.h>
#include "qosify.h"
static int usage(const char *progname)
{
fprintf(stderr, "Usage: %s [options]\n"
"Options:\n"
" -l <file> Load defaults from <file>\n"
" -o only load program/maps without running as daemon\n"
"\n", progname);
return 1;
}
int main(int argc, char **argv)
{
const char *load_file = NULL;
bool oneshot = false;
int ch;
while ((ch = getopt(argc, argv, "fl:o")) != -1) {
switch (ch) {
case 'f':
break;
case 'l':
load_file = optarg;
break;
case 'o':
oneshot = true;
break;
default:
return usage(argv[0]);
}
}
if (qosify_loader_init())
return 2;
if (qosify_map_init())
return 2;
if (qosify_map_load_file(load_file))
return 2;
if (oneshot)
return 0;
ulog_open(ULOG_SYSLOG, LOG_DAEMON, "qosify");
uloop_init();
if (qosify_ubus_init() ||
qosify_iface_init())
return 2;
uloop_run();
qosify_ubus_stop();
qosify_iface_stop();
uloop_done();
return 0;
}

View File

@@ -1,735 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
*/
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
#include <libubox/uloop.h>
#include "qosify.h"
static int qosify_map_entry_cmp(const void *k1, const void *k2, void *ptr);
static int qosify_map_fds[__CL_MAP_MAX];
static AVL_TREE(map_data, qosify_map_entry_cmp, false, NULL);
static LIST_HEAD(map_files);
static uint32_t next_timeout;
static uint8_t qosify_dscp_default[2] = { 0xff, 0xff };
int qosify_map_timeout;
int qosify_active_timeout;
struct qosify_config config;
struct qosify_map_file {
struct list_head list;
char filename[];
};
static const struct {
const char *name;
const char *type_name;
} qosify_map_info[] = {
[CL_MAP_TCP_PORTS] = { "tcp_ports", "tcp_port" },
[CL_MAP_UDP_PORTS] = { "udp_ports", "udp_port" },
[CL_MAP_IPV4_ADDR] = { "ipv4_map", "ipv4_addr" },
[CL_MAP_IPV6_ADDR] = { "ipv6_map", "ipv6_addr" },
[CL_MAP_CONFIG] = { "config", "config" },
[CL_MAP_DNS] = { "dns", "dns" },
};
static const struct {
const char name[5];
uint8_t val;
} codepoints[] = {
{ "CS0", 0 },
{ "CS1", 8 },
{ "CS2", 16 },
{ "CS3", 24 },
{ "CS4", 32 },
{ "CS5", 40 },
{ "CS6", 48 },
{ "CS7", 56 },
{ "AF11", 10 },
{ "AF12", 12 },
{ "AF13", 14 },
{ "AF21", 18 },
{ "AF22", 20 },
{ "AF22", 22 },
{ "AF31", 26 },
{ "AF32", 28 },
{ "AF33", 30 },
{ "AF41", 34 },
{ "AF42", 36 },
{ "AF43", 38 },
{ "EF", 46 },
{ "VA", 44 },
{ "LE", 1 },
{ "DF", 0 },
};
static void qosify_map_timer_cb(struct uloop_timeout *t)
{
qosify_map_gc();
}
static struct uloop_timeout qosify_map_timer = {
.cb = qosify_map_timer_cb,
};
static uint32_t qosify_gettime(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec;
}
static const char *
qosify_map_path(enum qosify_map_id id)
{
static char path[128];
const char *name;
if (id >= ARRAY_SIZE(qosify_map_info))
return NULL;
name = qosify_map_info[id].name;
if (!name)
return NULL;
snprintf(path, sizeof(path), "%s/%s", CLASSIFY_DATA_PATH, name);
return path;
}
static int qosify_map_get_fd(enum qosify_map_id id)
{
const char *path = qosify_map_path(id);
int fd;
if (!path)
return -1;
fd = bpf_obj_get(path);
if (fd < 0)
fprintf(stderr, "Failed to open map %s: %s\n", path, strerror(errno));
return fd;
}
static void qosify_map_clear_list(enum qosify_map_id id)
{
int fd = qosify_map_fds[id];
__u32 key[4] = {};
while (bpf_map_get_next_key(fd, &key, &key) != -1)
bpf_map_delete_elem(fd, &key);
}
static void __qosify_map_set_dscp_default(enum qosify_map_id id, uint8_t val)
{
struct qosify_map_data data = {
.id = id,
};
int fd = qosify_map_fds[id];
int i;
val |= QOSIFY_DSCP_DEFAULT_FLAG;
for (i = 0; i < (1 << 16); i++) {
data.addr.port = htons(i);
if (avl_find(&map_data, &data))
continue;
bpf_map_update_elem(fd, &data.addr, &val, BPF_ANY);
}
}
void qosify_map_set_dscp_default(enum qosify_map_id id, uint8_t val)
{
bool udp;
if (id == CL_MAP_TCP_PORTS)
udp = false;
else if (id == CL_MAP_UDP_PORTS)
udp = true;
else
return;
if (qosify_dscp_default[udp] == val)
return;
qosify_dscp_default[udp] = val;
__qosify_map_set_dscp_default(id, val);
}
int qosify_map_init(void)
{
int i;
for (i = 0; i < CL_MAP_DNS; i++) {
qosify_map_fds[i] = qosify_map_get_fd(i);
if (qosify_map_fds[i] < 0)
return -1;
}
qosify_map_clear_list(CL_MAP_IPV4_ADDR);
qosify_map_clear_list(CL_MAP_IPV6_ADDR);
qosify_map_reset_config();
return 0;
}
static char *str_skip(char *str, bool space)
{
while (*str && isspace(*str) == space)
str++;
return str;
}
static int
qosify_map_codepoint(const char *val)
{
int i;
for (i = 0; i < ARRAY_SIZE(codepoints); i++)
if (!strcmp(codepoints[i].name, val))
return codepoints[i].val;
return 0xff;
}
static int qosify_map_entry_cmp(const void *k1, const void *k2, void *ptr)
{
const struct qosify_map_data *d1 = k1;
const struct qosify_map_data *d2 = k2;
if (d1->id != d2->id)
return d2->id - d1->id;
if (d1->id == CL_MAP_DNS)
return strcmp(d1->addr.dns.pattern, d2->addr.dns.pattern);
return memcmp(&d1->addr, &d2->addr, sizeof(d1->addr));
}
static struct qosify_map_entry *
__qosify_map_alloc_entry(struct qosify_map_data *data)
{
struct qosify_map_entry *e;
char *pattern;
if (data->id < CL_MAP_DNS) {
e = calloc(1, sizeof(*e));
memcpy(&e->data.addr, &data->addr, sizeof(e->data.addr));
return e;
}
e = calloc_a(sizeof(*e), &pattern, strlen(data->addr.dns.pattern) + 1);
strcpy(pattern, data->addr.dns.pattern);
e->data.addr.dns.pattern = pattern;
if (regcomp(&e->data.addr.dns.regex, pattern,
REG_EXTENDED | REG_ICASE | REG_NOSUB)) {
free(e);
return NULL;
}
return e;
}
static void __qosify_map_set_entry(struct qosify_map_data *data)
{
int fd = qosify_map_fds[data->id];
struct qosify_map_entry *e;
bool file = data->file;
int32_t delta = 0;
bool add = data->dscp != 0xff;
uint8_t prev_dscp = 0xff;
e = avl_find_element(&map_data, data, e, avl);
if (!e) {
if (!add)
return;
e = __qosify_map_alloc_entry(data);
if (!e)
return;
e->avl.key = &e->data;
e->data.id = data->id;
avl_insert(&map_data, &e->avl);
} else {
prev_dscp = e->data.dscp;
}
if (file)
e->data.file = add;
else
e->data.user = add;
if (add) {
if (file)
e->data.file_dscp = data->dscp;
if (!e->data.user || !file)
e->data.dscp = data->dscp;
} else if (e->data.file && !file) {
e->data.dscp = e->data.file_dscp;
}
if (e->data.dscp != prev_dscp && data->id < CL_MAP_DNS) {
struct qosify_ip_map_val val = {
.dscp = e->data.dscp,
.seen = 1,
};
bpf_map_update_elem(fd, &data->addr, &val, BPF_ANY);
}
if (add) {
if (qosify_map_timeout == ~0 || file) {
e->timeout = ~0;
return;
}
e->timeout = qosify_gettime() + qosify_map_timeout;
delta = e->timeout - next_timeout;
if (next_timeout && delta >= 0)
return;
}
uloop_timeout_set(&qosify_map_timer, 1);
}
static int
qosify_map_set_port(struct qosify_map_data *data, const char *str)
{
unsigned long start_port, end_port;
char *err;
int i;
start_port = end_port = strtoul(str, &err, 0);
if (err && *err) {
if (*err == '-')
end_port = strtoul(err + 1, &err, 0);
if (*err)
return -1;
}
if (!start_port || end_port < start_port ||
end_port >= 65535)
return -1;
for (i = start_port; i <= end_port; i++) {
data->addr.port = htons(i);
__qosify_map_set_entry(data);
}
return 0;
}
static int
qosify_map_fill_ip(struct qosify_map_data *data, const char *str)
{
int af;
if (data->id == CL_MAP_IPV6_ADDR)
af = AF_INET6;
else
af = AF_INET;
if (inet_pton(af, str, &data->addr) != 1)
return -1;
return 0;
}
int qosify_map_set_entry(enum qosify_map_id id, bool file, const char *str, uint8_t dscp)
{
struct qosify_map_data data = {
.id = id,
.file = file,
.dscp = dscp,
};
switch (id) {
case CL_MAP_DNS:
data.addr.dns.pattern = str;
break;
case CL_MAP_TCP_PORTS:
case CL_MAP_UDP_PORTS:
return qosify_map_set_port(&data, str);
case CL_MAP_IPV4_ADDR:
case CL_MAP_IPV6_ADDR:
if (qosify_map_fill_ip(&data, str))
return -1;
break;
default:
return -1;
}
__qosify_map_set_entry(&data);
return 0;
}
int qosify_map_dscp_value(const char *val)
{
unsigned long dscp;
char *err;
bool fallback = false;
if (*val == '+') {
fallback = true;
val++;
}
dscp = strtoul(val, &err, 0);
if (err && *err)
dscp = qosify_map_codepoint(val);
if (dscp >= 64)
return -1;
return dscp + (fallback << 6);
}
static void
qosify_map_dscp_codepoint_str(char *dest, int len, uint8_t dscp)
{
int i;
if (dscp & QOSIFY_DSCP_FALLBACK_FLAG) {
*(dest++) = '+';
len--;
dscp &= ~QOSIFY_DSCP_FALLBACK_FLAG;
}
for (i = 0; i < ARRAY_SIZE(codepoints); i++) {
if (codepoints[i].val != dscp)
continue;
snprintf(dest, len, "%s", codepoints[i].name);
return;
}
snprintf(dest, len, "0x%x", dscp);
}
static void
qosify_map_parse_line(char *str)
{
const char *key, *value;
int dscp;
str = str_skip(str, true);
key = str;
str = str_skip(str, false);
if (!*str)
return;
*(str++) = 0;
str = str_skip(str, true);
value = str;
dscp = qosify_map_dscp_value(value);
if (dscp < 0)
return;
if (!strncmp(key, "dns:", 4))
qosify_map_set_entry(CL_MAP_DNS, true, key + 4, dscp);
if (!strncmp(key, "tcp:", 4))
qosify_map_set_entry(CL_MAP_TCP_PORTS, true, key + 4, dscp);
else if (!strncmp(key, "udp:", 4))
qosify_map_set_entry(CL_MAP_UDP_PORTS, true, key + 4, dscp);
else if (strchr(key, ':'))
qosify_map_set_entry(CL_MAP_IPV6_ADDR, true, key, dscp);
else if (strchr(key, '.'))
qosify_map_set_entry(CL_MAP_IPV4_ADDR, true, key, dscp);
}
static int __qosify_map_load_file(const char *file)
{
char line[1024];
char *cur;
FILE *f;
if (!file)
return 0;
f = fopen(file, "r");
if (!f) {
fprintf(stderr, "Can't open data file %s\n", file);
return -1;
}
while (fgets(line, sizeof(line), f)) {
cur = strchr(line, '#');
if (cur)
*cur = 0;
cur = line + strlen(line);
if (cur == line)
continue;
while (cur > line && isspace(cur[-1]))
cur--;
*cur = 0;
qosify_map_parse_line(line);
}
fclose(f);
return 0;
}
int qosify_map_load_file(const char *file)
{
struct qosify_map_file *f;
if (!file)
return 0;
f = calloc(1, sizeof(*f) + strlen(file) + 1);
strcpy(f->filename, file);
list_add_tail(&f->list, &map_files);
return __qosify_map_load_file(file);
}
static void qosify_map_reset_file_entries(void)
{
struct qosify_map_entry *e;
avl_for_each_element(&map_data, e, avl)
e->data.file = false;
}
void qosify_map_clear_files(void)
{
struct qosify_map_file *f, *tmp;
qosify_map_reset_file_entries();
list_for_each_entry_safe(f, tmp, &map_files, list) {
list_del(&f->list);
free(f);
}
}
void qosify_map_reset_config(void)
{
qosify_map_clear_files();
qosify_map_set_dscp_default(CL_MAP_TCP_PORTS, 0);
qosify_map_set_dscp_default(CL_MAP_UDP_PORTS, 0);
qosify_map_timeout = 3600;
qosify_active_timeout = 300;
memset(&config, 0, sizeof(config));
config.dscp_prio = 0xff;
config.dscp_bulk = 0xff;
config.dscp_icmp = 0xff;
}
void qosify_map_reload(void)
{
struct qosify_map_file *f;
qosify_map_reset_file_entries();
list_for_each_entry(f, &map_files, list)
__qosify_map_load_file(f->filename);
qosify_map_gc();
}
static void qosify_map_free_entry(struct qosify_map_entry *e)
{
int fd = qosify_map_fds[e->data.id];
avl_delete(&map_data, &e->avl);
if (e->data.id < CL_MAP_DNS)
bpf_map_delete_elem(fd, &e->data.addr);
free(e);
}
static bool
qosify_map_entry_refresh_timeout(struct qosify_map_entry *e)
{
struct qosify_ip_map_val val;
int fd = qosify_map_fds[e->data.id];
if (e->data.id != CL_MAP_IPV4_ADDR &&
e->data.id != CL_MAP_IPV6_ADDR)
return false;
if (bpf_map_lookup_elem(fd, &e->data.addr, &val))
return false;
if (!val.seen)
return false;
e->timeout = qosify_gettime() + qosify_active_timeout;
val.seen = 0;
bpf_map_update_elem(fd, &e->data.addr, &val, BPF_ANY);
return true;
}
void qosify_map_gc(void)
{
struct qosify_map_entry *e, *tmp;
int32_t timeout = 0;
uint32_t cur_time = qosify_gettime();
next_timeout = 0;
avl_for_each_element_safe(&map_data, e, avl, tmp) {
int32_t cur_timeout;
if (e->data.user && e->timeout != ~0) {
cur_timeout = e->timeout - cur_time;
if (cur_timeout <= 0 &&
qosify_map_entry_refresh_timeout(e))
cur_timeout = e->timeout - cur_time;
if (cur_timeout <= 0) {
e->data.user = false;
e->data.dscp = e->data.file_dscp;
} else if (!timeout || cur_timeout < timeout) {
timeout = cur_timeout;
next_timeout = e->timeout;
}
}
if (e->data.file || e->data.user)
continue;
qosify_map_free_entry(e);
}
if (!timeout)
return;
uloop_timeout_set(&qosify_map_timer, timeout * 1000);
}
int qosify_map_add_dns_host(const char *host, const char *addr, const char *type, int ttl)
{
struct qosify_map_data data = {
.id = CL_MAP_DNS,
.addr.dns.pattern = "",
};
struct qosify_map_entry *e;
int prev_timeout = qosify_map_timeout;
e = avl_find_ge_element(&map_data, &data, e, avl);
if (!e)
return 0;
memset(&data, 0, sizeof(data));
data.user = true;
if (!strcmp(type, "A"))
data.id = CL_MAP_IPV4_ADDR;
else if (!strcmp(type, "AAAA"))
data.id = CL_MAP_IPV6_ADDR;
else
return 0;
if (qosify_map_fill_ip(&data, addr))
return -1;
avl_for_element_to_last(&map_data, e, e, avl) {
regex_t *regex = &e->data.addr.dns.regex;
if (e->data.id != CL_MAP_DNS)
return 0;
if (regexec(regex, host, 0, NULL, 0) != 0)
continue;
if (ttl)
qosify_map_timeout = ttl;
data.dscp = e->data.dscp;
__qosify_map_set_entry(&data);
qosify_map_timeout = prev_timeout;
}
return 0;
}
void qosify_map_dump(struct blob_buf *b)
{
struct qosify_map_entry *e;
uint32_t cur_time = qosify_gettime();
int buf_len = INET6_ADDRSTRLEN + 1;
char *buf;
void *a;
int af;
a = blobmsg_open_array(b, "entries");
avl_for_each_element(&map_data, e, avl) {
void *c;
if (!e->data.file && !e->data.user)
continue;
c = blobmsg_open_table(b, NULL);
if (e->data.user && e->timeout != ~0) {
int32_t cur_timeout = e->timeout - cur_time;
if (cur_timeout < 0)
cur_timeout = 0;
blobmsg_add_u32(b, "timeout", cur_timeout);
}
blobmsg_add_u8(b, "file", e->data.file);
blobmsg_add_u8(b, "user", e->data.user);
buf = blobmsg_alloc_string_buffer(b, "dscp", buf_len);
qosify_map_dscp_codepoint_str(buf, buf_len, e->data.dscp);
blobmsg_add_string_buffer(b);
blobmsg_add_string(b, "type", qosify_map_info[e->data.id].type_name);
switch (e->data.id) {
case CL_MAP_TCP_PORTS:
case CL_MAP_UDP_PORTS:
blobmsg_printf(b, "addr", "%d", ntohs(e->data.addr.port));
break;
case CL_MAP_IPV4_ADDR:
case CL_MAP_IPV6_ADDR:
buf = blobmsg_alloc_string_buffer(b, "addr", buf_len);
af = e->data.id == CL_MAP_IPV6_ADDR ? AF_INET6 : AF_INET;
inet_ntop(af, &e->data.addr, buf, buf_len);
blobmsg_add_string_buffer(b);
break;
case CL_MAP_DNS:
blobmsg_add_string(b, "addr", e->data.addr.dns.pattern);
break;
default:
*buf = 0;
break;
}
blobmsg_close_table(b, c);
}
blobmsg_close_array(b, a);
}
void qosify_map_update_config(void)
{
int fd = qosify_map_fds[CL_MAP_CONFIG];
uint32_t key = 0;
bpf_map_update_elem(fd, &key, &config, BPF_ANY);
}

View File

@@ -1,464 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
*/
#define KBUILD_MODNAME "foo"
#include <uapi/linux/bpf.h>
#include <uapi/linux/if_ether.h>
#include <uapi/linux/if_packet.h>
#include <uapi/linux/ip.h>
#include <uapi/linux/ipv6.h>
#include <uapi/linux/in.h>
#include <uapi/linux/tcp.h>
#include <uapi/linux/udp.h>
#include <uapi/linux/filter.h>
#include <uapi/linux/pkt_cls.h>
#include <linux/ip.h>
#include <net/ipv6.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>
#include "qosify-bpf.h"
#define INET_ECN_MASK 3
#define FLOW_CHECK_INTERVAL ((u32)((1000000000ULL) >> 24))
#define FLOW_TIMEOUT ((u32)((30ULL * 1000000000ULL) >> 24))
#define FLOW_BULK_TIMEOUT 5
#define EWMA_SHIFT 12
const volatile static uint32_t module_flags = 0;
struct flow_bucket {
__u32 last_update;
__u32 pkt_len_avg;
__u16 pkt_count;
__u8 dscp;
__u8 bulk_timeout;
};
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(pinning, 1);
__type(key, __u32);
__type(value, struct qosify_config);
__uint(max_entries, 1);
} config SEC(".maps");
typedef struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(pinning, 1);
__type(key, __u32);
__type(value, __u8);
__uint(max_entries, 1 << 16);
} port_array_t;
struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__uint(pinning, 1);
__type(key, __u32);
__uint(value_size, sizeof(struct flow_bucket));
__uint(max_entries, QOSIFY_FLOW_BUCKETS);
} flow_map SEC(".maps");
port_array_t tcp_ports SEC(".maps");
port_array_t udp_ports SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(pinning, 1);
__uint(key_size, sizeof(struct in_addr));
__type(value, struct qosify_ip_map_val);
__uint(max_entries, 100000);
__uint(map_flags, BPF_F_NO_PREALLOC);
} ipv4_map SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(pinning, 1);
__uint(key_size, sizeof(struct in6_addr));
__type(value, struct qosify_ip_map_val);
__uint(max_entries, 100000);
__uint(map_flags, BPF_F_NO_PREALLOC);
} ipv6_map SEC(".maps");
static struct qosify_config *get_config(void)
{
__u32 key = 0;
return bpf_map_lookup_elem(&config, &key);
}
static __always_inline int proto_is_vlan(__u16 h_proto)
{
return !!(h_proto == bpf_htons(ETH_P_8021Q) ||
h_proto == bpf_htons(ETH_P_8021AD));
}
static __always_inline int proto_is_ip(__u16 h_proto)
{
return !!(h_proto == bpf_htons(ETH_P_IP) ||
h_proto == bpf_htons(ETH_P_IPV6));
}
static __always_inline void *skb_ptr(struct __sk_buff *skb, __u32 offset)
{
void *start = (void *)(unsigned long long)skb->data;
return start + offset;
}
static __always_inline void *skb_end_ptr(struct __sk_buff *skb)
{
return (void *)(unsigned long long)skb->data_end;
}
static __always_inline int skb_check(struct __sk_buff *skb, void *ptr)
{
if (ptr > skb_end_ptr(skb))
return -1;
return 0;
}
static __always_inline __u32 cur_time(void)
{
__u32 val = bpf_ktime_get_ns() >> 24;
if (!val)
val = 1;
return val;
}
static __always_inline __u32 ewma(__u32 *avg, __u32 val)
{
if (*avg)
*avg = (*avg * 3) / 4 + (val << EWMA_SHIFT) / 4;
else
*avg = val << EWMA_SHIFT;
return *avg >> EWMA_SHIFT;
}
static __always_inline void
ipv4_change_dsfield(struct iphdr *iph, __u8 mask, __u8 value, bool force)
{
__u32 check = bpf_ntohs(iph->check);
__u8 dsfield;
if ((iph->tos & mask) && !force)
return;
dsfield = (iph->tos & mask) | value;
if (iph->tos == dsfield)
return;
check += iph->tos;
if ((check + 1) >> 16)
check = (check + 1) & 0xffff;
check -= dsfield;
check += check >> 16;
iph->check = bpf_htons(check);
iph->tos = dsfield;
}
static __always_inline void
ipv6_change_dsfield(struct ipv6hdr *ipv6h, __u8 mask, __u8 value, bool force)
{
__u16 *p = (__u16 *)ipv6h;
__u16 val;
if (((*p >> 4) & mask) && !force)
return;
val = (*p & bpf_htons((((__u16)mask << 4) | 0xf00f))) | bpf_htons((__u16)value << 4);
if (val == *p)
return;
*p = val;
}
static __always_inline int
parse_ethernet(struct __sk_buff *skb, __u32 *offset)
{
struct ethhdr *eth;
__u16 h_proto;
int i;
eth = skb_ptr(skb, *offset);
if (skb_check(skb, eth + 1))
return -1;
h_proto = eth->h_proto;
*offset += sizeof(*eth);
#pragma unroll
for (i = 0; i < 2; i++) {
struct vlan_hdr *vlh = skb_ptr(skb, *offset);
if (!proto_is_vlan(h_proto))
break;
if (skb_check(skb, vlh + 1))
return -1;
h_proto = vlh->h_vlan_encapsulated_proto;
*offset += sizeof(*vlh);
}
return h_proto;
}
static void
parse_l4proto(struct qosify_config *config, struct __sk_buff *skb,
__u32 offset, __u8 proto, __u8 *dscp_out)
{
struct udphdr *udp;
__u32 src, dest, key;
__u8 *value;
udp = skb_ptr(skb, offset);
if (skb_check(skb, &udp->len))
return;
if (config && (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)) {
*dscp_out = config->dscp_icmp;
return;
}
src = udp->source;
dest = udp->dest;
if (module_flags & QOSIFY_INGRESS)
key = src;
else
key = dest;
if (proto == IPPROTO_TCP) {
value = bpf_map_lookup_elem(&tcp_ports, &key);
} else {
if (proto != IPPROTO_UDP)
key = 0;
value = bpf_map_lookup_elem(&udp_ports, &key);
}
if (!value)
return;
*dscp_out = *value;
}
static void
check_flow(struct qosify_config *config, struct __sk_buff *skb,
uint8_t *dscp)
{
struct flow_bucket flow_data;
struct flow_bucket *flow;
__s32 delta;
__u32 hash;
__u32 time;
if (!(*dscp & QOSIFY_DSCP_DEFAULT_FLAG))
return;
if (!config)
return;
if (!config->bulk_trigger_pps &&
!config->prio_max_avg_pkt_len)
return;
time = cur_time();
hash = bpf_get_hash_recalc(skb);
flow = bpf_map_lookup_elem(&flow_map, &hash);
if (!flow) {
memset(&flow_data, 0, sizeof(flow_data));
bpf_map_update_elem(&flow_map, &hash, &flow_data, BPF_ANY);
flow = bpf_map_lookup_elem(&flow_map, &hash);
if (!flow)
return;
}
if (!flow->last_update)
goto reset;
delta = time - flow->last_update;
if ((u32)delta > FLOW_TIMEOUT)
goto reset;
if (delta >= FLOW_CHECK_INTERVAL) {
if (flow->bulk_timeout) {
flow->bulk_timeout--;
if (!flow->bulk_timeout)
flow->dscp = 0xff;
}
goto clear;
}
if (flow->pkt_count < 0xffff)
flow->pkt_count++;
if (config->bulk_trigger_pps &&
flow->pkt_count > config->bulk_trigger_pps) {
flow->dscp = config->dscp_bulk;
flow->bulk_timeout = config->bulk_trigger_timeout;
}
out:
if (config->prio_max_avg_pkt_len &&
flow->dscp != config->dscp_bulk) {
if (ewma(&flow->pkt_len_avg, skb->len) <
config->prio_max_avg_pkt_len)
flow->dscp = config->dscp_prio;
else
flow->dscp = 0xff;
}
if (flow->dscp != 0xff)
*dscp = flow->dscp;
return;
reset:
flow->dscp = 0xff;
flow->pkt_len_avg = 0;
clear:
flow->pkt_count = 1;
flow->last_update = time;
goto out;
}
static __always_inline void
parse_ipv4(struct __sk_buff *skb, __u32 *offset)
{
struct qosify_config *config;
struct qosify_ip_map_val *ip_val;
const __u32 zero_port = 0;
struct iphdr *iph;
__u8 dscp = 0xff;
__u8 *value;
__u8 ipproto;
int hdr_len;
void *key;
bool force;
config = get_config();
iph = skb_ptr(skb, *offset);
if (skb_check(skb, iph + 1))
return;
hdr_len = iph->ihl * 4;
if (bpf_skb_pull_data(skb, *offset + hdr_len + sizeof(struct udphdr)))
return;
iph = skb_ptr(skb, *offset);
*offset += hdr_len;
if (skb_check(skb, (void *)(iph + 1)))
return;
ipproto = iph->protocol;
parse_l4proto(config, skb, *offset, ipproto, &dscp);
if (module_flags & QOSIFY_INGRESS)
key = &iph->saddr;
else
key = &iph->daddr;
ip_val = bpf_map_lookup_elem(&ipv4_map, key);
if (ip_val) {
if (!ip_val->seen)
ip_val->seen = 1;
dscp = ip_val->dscp;
} else if (dscp == 0xff) {
/* use udp port 0 entry as fallback for non-tcp/udp */
value = bpf_map_lookup_elem(&udp_ports, &zero_port);
if (value)
dscp = *value;
}
check_flow(config, skb, &dscp);
force = !(dscp & QOSIFY_DSCP_FALLBACK_FLAG);
dscp &= GENMASK(5, 0);
ipv4_change_dsfield(iph, INET_ECN_MASK, dscp << 2, force);
}
static __always_inline void
parse_ipv6(struct __sk_buff *skb, __u32 *offset)
{
struct qosify_config *config;
struct qosify_ip_map_val *ip_val;
const __u32 zero_port = 0;
struct ipv6hdr *iph;
__u8 dscp = 0;
__u8 *value;
__u8 ipproto;
void *key;
bool force;
config = get_config();
if (bpf_skb_pull_data(skb, *offset + sizeof(*iph) + sizeof(struct udphdr)))
return;
iph = skb_ptr(skb, *offset);
*offset += sizeof(*iph);
if (skb_check(skb, (void *)(iph + 1)))
return;
ipproto = iph->nexthdr;
if (module_flags & QOSIFY_INGRESS)
key = &iph->saddr;
else
key = &iph->daddr;
parse_l4proto(config, skb, *offset, ipproto, &dscp);
ip_val = bpf_map_lookup_elem(&ipv6_map, key);
if (ip_val) {
if (!ip_val->seen)
ip_val->seen = 1;
dscp = ip_val->dscp;
} else if (dscp == 0xff) {
/* use udp port 0 entry as fallback for non-tcp/udp */
value = bpf_map_lookup_elem(&udp_ports, &zero_port);
if (value)
dscp = *value;
}
check_flow(config, skb, &dscp);
force = !(dscp & QOSIFY_DSCP_FALLBACK_FLAG);
dscp &= GENMASK(5, 0);
ipv6_change_dsfield(iph, INET_ECN_MASK, dscp << 2, force);
}
SEC("classifier")
int classify(struct __sk_buff *skb)
{
__u32 offset = 0;
int type;
if (module_flags & QOSIFY_IP_ONLY)
type = skb->protocol;
else
type = parse_ethernet(skb, &offset);
if (type == bpf_htons(ETH_P_IP))
parse_ipv4(skb, &offset);
else if (type == bpf_htons(ETH_P_IPV6))
parse_ipv6(skb, &offset);
return TC_ACT_OK;
}
char _license[] SEC("license") = "GPL";

View File

@@ -1,39 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
*/
#ifndef __BPF_QOSIFY_H
#define __BPF_QOSIFY_H
#ifndef QOSIFY_FLOW_BUCKET_SHIFT
#define QOSIFY_FLOW_BUCKET_SHIFT 13
#endif
#define QOSIFY_FLOW_BUCKETS (1 << QOSIFY_FLOW_BUCKET_SHIFT)
/* rodata per-instance flags */
#define QOSIFY_INGRESS (1 << 0)
#define QOSIFY_IP_ONLY (1 << 1)
#define QOSIFY_DSCP_FALLBACK_FLAG (1 << 6)
#define QOSIFY_DSCP_DEFAULT_FLAG (1 << 7)
/* global config data */
struct qosify_config {
uint8_t dscp_prio;
uint8_t dscp_bulk;
uint8_t dscp_icmp;
uint8_t bulk_trigger_timeout;
uint16_t bulk_trigger_pps;
uint16_t prio_max_avg_pkt_len;
};
struct qosify_ip_map_val {
uint8_t dscp; /* must be first */
uint8_t seen;
};
#endif

View File

@@ -1,95 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
*/
#ifndef __QOS_CLASSIFY_H
#define __QOS_CLASSIFY_H
#include <stdbool.h>
#include <regex.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include "qosify-bpf.h"
#include <libubox/utils.h>
#include <libubox/avl.h>
#include <libubox/blobmsg.h>
#include <libubox/ulog.h>
#include <netinet/in.h>
#define CLASSIFY_PROG_PATH "/lib/bpf/qosify-bpf.o"
#define CLASSIFY_PIN_PATH "/sys/fs/bpf/qosify"
#define CLASSIFY_DATA_PATH "/sys/fs/bpf/qosify_data"
enum qosify_map_id {
CL_MAP_TCP_PORTS,
CL_MAP_UDP_PORTS,
CL_MAP_IPV4_ADDR,
CL_MAP_IPV6_ADDR,
CL_MAP_CONFIG,
CL_MAP_DNS,
__CL_MAP_MAX,
};
struct qosify_map_data {
enum qosify_map_id id;
bool file : 1;
bool user : 1;
uint8_t dscp;
uint8_t file_dscp;
union {
uint32_t port;
struct in_addr ip;
struct in6_addr ip6;
struct {
const char *pattern;
regex_t regex;
} dns;
} addr;
};
struct qosify_map_entry {
struct avl_node avl;
uint32_t timeout;
struct qosify_map_data data;
};
extern int qosify_map_timeout;
extern int qosify_active_timeout;
extern struct qosify_config config;
int qosify_loader_init(void);
int qosify_map_init(void);
int qosify_map_dscp_value(const char *val);
int qosify_map_load_file(const char *file);
int qosify_map_set_entry(enum qosify_map_id id, bool file, const char *str, uint8_t dscp);
void qosify_map_reload(void);
void qosify_map_clear_files(void);
void qosify_map_gc(void);
void qosify_map_dump(struct blob_buf *b);
void qosify_map_set_dscp_default(enum qosify_map_id id, uint8_t val);
void qosify_map_reset_config(void);
void qosify_map_update_config(void);
int qosify_map_add_dns_host(const char *host, const char *addr, const char *type, int ttl);
int qosify_iface_init(void);
void qosify_iface_config_update(struct blob_attr *ifaces, struct blob_attr *devs);
void qosify_iface_check(void);
void qosify_iface_status(struct blob_buf *b);
void qosify_iface_stop(void);
int qosify_ubus_init(void);
void qosify_ubus_stop(void);
int qosify_ubus_check_interface(const char *name, char *ifname, int ifname_len);
#endif

View File

@@ -1,416 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
*/
#include <libubus.h>
#include "qosify.h"
static struct blob_buf b;
static int
qosify_ubus_add_array(struct blob_attr *attr, uint8_t val, enum qosify_map_id id)
{
struct blob_attr *cur;
int rem;
if (blobmsg_check_array(attr, BLOBMSG_TYPE_STRING) < 0)
return UBUS_STATUS_INVALID_ARGUMENT;
blobmsg_for_each_attr(cur, attr, rem)
qosify_map_set_entry(id, false, blobmsg_get_string(cur), val);
return 0;
}
static int
qosify_ubus_set_files(struct blob_attr *attr)
{
struct blob_attr *cur;
int rem;
if (blobmsg_check_array(attr, BLOBMSG_TYPE_STRING) < 0)
return UBUS_STATUS_INVALID_ARGUMENT;
qosify_map_clear_files();
blobmsg_for_each_attr(cur, attr, rem)
qosify_map_load_file(blobmsg_get_string(cur));
qosify_map_gc();
return 0;
}
enum {
CL_ADD_DSCP,
CL_ADD_TIMEOUT,
CL_ADD_IPV4,
CL_ADD_IPV6,
CL_ADD_TCP_PORT,
CL_ADD_UDP_PORT,
CL_ADD_DNS,
__CL_ADD_MAX
};
static const struct blobmsg_policy qosify_add_policy[__CL_ADD_MAX] = {
[CL_ADD_DSCP] = { "dscp", BLOBMSG_TYPE_STRING },
[CL_ADD_TIMEOUT] = { "timeout", BLOBMSG_TYPE_INT32 },
[CL_ADD_IPV4] = { "ipv4", BLOBMSG_TYPE_ARRAY },
[CL_ADD_IPV6] = { "ipv6", BLOBMSG_TYPE_ARRAY },
[CL_ADD_TCP_PORT] = { "tcp_port", BLOBMSG_TYPE_ARRAY },
[CL_ADD_UDP_PORT] = { "udp_port", BLOBMSG_TYPE_ARRAY },
[CL_ADD_DNS] = { "dns", BLOBMSG_TYPE_ARRAY },
};
static int
qosify_ubus_reload(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
qosify_map_reload();
return 0;
}
static int
qosify_ubus_add(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
int prev_timemout = qosify_map_timeout;
struct blob_attr *tb[__CL_ADD_MAX];
struct blob_attr *cur;
int dscp = -1;
int ret;
blobmsg_parse(qosify_add_policy, __CL_ADD_MAX, tb,
blobmsg_data(msg), blobmsg_len(msg));
if (!strcmp(method, "add")) {
if ((cur = tb[CL_ADD_DSCP]) != NULL)
dscp = qosify_map_dscp_value(blobmsg_get_string(cur));
else
return UBUS_STATUS_INVALID_ARGUMENT;
if (dscp < 0)
return UBUS_STATUS_INVALID_ARGUMENT;
if ((cur = tb[CL_ADD_TIMEOUT]) != NULL)
qosify_map_timeout = blobmsg_get_u32(cur);
} else {
dscp = 0xff;
}
if ((cur = tb[CL_ADD_IPV4]) != NULL &&
(ret = qosify_ubus_add_array(cur, dscp, CL_MAP_IPV4_ADDR) != 0))
return ret;
if ((cur = tb[CL_ADD_IPV6]) != NULL &&
(ret = qosify_ubus_add_array(cur, dscp, CL_MAP_IPV6_ADDR) != 0))
return ret;
if ((cur = tb[CL_ADD_TCP_PORT]) != NULL &&
(ret = qosify_ubus_add_array(cur, dscp, CL_MAP_TCP_PORTS) != 0))
return ret;
if ((cur = tb[CL_ADD_UDP_PORT]) != NULL &&
(ret = qosify_ubus_add_array(cur, dscp, CL_MAP_UDP_PORTS) != 0))
return ret;
if ((cur = tb[CL_ADD_DNS]) != NULL &&
(ret = qosify_ubus_add_array(cur, dscp, CL_MAP_DNS) != 0))
return ret;
qosify_map_timeout = prev_timemout;
return 0;
}
enum {
CL_CONFIG_RESET,
CL_CONFIG_FILES,
CL_CONFIG_TIMEOUT,
CL_CONFIG_DSCP_UDP,
CL_CONFIG_DSCP_TCP,
CL_CONFIG_DSCP_PRIO,
CL_CONFIG_DSCP_BULK,
CL_CONFIG_DSCP_ICMP,
CL_CONFIG_BULK_TIMEOUT,
CL_CONFIG_BULK_PPS,
CL_CONFIG_PRIO_PKT_LEN,
CL_CONFIG_INTERFACES,
CL_CONFIG_DEVICES,
__CL_CONFIG_MAX
};
static const struct blobmsg_policy qosify_config_policy[__CL_CONFIG_MAX] = {
[CL_CONFIG_RESET] = { "reset", BLOBMSG_TYPE_BOOL },
[CL_CONFIG_FILES] = { "files", BLOBMSG_TYPE_ARRAY },
[CL_CONFIG_TIMEOUT] = { "timeout", BLOBMSG_TYPE_INT32 },
[CL_CONFIG_DSCP_UDP] = { "dscp_default_udp", BLOBMSG_TYPE_STRING },
[CL_CONFIG_DSCP_TCP] = { "dscp_default_tcp", BLOBMSG_TYPE_STRING },
[CL_CONFIG_DSCP_PRIO] = { "dscp_prio", BLOBMSG_TYPE_STRING },
[CL_CONFIG_DSCP_BULK] = { "dscp_bulk", BLOBMSG_TYPE_STRING },
[CL_CONFIG_DSCP_ICMP] = { "dscp_icmp", BLOBMSG_TYPE_STRING },
[CL_CONFIG_BULK_TIMEOUT] = { "bulk_trigger_timeout", BLOBMSG_TYPE_INT32 },
[CL_CONFIG_BULK_PPS] = { "bulk_trigger_pps", BLOBMSG_TYPE_INT32 },
[CL_CONFIG_PRIO_PKT_LEN] = { "prio_max_avg_pkt_len", BLOBMSG_TYPE_INT32 },
[CL_CONFIG_INTERFACES] = { "interfaces", BLOBMSG_TYPE_TABLE },
[CL_CONFIG_DEVICES] = { "devices", BLOBMSG_TYPE_TABLE },
};
static int __set_dscp(uint8_t *dest, struct blob_attr *attr, bool reset)
{
int dscp;
if (reset)
*dest = 0xff;
if (!attr)
return 0;
dscp = qosify_map_dscp_value(blobmsg_get_string(attr));
if (dscp < 0)
return -1;
*dest = dscp;
return 0;
}
static int
qosify_ubus_config(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct blob_attr *tb[__CL_CONFIG_MAX];
struct blob_attr *cur;
uint8_t dscp;
bool reset = false;
int ret;
blobmsg_parse(qosify_config_policy, __CL_CONFIG_MAX, tb,
blobmsg_data(msg), blobmsg_len(msg));
if ((cur = tb[CL_CONFIG_RESET]) != NULL)
reset = blobmsg_get_bool(cur);
if (reset)
qosify_map_reset_config();
if ((cur = tb[CL_CONFIG_TIMEOUT]) != NULL)
qosify_map_timeout = blobmsg_get_u32(cur);
if ((cur = tb[CL_CONFIG_FILES]) != NULL &&
(ret = qosify_ubus_set_files(cur) != 0))
return ret;
__set_dscp(&dscp, tb[CL_CONFIG_DSCP_UDP], true);
if (dscp != 0xff)
qosify_map_set_dscp_default(CL_MAP_UDP_PORTS, dscp);
__set_dscp(&dscp, tb[CL_CONFIG_DSCP_TCP], true);
if (dscp != 0xff)
qosify_map_set_dscp_default(CL_MAP_TCP_PORTS, dscp);
__set_dscp(&config.dscp_prio, tb[CL_CONFIG_DSCP_PRIO], reset);
__set_dscp(&config.dscp_bulk, tb[CL_CONFIG_DSCP_BULK], reset);
__set_dscp(&config.dscp_icmp, tb[CL_CONFIG_DSCP_ICMP], reset);
if ((cur = tb[CL_CONFIG_BULK_TIMEOUT]) != NULL)
config.bulk_trigger_timeout = blobmsg_get_u32(cur);
if ((cur = tb[CL_CONFIG_BULK_PPS]) != NULL)
config.bulk_trigger_pps = blobmsg_get_u32(cur);
if ((cur = tb[CL_CONFIG_PRIO_PKT_LEN]) != NULL)
config.prio_max_avg_pkt_len = blobmsg_get_u32(cur);
qosify_map_update_config();
qosify_iface_config_update(tb[CL_CONFIG_INTERFACES], tb[CL_CONFIG_DEVICES]);
qosify_iface_check();
return 0;
}
static int
qosify_ubus_dump(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
blob_buf_init(&b, 0);
qosify_map_dump(&b);
ubus_send_reply(ctx, req, b.head);
blob_buf_free(&b);
return 0;
}
static int
qosify_ubus_status(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
blob_buf_init(&b, 0);
qosify_iface_status(&b);
ubus_send_reply(ctx, req, b.head);
blob_buf_free(&b);
return 0;
}
static int
qosify_ubus_check_devices(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
qosify_iface_check();
return 0;
}
enum {
CL_DNS_HOST_NAME,
CL_DNS_HOST_TYPE,
CL_DNS_HOST_ADDR,
CL_DNS_HOST_TTL,
__CL_DNS_HOST_MAX
};
static const struct blobmsg_policy qosify_dns_policy[__CL_DNS_HOST_MAX] = {
[CL_DNS_HOST_NAME] = { "name", BLOBMSG_TYPE_STRING },
[CL_DNS_HOST_TYPE] = { "type", BLOBMSG_TYPE_STRING },
[CL_DNS_HOST_ADDR] = { "address", BLOBMSG_TYPE_STRING },
[CL_DNS_HOST_TTL] = { "ttl", BLOBMSG_TYPE_INT32 },
};
static int
qosify_ubus_add_dns_host(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct blob_attr *tb[__CL_DNS_HOST_MAX];
struct blob_attr *cur;
uint32_t ttl = 0;
blobmsg_parse(qosify_dns_policy, __CL_DNS_HOST_MAX, tb,
blobmsg_data(msg), blobmsg_len(msg));
if (!tb[CL_DNS_HOST_NAME] || !tb[CL_DNS_HOST_TYPE] ||
!tb[CL_DNS_HOST_ADDR])
return UBUS_STATUS_INVALID_ARGUMENT;
if ((cur = tb[CL_DNS_HOST_TTL]) != NULL)
ttl = blobmsg_get_u32(cur);
if (qosify_map_add_dns_host(blobmsg_get_string(tb[CL_DNS_HOST_NAME]),
blobmsg_get_string(tb[CL_DNS_HOST_ADDR]),
blobmsg_get_string(tb[CL_DNS_HOST_TYPE]),
ttl))
return UBUS_STATUS_INVALID_ARGUMENT;
return 0;
}
static const struct ubus_method qosify_methods[] = {
UBUS_METHOD_NOARG("reload", qosify_ubus_reload),
UBUS_METHOD("add", qosify_ubus_add, qosify_add_policy),
UBUS_METHOD_MASK("remove", qosify_ubus_add, qosify_add_policy,
((1 << __CL_ADD_MAX) - 1) & ~(1 << CL_ADD_DSCP)),
UBUS_METHOD("config", qosify_ubus_config, qosify_config_policy),
UBUS_METHOD_NOARG("dump", qosify_ubus_dump),
UBUS_METHOD_NOARG("status", qosify_ubus_status),
UBUS_METHOD("add_dns_host", qosify_ubus_add_dns_host, qosify_dns_policy),
UBUS_METHOD_NOARG("check_devices", qosify_ubus_check_devices),
};
static struct ubus_object_type qosify_object_type =
UBUS_OBJECT_TYPE("qosify", qosify_methods);
static struct ubus_object qosify_object = {
.name = "qosify",
.type = &qosify_object_type,
.methods = qosify_methods,
.n_methods = ARRAY_SIZE(qosify_methods),
};
static void
ubus_connect_handler(struct ubus_context *ctx)
{
ubus_add_object(ctx, &qosify_object);
}
static struct ubus_auto_conn conn;
int qosify_ubus_init(void)
{
conn.cb = ubus_connect_handler;
ubus_auto_connect(&conn);
return 0;
}
void qosify_ubus_stop(void)
{
ubus_auto_shutdown(&conn);
}
struct iface_req {
char *name;
int len;
};
static void
netifd_if_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
struct iface_req *ifr = req->priv;
enum {
IFS_ATTR_UP,
IFS_ATTR_DEV,
__IFS_ATTR_MAX
};
static const struct blobmsg_policy policy[__IFS_ATTR_MAX] = {
[IFS_ATTR_UP] = { "up", BLOBMSG_TYPE_BOOL },
[IFS_ATTR_DEV] = { "l3_device", BLOBMSG_TYPE_STRING },
};
struct blob_attr *tb[__IFS_ATTR_MAX];
blobmsg_parse(policy, __IFS_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_len(msg));
if (!tb[IFS_ATTR_UP] || !tb[IFS_ATTR_DEV])
return;
if (!blobmsg_get_bool(tb[IFS_ATTR_UP]))
return;
snprintf(ifr->name, ifr->len, "%s", blobmsg_get_string(tb[IFS_ATTR_DEV]));
}
int qosify_ubus_check_interface(const char *name, char *ifname, int ifname_len)
{
struct iface_req req = { ifname, ifname_len };
char *obj_name = "network.interface.";
uint32_t id;
#define PREFIX "network.interface."
obj_name = alloca(sizeof(PREFIX) + strlen(name) + 1);
sprintf(obj_name, PREFIX "%s", name);
#undef PREFIX
ifname[0] = 0;
if (ubus_lookup_id(&conn.ctx, obj_name, &id))
return -1;
ubus_invoke(&conn.ctx, id, "status", b.head, netifd_if_cb, &req, 1000);
if (!ifname[0])
return -1;
return 0;
}

View File

@@ -0,0 +1,25 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=radius-gw-proxy
PKG_RELEASE:=1
PKG_LICENSE:=BSD-3-Clause
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/radius-gw-proxy
SECTION:=ucentral
CATEGORY:=uCentral
TITLE:=uCentral Gateway radius-gw-proxy
DEPENDS:=+libubox +libubus
endef
define Package/radius-gw-proxy/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/radius-gw-proxy $(1)/usr/sbin/
$(CP) ./files/* $(1)
endef
$(eval $(call BuildPackage,radius-gw-proxy))

View File

@@ -0,0 +1,11 @@
#!/bin/sh /etc/rc.common
START=99
USE_PROCD=1
start_service() {
procd_open_instance
procd_set_param command "/usr/sbin/radius-gw-proxy"
procd_close_instance
}

View File

@@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 2.6)
PROJECT(radius-gw-proxy C)
ADD_DEFINITIONS(-Wall -Werror)
IF(CMAKE_C_COMPILER_VERSION VERSION_GREATER 6)
ADD_DEFINITIONS(-Wextra -Werror=implicit-function-declaration)
ADD_DEFINITIONS(-Wformat -Werror=format-security -Werror=format-nonliteral)
ENDIF()
ADD_DEFINITIONS(-Os -std=gnu99 -g3 -Wmissing-declarations -Wno-unused-parameter -Wno-strict-aliasing)
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
SET(SOURCES main.c)
FIND_LIBRARY(ubus NAMES ubus)
FIND_LIBRARY(ubox NAMES ubox)
FIND_PATH(ubox_include_dir libubox/uloop.h)
FIND_PATH(ubus_include_dir NAMES libubus.h)
INCLUDE_DIRECTORIES(${ubox_include_dir} ${ubus_include_dir})
ADD_EXECUTABLE(radius-gw-proxy ${SOURCES})
TARGET_LINK_LIBRARIES(radius-gw-proxy ${ubox} ${ubus})
INSTALL(TARGETS radius-gw-proxy
RUNTIME DESTINATION sbin
)

View File

@@ -0,0 +1,356 @@
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libubox/uloop.h>
#include <libubox/usock.h>
#include <libubox/avl.h>
#include <libubox/avl-cmp.h>
#include <libubus.h>
#define RAD_PROX_BUFLEN (4 * 1024)
#define TLV_STATION_ID 30
#define TLV_VENDOR 26
#define TLV_TIP_SERVER_V4 2
#define TIP_VENDOR 58888
enum socket_type {
RADIUS_AUTH = 0,
RADIUS_ACCT,
RADIUS_DAS
};
struct radius_socket {
struct uloop_fd fd;
enum socket_type type;
};
struct radius_header {
uint8_t code;
uint8_t id;
uint16_t len;
char auth[16];
char avp[];
};
struct radius_tlv {
uint8_t id;
uint8_t len;
char data[];
};
struct radius_station_id {
char id[256];
enum socket_type type;
};
struct radius_station {
struct avl_node avl;
struct radius_station_id key;
int port;
};
static struct ubus_auto_conn conn;
static uint32_t ucentral;
static struct blob_buf b;
static int
avl_memcmp(const void *k1, const void *k2, void *ptr)
{
return memcmp(k1, k2, sizeof(struct radius_station_id));
}
static AVL_TREE(radius_stations, avl_memcmp, false, NULL);
static void
radius_station_add(char *id, int port, enum socket_type type)
{
struct radius_station *station;
struct radius_station_id key = { .type = type };
strcpy(key.id, id);
station = avl_find_element(&radius_stations, &key, station, avl);
if (!station) {
printf("new station/port, adding to avl tree\n");
station = malloc(sizeof(*station));
memset(station, 0, sizeof(*station));
strcpy(station->key.id, id);
station->key.type = type;
station->avl.key = &station->key;
avl_insert(&radius_stations, &station->avl);
}
station->port = port;
}
static char *
b64(char *src, int len)
{
char *dst;
int ret;
if (!src)
return NULL;
dst = malloc(len * 4);
ret = b64_encode(src, len, dst, len * 4);
if (ret < 1) {
free(dst);
return NULL;
}
return dst;
}
static void
radius_forward(char *buf, char *server, enum socket_type type)
{
struct radius_header *hdr = (struct radius_header *) buf;
struct ubus_request async = { };
char *data = b64(buf, hdr->len);
if (!data)
return;
blob_buf_init(&b, 0);
switch (type) {
case RADIUS_AUTH:
blobmsg_add_string(&b, "radius", "auth");
break;
case RADIUS_ACCT:
blobmsg_add_string(&b, "radius", "acct");
break;
default:
return;
}
blobmsg_add_string(&b, "data", data);
blobmsg_add_string(&b, "dst", server);
ubus_invoke_async(&conn.ctx, ucentral, "radius", b.head, &async);
ubus_abort_request(&conn.ctx, &async);
free(data);
}
static int
radius_parse(char *buf, int len, int port, enum socket_type type)
{
struct radius_header *hdr = (struct radius_header *) buf;
struct radius_tlv *station_id = NULL;
char station_id_str[256] = {};
char server_ip_str[256] = {};
void *avp = hdr->avp;
hdr->len = ntohs(hdr->len);
if (hdr->len != len) {
printf("invalid header length\n");
return -1;
}
printf("\tcode:%d, id:%d, len:%d\n", hdr->code, hdr->id, hdr->len);
len -= sizeof(*hdr);
while (len > 0) {
struct radius_tlv *tlv = (struct radius_tlv *)avp;
if (len < tlv->len) {
printf("invalid TLV length\n");
return -1;
}
if (tlv->id == TLV_STATION_ID)
station_id = tlv;
if (tlv->id == TLV_VENDOR && ntohl(*(uint32_t *) tlv->data) == TIP_VENDOR) {
struct radius_tlv *vendor = (struct radius_tlv *) &tlv->data[6];
if (vendor->id == TLV_TIP_SERVER_V4)
strncpy(server_ip_str, vendor->data, vendor->len - 2);
}
printf("\tID:%d, len:%d\n", tlv->id, tlv->len);
avp += tlv->len;
len -= tlv->len;
}
if (!station_id) {
printf("no station ID found\n");
return -1;
}
if (!*server_ip_str) {
printf("no server ip found\n");
return -1;
}
memcpy(station_id_str, station_id->data, station_id->len - 2);
printf("\tcalling station id:%s, server ip:%s\n", station_id_str, server_ip_str);
radius_station_add(station_id_str, port, type);
radius_forward(buf, server_ip_str, type);
return 0;
}
static void
sock_recv(struct uloop_fd *u, unsigned int events)
{
static char buf[RAD_PROX_BUFLEN];
static char cmsg_buf[( CMSG_SPACE(sizeof(struct in_pktinfo)) + sizeof(int)) + 1];
static struct sockaddr_in sin;
char addr_str[INET_ADDRSTRLEN];
static struct iovec iov = {
.iov_base = buf,
.iov_len = sizeof(buf)
};
static struct msghdr msg = {
.msg_name = &sin,
.msg_namelen = sizeof(sin),
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = cmsg_buf,
.msg_controllen = sizeof(cmsg_buf),
};
struct cmsghdr *cmsg;
struct radius_socket *sock = container_of(u, struct radius_socket, fd);
int len;
do {
struct in_pktinfo *pkti = NULL;
len = recvmsg(u->fd, &msg, 0);
if (len < 0) {
switch (errno) {
case EAGAIN:
return;
case EINTR:
continue;
default:
perror("recvmsg");
uloop_fd_delete(u);
return;
}
}
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_type != IP_PKTINFO)
continue;
pkti = (struct in_pktinfo *) CMSG_DATA(cmsg);
}
if (!pkti) {
printf("Received packet without ifindex\n");
continue;
}
inet_ntop(AF_INET, &sin.sin_addr, addr_str, sizeof(addr_str));
printf("RX: src:%s:%d, len=%d\n", addr_str, sin.sin_port, len);
radius_parse(buf, len, sin.sin_port, sock->type);
} while (1);
}
static struct radius_socket *
sock_open(char *port, enum socket_type type)
{
struct radius_socket *sock = malloc(sizeof(*sock));
int yes = 1;
if (!sock)
return NULL;
memset(sock, 0, sizeof(*sock));
sock->fd.fd = usock(USOCK_UDP | USOCK_SERVER | USOCK_NONBLOCK |
USOCK_NUMERIC | USOCK_IPV4ONLY,
"127.0.0.1", port);
if (sock->fd.fd < 0) {
perror("usock");
free(sock);
return NULL;
}
if (setsockopt(sock->fd.fd, IPPROTO_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0)
perror("setsockopt(IP_PKTINFO)");
sock->type = type;
sock->fd.cb = sock_recv;
uloop_fd_add(&sock->fd, ULOOP_READ);
return sock;
}
static void
ubus_event_handler_cb(struct ubus_context *ctx, struct ubus_event_handler *ev,
const char *type, struct blob_attr *msg)
{
enum {
EVENT_ID,
EVENT_PATH,
__EVENT_MAX
};
static const struct blobmsg_policy status_policy[__EVENT_MAX] = {
[EVENT_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 },
[EVENT_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
};
struct blob_attr *tb[__EVENT_MAX];
char *path;
uint32_t id;
blobmsg_parse(status_policy, __EVENT_MAX, tb, blob_data(msg), blob_len(msg));
if (!tb[EVENT_ID] || !tb[EVENT_PATH])
return;
path = blobmsg_get_string(tb[EVENT_PATH]);
id = blobmsg_get_u32(tb[EVENT_ID]);
if (strcmp(path, "ucentral"))
return;
if (!strcmp("ubus.object.remove", type))
ucentral = 0;
else
ucentral = id;
}
static struct ubus_event_handler ubus_event_handler = { .cb = ubus_event_handler_cb };
static void
ubus_connect_handler(struct ubus_context *ctx)
{
ubus_register_event_handler(ctx, &ubus_event_handler, "ubus.object.add");
ubus_register_event_handler(ctx, &ubus_event_handler, "ubus.object.remove");
ubus_lookup_id(ctx, "ucentral", &ucentral);
}
int main(int argc, char **argv)
{
uloop_init();
conn.cb = ubus_connect_handler;
ubus_auto_connect(&conn);
sock_open("1812", RADIUS_AUTH);
sock_open("1813", RADIUS_ACCT);
uloop_run();
uloop_end();
return 0;
}

View File

@@ -101,6 +101,7 @@ deliface() {
found=0
find_ssid() {
local ssid
config_get ssid $1 ssid
[ "$ssid" == "$2" ] || return
found=1
@@ -119,7 +120,7 @@ addiface() {
echo -n startup > /tmp/ratelimit.$iface
sleep 2
ssid=$(ubus call network.wireless status | jsonfilter -e '@[*].interfaces[@.ifname="'"$iface"'"].config.ssid')
ssid=$(ubus call hostapd.$iface get_status | jsonfilter -e '@.ssid')
[ -z "$ssid" ] && {
rm /tmp/ratelimit.$iface
logger "ratelimit: failed to lookup ssid"

View File

@@ -3,11 +3,11 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=ucentral-client
PKG_RELEASE:=1
PKG_SOURCE_URL=https://github.com/blogic/ucentral-client.git
PKG_MIRROR_HASH:=f00e800d97335d088281670aa1b459da1fdd5e4a2927ce280b7d9cb369ebc21a
PKG_SOURCE_URL=https://github.com/Telecominfraproject/wlan-ucentral-client.git
PKG_MIRROR_HASH:=afcdce6a4ea24405b98147bac342a24c21ad6ba91e57a2a966018949ece9a294
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2022-01-10
PKG_SOURCE_VERSION:=e3b71c61e1a07bb3b5fa34fe835fd8f6f708caa3
PKG_SOURCE_DATE:=2022-05-29
PKG_SOURCE_VERSION:=a4671bbe7d30b1286b718e08573d73dae4df344a
PKG_LICENSE:=BSD-3-Clause
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
@@ -19,7 +19,7 @@ define Package/ucentral-client
SECTION:=ucentral
CATEGORY:=uCentral
TITLE:=OpenWrt uCentral websocket client
DEPENDS:=+ucode +ucode-mod-fs +ucode-mod-ubus +ucode-mod-uci +ucode-mod-math +ucode-mod-resolv \
DEPENDS:=+ucode +ucode-mod-fs +ucode-mod-ubus +ucode-mod-uci +ucode-mod-math +ucode-mod-resolv +ucode-mod-uloop \
+libubox +libwebsockets-openssl +libblobmsg-json +libubus
endef

View File

@@ -21,7 +21,7 @@ start_service() {
mkdir -p /tmp/ucentral/
ucode -m fs -i /usr/share/ucentral/crashlog.uc
ucode -l fs /usr/share/ucentral/crashlog.uc
. /lib/functions.sh
cp /etc/config-shadow/ucentral /etc/config/
@@ -32,8 +32,6 @@ start_service() {
config_get debug 'config' 'debug' 0
config_get insecure 'config' 'insecure' 0
interval=$(uci get ustats.health.interval)
procd_open_instance
procd_set_param command "$PROG"
[ -n "$serial" ] && procd_append_param command -S $serial
@@ -41,7 +39,6 @@ start_service() {
[ -n "$port" ] && procd_append_param command -P $port
[ "$debug" -eq 0 ] || procd_append_param command -d
[ "$insecure" -eq 0 ] || procd_append_param command -i
[ -z "$interval" ] || procd_append_param command -H $interval
[ -z "$(mount | grep 'tmpfs on / type tmpfs')" ] || procd_append_param command -r
procd_append_param command -f "$(cat /tmp/ucentral.version)"
procd_set_param respawn 3600 5 0

View File

@@ -0,0 +1,29 @@
#!/bin/sh /etc/rc.common
START=99
USE_PROCD=1
PROG=/usr/share/ucentral/health.uc
boot() {
# dummy stub to make sure health does not start before
# a config is applied
true
}
service_triggers() {
procd_add_reload_trigger ustats
}
start_service() {
. /lib/functions.sh
config_load 'ustats'
config_get interval 'health' 'interval' 120
[ "$interval" -eq 0 ] || {
procd_open_instance
procd_set_param command "$PROG"
procd_set_param respawn 1 $interval 0
procd_close_instance
}
}

View File

@@ -20,9 +20,4 @@ start_service() {
procd_set_param respawn 1 $interval 0
procd_close_instance
}
config_get interval 'health' 'interval' 0
[ "$interval" -eq 0 ] || {
ubus call ucentral config '{"health": '$interval' }'
}
}

View File

@@ -4,10 +4,10 @@ PKG_NAME:=ucentral-event
PKG_RELEASE:=1
PKG_SOURCE_URL=https://github.com/blogic/ucentral-event.git
PKG_MIRROR_HASH:=615563b31f55b18b8900f8614c6c8add0d6a812da57d220a7632109b06795036
PKG_MIRROR_HASH:=8cb470d7cc6c458fe748ee6f54e4bf79bec5500735d7b992d83c1aa10f700c6b
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2021-04-13
PKG_SOURCE_VERSION:=7b0d136e8556bb099d7032823139d275448714cb
PKG_SOURCE_VERSION:=24b7fb36e456d99b470c212674b3bf50bac64c74
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
PKG_LICENSE:=BSD-3-Clause

View File

@@ -3,10 +3,11 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=ucentral-schema
PKG_RELEASE:=1
PKG_SOURCE_URL=https://github.com/blogic/ucentral-schema.git
PKG_SOURCE_URL=https://github.com/Telecominfraproject/wlan-ucentral-schema.git
PKG_MIRROR_HASH:=3ba2d66f8e52c784f136bf340ab2fb81568a1d8df8dbebfa487fc57652bea04f
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2022-01-17
PKG_SOURCE_VERSION:=19fcc8d8163e84734d34dc7dd9767c2fa133fa16
PKG_SOURCE_DATE:=2022-05-29
PKG_SOURCE_VERSION:=96324e2f7443cb3ae70f8fca10f37548f673e3f8
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
PKG_LICENSE:=BSD-3-Clause

View File

@@ -6,9 +6,9 @@ USE_PROCD=1
PROG=/usr/bin/ucode
start_service() {
local interval=$(uci get onlinecheck.@config.check_interval)
local interval=$(uci get onlinecheck.@config[-1].check_interval)
procd_open_instance
procd_set_param command "$PROG" -m uci -m fs -i /usr/share/ucentral/onlinecheck.uc
procd_set_param command "$PROG" -l uci -l fs /usr/share/ucentral/onlinecheck.uc
procd_set_param respawn 1 $interval 0
procd_close_instance
}

View File

@@ -97,7 +97,7 @@
"online-check": {
"ping-hosts": [
"192.168.178.1",
"uecntral.io"
"ucentral.io"
],
"download-hosts": [
"ucentral.io"

View File

@@ -0,0 +1,91 @@
{
"uuid": 2,
"radios": [
{
"band": "2G",
"country": "CA",
"channel-mode": "HE",
"channel-width": 20,
"channel": 6
}
],
"interfaces": [
{
"name": "WAN",
"role": "upstream",
"services": [ "ssh" ],
"ethernet": [
{
"select-ports": [
"WAN*"
]
}
],
"ipv4": {
"addressing": "dynamic"
},
"ssids": [
{
"name": "OpenWifi",
"wifi-bands": [
"2G"
],
"bss-mode": "ap",
"encryption": {
"proto": "psk2-radius",
"ieee80211w": "optional"
},
"radius": {
"authentication": {
"host": "192.168.50.30",
"port": 1812,
"secret": "secret"
},
"accounting": {
"host": "192.168.50.30",
"port": 1813,
"secret": "secret"
}
}
}
]
},
{
"name": "LAN",
"role": "downstream",
"services": [ "ssh" ],
"ethernet": [
{
"select-ports": [
"LAN*"
]
}
],
"ipv4": {
"addressing": "static",
"subnet": "192.168.1.1/24",
"dhcp": {
"lease-first": 10,
"lease-count": 100,
"lease-time": "6h"
}
}
}
],
"metrics": {
"statistics": {
"interval": 120,
"types": [ "ssids", "lldp", "clients" ]
},
"health": {
"interval": 120
}
},
"services": {
"ssh": {
"port": 22
}
}
}

View File

@@ -0,0 +1,91 @@
{
"uuid": 2,
"radios": [
{
"band": "5G",
"country": "CA",
"channel-mode": "HE",
"channel-width": 80,
"channel": 36
}
],
"interfaces": [
{
"name": "WAN",
"role": "upstream",
"ethernet": [
{
"select-ports": [
"WAN*"
]
}
],
"ipv4": {
"addressing": "dynamic"
},
"ssids": [
{
"name": "OpenWifi",
"wifi-bands": [
"2G", "5G"
],
"bss-mode": "ap",
"encryption": {
"proto": "wpa2",
"ieee80211w": "optional"
},
"radius": {
"authentication": {
"host": "192.168.178.192",
"port": 1812,
"secret": "secret"
},
"accounting": {
"host": "192.168.178.192",
"port": 1813,
"secret": "secret"
}
},
"services": [ "radius-gw-proxy" ]
}
]
},
{
"name": "LAN",
"role": "downstream",
"services": [ "ssh" ],
"ethernet": [
{
"select-ports": [
"LAN*"
]
}
],
"ipv4": {
"addressing": "static",
"subnet": "192.168.1.1/24",
"dhcp": {
"lease-first": 10,
"lease-count": 100,
"lease-time": "6h"
}
}
}
],
"metrics": {
"statistics": {
"interval": 120,
"types": [ "ssids", "lldp", "clients" ]
},
"health": {
"interval": 120
}
},
"services": {
"ssh": {
"port": 22
}
}
}

View File

@@ -103,14 +103,29 @@
"radius-proxy": {
"realms": [
{
"realm": "test",
"protocol": "radsec",
"realm": [ "radsec1", "radsec2" ],
"host": "192.168.1.10",
"secret": "secret",
"ca-certificate": "Zm9vbwo=",
"certificate": "Zm9vbwo=",
"private-key": "Zm9vbwo="
}, {
"realm": "*",
"protocol": "radius",
"realm": [ "radius1", "radius2" ],
"auth-server": "192.168.1.11",
"auth-port": 1812,
"auth-secret": "secret",
"acct-server": "192.168.1.11",
"acct-port": 1813,
"acct-secret": "secret"
}, {
"protocol": "block",
"realm": [ "block1", "block2" ],
"message": "Access Denied"
}, {
"protocol": "radsec",
"realm": [ "*" ],
"auto-discover": true,
"use-local-certificates": true
}

View File

@@ -0,0 +1,123 @@
{
"uuid": 2,
"radios": [
{
"band": "2G",
"country": "US",
"channel-mode": "HE",
"channel-width": 20,
"channel": "auto"
}, {
"band": "5G",
"country": "US",
"channel-mode": "HE",
"channel-width": 80,
"channel": 36
}, {
"band": "6G",
"country": "US",
"channel-mode": "HE",
"channel-width": 80,
"channel": 33
}
],
"interfaces": [
{
"name": "WAN",
"role": "upstream",
"services": [ "lldp" ],
"ethernet": [
{
"select-ports": [
"WAN*"
]
}
],
"ipv4": {
"addressing": "dynamic"
},
"ssids": [
{
"name": "OpenWifi2",
"wifi-bands": [
"2G"
],
"bss-mode": "ap",
"encryption": {
"proto": "psk2",
"key": "OpenWifi",
"ieee80211w": "optional"
},
"rrm": {
"reduced-neighbor-reporting": true
}
}, {
"name": "OpenWifi5",
"wifi-bands": [
"5G"
],
"bss-mode": "ap",
"encryption": {
"proto": "psk2",
"key": "OpenWifi",
"ieee80211w": "optional"
},
"rrm": {
"reduced-neighbor-reporting": true
}
}, {
"name": "OpenWifi6",
"wifi-bands": [
"6G"
],
"bss-mode": "ap",
"encryption": {
"proto": "sae",
"key": "OpenWifi",
"ieee80211w": "required"
}
}
]
},
{
"name": "LAN",
"role": "downstream",
"services": [ "ssh", "lldp" ],
"ethernet": [
{
"select-ports": [
"LAN*"
]
}
],
"ipv4": {
"addressing": "static",
"subnet": "192.168.1.1/24",
"dhcp": {
"lease-first": 10,
"lease-count": 100,
"lease-time": "6h"
}
}
}
],
"metrics": {
"statistics": {
"interval": 120,
"types": [ "ssids", "lldp", "clients" ]
},
"health": {
"interval": 120
}
},
"services": {
"lldp": {
"describe": "uCentral",
"location": "universe"
},
"ssh": {
"port": 22
}
}
}

View File

@@ -1,4 +1,4 @@
#!/usr/bin/ucode -R
#!/usr/bin/ucode
let nl = require("nl80211");
let def = nl.const;

View File

@@ -1,4 +1 @@
[ ifup = "$ACTION" ] && {
ip-collide
[ $? -eq 0 ] || ubus call ucentral send '{"msg": "ip/domain collision detected", "severity": 3}'
}
[ ifup = "$ACTION" ] && /usr/share/ucentral/ip-collide.uc

View File

@@ -4,10 +4,11 @@ PKG_NAME:=ucentral-wifi
PKG_RELEASE:=1
PKG_SOURCE_URL=https://github.com/blogic/ucentral-wifi.git
PKG_MIRROR_HASH:=b6a3bfbd0823c54bb6fb3899e583db8580474a24c1b238d97be152ea8eccf6e5
PKG_MIRROR_HASH:=8e730a37026a37f113038ae27489bb92104d0a091403b7cc1f379188dddd2699
#PKG_MIRROR_HASH:=b6a3bfbd0823c54bb6fb3899e583db8580474a24c1b238d97be152ea8eccf6e5
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2022-01-10
PKG_SOURCE_VERSION:=40d0eb9d6f36f558d14d6a1783711c3cf07638c5
PKG_SOURCE_VERSION:=aa9c3ee716929d75852a11640362a09bb32c5262
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
PKG_LICENSE:=BSD-3-Clause

View File

@@ -12,13 +12,13 @@ PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=https://github.com/jow-/ucode.git
PKG_SOURCE_DATE:=2021-07-30
PKG_SOURCE_VERSION:=03b6a8efc1834a4114f0d11e1a7cecff3242b305
PKG_MIRROR_HASH:=6af37293d6d7023f30728c76a02b4e48d323262a45058410760a30256e0dbe2b
PKG_SOURCE_DATE:=2022-04-07
PKG_SOURCE_VERSION:=33f1e0b0926e973fb5ae445e9a995848762143bb
PKG_MIRROR_HASH:=e419678244c5402c739e3a200d6d1d7cd6989a711c73744bc68b2d5b76bae33a
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
PKG_LICENSE:=ISC
PKG_ABI_VERSION:=20210730
PKG_ABI_VERSION:=20220322
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
@@ -65,17 +65,6 @@ define Package/ucode-mod-fs/description
endef
define Package/ucode-mod-resolv
$(Package/ucode/default)
TITLE+= (resolv module)
DEPENDS:=ucode
endef
define Package/ucode-mod-resolv/description
The resolv plugin module allows making DNS resolves.
endef
define Package/ucode-mod-math
$(Package/ucode/default)
TITLE+= (math module)
@@ -87,6 +76,50 @@ define Package/ucode-mod-math/description
endef
define Package/ucode-mod-nl80211
$(Package/ucode/default)
TITLE+= (nl80211 module)
DEPENDS:=ucode +libnl-tiny +kmod-mac80211
endef
define Package/ucode-mod-nl80211/description
The nl80211 plugin provides access to the Linux wireless 802.11 netlink API.
endef
define Package/ucode-mod-resolv
$(Package/ucode/default)
TITLE+= (resolv module)
DEPENDS:=ucode
endef
define Package/ucode-mod-resolv/description
The resolv plugin implements simple DNS resolving.
endef
define Package/ucode-mod-rtnl
$(Package/ucode/default)
TITLE+= (rtnl module)
DEPENDS:=ucode +libnl-tiny
endef
define Package/ucode-mod-rtnl/description
The rtnl plugin provides access to the Linux routing netlink API.
endef
define Package/ucode-mod-struct
$(Package/ucode/default)
TITLE+= (struct module)
DEPENDS:=ucode
endef
define Package/ucode-mod-struct/description
The struct plugin implemnts Python 3 compatible struct.pack/unpack functionality.
endef
define Package/ucode-mod-ubus
$(Package/ucode/default)
TITLE+= (ubus module)
@@ -109,40 +142,16 @@ define Package/ucode-mod-uci/description
The uci module allows templates to read and modify uci configuration.
endef
define Package/ucode-mod-nl80211
define Package/ucode-mod-uloop
$(Package/ucode/default)
TITLE+= (nl80211 module)
DEPENDS:=ucode +libnl-tiny +kmod-mac80211
TITLE+= (uloop module)
DEPENDS:=ucode +libubox
endef
define Package/ucode-mod-nl80211/description
The nl80211 module allows templates to send and receive nl80211 messages..
define Package/ucode-mod-uloop/description
The uloop module allows templates to run a main loop.
endef
define Package/ucode-mod-struct
$(Package/ucode/default)
TITLE+= (struct module)
DEPENDS:=ucode
endef
define Package/ucode-mod-struct/description
The struct module allows templates to unpack binary buffers.
endef
define Package/ucode-mod-rtnl
$(Package/ucode/default)
TITLE+= (rtnl module)
DEPENDS:=ucode +libnl-tiny
endef
define Package/ucode-mod-struct/description
The rtnl module allows templates to send and receive rtnl messages..
endef
define Build/Prepare
$(Build/Prepare/Default)
$(CP) $(STAGING_DIR)/usr/include/mac80211/uapi/linux/nl80211.h $(PKG_BUILD_DIR)/nl80211_copy.h
@@ -157,7 +166,7 @@ endef
define Package/ucode/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ucode $(1)/usr/bin/ucode
$(CP) $(PKG_INSTALL_DIR)/usr/bin/u* $(1)/usr/bin/
endef
define Package/libucode/install
@@ -170,14 +179,29 @@ define Package/ucode-mod-fs/install
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/fs.so $(1)/usr/lib/ucode/
endef
define Package/ucode-mod-math/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/math.so $(1)/usr/lib/ucode/
endef
define Package/ucode-mod-nl80211/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/nl80211.so $(1)/usr/lib/ucode/
endef
define Package/ucode-mod-resolv/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/resolv.so $(1)/usr/lib/ucode/
endef
define Package/ucode-mod-math/install
define Package/ucode-mod-rtnl/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/math.so $(1)/usr/lib/ucode/
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/rtnl.so $(1)/usr/lib/ucode/
endef
define Package/ucode-mod-struct/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/struct.so $(1)/usr/lib/ucode/
endef
define Package/ucode-mod-ubus/install
@@ -190,29 +214,20 @@ define Package/ucode-mod-uci/install
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/uci.so $(1)/usr/lib/ucode/
endef
define Package/ucode-mod-nl80211/install
define Package/ucode-mod-uloop/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/nl80211.so $(1)/usr/lib/ucode/
endef
define Package/ucode-mod-struct/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/struct.so $(1)/usr/lib/ucode/
endef
define Package/ucode-mod-rtnl/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/rtnl.so $(1)/usr/lib/ucode/
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/uloop.so $(1)/usr/lib/ucode/
endef
$(eval $(call BuildPackage,ucode))
$(eval $(call BuildPackage,libucode))
$(eval $(call BuildPackage,ucode-mod-fs))
$(eval $(call BuildPackage,ucode-mod-resolv))
$(eval $(call BuildPackage,ucode-mod-math))
$(eval $(call BuildPackage,ucode-mod-nl80211))
$(eval $(call BuildPackage,ucode-mod-resolv))
$(eval $(call BuildPackage,ucode-mod-rtnl))
$(eval $(call BuildPackage,ucode-mod-struct))
$(eval $(call BuildPackage,ucode-mod-ubus))
$(eval $(call BuildPackage,ucode-mod-uci))
$(eval $(call BuildPackage,ucode-mod-nl80211))
$(eval $(call BuildPackage,ucode-mod-struct))
$(eval $(call BuildPackage,ucode-mod-rtnl))
$(eval $(call BuildPackage,ucode-mod-uloop))

View File

@@ -1,7 +1,7 @@
Index: ucode-2021-07-30-03b6a8ef/lib/nl80211.c
Index: ucode-2022-04-07-33f1e0b0/lib/nl80211.c
===================================================================
--- ucode-2021-07-30-03b6a8ef.orig/lib/nl80211.c
+++ ucode-2021-07-30-03b6a8ef/lib/nl80211.c
--- ucode-2022-04-07-33f1e0b0.orig/lib/nl80211.c
+++ ucode-2022-04-07-33f1e0b0/lib/nl80211.c
@@ -38,7 +38,7 @@ limitations under the License.
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>

View File

@@ -1,27 +1,27 @@
From eac420899717e2d23f6d13304bd67278a7e91730 Mon Sep 17 00:00:00 2001
From 25df1c3e41f274f70e4fbf5fdc10e4290ba019f5 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Thu, 20 Jan 2022 10:48:35 +0100
Subject: [PATCH 1/2] fixes
Subject: [PATCH] fixes
---
lib/nl80211.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++----
lib/nl80211.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++----
lib/rtnl.c | 1 +
2 files changed, 71 insertions(+), 6 deletions(-)
2 files changed, 87 insertions(+), 6 deletions(-)
diff --git a/lib/nl80211.c b/lib/nl80211.c
index fc24fb8..1d0871a 100644
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -45,6 +45,8 @@ limitations under the License.
Index: ucode-2022-04-07-33f1e0b0/lib/nl80211.c
===================================================================
--- ucode-2022-04-07-33f1e0b0.orig/lib/nl80211.c
+++ ucode-2022-04-07-33f1e0b0/lib/nl80211.c
@@ -51,6 +51,8 @@ limitations under the License.
#define err_return(code, ...) do { set_error(code, __VA_ARGS__); return NULL; } while(0)
#define NL80211_ATTR_NOT_IMPLEMENTED 0x10000
+#define NL80211_ATTR_NOT_IMPLEMENTED 0x10000
+
static struct {
int code;
char *msg;
@@ -257,6 +259,14 @@ static const uc_nl_nested_spec_t nl80211_keys_nla = {
@@ -263,6 +265,14 @@ static const uc_nl_nested_spec_t nl80211
}
};
@@ -36,7 +36,7 @@ index fc24fb8..1d0871a 100644
static const uc_nl_nested_spec_t nl80211_mesh_params_nla = {
.headsize = 0,
.nattrs = 29,
@@ -348,6 +358,14 @@ static const uc_nl_nested_spec_t nl80211_nan_func_nla = {
@@ -354,6 +364,14 @@ static const uc_nl_nested_spec_t nl80211
}
};
@@ -51,7 +51,7 @@ index fc24fb8..1d0871a 100644
static const uc_nl_nested_spec_t nl80211_peer_measurements_peers_req_data_ftm_nla = {
.headsize = 0,
.nattrs = 13,
@@ -497,6 +515,26 @@ static const uc_nl_nested_spec_t nl80211_wiphy_bands_freqs_wmm_nla = {
@@ -503,6 +521,26 @@ static const uc_nl_nested_spec_t nl80211
}
};
@@ -78,7 +78,7 @@ index fc24fb8..1d0871a 100644
static const uc_nl_nested_spec_t nl80211_wiphy_bands_freqs_nla = {
.headsize = 0,
.nattrs = 25,
@@ -538,6 +576,10 @@ static const uc_nl_nested_spec_t nl80211_wiphy_bands_rates_nla = {
@@ -544,6 +582,10 @@ static const uc_nl_nested_spec_t nl80211
}
};
@@ -89,35 +89,7 @@ index fc24fb8..1d0871a 100644
static const uc_nl_nested_spec_t nl80211_wiphy_bands_iftype_data_nla = {
.headsize = 0,
.nattrs = 7,
@@ -645,13 +687,26 @@ static const uc_nl_nested_spec_t nl80211_bss_nla = {
static const uc_nl_nested_spec_t nl80211_sta_info_bitrate_nla = {
.headsize = 0,
- .nattrs = 5,
+ .nattrs = 18,
.attrs = {
{ NL80211_RATE_INFO_BITRATE, "bitrate", DT_U16, 0, NULL },
{ NL80211_RATE_INFO_BITRATE32, "bitrate32", DT_U32, 0, NULL },
{ NL80211_RATE_INFO_MCS, "mcs", DT_U8, 0, NULL },
{ NL80211_RATE_INFO_40_MHZ_WIDTH, "40_mhz_width", DT_FLAG, 0, NULL },
{ NL80211_RATE_INFO_SHORT_GI, "short_gi", DT_FLAG, 0, NULL },
+ { NL80211_RATE_INFO_VHT_MCS, "vht_mcs", DT_U8, 0, NULL },
+ { NL80211_RATE_INFO_VHT_NSS, "vht_nss", DT_U8, 0, NULL },
+ { NL80211_RATE_INFO_HE_MCS, "he_mcs", DT_U8, 0, NULL },
+ { NL80211_RATE_INFO_HE_NSS, "he_nss", DT_U8, 0, NULL },
+ { NL80211_RATE_INFO_HE_GI, "he_gi", DT_U8, 0, NULL },
+ { NL80211_RATE_INFO_HE_DCM, "he_dcm", DT_U8, 0, NULL },
+ { NL80211_RATE_INFO_HE_RU_ALLOC, "he_ru_alloc", DT_U8, 0, NULL },
+ { NL80211_RATE_INFO_40_MHZ_WIDTH, "width_40", DT_FLAG, 0, NULL },
+ { NL80211_RATE_INFO_80_MHZ_WIDTH, "width_80", DT_FLAG, 0, NULL },
+ { NL80211_RATE_INFO_80P80_MHZ_WIDTH, "width_80p80", DT_FLAG, 0, NULL },
+ { NL80211_RATE_INFO_160_MHZ_WIDTH, "width_160", DT_FLAG, 0, NULL },
+ { NL80211_RATE_INFO_10_MHZ_WIDTH, "width_10", DT_FLAG, 0, NULL },
+ { NL80211_RATE_INFO_5_MHZ_WIDTH, "width_5", DT_FLAG, 0, NULL },
}
};
@@ -695,9 +750,13 @@ static const uc_nl_nested_spec_t nl80211_bss_param_nla = {
@@ -714,6 +756,10 @@ static const uc_nl_nested_spec_t nl80211
}
};
@@ -127,61 +99,12 @@ index fc24fb8..1d0871a 100644
+
static const uc_nl_nested_spec_t nl80211_sta_info_nla = {
.headsize = 0,
- .nattrs = 34,
+ .nattrs = 35,
.attrs = {
{ NL80211_STA_INFO_INACTIVE_TIME, "inactive_time", DT_U32, 0, NULL },
{ NL80211_STA_INFO_RX_BYTES, "rx_bytes", DT_U32, 0, NULL },
@@ -724,21 +783,22 @@ static const uc_nl_nested_spec_t nl80211_sta_info_nla = {
{ NL80211_STA_INFO_NONPEER_PM, "nonpeer_pm", DT_U32, 0, NULL },
{ NL80211_STA_INFO_CHAIN_SIGNAL, "chain_signal", DT_S8, DF_MULTIPLE|DF_AUTOIDX, NULL },
{ NL80211_STA_INFO_CHAIN_SIGNAL_AVG, "chain_signal_avg", DT_S8, DF_MULTIPLE|DF_AUTOIDX, NULL },
- { NL80211_STA_INFO_TID_STATS, "tid_stats", DT_NESTED, 0, &nl80211_tid_stats_nla },
+ { NL80211_STA_INFO_TID_STATS, "tid_stats", DT_NESTED, DF_MULTIPLE|DF_AUTOIDX, &nl80211_tid_stats_nla },
{ NL80211_STA_INFO_BSS_PARAM, "bss_param", DT_NESTED, 0, &nl80211_bss_param_nla },
{ NL80211_STA_INFO_RX_DURATION, "rx_duration", DT_U64, 0, NULL },
{ NL80211_STA_INFO_TX_DURATION, "tx_duration", DT_U64, 0, NULL },
- { NL80211_STA_INFO_ACK_SIGNAL, "ack_signal", DT_U8, 0, NULL },
- { NL80211_STA_INFO_ACK_SIGNAL_AVG, "ack_signal_avg", DT_U8, 0, NULL },
+ { NL80211_STA_INFO_ACK_SIGNAL, "ack_signal", DT_S8, 0, NULL },
+ { NL80211_STA_INFO_ACK_SIGNAL_AVG, "ack_signal_avg", DT_S8, 0, NULL },
{ NL80211_STA_INFO_AIRTIME_LINK_METRIC, "airtime_link_metric", DT_U32, 0, NULL },
{ NL80211_STA_INFO_CONNECTED_TO_AS, "connected_to_as", DT_BOOL, 0, NULL },
{ NL80211_STA_INFO_CONNECTED_TO_GATE, "connected_to_gate", DT_BOOL, 0, NULL },
+ { NL80211_STA_INFO_CONNECTED_TIME, "connected_time", DT_U32, 0, NULL },
}
};
static const uc_nl_nested_spec_t nl80211_msg = {
.headsize = 0,
- .nattrs = 124,
+ .nattrs = 125,
.attrs = {
{ NL80211_ATTR_4ADDR, "4addr", DT_U8, 0, NULL },
{ NL80211_ATTR_AIRTIME_WEIGHT, "airtime_weight", DT_U16, 0, NULL },
@@ -864,6 +924,7 @@ static const uc_nl_nested_spec_t nl80211_msg = {
{ NL80211_ATTR_WPA_VERSIONS, "wpa_versions", DT_U32, 0, NULL },
{ NL80211_ATTR_SUPPORTED_IFTYPES, "supported_iftypes", DT_NESTED, 0, &nl80211_ifcomb_limit_types_nla },
{ NL80211_ATTR_SOFTWARE_IFTYPES, "software_iftypes", DT_NESTED, 0, &nl80211_ifcomb_limit_types_nla },
+ { NL80211_ATTR_MAX_AP_ASSOC_STA, "max_ap_assoc", DT_U16, 0, NULL },
}
};
@@ -1044,6 +1105,9 @@ uc_nl_parse_attrs(struct nl_msg *msg, char *base, const uc_nl_attr_spec_t *attrs
bool exists;
for (i = 0; i < nattrs; i++) {
+ if (attrs[i].attr == NL80211_ATTR_NOT_IMPLEMENTED)
+ continue;
+
v = ucv_object_get(obj, attrs[i].key, &exists);
if (!exists)
diff --git a/lib/rtnl.c b/lib/rtnl.c
index b6a3e38..c1d2088 100644
--- a/lib/rtnl.c
+++ b/lib/rtnl.c
@@ -682,6 +682,7 @@ static const uc_nl_nested_spec_t link_msg = {
.nattrs = 35,
Index: ucode-2022-04-07-33f1e0b0/lib/rtnl.c
===================================================================
--- ucode-2022-04-07-33f1e0b0.orig/lib/rtnl.c
+++ ucode-2022-04-07-33f1e0b0/lib/rtnl.c
@@ -682,6 +682,7 @@ static const uc_nl_nested_spec_t link_ms
{ IFLA_UNSPEC, "type", DT_U16, 0, MEMBER(ifinfomsg, ifi_type) },
{ IFLA_UNSPEC, "dev", DT_NETDEV, 0, MEMBER(ifinfomsg, ifi_index) },
{ IFLA_UNSPEC, "flags", DT_FLAGS, 0, MEMBER(ifinfomsg, ifi_flags) },
@@ -189,6 +112,3 @@ index b6a3e38..c1d2088 100644
{ IFLA_ADDRESS, "address", DT_LLADDR, 0, NULL },
{ IFLA_BROADCAST, "broadcast", DT_LLADDR, 0, NULL },
{ IFLA_TXQLEN, "txqlen", DT_U32, 0, NULL },
--
2.25.1

View File

@@ -1,213 +0,0 @@
From 9c77d85f8e121bf0994eb4bc572eea5cf093f0c6 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Tue, 25 Jan 2022 16:54:48 +0100
Subject: [PATCH] add os library
Signed-off-by: John Crispin <john@phrozen.org>
---
CMakeLists.txt | 7 +++
lib/os.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 174 insertions(+)
create mode 100644 lib/os.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7c84fc3..f7d4f83 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,6 +27,7 @@ OPTION(RTNL_SUPPORT "Route Netlink plugin support" ON)
OPTION(NL80211_SUPPORT "Wireless Netlink plugin support" ON)
OPTION(RESOLV_SUPPORT "NS resolve plugin support" ON)
OPTION(STRUCT_SUPPORT "Struct plugin support" ON)
+OPTION(OS_SUPPORT "OS plugin support" ON)
SET(LIB_SEARCH_PATH "${CMAKE_INSTALL_PREFIX}/lib/ucode/*.so:${CMAKE_INSTALL_PREFIX}/share/ucode/*.uc:./*.so:./*.uc" CACHE STRING "Default library search path")
STRING(REPLACE ":" "\", \"" LIB_SEARCH_DEFINE "${LIB_SEARCH_PATH}")
@@ -143,6 +144,12 @@ IF(NL80211_SUPPORT)
TARGET_LINK_LIBRARIES(nl80211_lib ${nl})
ENDIF()
+IF(OS_SUPPORT)
+ SET(LIBRARIES ${LIBRARIES} os_lib)
+ ADD_LIBRARY(os_lib MODULE lib/os.c)
+ SET_TARGET_PROPERTIES(os_lib PROPERTIES OUTPUT_NAME os PREFIX "")
+ENDIF()
+
IF(RESOLV_SUPPORT)
SET(LIBRARIES ${LIBRARIES} resolv_lib)
ADD_LIBRARY(resolv_lib MODULE lib/resolv.c)
diff --git a/lib/os.c b/lib/os.c
new file mode 100644
index 0000000..cebad15
--- /dev/null
+++ b/lib/os.c
@@ -0,0 +1,167 @@
+#include <glob.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <regex.h>
+
+#include <sys/sysinfo.h>
+
+#include "ucode/module.h"
+
+static regex_t pat_vmdata, pat_vmstk;
+static struct sysinfo info;
+static long systick;
+
+static void __attribute__((constructor))
+measure_init()
+{
+ regcomp(&pat_vmdata, "VmData:[ \t]*([0-9]*) kB", REG_EXTENDED);
+ regcomp(&pat_vmstk, "VmStk:[ \t]*([0-9]*) kB", REG_EXTENDED);
+ sysinfo(&info);
+ systick = sysconf(_SC_CLK_TCK);
+}
+
+static void __attribute__((destructor))
+measure_fini()
+{
+ regfree(&pat_vmdata);
+ regfree(&pat_vmstk);
+}
+
+static char *
+strnchr(char *buf, int c, int i)
+{
+ while (*buf && i) {
+ buf = strchr(buf, c);
+ buf++;
+ i--;
+ }
+ return buf;
+}
+
+static int
+measure_process(uc_value_t *obj, pid_t pid)
+{
+ int fd;
+ char buffer[512] = "";
+ ssize_t rxed;
+ regmatch_t matches[2];
+ glob_t gl;
+ size_t i;
+ char *ch;
+
+ uint32_t fdcount = 0;
+ uint32_t mem = 0;
+
+ snprintf(buffer, sizeof(buffer), "/proc/%i/fd/*", (int)pid);
+
+ if (glob(buffer, GLOB_NOESCAPE | GLOB_MARK, NULL, &gl))
+ return -1;
+
+ for (i = 0; i < gl.gl_pathc; i++)
+ if (isdigit(basename(gl.gl_pathv[i])[0]))
+ fdcount = fdcount + 1;
+ globfree(&gl);
+ ucv_object_add(obj, "fd", ucv_int64_new(fdcount));
+
+ snprintf(buffer, sizeof(buffer), "/proc/%i/stat", (int)pid);
+ fd = open(buffer, O_RDONLY);
+ if (fd == -1)
+ return -1;
+
+ rxed = read(fd, buffer, sizeof(buffer) - 1);
+ close(fd);
+ if (rxed == -1)
+ return -1;
+
+ buffer[rxed] = 0;
+
+ ch = strnchr(buffer, ' ', 14);
+ if (ch)
+ ucv_object_add(obj, "load", ucv_int64_new(atoll(ch)));
+
+ ch = strnchr(buffer, ' ', 21);
+ if (ch)
+ ucv_object_add(obj, "age", ucv_int64_new(info.uptime - atol(ch) / systick));
+
+ snprintf(buffer, sizeof(buffer), "/proc/%i/status", (int)pid);
+ fd = open(buffer, O_RDONLY);
+ if (fd == -1)
+ return -1;
+
+ rxed = read(fd, buffer, sizeof(buffer) - 1);
+ close(fd);
+ if (rxed == -1)
+ return -1;
+
+ buffer[rxed] = 0;
+
+ if (!regexec(&pat_vmdata, buffer, 2, matches, 0))
+ mem += atoi(buffer + matches[1].rm_so) * 1024;
+
+ if (!regexec(&pat_vmstk, buffer, 2, matches, 0))
+ mem += atoi(buffer + matches[1].rm_so) * 1024;
+
+ ucv_object_add(obj, "memory", ucv_int64_new(mem));
+
+ return 0;
+}
+
+static uc_value_t *
+uc_system_hostname(uc_vm_t *vm, size_t nargs)
+{
+ char buf[255] = {};
+
+ if (gethostname(buf, sizeof(buf)) < 0)
+ return NULL;
+
+ return ucv_string_new(buf);
+}
+
+static uc_value_t *
+uc_system_loadavg(uc_vm_t *vm, size_t nargs)
+{
+ uc_value_t *res_obj = NULL;
+ int i;
+
+ sysinfo(&info);
+
+ res_obj = ucv_array_new(vm);
+ for (i = 0; i < 3; i++)
+ ucv_array_push(res_obj, ucv_double_new(((double) info.loads[i]) / 65535.0f));
+
+ return res_obj;
+}
+
+static uc_value_t *
+uc_system_process(uc_vm_t *vm, size_t nargs)
+{
+ uc_value_t *pid = uc_fn_arg(0);
+ uc_value_t *res_obj = NULL;
+
+ if (ucv_type(pid) != UC_INTEGER)
+ return NULL;
+
+ res_obj = ucv_object_new(vm);
+
+ measure_process(res_obj, ucv_uint64_get(pid));
+
+ return res_obj;
+}
+
+static const uc_function_list_t system_fns[] = {
+ { "hostname", uc_system_hostname },
+ { "loadavg", uc_system_loadavg },
+ { "process", uc_system_process },
+};
+
+void uc_module_init(uc_vm_t *vm, uc_value_t *scope)
+{
+ uc_function_list_register(scope, system_fns);
+}
--
2.25.1

View File

@@ -0,0 +1,51 @@
#
# Copyright (C) 2022 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=unetd
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=https://github.com/nbd168/unetd
PKG_SOURCE_DATE:=2022-05-23
PKG_SOURCE_VERSION:=f75c2e70c0e494566dbbb20d408309412b4110e6
PKG_MIRROR_HASH:=633e6b0406b89850d0caf933fb419345be37d5deab812251d6183a7ab3f2cd42
PKG_LICENSE:=GPL-2.0
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/unetd
SECTION:=utils
CATEGORY:=Base system
TITLE:=Wireguard network configuration service
DEPENDS:=+libubox +libubus +libblobmsg-json +libnl-tiny +TARGET_ipq807x:kmod-wireguard-backport +!TARGET_ipq807x:kmod-wireguard
endef
TARGET_CFLAGS += \
-I$(STAGING_DIR)/usr/include/libnl-tiny \
-I$(STAGING_DIR)/usr/include
CMAKE_OPTIONS += \
-DLIBNL_LIBS=-lnl-tiny
define Package/unetd/install
$(INSTALL_DIR) \
$(1)/etc/init.d \
$(1)/lib/netifd/proto \
$(1)/usr/sbin
$(INSTALL_BIN) \
$(PKG_INSTALL_DIR)/usr/sbin/unetd \
$(1)/usr/sbin/
$(INSTALL_BIN) ./files/unetd.init $(1)/etc/init.d/unetd
$(INSTALL_BIN) ./files/unetd.sh $(1)/lib/netifd/proto
endef
$(eval $(call BuildPackage,unetd))

View File

@@ -0,0 +1,15 @@
#!/bin/sh /etc/rc.common
# Copyright (c) 2021 OpenWrt.org
START=19
USE_PROCD=1
PROG=/usr/sbin/unetd
start_service() {
mkdir -p /var/run/unetd
procd_open_instance
procd_set_param command "$PROG" -h /var/run/unetd/hosts
procd_set_param respawn
procd_close_instance
}

View File

@@ -0,0 +1,67 @@
#!/bin/sh
[ -x /usr/sbin/unetd ] || exit 0
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
proto_unet_init_config() {
proto_config_add_string device
proto_config_add_string type
proto_config_add_string key
proto_config_add_string file
proto_config_add_int keepalive
proto_config_add_string domain
no_device=1
available=1
no_proto_task=1
}
proto_unet_setup() {
local config="$1"
local device type key file keepalive domain
json_get_vars device type key file keepalive domain
device="${device:-$config}"
[ -n "$file" ] && type="${type:-file}"
json_init
json_add_string name "$device"
json_add_string type "$type"
json_add_string interface "$config"
json_add_string key "$key"
json_add_string file "$file"
[ -n "$keepalive" ] && json_add_int keepalive "$keepalive"
json_add_string domain "$domain"
ip link del dev "$device" >/dev/null 2>&1
ip link add dev "$device" type wireguard || {
echo "Could not create wireguard device $device"
proto_setup_failed "$config"
exit 1
}
ubus call unetd network_add "$(json_dump)"
}
proto_unet_teardown() {
local config="$1"
local iface="$2"
local device
json_get_vars device
device="${device:-$iface}"
json_init
json_add_string name "$device"
ip link del dev "$device"
ubus call unetd network_del "$(json_dump)"
}
add_protocol unet

View File

@@ -143,5 +143,5 @@ start_service()
procd_open_instance
procd_set_param command "/usr/libexec/uchannel.uc"
procd_set_param respawn 1 300 0
procd_close_instancea
procd_close_instance
}

View File

@@ -1,5 +1,4 @@
#!/usr/bin/ucode
{%
let fs = require("fs");
let ubus = require("ubus");
let conn = ubus.connect();
@@ -56,7 +55,7 @@ function state_get() {
function state_set(state) {
let file = fs.open("/tmp/uchannel.json", "w");
state.uptime = uptime;
state.executed = uptime;
file.write(state);
file.close();
@@ -64,7 +63,7 @@ function state_set(state) {
node: "*",
data: {
status: state.status,
uptime: state.uptime,
uptime: state.executed,
}
});
printf("entering %s state\n", state.status);
@@ -259,8 +258,8 @@ function channel_balance(band, mask) {
function youngest() {
for (let ip, host in hosts) {
if (host.host_info.status == "overlap" &&
host.host_info.uptime < uptime) {
if (host.host_info?.status == "overlap" &&
host.host_info?.uptime < uptime) {
print("Found a younger host\n");
return 1;
}
@@ -272,7 +271,7 @@ function youngest() {
let state = state_get();
if (state.status == "waiting" &&
(uptime - state.uptime < (12 * 60 * 60))) {
(uptime - state.changed < (12 * 60 * 60))) {
state_set(state);
return;
}
@@ -328,4 +327,3 @@ for (let freq, obj in overlap) {
state.status = "waiting";
state.changed = uptime;
state_set(state);
%}

View File

@@ -7,6 +7,7 @@ PKG_LICENSE:=GPLv2
PKG_LICENSE_FILES:=
PKG_SOURCE_URL:=https://github.com/greearb/ath10k-ct.git
PKG_MIRROR_HASH:=37b4f00231cb0ae00f63da1c94ae53c940c76d047ce0fb081c08a35fffbfd2c0
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2021-05-22b
PKG_SOURCE_VERSION:=54a9ac02f1139596ea4361ebbc3e444955d86cfd

View File

@@ -132,7 +132,7 @@ mac80211_hostapd_setup_base() {
json_select config
[ "$auto_channel" -gt 0 ] && channel=acs_survey
[ "$auto_channel" -gt 0 ] && channel=0
[ "$auto_channel" -gt 0 ] && json_get_vars acs_exclude_dfs
[ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] &&
@@ -1162,10 +1162,13 @@ drv_mac80211_setup() {
if [ "$no_reload" != "0" ]; then
add_ap=1
ubus wait_for hostapd
local hostapd_res="$(ubus call hostapd config_add "{\"iface\":\"$primary_ap\", \"config\":\"${hostapd_conf_file}\"}")"
local hostapd_res
[ -f /tmp/wifi_fail_test ] || hostapd_res="$(ubus call hostapd config_add "{\"iface\":\"$primary_ap\", \"config\":\"${hostapd_conf_file}\"}")"
ret="$?"
rm -f /tmp/wifi_fail_test
[ "$ret" != 0 -o -z "$hostapd_res" ] && {
wireless_setup_failed HOSTAPD_START_FAILED
logger failed to start wifi trying again
# wireless_setup_failed HOSTAPD_START_FAILED
return
}
wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1

View File

@@ -0,0 +1,45 @@
include $(TOPDIR)/rules.mk
PKG:=ath11k-fwtest
PKG_NAME:=$(PKG)
PKG_VERSION:=1.0
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG)
include $(INCLUDE_DIR)/package.mk
define Package/ath11k-fwtest
SECTION:=QCA
CATEGORY:=QCA
URL:=http://www.qca.qualcomm.com
MAINTAINER:=Qualcomm Atheros, Inc.
TITLE:=QCA ath11k fwtest utility
DEPENDS:= +libnl
endef
define Package/ath11k-fwtest/description
This Package contains ath11k fwtest utility
endef
TARGET_CFLAGS += -O1 -Wall -fpie -I. -I$(STAGING_DIR)/usr/include/ -I $(STAGING_DIR)/usr/include/mac80211/uapi -I $(STAGING_DIR)/usr/include/libnl3
TARGET_LDFLAGS += -lnl-3 -lnl-genl-3
define Build/Compile
mkdir -p $(PKG_BUILD_DIR)/install/sbin
$(MAKE) -C $(PKG_BUILD_DIR)/ \
CC="$(TARGET_CC)" \
CFLAGS="$(TARGET_CFLAGS)" \
LDFLAGS="$(TARGET_LDFLAGS)"
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ath11k-fwtest $(1)/usr/sbin
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ath11k-fwtest $(1)/usr/sbin
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@@ -0,0 +1,29 @@
# Makefile for ath11k-fwtest
ALL=ath11k-fwtest
OBJS = fwtest.o
# Making default targets:
all: local install
@echo All done in `pwd`
local : $(ALL)
@echo Made outputs in `pwd`
install: local
@cp -a -f ath11k-fwtest ./install/sbin
@echo Installed outputs from `pwd`
fwtest.o : fwtest.c
$(CC) -c $(CFLAGS) fwtest.c
ath11k-fwtest: $(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $@
# Remove all generated files
clean:
@rm -f *.o
.PHONY: all clean install

View File

@@ -0,0 +1,429 @@
/*
* Copyright (c) 2014, 2019 Qualcomm Technologies, Inc.
*
* All Rights Reserved.
* Confidential and Proprietary - Qualcomm Technologies, Inc.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <linux/nl80211.h>
#include <linux/netlink.h>
#include <net/if.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#include <netlink/msg.h>
#include <netlink/attr.h>
#define ATH11K_TM_DATA_MAX_LEN 5000
#define ATH11K_WMI_UNIT_TEST_MAX_NUM_ARGS 100
#define WMI_TAG_ARRAY_UINT32 16
#define WMI_TAG_VDEV_SET_PARAM_CMD 95
#define WMI_TAG_PDEV_SET_PARAM_CMD 82
#define WMI_TAG_UNIT_TEST_CMD 327
#define WMI_TLV_HDR_SIZE (sizeof(unsigned int))
#define WMI_TLV_LEN_SHIFT 0
#define WMI_TLV_LEN_MASK 0x0000ffff
#define WMI_TLV_TAG_SHIFT 16
#define WMI_TLV_TAG_MASK 0xffff0000
#define FIELD_PREP(a, b) (((a) << (b##_SHIFT)) & (b##_MASK))
#define WMI_GRP_FWTEST 0x1f
#define WMI_GRP_PDEV 0x04
#define WMI_GRP_VDEV 0x05
#define WMI_TLV_CMD(grp_id) (((grp_id) << 12) | 0x1)
#define WMI_UNIT_TEST_CMDID (WMI_TLV_CMD(WMI_GRP_FWTEST) + 2)
#define WMI_VDEV_SET_PARAM_CMDID (WMI_TLV_CMD(WMI_GRP_VDEV) + 7)
#define WMI_PDEV_SET_PARAM_CMDID (WMI_TLV_CMD(WMI_GRP_PDEV) + 2)
enum ath11k_tm_attr {
__ATH11K_TM_ATTR_INVALID = 0,
ATH11K_TM_ATTR_CMD = 1,
ATH11K_TM_ATTR_DATA = 2,
ATH11K_TM_ATTR_WMI_CMDID = 3,
ATH11K_TM_ATTR_VERSION_MAJOR = 4,
ATH11K_TM_ATTR_VERSION_MINOR = 5,
ATH11K_TM_ATTR_WMI_OP_VERSION = 6,
/* keep last */
__ATH11K_TM_ATTR_AFTER_LAST,
ATH11K_TM_ATTR_MAX = __ATH11K_TM_ATTR_AFTER_LAST - 1,
};
/* All ath11k testmode interface commands specified in
* ATH11K_TM_ATTR_CMD
*/
enum ath11k_tm_cmd {
/* Returns the supported ath11k testmode interface version in
* ATH11K_TM_ATTR_VERSION. Always guaranteed to work. User space
* uses this to verify it's using the correct version of the
* testmode interface
*/
ATH11K_TM_CMD_GET_VERSION = 0,
/* Boots the UTF firmware, the netdev interface must be down at the
* time.
*/
ATH11K_TM_CMD_TESTMODE_START = 1,
/* Shuts down the UTF firmware and puts the driver back into OFF
* state.
*/
ATH11K_TM_CMD_TESTMODE_STOP = 2,
/* The command used to transmit a FW test WMI command to the firmware
* and the event to receive WMI events from the firmware. Without
* struct wmi_cmd_hdr header, only the WMI payload. Command id is
* provided with ATH11K_TM_ATTR_WMI_CMDID and payload in
* ATH11K_TM_ATTR_DATA.
*/
ATH11K_TM_CMD_WMI_FW_TEST = 3,
/* The command used to transmit a FTM WMI command to the firmware
* and the event to receive WMI events from the firmware.The data
* received only contain the payload, Need to add the tlv
* header and send the cmd to fw with commandid WMI_PDEV_UTF_CMDID.
*/
ATH11K_TM_CMD_WMI_FTM = 4,
};
struct nl80211_socket_info {
struct nl_sock *nl_sock;
int genl_family_id;
};
struct wmi_unit_test_cmd {
unsigned int tlv_header;
unsigned int vdev_id;
unsigned int module_id;
unsigned int num_args;
unsigned int diag_token;
};
struct wmi_vdev_pdev_set_param_cmd {
unsigned int tlv_header;
unsigned int vdev_pdev_id;
unsigned int param_id;
unsigned int param_value;
};
enum wmi_unit_test_cmd_type {
ATH11K_WMI_FW_UNIT_TEST_CMD,
ATH11K_WMI_VDEV_SET_PARAM_CMD,
ATH11K_WMI_PDEV_SET_PARAM_CMD,
};
int init_nl_sock(struct nl80211_socket_info *sock)
{
int ret;
sock->nl_sock = nl_socket_alloc();
if (!sock->nl_sock) {
fprintf(stderr, "Failed to create nl socket\n");
return -ENOMEM;
}
if (genl_connect(sock->nl_sock)) {
fprintf(stderr, "Failed to connect to nl socket\n");
ret = -ENOLINK;
goto free_nl_sock;
}
nl_socket_set_buffer_size(sock->nl_sock, 0, ATH11K_TM_DATA_MAX_LEN);
sock->genl_family_id = genl_ctrl_resolve(sock->nl_sock, "nl80211");
if (sock->genl_family_id < 0) {
fprintf(stderr, "genl family not found!!\n");
ret = -ENOENT;
goto free_nl_sock;
}
return 0;
free_nl_sock:
nl_socket_free(sock->nl_sock);
return ret;
}
void usage(char *argv[])
{
fprintf(stderr, "Usage: %s -t <cmd type> -i <wlanX> -m <moduleid> -v <vdevid> <argument list>\n",
argv[0]);
}
static int nl_cb_error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
{
int *ret = arg;
*ret = err->error;
return NL_STOP;
}
static int nl_cb_finish_handler(struct nl_msg *msg, void *arg)
{
int *ret = arg;
*ret = 0;
return NL_SKIP;
}
static int nl_cb_ack_handler(struct nl_msg *msg, void *arg)
{
int *ret = arg;
*ret = 0;
return NL_STOP;
}
void *ath11k_fwtest_fill_cmd_buf(unsigned int module_id, unsigned int vdev_id,
int num_args, char *argv[], int optind, int *buf_sz)
{
struct wmi_unit_test_cmd *cmd;
unsigned int *buf;
int buf_size, i;
buf_size = sizeof(struct wmi_unit_test_cmd) + WMI_TLV_HDR_SIZE + num_args * sizeof(unsigned int);
*buf_sz = buf_size;
buf = (unsigned int *) malloc(buf_size);
if (!buf) {
fprintf(stderr, "Failed to allocate memory\n");
return NULL;
}
memset((void *)buf, 0, buf_size);
cmd = (struct wmi_unit_test_cmd *) buf;
cmd->tlv_header = FIELD_PREP(WMI_TAG_UNIT_TEST_CMD, WMI_TLV_TAG) |
FIELD_PREP(sizeof(struct wmi_unit_test_cmd) - WMI_TLV_HDR_SIZE, WMI_TLV_LEN);
cmd->module_id = module_id;
cmd->vdev_id = vdev_id;
cmd->num_args = num_args;
cmd->diag_token = 0;
buf = (unsigned int *)((char *)buf + sizeof(struct wmi_unit_test_cmd));
*buf = FIELD_PREP(WMI_TAG_ARRAY_UINT32, WMI_TLV_TAG) |
FIELD_PREP(num_args * sizeof(unsigned int), WMI_TLV_LEN);
buf++;
for (i = 0; i < num_args; i++, buf++)
*buf = strtoul(argv[optind + i], NULL, 0);
return cmd;
}
void *ath11k_wmi_vdev_pdev_set_cmd_fill_buf(unsigned int type, unsigned int vdev_pdev_id,
char *argv[], int optind, int *buf_sz)
{
struct wmi_vdev_pdev_set_param_cmd *cmd;
unsigned int *buf;
int buf_size;
int tag;
buf_size = sizeof(struct wmi_vdev_pdev_set_param_cmd);
*buf_sz = buf_size;
buf = (unsigned int *) malloc(buf_size);
if (!buf) {
fprintf(stderr, "Failed to allocate memory\n");
return NULL;
}
memset((void *)buf, 0, buf_size);
cmd = (struct wmi_vdev_pdev_set_param_cmd *) buf;
if (type == ATH11K_WMI_VDEV_SET_PARAM_CMD)
tag = WMI_TAG_VDEV_SET_PARAM_CMD;
else
tag = WMI_TAG_PDEV_SET_PARAM_CMD;
cmd->tlv_header = FIELD_PREP(tag, WMI_TLV_TAG) |
FIELD_PREP(sizeof(struct wmi_vdev_pdev_set_param_cmd) - WMI_TLV_HDR_SIZE, WMI_TLV_LEN);
cmd->vdev_pdev_id = vdev_pdev_id;
cmd->param_id = strtoul(argv[optind], NULL, 0);
cmd->param_value = strtoul(argv[optind + 1], NULL, 0);
return cmd;
}
int main(int argc, char *argv[])
{
struct nl80211_socket_info sock;
void *cmd = NULL;
struct nl_msg *msg;
struct nlattr *nest;
struct nl_cb *cb;
unsigned int cmd_id;
char *ifname = NULL;
int netdev_idx;
unsigned int module_id = UINT_MAX;
unsigned int vdev_id = UINT_MAX;
unsigned int pdev_id = UINT_MAX;
unsigned int type = ATH11K_WMI_FW_UNIT_TEST_CMD;
int num_args;
int buf_size;
int opt;
int ret = 1;
while (1) {
opt = getopt(argc, argv, "t:i:m:v:p:h");
if (opt < 0)
break;
switch (opt) {
case 'i':
ifname = optarg;
break;
case 't':
type = strtoul(optarg, NULL, 0);
break;
case 'm':
module_id = strtoul(optarg, NULL, 0);
break;
case 'v':
vdev_id = strtoul(optarg, NULL, 0);
break;
case 'p':
pdev_id = strtoul(optarg, NULL, 0);
break;
case 'h':
/* fall through */
default:
usage(argv);
return ret;
}
}
if (!ifname || module_id == UINT_MAX ||
(type != ATH11K_WMI_PDEV_SET_PARAM_CMD && vdev_id == UINT_MAX)) {
fprintf(stderr, "Mandatory options are missing!!\n");
usage(argv);
return -EINVAL;
}
if (optind >= argc) {
fprintf(stderr, "Argument list missing!!\n");
usage(argv);
return ret;
}
num_args = argc - optind;
if (num_args > ATH11K_WMI_UNIT_TEST_MAX_NUM_ARGS) {
fprintf(stderr, "Arguments exceeded max limit, limit:%d\n",
ATH11K_WMI_UNIT_TEST_MAX_NUM_ARGS);
return ret;
}
netdev_idx = if_nametoindex(ifname);
if (!netdev_idx) {
fprintf(stderr, "%s not found\n", ifname);
return -ENOENT;
}
ret = init_nl_sock(&sock);
if (ret < 0) {
fprintf(stderr, "Failed to initialize nl socket\n");
return ret;
}
msg = nlmsg_alloc();
if (!msg) {
fprintf(stderr, "Failed to allocate nl message\n");
ret = -ENOMEM;
goto free_nl_sock;
}
cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!cb) {
fprintf(stderr, "failed to allocate netlink callback\n");
ret = -ENOMEM;
goto free_nl_msg;
}
switch (type) {
case ATH11K_WMI_FW_UNIT_TEST_CMD:
cmd = ath11k_fwtest_fill_cmd_buf(module_id, vdev_id, num_args, argv, optind, &buf_size);
cmd_id = WMI_UNIT_TEST_CMDID;
break;
case ATH11K_WMI_VDEV_SET_PARAM_CMD:
cmd = ath11k_wmi_vdev_pdev_set_cmd_fill_buf(type, vdev_id, argv, optind, &buf_size);
cmd_id = WMI_VDEV_SET_PARAM_CMDID;
break;
case ATH11K_WMI_PDEV_SET_PARAM_CMD:
if (pdev_id == 0 || pdev_id == UINT_MAX)
break;
cmd = ath11k_wmi_vdev_pdev_set_cmd_fill_buf(type, pdev_id, argv, optind, &buf_size);
cmd_id = WMI_PDEV_SET_PARAM_CMDID;
break;
default:
fprintf(stderr, "Unknown fw unittest type\n");
ret = -EINVAL;
goto free_nl_msg;
}
if (!cmd) {
fprintf(stderr, "failed to fill cmd buffer, please check inputs\n");
ret = -EINVAL;
goto free_nl_msg;
}
genlmsg_put(msg, 0, 0, sock.genl_family_id, 0, 0,
NL80211_CMD_TESTMODE, 0);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev_idx);
nest = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
if (!nest) {
fprintf(stderr, "Failed to nest test input\n");
ret = -ENOMEM;
goto free_cmd_buf;
}
NLA_PUT_U32(msg, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI_FW_TEST);
NLA_PUT_U32(msg, ATH11K_TM_ATTR_WMI_CMDID, cmd_id);
NLA_PUT(msg, ATH11K_TM_ATTR_DATA, buf_size, cmd);
nla_nest_end(msg, nest);
ret = nl_send_auto_complete(sock.nl_sock, msg);
if (ret < 0) {
fprintf(stderr, "Failed to send nl msg: %d\n", ret);
goto free_cmd_buf;
}
ret = 1;
nl_cb_err(cb, NL_CB_CUSTOM, nl_cb_error_handler, &ret);
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl_cb_finish_handler, &ret);
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, nl_cb_ack_handler, &ret);
while (ret > 0)
nl_recvmsgs(sock.nl_sock, cb);
if (ret < 0)
fprintf(stderr, "command failed: %s (%d)\n", strerror(-ret), ret);
goto free_cmd_buf;
nla_put_failure:
fprintf(stderr, "nl put operation failed!!\n");
free_cmd_buf:
free(cmd);
nl_cb_put(cb);
free_nl_msg:
nlmsg_free(msg);
free_nl_sock:
nl_socket_free(sock.nl_sock);
return ret;
}

View File

@@ -31,13 +31,15 @@ ALLWIFIBOARDS:= \
cig-wf196 \
cybertan-eww622-a1 \
edgecore-eap101 \
gl-ax1800 \
sercomm-wallaby \
edgecore-eap102 \
edgecore-eap104 \
wallys-dr6018 \
wallys-dr6018-v4 \
tplink-ex227 \
tplink-ex447
tplink-ex447 \
yuncore-ax840
ALLWIFIPACKAGES:=$(foreach BOARD,$(ALLWIFIBOARDS),ath11k-wifi-$(BOARD))
@@ -79,6 +81,11 @@ $(call Package/ath11k-wifi-default)
TITLE:=cig-wf196 6G bdf
endef
define Package/ath11k-wifi-gl-ax1800
$(call Package/ath11k-wifi-default)
TITLE:=gl-ax1800 bdf
endef
define ath11k-wifi-install-one-to
$(INSTALL_DIR) $(2)/lib/firmware/$(3)/
$(INSTALL_DATA) $(1) $(2)/lib/firmware/$(3)/board.bin
@@ -161,6 +168,11 @@ define Package/ath11k-wifi-cig-wf196_6g/install
$(INSTALL_DATA) ./board-cig-wf196_6g.bin.QCN9074 $(1)/lib/firmware/ath11k/QCN9074/hw1.0/board.bin
endef
define Package/ath11k-wifi-gl-ax1800/install
$(INSTALL_DIR) $(1)/lib/firmware/ath11k/IPQ6018/hw1.0/
$(INSTALL_DATA) ./board-gl-ax1800.bin.IPQ6018 $(1)/lib/firmware/ath11k/IPQ6018/hw1.0/board-2.bin
endef
$(eval $(call generate-ath11k-wifi-package,cig-wf188,Cigtech WF188))
$(eval $(call generate-ath11k-wifi-package,cig-wf188n,Cigtech WF188n))
$(eval $(call generate-ath11k-wifi-package,cig-wf194c,Cigtech WF194c))
@@ -175,6 +187,7 @@ $(eval $(call generate-ath11k-wifi-package,edgecore-eap102,Edgecore EAP102))
$(eval $(call generate-ath11k-wifi-package,edgecore-eap104,Edgecore EAP104))
$(eval $(call generate-ath11k-wifi-package,tplink-ex227,TP-Link EX227))
$(eval $(call generate-ath11k-wifi-package,tplink-ex447,TP-Link EX447))
$(eval $(call generate-ath11k-wifi-package,yuncore-ax840,YunCore AX840))
$(foreach PACKAGE,$(ALLWIFIPACKAGES),$(eval $(call BuildPackage,$(PACKAGE))))
$(eval $(call BuildPackage,ath11k-wifi-qcom-ipq5018))

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More