mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-31 02:17:58 +00:00 
			
		
		
		
	Compare commits
	
		
			62 Commits
		
	
	
		
			v2.5.0-rc4
			...
			v2.5.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 36b5478005 | ||
|   | 1ad19297c1 | ||
|   | f5357f7854 | ||
|   | 8a3140b89b | ||
|   | 16e0724ace | ||
|   | 17ff9eecf5 | ||
|   | 4b870f978c | ||
|   | 8b83365961 | ||
|   | c6ebb5537a | ||
|   | 6ebe189d71 | ||
|   | 98b56551d5 | ||
|   | 606e27e256 | ||
|   | 94fe14b9f9 | ||
|   | 58388f84b6 | ||
|   | 79ea04af49 | ||
|   | 396e2bd06c | ||
|   | 1a484c7f39 | ||
|   | e6b1030991 | ||
|   | 6e32e68302 | ||
|   | 0f13f7f5cd | ||
|   | 2ac4f9ef1d | ||
|   | f1a75c25f9 | ||
|   | ff8d70753d | ||
|   | caea6baecd | ||
|   | 2e914c9b35 | ||
|   | da65d7e06f | ||
|   | d18eef480c | ||
|   | f3532c66e5 | ||
|   | 9678b1d6a5 | ||
|   | 379a4e2382 | ||
|   | edb33cd560 | ||
|   | 2ff425ddeb | ||
|   | 7d016ac27f | ||
|   | 9790377dec | ||
|   | 597c547101 | ||
|   | 73b2645027 | ||
|   | 8d58387d15 | ||
|   | 54dac4d348 | ||
|   | a0880ed0f1 | ||
|   | ed6d683980 | ||
|   | 4c72c6a35a | ||
|   | 125d56866e | ||
|   | a70a767ec0 | ||
|   | b8a6764207 | ||
|   | 98c9fcfd5d | ||
|   | eac5504fec | ||
|   | c2c75b67eb | ||
|   | ef3eacefa7 | ||
|   | ef7481596a | ||
|   | 6f4e00aa46 | ||
|   | be65578a7f | ||
|   | 20d4bd0c7d | ||
|   | 531f4eb811 | ||
|   | 3b0dae7189 | ||
|   | 79395593ba | ||
|   | 61248b98e0 | ||
|   | 72b5abb72a | ||
|   | 673a029a02 | ||
|   | 7efb85180f | ||
|   | f95eadaa8f | ||
|   | 6f6b40a94f | ||
|   | d84982f161 | 
							
								
								
									
										2
									
								
								.github/workflows/build-dev.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build-dev.yml
									
									
									
									
										vendored
									
									
								
							| @@ -11,7 +11,7 @@ jobs: | |||||||
|     strategy: |     strategy: | ||||||
|       fail-fast: false |       fail-fast: false | ||||||
|       matrix: |       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_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', 'udaya_a5-id2', 'wallys_dr40x9', 'wallys_dr6018', 'wallys_dr6018_v4' ] | ||||||
|  |  | ||||||
|     steps: |     steps: | ||||||
|     - uses: actions/checkout@v2 |     - uses: actions/checkout@v2 | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								.github/workflows/x64_vm-build-test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								.github/workflows/x64_vm-build-test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | name: Test x64_vm build and AMI creation | ||||||
|  |  | ||||||
|  | on: | ||||||
|  |   workflow_dispatch: | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   build: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |     - run: echo 'Test x64_vm build and AMI creation' | ||||||
| @@ -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. | 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 | cd openwrt | ||||||
| ./scripts/gen_config.py ea8300 | ./scripts/gen_config.py linksys_ea8300 | ||||||
| ``` | ``` | ||||||
| Finally we can build the tree. | Finally we can build the tree. | ||||||
| ``` | ``` | ||||||
|   | |||||||
| @@ -39,6 +39,10 @@ hfcl,ion4xe) | |||||||
|         ucidef_set_led_wlan "wlan5g" "WLAN5G" "blue:wifi5" "phy0tpt" |         ucidef_set_led_wlan "wlan5g" "WLAN5G" "blue:wifi5" "phy0tpt" | ||||||
|         ucidef_set_led_wlan "wlan2g" "WLAN2G" "blue:wifi2" "phy1tpt" |         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 | esac | ||||||
|  |  | ||||||
| board_config_flush | board_config_flush | ||||||
|   | |||||||
| @@ -32,11 +32,13 @@ qcom_setup_interfaces() | |||||||
| 	cig,wf194c4|\ | 	cig,wf194c4|\ | ||||||
| 	edgecore,eap106|\ | 	edgecore,eap106|\ | ||||||
| 	qcom,ipq5018-mp03.3|\ | 	qcom,ipq5018-mp03.3|\ | ||||||
|  | 	yuncore,ax840|\ | ||||||
| 	sercomm,wallaby) | 	sercomm,wallaby) | ||||||
| 		ucidef_set_interface_lan "eth0" | 		ucidef_set_interface_lan "eth0" | ||||||
| 		ucidef_set_interface_wan "eth1" | 		ucidef_set_interface_wan "eth1" | ||||||
| 		;; | 		;; | ||||||
| 	edgecore,eap101) | 	edgecore,eap101|\ | ||||||
|  | 	glinet,axt1800) | ||||||
| 		ucidef_set_interface_lan "eth1 eth2" | 		ucidef_set_interface_lan "eth1 eth2" | ||||||
| 		ucidef_set_interface_wan "eth0" | 		ucidef_set_interface_wan "eth0" | ||||||
| 		;; | 		;; | ||||||
| @@ -52,7 +54,8 @@ qcom_setup_interfaces() | |||||||
| 		ucidef_set_interface_lan "eth0 eth1 eth2 eth3" | 		ucidef_set_interface_lan "eth0 eth1 eth2 eth3" | ||||||
| 		ucidef_set_interface_wan "eth4" | 		ucidef_set_interface_wan "eth4" | ||||||
| 		;; | 		;; | ||||||
| 	wallys,dr6018-v4) | 	wallys,dr6018-v4|\ | ||||||
|  | 	glinet,ax1800) | ||||||
| 		ucidef_set_interface_lan "eth1 eth2 eth3 eth4" | 		ucidef_set_interface_lan "eth1 eth2 eth3 eth4" | ||||||
| 		ucidef_set_interface_wan "eth0" | 		ucidef_set_interface_wan "eth0" | ||||||
| 		;; | 		;; | ||||||
| @@ -73,7 +76,8 @@ qcom_setup_macs() | |||||||
|  |  | ||||||
| 	case $board in | 	case $board in | ||||||
| 	cig,wf194c|\ | 	cig,wf194c|\ | ||||||
| 	cig,wf194c4) | 	cig,wf194c4|\ | ||||||
|  | 	cig,wf196) | ||||||
| 		mac=$(grep BaseMacAddress= /dev/mtd14 | cut -dx -f2) | 		mac=$(grep BaseMacAddress= /dev/mtd14 | cut -dx -f2) | ||||||
| 		wan_mac=$(macaddr_canonicalize $mac) | 		wan_mac=$(macaddr_canonicalize $mac) | ||||||
| 		lan_mac=$(macaddr_add "$wan_mac" 1) | 		lan_mac=$(macaddr_add "$wan_mac" 1) | ||||||
| @@ -81,6 +85,15 @@ qcom_setup_macs() | |||||||
| 		ucidef_set_network_device_mac eth1 $wan_mac | 		ucidef_set_network_device_mac eth1 $wan_mac | ||||||
| 		ucidef_set_label_macaddr $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) | 		wan_mac=$(cat /sys/class/net/eth0/address) | ||||||
| 		lan_mac=$(macaddr_add "$wan_mac" 1) | 		lan_mac=$(macaddr_add "$wan_mac" 1) | ||||||
| @@ -88,6 +101,7 @@ qcom_setup_macs() | |||||||
| 	esac | 	esac | ||||||
| 	[ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac | 	[ -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_interface_macaddr "wan" $wan_mac | ||||||
|  | 	[ -n "$wan_mac" ] && ucidef_set_label_macaddr "$wan_mac" | ||||||
| } | } | ||||||
|  |  | ||||||
| board_config_update | board_config_update | ||||||
|   | |||||||
| @@ -81,6 +81,7 @@ case "$FIRMWARE" in | |||||||
| 	qcom,ipq807x-hk14|\ | 	qcom,ipq807x-hk14|\ | ||||||
| 	tplink,ex227|\ | 	tplink,ex227|\ | ||||||
| 	tplink,ex447|\ | 	tplink,ex447|\ | ||||||
|  | 	yuncore,ax840|\ | ||||||
| 	sercomm,wallaby) | 	sercomm,wallaby) | ||||||
|                 caldata_extract "0:ART" 0x1000 0x20000 |                 caldata_extract "0:ART" 0x1000 0x20000 | ||||||
| 		;; | 		;; | ||||||
| @@ -96,7 +97,8 @@ case "$FIRMWARE" in | |||||||
| 	wallys,dr6018|\ | 	wallys,dr6018|\ | ||||||
| 	wallys,dr6018-v4|\ | 	wallys,dr6018-v4|\ | ||||||
| 	qcom,ipq6018-cp01|\ | 	qcom,ipq6018-cp01|\ | ||||||
| 	xiaomi,ax1800) | 	xiaomi,ax1800|\ | ||||||
|  | 	glinet,ax1800) | ||||||
|                 caldata_extract "0:ART" 0x1000 0x20000   |                 caldata_extract "0:ART" 0x1000 0x20000   | ||||||
| 		;; | 		;; | ||||||
| 	esac | 	esac | ||||||
|   | |||||||
| @@ -6,7 +6,11 @@ boot() { | |||||||
| 	case "$(board_name)" in | 	case "$(board_name)" in | ||||||
| 	edgecore,eap101|\ | 	edgecore,eap101|\ | ||||||
| 	edgecore,eap102) | 	edgecore,eap102) | ||||||
|  | 		avail=$(fw_printenv -n upgrade_available) | ||||||
|  | 		[ ${avail} -eq 0 ] || { | ||||||
| 			fw_setenv bootcount 0 | 			fw_setenv bootcount 0 | ||||||
|  | 			fw_setenv upgrade_available 0 | ||||||
|  | 		} | ||||||
| 		;; | 		;; | ||||||
| 	esac | 	esac | ||||||
| } | } | ||||||
|   | |||||||
| @@ -26,6 +26,8 @@ platform_check_image() { | |||||||
| 	cig,wf194c4|\ | 	cig,wf194c4|\ | ||||||
| 	cig,wf196|\ | 	cig,wf196|\ | ||||||
| 	cybertan,eww622-a1|\ | 	cybertan,eww622-a1|\ | ||||||
|  | 	glinet,ax1800|\ | ||||||
|  | 	glinet,axt1800|\ | ||||||
| 	wallys,dr6018|\ | 	wallys,dr6018|\ | ||||||
| 	wallys,dr6018-v4|\ | 	wallys,dr6018-v4|\ | ||||||
| 	edgecore,eap101|\ | 	edgecore,eap101|\ | ||||||
| @@ -36,6 +38,7 @@ platform_check_image() { | |||||||
| 	hfcl,ion4xe|\ | 	hfcl,ion4xe|\ | ||||||
| 	tplink,ex227|\ | 	tplink,ex227|\ | ||||||
| 	tplink,ex447|\ | 	tplink,ex447|\ | ||||||
|  | 	yuncore,ax840|\ | ||||||
| 	qcom,ipq6018-cp01|\ | 	qcom,ipq6018-cp01|\ | ||||||
| 	qcom,ipq807x-hk01|\ | 	qcom,ipq807x-hk01|\ | ||||||
| 	qcom,ipq807x-hk14|\ | 	qcom,ipq807x-hk14|\ | ||||||
| @@ -62,6 +65,8 @@ platform_do_upgrade() { | |||||||
| 	cig,wf196|\ | 	cig,wf196|\ | ||||||
| 	cybertan,eww622-a1|\ | 	cybertan,eww622-a1|\ | ||||||
| 	edgecore,eap104|\ | 	edgecore,eap104|\ | ||||||
|  | 	glinet,ax1800|\ | ||||||
|  | 	glinet,axt1800|\ | ||||||
| 	hfcl,ion4xi|\ | 	hfcl,ion4xi|\ | ||||||
| 	hfcl,ion4xe|\ | 	hfcl,ion4xe|\ | ||||||
| 	qcom,ipq6018-cp01|\ | 	qcom,ipq6018-cp01|\ | ||||||
| @@ -70,6 +75,7 @@ platform_do_upgrade() { | |||||||
| 	qcom,ipq5018-mp03.3|\ | 	qcom,ipq5018-mp03.3|\ | ||||||
| 	wallys,dr6018|\ | 	wallys,dr6018|\ | ||||||
| 	wallys,dr6018-v4|\ | 	wallys,dr6018-v4|\ | ||||||
|  | 	yuncore,ax840|\ | ||||||
| 	tplink,ex447|\ | 	tplink,ex447|\ | ||||||
| 	tplink,ex227)	 | 	tplink,ex227)	 | ||||||
| 		nand_upgrade_tar "$1" | 		nand_upgrade_tar "$1" | ||||||
|   | |||||||
| @@ -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" | ||||||
| @@ -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" | ||||||
| @@ -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" | ||||||
| @@ -32,6 +32,10 @@ | |||||||
| 		serial1 = &blsp1_uart2; | 		serial1 = &blsp1_uart2; | ||||||
| 		ethernet0 = "/soc/dp1"; | 		ethernet0 = "/soc/dp1"; | ||||||
| 		ethernet1 = "/soc/dp2"; | 		ethernet1 = "/soc/dp2"; | ||||||
|  | 	        led-boot = &led_sys; | ||||||
|  | 		led-failsafe = &led_sys; | ||||||
|  | 		led-running = &led_sys; | ||||||
|  | 		led-upgrade = &led_sys; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	chosen { | 	chosen { | ||||||
| @@ -708,32 +712,20 @@ | |||||||
| 		pinctrl-0 = <&leds_pins>; | 		pinctrl-0 = <&leds_pins>; | ||||||
| 		pinctrl-names = "default"; | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
| 		led@1 { | 		led_sys: led@1 { | ||||||
| 			label = "sys:blue"; | 			label = "sys:blue"; | ||||||
| 			gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>;  /* GPIO_1 */ | 			gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>;  /* GPIO_1 */ | ||||||
| 		/*	default-state="on"; */ |  | ||||||
| 			linux,default-trigger = "timer"; |  | ||||||
| 			active-delay = <700>; |  | ||||||
| 			inactive-delay = <700>; |  | ||||||
| 			default-state="on"; | 			default-state="on"; | ||||||
| 		}; | 		}; | ||||||
| 		led@35 { | 		led@35 { | ||||||
| 			label = "sys:green"; | 			label = "sys:green"; | ||||||
| 			gpios = <&tlmm 35 GPIO_ACTIVE_HIGH>;  /* GPIO_35 */ | 			gpios = <&tlmm 35 GPIO_ACTIVE_HIGH>;  /* GPIO_35 */ | ||||||
| 			default-state="off"; | 			default-state="off"; | ||||||
| 		/*	linux,default-trigger = "timer"; |  | ||||||
| 			active-delay = <700>; |  | ||||||
| 			inactive-delay = <700>; |  | ||||||
| 			default-state="on";		*/ |  | ||||||
| 		}; | 		}; | ||||||
| 		led@31 { | 		led@31 { | ||||||
| 			label = "sys:red"; | 			label = "sys:red"; | ||||||
| 			gpios = <&tlmm 31 GPIO_ACTIVE_HIGH>;  /* GPIO_31 */ | 			gpios = <&tlmm 31 GPIO_ACTIVE_HIGH>;  /* GPIO_31 */ | ||||||
| 			default-state="off"; | 			default-state="off"; | ||||||
| 		/*	linux,default-trigger = "timer"; |  | ||||||
| 			active-delay = <700>; |  | ||||||
| 			inactive-delay = <700>; |  | ||||||
| 			default-state="on";		*/ |  | ||||||
| 		}; | 		}; | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -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"; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
| @@ -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>; | ||||||
|  | }; | ||||||
| @@ -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"; | ||||||
|  | }; | ||||||
| @@ -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"; | ||||||
|  | }; | ||||||
| @@ -51,7 +51,7 @@ | |||||||
| 		#ifdef __IPQ_MEM_PROFILE_256_MB__ | 		#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||||
| 			bootargs-append = " swiotlb=1"; | 			bootargs-append = " swiotlb=1"; | ||||||
| 		#else | 		#else | ||||||
| 			bootargs-append = " swiotlb=1 coherent_pool=2M"; | 			bootargs-append = " swiotlb=1 coherent_pool=2M vmalloc=600M"; | ||||||
| 		#endif | 		#endif | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -72,3 +72,30 @@ define Device/qcom_cp01_c1 | |||||||
|   DEVICE_PACKAGES := ath11k-wifi-qcom-ipq6018 |   DEVICE_PACKAGES := ath11k-wifi-qcom-ipq6018 | ||||||
| endef | endef | ||||||
| TARGET_DEVICES += qcom_cp01_c1 | 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-ax1800 -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 | ||||||
|   | |||||||
| @@ -41,6 +41,8 @@ define Device/cig_wf196 | |||||||
|   DEVICE_DTS := qcom-ipq807x-wf196 |   DEVICE_DTS := qcom-ipq807x-wf196 | ||||||
|   DEVICE_DTS_CONFIG=config@hk14 |   DEVICE_DTS_CONFIG=config@hk14 | ||||||
|   SUPPORTED_DEVICES := cig,wf196 |   SUPPORTED_DEVICES := cig,wf196 | ||||||
|  |   BLOCKSIZE := 256k | ||||||
|  |   PAGESIZE := 4096 | ||||||
|   DEVICE_PACKAGES := ath11k-wifi-cig-wf196 aq-fw-download uboot-envtools kmod-usb3 kmod-usb2 \ |   DEVICE_PACKAGES := ath11k-wifi-cig-wf196 aq-fw-download uboot-envtools kmod-usb3 kmod-usb2 \ | ||||||
|   	ath11k-firmware-qcn9000 ath11k-wifi-cig-wf196_6g |   	ath11k-firmware-qcn9000 ath11k-wifi-cig-wf196_6g | ||||||
| endef | endef | ||||||
|   | |||||||
| @@ -111,3 +111,22 @@ define KernelPackage/diag-char/description | |||||||
| endef | endef | ||||||
|  |  | ||||||
| $(eval $(call KernelPackage,diag-char)) | $(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)) | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								feeds/ipq807x/ipq807x/patches/001-backport_kbuild_fix.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								feeds/ipq807x/ipq807x/patches/001-backport_kbuild_fix.patch
									
									
									
									
									
										Normal 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) | ||||||
| @@ -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; | ||||||
| @@ -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); | ||||||
| @@ -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); | ||||||
| @@ -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); | ||||||
| @@ -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; | ||||||
|  |  } | ||||||
|  |   | ||||||
| @@ -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"); | ||||||
| @@ -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)) |  | ||||||
|  |  | ||||||
| @@ -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 |  | ||||||
| @@ -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)) |  | ||||||
							
								
								
									
										11
									
								
								feeds/ipq807x/qca-nss-drv/patches/200-napi_threaded.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								feeds/ipq807x/qca-nss-drv/patches/200-napi_threaded.patch
									
									
									
									
									
										Normal 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); | ||||||
| @@ -8,7 +8,7 @@ generate_certificate_volume() { | |||||||
| 	ubinfo /dev/ubi0 -N certificates > /dev/null | 	ubinfo /dev/ubi0 -N certificates > /dev/null | ||||||
| 	[ $? -eq 0 ] || { | 	[ $? -eq 0 ] || { | ||||||
| 		ubirsvol /dev/ubi0 -N rootfs_data -s 20MiB | 		ubirsvol /dev/ubi0 -N rootfs_data -s 20MiB | ||||||
| 		ubimkvol /dev/ubi0 -N certificates -s 2MiB | 		ubimkvol /dev/ubi0 -N certificates -S 20 | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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. | # This is free software, licensed under the GNU General Public License v2. | ||||||
| # See /LICENSE for more information. | # See /LICENSE for more information. | ||||||
| @@ -9,26 +9,31 @@ include $(TOPDIR)/rules.mk | |||||||
| include $(INCLUDE_DIR)/kernel.mk | include $(INCLUDE_DIR)/kernel.mk | ||||||
|  |  | ||||||
| PKG_NAME:=qosify | 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_LICENSE:=GPL-2.0 | ||||||
|  | PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name> | ||||||
|  |  | ||||||
| PKG_BUILD_DEPENDS:=bpf-headers | PKG_BUILD_DEPENDS:=bpf-headers | ||||||
|  | PKG_FLAGS:=nonshared | ||||||
|  |  | ||||||
| include $(INCLUDE_DIR)/package.mk | include $(INCLUDE_DIR)/package.mk | ||||||
| include $(INCLUDE_DIR)/cmake.mk | include $(INCLUDE_DIR)/cmake.mk | ||||||
| include $(INCLUDE_DIR)/bpf.mk | include $(INCLUDE_DIR)/bpf.mk | ||||||
|  | include $(INCLUDE_DIR)/nls.mk | ||||||
|  |  | ||||||
| define Package/qosify | define Package/qosify | ||||||
|   SECTION:=kernel |   SECTION:=utils | ||||||
|   CATEGORY:=Kernel modules |   CATEGORY:=Base system | ||||||
|   SUBMENU:=Network Support |   TITLE:=A simple QoS solution based eBPF + CAKE | ||||||
|   TITLE:=QoS classifier eBPF module |   DEPENDS:=+libbpf +libubox +libubus +kmod-sched-cake +kmod-sched-bpf +kmod-ifb +tc-full $(BPF_DEPENDS) | ||||||
|   DEPENDS:=+libbpf +libubox +libubus +kmod-sched-cake +tc-full |  | ||||||
|   PKGFLAGS+=nonshared |  | ||||||
| endef | endef | ||||||
|  |  | ||||||
| BPF_DOC = $(wildcard $(patsubst %,$(BPF_HEADERS_DIR)/scripts/%.py,bpf_doc bpf_helpers_doc)) |  | ||||||
|  |  | ||||||
| define Build/Compile | define Build/Compile | ||||||
| 	$(call CompileBPF,$(PKG_BUILD_DIR)/qosify-bpf.c) | 	$(call CompileBPF,$(PKG_BUILD_DIR)/qosify-bpf.c) | ||||||
| 	$(Build/Compile/Default) | 	$(Build/Compile/Default) | ||||||
| @@ -36,17 +41,28 @@ endef | |||||||
|  |  | ||||||
| define Package/qosify/conffiles | define Package/qosify/conffiles | ||||||
| /etc/config/qosify | /etc/config/qosify | ||||||
| /etc/qosify-defaults.conf | /etc/qosify/00-defaults.conf | ||||||
| endef | endef | ||||||
|  |  | ||||||
| define Package/qosify/install | 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_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_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.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/net/10-qosify | ||||||
|  | 	$(INSTALL_DATA) ./files/qosify.hotplug $(1)/etc/hotplug.d/iface/10-qosify | ||||||
| endef | endef | ||||||
|  |  | ||||||
| $(eval $(call BuildPackage,qosify)) | $(eval $(call BuildPackage,qosify)) | ||||||
|   | |||||||
										
											Binary file not shown.
										
									
								
							| @@ -1,17 +1,17 @@ | |||||||
| # DNS | # DNS | ||||||
| tcp:53		CS5 | tcp:53		voice | ||||||
| tcp:5353	CS5 | tcp:5353	voice | ||||||
| udp:53		CS5 | udp:53		voice | ||||||
| udp:5353	CS5 | udp:5353	voice | ||||||
|  |  | ||||||
| # NTP | # NTP | ||||||
| udp:123		CS6 | udp:123		voice | ||||||
|  |  | ||||||
| # SSH | # SSH | ||||||
| tcp:22		+CS4 | tcp:22		+video | ||||||
|  |  | ||||||
| # HTTP/QUIC | # HTTP/QUIC | ||||||
| tcp:80		+CS3 | tcp:80		+besteffort | ||||||
| tcp:443		+CS3 | tcp:443		+besteffort | ||||||
| udp:80		+CS3 | udp:80		+besteffort | ||||||
| udp:443		+CS3 | udp:443		+besteffort | ||||||
|   | |||||||
							
								
								
									
										70
									
								
								feeds/ucentral/qosify/files/qosify-status
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								feeds/ucentral/qosify/files/qosify-status
									
									
									
									
									
										Normal 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 | ||||||
| @@ -1,24 +1,42 @@ | |||||||
| config defaults | config defaults | ||||||
| 	list defaults /etc/qosify-defaults.conf | 	list defaults /etc/qosify/*.conf | ||||||
| 	option dscp_prio CS5 | 	option dscp_prio video | ||||||
| 	option dscp_icmp CS6 | 	option dscp_icmp +besteffort | ||||||
| 	option dscp_bulk CS0 | 	option dscp_default_udp besteffort | ||||||
| 	option dscp_default_udp	CS4 |  | ||||||
| 	option bulk_trigger_timeout 5 |  | ||||||
| 	option bulk_trigger_pps	100 |  | ||||||
| 	option prio_max_avg_pkt_len 500 | 	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 | config interface wan | ||||||
| 	option name wan | 	option name wan | ||||||
| 	option disabled 1 | 	option disabled 1 | ||||||
| 	option bandwidth_up 100mbit | 	option bandwidth_up 100mbit | ||||||
| 	option bandwidth_down 100mbit | 	option bandwidth_down 100mbit | ||||||
|  | 	option overhead_type none | ||||||
| 	# defaults: | 	# defaults: | ||||||
| 	option ingress 1 | 	option ingress 1 | ||||||
| 	option egress 1 | 	option egress 1 | ||||||
| 	option mode diffserv4 | 	option mode diffserv4 | ||||||
|  | 	option nat 1 | ||||||
| 	option host_isolate 1 | 	option host_isolate 1 | ||||||
| 	option autorate_ingress 1 | 	option autorate_ingress 0 | ||||||
| 	option ingress_options "" | 	option ingress_options "" | ||||||
| 	option egress_options "" | 	option egress_options "" | ||||||
| 	option options "" | 	option options "" | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| #!/bin/sh /etc/rc.common | #!/bin/sh /etc/rc.common | ||||||
| # Copyright (c) 2014 OpenWrt.org | # Copyright (c) 2021 OpenWrt.org | ||||||
|  |  | ||||||
| START=19 | START=19 | ||||||
|  |  | ||||||
| @@ -15,6 +15,16 @@ add_option() { | |||||||
| 	[ -n "$val" ] && json_add_$type "$name" "$val" | 	[ -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() { | add_defaults() { | ||||||
| 	cfg="$1" | 	cfg="$1" | ||||||
|  |  | ||||||
| @@ -27,15 +37,11 @@ add_defaults() { | |||||||
| 	done | 	done | ||||||
| 	json_close_array | 	json_close_array | ||||||
|  |  | ||||||
|  | 	add_flow_config "$cfg" | ||||||
| 	add_option int timeout | 	add_option int timeout | ||||||
| 	add_option string dscp_prio |  | ||||||
| 	add_option string dscp_bulk |  | ||||||
| 	add_option string dscp_icmp | 	add_option string dscp_icmp | ||||||
| 	add_option string dscp_default_udp | 	add_option string dscp_default_udp | ||||||
| 	add_option string dscp_default_tcp | 	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() { | add_interface() { | ||||||
| @@ -61,15 +67,70 @@ add_interface() { | |||||||
| 	add_option boolean ingress | 	add_option boolean ingress | ||||||
| 	add_option boolean egress | 	add_option boolean egress | ||||||
| 	add_option string mode | 	add_option string mode | ||||||
|  | 	add_option boolean nat | ||||||
| 	add_option boolean host_isolate | 	add_option boolean host_isolate | ||||||
| 	add_option boolean autorate_ingress | 	add_option boolean autorate_ingress | ||||||
| 	add_option string ingress_options | 	add_option string ingress_options | ||||||
| 	add_option string egress_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 | 	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() { | reload_service() { | ||||||
| 	json_init | 	json_init | ||||||
|  |  | ||||||
| @@ -81,6 +142,11 @@ reload_service() { | |||||||
| 	config_foreach add_interface interface | 	config_foreach add_interface interface | ||||||
| 	json_close_object | 	json_close_object | ||||||
|  |  | ||||||
|  | 	json_add_object classes | ||||||
|  | 	config_foreach add_class class | ||||||
|  | 	config_foreach add_class alias | ||||||
|  | 	json_close_object | ||||||
|  |  | ||||||
| 	json_add_object devices | 	json_add_object devices | ||||||
| 	config_foreach add_interface device | 	config_foreach add_interface device | ||||||
| 	json_close_object | 	json_close_object | ||||||
|   | |||||||
| @@ -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} |  | ||||||
| ) |  | ||||||
| @@ -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 |  | ||||||
| @@ -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); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @@ -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; |  | ||||||
| } |  | ||||||
| @@ -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; |  | ||||||
| } |  | ||||||
| @@ -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); |  | ||||||
| } |  | ||||||
| @@ -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"; |  | ||||||
| @@ -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 |  | ||||||
| @@ -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 |  | ||||||
| @@ -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; |  | ||||||
| } |  | ||||||
| @@ -4,10 +4,10 @@ PKG_NAME:=ucentral-client | |||||||
| PKG_RELEASE:=1 | PKG_RELEASE:=1 | ||||||
|  |  | ||||||
| PKG_SOURCE_URL=https://github.com/blogic/ucentral-client.git | PKG_SOURCE_URL=https://github.com/blogic/ucentral-client.git | ||||||
| PKG_MIRROR_HASH:=f00e800d97335d088281670aa1b459da1fdd5e4a2927ce280b7d9cb369ebc21a | PKG_MIRROR_HASH:=37a1b7393cf5d15dbcd4840d9ffb2b16bf5b43cdd5c0da955c744bfc10211cbc | ||||||
| PKG_SOURCE_PROTO:=git | PKG_SOURCE_PROTO:=git | ||||||
| PKG_SOURCE_DATE:=2022-01-10 | PKG_SOURCE_DATE:=2022-01-10 | ||||||
| PKG_SOURCE_VERSION:=e3b71c61e1a07bb3b5fa34fe835fd8f6f708caa3 | PKG_SOURCE_VERSION:=6cb4485ab49c5ab9244fb55af9fd0e1801f154f4 | ||||||
|  |  | ||||||
| PKG_LICENSE:=BSD-3-Clause | PKG_LICENSE:=BSD-3-Clause | ||||||
| PKG_MAINTAINER:=John Crispin <john@phrozen.org> | PKG_MAINTAINER:=John Crispin <john@phrozen.org> | ||||||
|   | |||||||
| @@ -32,8 +32,6 @@ start_service() { | |||||||
| 	config_get debug 'config' 'debug' 0 | 	config_get debug 'config' 'debug' 0 | ||||||
| 	config_get insecure 'config' 'insecure' 0 | 	config_get insecure 'config' 'insecure' 0 | ||||||
|  |  | ||||||
| 	interval=$(uci get ustats.health.interval) |  | ||||||
|  |  | ||||||
| 	procd_open_instance | 	procd_open_instance | ||||||
| 	procd_set_param command "$PROG" | 	procd_set_param command "$PROG" | ||||||
| 	[ -n "$serial" ] && procd_append_param command -S $serial | 	[ -n "$serial" ] && procd_append_param command -S $serial | ||||||
| @@ -41,7 +39,6 @@ start_service() { | |||||||
| 	[ -n "$port" ] && procd_append_param command -P $port | 	[ -n "$port" ] && procd_append_param command -P $port | ||||||
| 	[ "$debug" -eq 0 ] || procd_append_param command -d | 	[ "$debug" -eq 0 ] || procd_append_param command -d | ||||||
| 	[ "$insecure" -eq 0 ] || procd_append_param command -i | 	[ "$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 | 	[ -z "$(mount | grep 'tmpfs on / type tmpfs')" ] || procd_append_param command -r | ||||||
| 	procd_append_param command -f "$(cat /tmp/ucentral.version)" | 	procd_append_param command -f "$(cat /tmp/ucentral.version)" | ||||||
| 	procd_set_param respawn 3600 5 0 | 	procd_set_param respawn 3600 5 0 | ||||||
|   | |||||||
							
								
								
									
										29
									
								
								feeds/ucentral/ucentral-client/files/etc/init.d/uhealth
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										29
									
								
								feeds/ucentral/ucentral-client/files/etc/init.d/uhealth
									
									
									
									
									
										Executable 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 | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -20,9 +20,4 @@ start_service() { | |||||||
| 		procd_set_param respawn 1 $interval 0 | 		procd_set_param respawn 1 $interval 0 | ||||||
| 		procd_close_instance | 		procd_close_instance | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|         config_get interval 'health' 'interval' 0 |  | ||||||
| 	[ "$interval" -eq 0 ] || { |  | ||||||
| 		ubus call ucentral config '{"health": '$interval' }' |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,10 +4,10 @@ PKG_NAME:=ucentral-event | |||||||
| PKG_RELEASE:=1 | PKG_RELEASE:=1 | ||||||
|  |  | ||||||
| PKG_SOURCE_URL=https://github.com/blogic/ucentral-event.git | PKG_SOURCE_URL=https://github.com/blogic/ucentral-event.git | ||||||
| PKG_MIRROR_HASH:=615563b31f55b18b8900f8614c6c8add0d6a812da57d220a7632109b06795036 | PKG_MIRROR_HASH:=8cb470d7cc6c458fe748ee6f54e4bf79bec5500735d7b992d83c1aa10f700c6b | ||||||
| PKG_SOURCE_PROTO:=git | PKG_SOURCE_PROTO:=git | ||||||
| PKG_SOURCE_DATE:=2021-04-13 | PKG_SOURCE_DATE:=2021-04-13 | ||||||
| PKG_SOURCE_VERSION:=7b0d136e8556bb099d7032823139d275448714cb | PKG_SOURCE_VERSION:=24b7fb36e456d99b470c212674b3bf50bac64c74 | ||||||
|  |  | ||||||
| PKG_MAINTAINER:=John Crispin <john@phrozen.org> | PKG_MAINTAINER:=John Crispin <john@phrozen.org> | ||||||
| PKG_LICENSE:=BSD-3-Clause | PKG_LICENSE:=BSD-3-Clause | ||||||
|   | |||||||
| @@ -4,9 +4,10 @@ PKG_NAME:=ucentral-schema | |||||||
| PKG_RELEASE:=1 | PKG_RELEASE:=1 | ||||||
|  |  | ||||||
| PKG_SOURCE_URL=https://github.com/blogic/ucentral-schema.git | PKG_SOURCE_URL=https://github.com/blogic/ucentral-schema.git | ||||||
|  | PKG_MIRROR_HASH:=af89f22de096e860cfe5295837507d288d7c919d1cb61d7deca012895ed80321 | ||||||
| PKG_SOURCE_PROTO:=git | PKG_SOURCE_PROTO:=git | ||||||
| PKG_SOURCE_DATE:=2022-01-17 | PKG_SOURCE_DATE:=2022-01-17 | ||||||
| PKG_SOURCE_VERSION:=19fcc8d8163e84734d34dc7dd9767c2fa133fa16 | PKG_SOURCE_VERSION:=7015febc04ad70a956b1ad79f2911bbdc24458a5 | ||||||
|  |  | ||||||
| PKG_MAINTAINER:=John Crispin <john@phrozen.org> | PKG_MAINTAINER:=John Crispin <john@phrozen.org> | ||||||
| PKG_LICENSE:=BSD-3-Clause | PKG_LICENSE:=BSD-3-Clause | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ USE_PROCD=1 | |||||||
| PROG=/usr/bin/ucode | PROG=/usr/bin/ucode | ||||||
|  |  | ||||||
| start_service() { | start_service() { | ||||||
| 	local interval=$(uci get onlinecheck.@config.check_interval) | 	local interval=$(uci get onlinecheck.@config[-1].check_interval) | ||||||
| 	procd_open_instance | 	procd_open_instance | ||||||
| 	procd_set_param command "$PROG" -m uci -m fs -i /usr/share/ucentral/onlinecheck.uc | 	procd_set_param command "$PROG" -m uci -m fs -i /usr/share/ucentral/onlinecheck.uc | ||||||
| 	procd_set_param respawn 1 $interval 0 | 	procd_set_param respawn 1 $interval 0 | ||||||
|   | |||||||
| @@ -97,7 +97,7 @@ | |||||||
| 		"online-check": { | 		"online-check": { | ||||||
| 			"ping-hosts": [ | 			"ping-hosts": [ | ||||||
| 				"192.168.178.1", | 				"192.168.178.1", | ||||||
| 				"uecntral.io" | 				"ucentral.io" | ||||||
| 			], | 			], | ||||||
| 			"download-hosts": [ | 			"download-hosts": [ | ||||||
| 				"ucentral.io" | 				"ucentral.io" | ||||||
|   | |||||||
							
								
								
									
										0
									
								
								feeds/ucentral/ucentral-schema/files/usr/share/ucentral/wifi_max_user.uc
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								feeds/ucentral/ucentral-schema/files/usr/share/ucentral/wifi_max_user.uc
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -4,10 +4,11 @@ PKG_NAME:=ucentral-wifi | |||||||
| PKG_RELEASE:=1 | PKG_RELEASE:=1 | ||||||
|  |  | ||||||
| PKG_SOURCE_URL=https://github.com/blogic/ucentral-wifi.git | 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_PROTO:=git | ||||||
| PKG_SOURCE_DATE:=2022-01-10 | PKG_SOURCE_DATE:=2022-01-10 | ||||||
| PKG_SOURCE_VERSION:=40d0eb9d6f36f558d14d6a1783711c3cf07638c5 | PKG_SOURCE_VERSION:=aa9c3ee716929d75852a11640362a09bb32c5262 | ||||||
|  |  | ||||||
| PKG_MAINTAINER:=John Crispin <john@phrozen.org> | PKG_MAINTAINER:=John Crispin <john@phrozen.org> | ||||||
| PKG_LICENSE:=BSD-3-Clause | PKG_LICENSE:=BSD-3-Clause | ||||||
|   | |||||||
| @@ -12,9 +12,9 @@ PKG_RELEASE:=1 | |||||||
|  |  | ||||||
| PKG_SOURCE_PROTO:=git | PKG_SOURCE_PROTO:=git | ||||||
| PKG_SOURCE_URL=https://github.com/jow-/ucode.git | PKG_SOURCE_URL=https://github.com/jow-/ucode.git | ||||||
|  | PKG_MIRROR_HASH:=376b89c35967d3761acb192af9fb6b7b20dbcc50d03c8ed851751d2376bf26b4 | ||||||
| PKG_SOURCE_DATE:=2021-07-30 | PKG_SOURCE_DATE:=2021-07-30 | ||||||
| PKG_SOURCE_VERSION:=03b6a8efc1834a4114f0d11e1a7cecff3242b305 | PKG_SOURCE_VERSION:=8fd4746da31b945a6259ac846f7cf8dcfef0b1ef | ||||||
| PKG_MIRROR_HASH:=6af37293d6d7023f30728c76a02b4e48d323262a45058410760a30256e0dbe2b |  | ||||||
| PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io> | PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io> | ||||||
| PKG_LICENSE:=ISC | PKG_LICENSE:=ISC | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,15 +1,15 @@ | |||||||
| From eac420899717e2d23f6d13304bd67278a7e91730 Mon Sep 17 00:00:00 2001 | From 25df1c3e41f274f70e4fbf5fdc10e4290ba019f5 Mon Sep 17 00:00:00 2001 | ||||||
| From: John Crispin <john@phrozen.org> | From: John Crispin <john@phrozen.org> | ||||||
| Date: Thu, 20 Jan 2022 10:48:35 +0100 | 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 + |  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 | diff --git a/lib/nl80211.c b/lib/nl80211.c | ||||||
| index fc24fb8..1d0871a 100644 | index fc24fb8..3e21141 100644 | ||||||
| --- a/lib/nl80211.c | --- a/lib/nl80211.c | ||||||
| +++ b/lib/nl80211.c | +++ b/lib/nl80211.c | ||||||
| @@ -45,6 +45,8 @@ limitations under the License. | @@ -45,6 +45,8 @@ limitations under the License. | ||||||
| @@ -132,7 +132,7 @@ index fc24fb8..1d0871a 100644 | |||||||
|  	.attrs = { |  	.attrs = { | ||||||
|  		{ NL80211_STA_INFO_INACTIVE_TIME, "inactive_time", DT_U32, 0, NULL }, |  		{ NL80211_STA_INFO_INACTIVE_TIME, "inactive_time", DT_U32, 0, NULL }, | ||||||
|  		{ NL80211_STA_INFO_RX_BYTES, "rx_bytes", 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 = { | @@ -724,21 +783,37 @@ 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_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, "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_CHAIN_SIGNAL_AVG, "chain_signal_avg", DT_S8, DF_MULTIPLE|DF_AUTOIDX, NULL }, | ||||||
| @@ -149,25 +149,41 @@ index fc24fb8..1d0871a 100644 | |||||||
|  		{ NL80211_STA_INFO_CONNECTED_TO_AS, "connected_to_as", DT_BOOL, 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_TO_GATE, "connected_to_gate", DT_BOOL, 0, NULL }, | ||||||
| +		{ NL80211_STA_INFO_CONNECTED_TIME, "connected_time", DT_U32, 0, NULL }, | +		{ NL80211_STA_INFO_CONNECTED_TIME, "connected_time", DT_U32, 0, NULL }, | ||||||
|  | +	} | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static const uc_nl_nested_spec_t nl80211_survey_info_nla = { | ||||||
|  | +	.headsize = 0, | ||||||
|  | +	.nattrs = 8, | ||||||
|  | +	.attrs = { | ||||||
|  | +		{ NL80211_SURVEY_INFO_FREQUENCY, "frequency", DT_U32, 0, NULL }, | ||||||
|  | +		{ NL80211_SURVEY_INFO_TIME, "time", DT_U64, 0, NULL }, | ||||||
|  | +		{ NL80211_SURVEY_INFO_TIME_TX, "time_tx", DT_U64, 0, NULL }, | ||||||
|  | +		{ NL80211_SURVEY_INFO_TIME_RX, "time_rx", DT_U64, 0, NULL }, | ||||||
|  | +		{ NL80211_SURVEY_INFO_TIME_BUSY, "busy", DT_U64, 0, NULL }, | ||||||
|  | +		{ NL80211_SURVEY_INFO_TIME_EXT_BUSY, "ext_busy", DT_U64, 0, NULL }, | ||||||
|  | +		{ NL80211_SURVEY_INFO_TIME_SCAN, "scan", DT_U64, 0, NULL }, | ||||||
|  | +		{ NL80211_SURVEY_INFO_NOISE, "noise", DT_U8, 0, NULL }, | ||||||
|  	} |  	} | ||||||
|  }; |  }; | ||||||
|   |   | ||||||
|  static const uc_nl_nested_spec_t nl80211_msg = { |  static const uc_nl_nested_spec_t nl80211_msg = { | ||||||
|  	.headsize = 0, |  	.headsize = 0, | ||||||
| -	.nattrs = 124, | -	.nattrs = 124, | ||||||
| +	.nattrs = 125, | +	.nattrs = 126, | ||||||
|  	.attrs = { |  	.attrs = { | ||||||
|  		{ NL80211_ATTR_4ADDR, "4addr", DT_U8, 0, NULL }, |  		{ NL80211_ATTR_4ADDR, "4addr", DT_U8, 0, NULL }, | ||||||
|  		{ NL80211_ATTR_AIRTIME_WEIGHT, "airtime_weight", DT_U16, 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 = { | @@ -864,6 +939,8 @@ static const uc_nl_nested_spec_t nl80211_msg = { | ||||||
|  		{ NL80211_ATTR_WPA_VERSIONS, "wpa_versions", DT_U32, 0, NULL }, |  		{ 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_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_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 }, | +		{ NL80211_ATTR_MAX_AP_ASSOC_STA, "max_ap_assoc", DT_U16, 0, NULL }, | ||||||
|  | +		{ NL80211_ATTR_SURVEY_INFO, "survey_info", DT_NESTED, 0, &nl80211_survey_info_nla }, | ||||||
|  	} |  	} | ||||||
|  }; |  }; | ||||||
|   |   | ||||||
| @@ -1044,6 +1105,9 @@ uc_nl_parse_attrs(struct nl_msg *msg, char *base, const uc_nl_attr_spec_t *attrs | @@ -1044,6 +1121,9 @@ uc_nl_parse_attrs(struct nl_msg *msg, char *base, const uc_nl_attr_spec_t *attrs | ||||||
|  	bool exists; |  	bool exists; | ||||||
|   |   | ||||||
|  	for (i = 0; i < nattrs; i++) { |  	for (i = 0; i < nattrs; i++) { | ||||||
|   | |||||||
| @@ -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 |  | ||||||
|  |  | ||||||
| @@ -7,6 +7,7 @@ PKG_LICENSE:=GPLv2 | |||||||
| PKG_LICENSE_FILES:= | PKG_LICENSE_FILES:= | ||||||
|  |  | ||||||
| PKG_SOURCE_URL:=https://github.com/greearb/ath10k-ct.git | PKG_SOURCE_URL:=https://github.com/greearb/ath10k-ct.git | ||||||
|  | PKG_MIRROR_HASH:=37b4f00231cb0ae00f63da1c94ae53c940c76d047ce0fb081c08a35fffbfd2c0 | ||||||
| PKG_SOURCE_PROTO:=git | PKG_SOURCE_PROTO:=git | ||||||
| PKG_SOURCE_DATE:=2021-05-22b | PKG_SOURCE_DATE:=2021-05-22b | ||||||
| PKG_SOURCE_VERSION:=54a9ac02f1139596ea4361ebbc3e444955d86cfd | PKG_SOURCE_VERSION:=54a9ac02f1139596ea4361ebbc3e444955d86cfd | ||||||
|   | |||||||
| @@ -132,7 +132,7 @@ mac80211_hostapd_setup_base() { | |||||||
|  |  | ||||||
| 	json_select config | 	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 | 	[ "$auto_channel" -gt 0 ] && json_get_vars acs_exclude_dfs | ||||||
| 	[ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] && | 	[ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] && | ||||||
| @@ -1162,10 +1162,13 @@ drv_mac80211_setup() { | |||||||
| 		if [ "$no_reload" != "0" ]; then | 		if [ "$no_reload" != "0" ]; then | ||||||
| 			add_ap=1 | 			add_ap=1 | ||||||
| 			ubus wait_for hostapd | 			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="$?" | 			ret="$?" | ||||||
|  | 			rm -f /tmp/wifi_fail_test | ||||||
| 			[ "$ret" != 0 -o -z "$hostapd_res" ] && { | 			[ "$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 | 				return | ||||||
| 			} | 			} | ||||||
| 			wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1 | 			wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1 | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								feeds/wifi-ax/ath11k-fwtest/Makefile
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										45
									
								
								feeds/wifi-ax/ath11k-fwtest/Makefile
									
									
									
									
									
										Executable 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))) | ||||||
							
								
								
									
										29
									
								
								feeds/wifi-ax/ath11k-fwtest/src/Makefile
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										29
									
								
								feeds/wifi-ax/ath11k-fwtest/src/Makefile
									
									
									
									
									
										Executable 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 | ||||||
|  |  | ||||||
							
								
								
									
										429
									
								
								feeds/wifi-ax/ath11k-fwtest/src/fwtest.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										429
									
								
								feeds/wifi-ax/ath11k-fwtest/src/fwtest.c
									
									
									
									
									
										Executable 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; | ||||||
|  | } | ||||||
| @@ -31,13 +31,15 @@ ALLWIFIBOARDS:= \ | |||||||
| 	cig-wf196 \ | 	cig-wf196 \ | ||||||
| 	cybertan-eww622-a1 \ | 	cybertan-eww622-a1 \ | ||||||
| 	edgecore-eap101 \ | 	edgecore-eap101 \ | ||||||
|  | 	gl-ax1800 \ | ||||||
| 	sercomm-wallaby \ | 	sercomm-wallaby \ | ||||||
| 	edgecore-eap102 \ | 	edgecore-eap102 \ | ||||||
| 	edgecore-eap104 \ | 	edgecore-eap104 \ | ||||||
| 	wallys-dr6018 \ | 	wallys-dr6018 \ | ||||||
| 	wallys-dr6018-v4 \ | 	wallys-dr6018-v4 \ | ||||||
| 	tplink-ex227 \ | 	tplink-ex227 \ | ||||||
| 	tplink-ex447 | 	tplink-ex447 \ | ||||||
|  | 	yuncore-ax840 | ||||||
|  |  | ||||||
| ALLWIFIPACKAGES:=$(foreach BOARD,$(ALLWIFIBOARDS),ath11k-wifi-$(BOARD)) | ALLWIFIPACKAGES:=$(foreach BOARD,$(ALLWIFIBOARDS),ath11k-wifi-$(BOARD)) | ||||||
|  |  | ||||||
| @@ -79,6 +81,11 @@ $(call Package/ath11k-wifi-default) | |||||||
|     TITLE:=cig-wf196 6G bdf |     TITLE:=cig-wf196 6G bdf | ||||||
| endef | endef | ||||||
|  |  | ||||||
|  | define Package/ath11k-wifi-gl-ax1800 | ||||||
|  | $(call Package/ath11k-wifi-default) | ||||||
|  |     TITLE:=gl-ax1800 bdf | ||||||
|  | endef | ||||||
|  |  | ||||||
| define ath11k-wifi-install-one-to | define ath11k-wifi-install-one-to | ||||||
|   $(INSTALL_DIR)  $(2)/lib/firmware/$(3)/ |   $(INSTALL_DIR)  $(2)/lib/firmware/$(3)/ | ||||||
|   $(INSTALL_DATA) $(1) $(2)/lib/firmware/$(3)/board.bin |   $(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 | 	$(INSTALL_DATA) ./board-cig-wf196_6g.bin.QCN9074 $(1)/lib/firmware/ath11k/QCN9074/hw1.0/board.bin | ||||||
| endef | 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-wf188,Cigtech WF188)) | ||||||
| $(eval $(call generate-ath11k-wifi-package,cig-wf188n,Cigtech WF188n)) | $(eval $(call generate-ath11k-wifi-package,cig-wf188n,Cigtech WF188n)) | ||||||
| $(eval $(call generate-ath11k-wifi-package,cig-wf194c,Cigtech WF194c)) | $(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,edgecore-eap104,Edgecore EAP104)) | ||||||
| $(eval $(call generate-ath11k-wifi-package,tplink-ex227,TP-Link EX227)) | $(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,tplink-ex447,TP-Link EX447)) | ||||||
|  | $(eval $(call generate-ath11k-wifi-package,yuncore-ax840,YunCore AX840)) | ||||||
|  |  | ||||||
| $(foreach PACKAGE,$(ALLWIFIPACKAGES),$(eval $(call BuildPackage,$(PACKAGE)))) | $(foreach PACKAGE,$(ALLWIFIPACKAGES),$(eval $(call BuildPackage,$(PACKAGE)))) | ||||||
| $(eval $(call BuildPackage,ath11k-wifi-qcom-ipq5018)) | $(eval $(call BuildPackage,ath11k-wifi-qcom-ipq5018)) | ||||||
|   | |||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								feeds/wifi-ax/ath11k-wifi/board-gl-ax1800.bin.IPQ6018
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								feeds/wifi-ax/ath11k-wifi/board-gl-ax1800.bin.IPQ6018
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								feeds/wifi-ax/ath11k-wifi/board-yuncore-ax840.bin.IPQ6018
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								feeds/wifi-ax/ath11k-wifi/board-yuncore-ax840.bin.IPQ6018
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -61,6 +61,7 @@ PKG_EXTRA_CFLAGS:= \ | |||||||
| 	$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(PKG_EXTRA_KCONFIG)))) \ | 	$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(PKG_EXTRA_KCONFIG)))) \ | ||||||
|  |  | ||||||
| NOSTDINC_FLAGS = \ | NOSTDINC_FLAGS = \ | ||||||
|  | 	$(KERNEL_NOSTDINC_FLAGS) \ | ||||||
| 	-I$(PKG_BUILD_DIR)/net/batman-adv \ | 	-I$(PKG_BUILD_DIR)/net/batman-adv \ | ||||||
| 	-I$(STAGING_DIR)/usr/include/mac80211-backport \ | 	-I$(STAGING_DIR)/usr/include/mac80211-backport \ | ||||||
| 	-I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \ | 	-I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \ | ||||||
|   | |||||||
| @@ -12,11 +12,9 @@ or newer - otherwise it will not work as expected. | |||||||
|  |  | ||||||
| This reverts commit 725b4ef5be840cfcd0ca33b9393c14dee40c10f7. | This reverts commit 725b4ef5be840cfcd0ca33b9393c14dee40c10f7. | ||||||
|  |  | ||||||
| diff --git a/compat-include/net/genetlink.h b/compat-include/net/genetlink.h |  | ||||||
| index 56a9ab22c062b1d0d01ef9d09ce796075d3d6df7..8f542bef10dc0f2682ab2d428c90df9ab97977ce 100644 |  | ||||||
| --- a/compat-include/net/genetlink.h | --- a/compat-include/net/genetlink.h | ||||||
| +++ b/compat-include/net/genetlink.h | +++ b/compat-include/net/genetlink.h | ||||||
| @@ -31,17 +31,15 @@ void batadv_genl_dump_check_consistent(struct netlink_callback *cb, | @@ -31,17 +31,15 @@ void batadv_genl_dump_check_consistent(s | ||||||
|  #endif /* LINUX_VERSION_IS_LESS(4, 15, 0) */ |  #endif /* LINUX_VERSION_IS_LESS(4, 15, 0) */ | ||||||
|   |   | ||||||
|   |   | ||||||
| @@ -48,7 +46,7 @@ index 56a9ab22c062b1d0d01ef9d09ce796075d3d6df7..8f542bef10dc0f2682ab2d428c90df9a | |||||||
|  	unsigned int n_mcgrps; |  	unsigned int n_mcgrps; | ||||||
|  	struct module *module; |  	struct module *module; | ||||||
|   |   | ||||||
| @@ -96,32 +94,24 @@ static inline int batadv_genl_register_family(struct batadv_genl_family *family) | @@ -96,32 +94,24 @@ static inline int batadv_genl_register_f | ||||||
|  	family->family.pre_doit = family->pre_doit; |  	family->family.pre_doit = family->pre_doit; | ||||||
|  	family->family.post_doit = family->post_doit; |  	family->family.post_doit = family->post_doit; | ||||||
|  	family->family.mcgrps = family->mcgrps; |  	family->family.mcgrps = family->mcgrps; | ||||||
| @@ -89,7 +87,7 @@ index 56a9ab22c062b1d0d01ef9d09ce796075d3d6df7..8f542bef10dc0f2682ab2d428c90df9a | |||||||
|  	family->family.ops = ops; |  	family->family.ops = ops; | ||||||
|  	family->copy_ops = ops; |  	family->copy_ops = ops; | ||||||
|   |   | ||||||
| @@ -136,7 +126,7 @@ typedef struct genl_ops batadv_genl_ops_old; | @@ -136,7 +126,7 @@ typedef struct genl_ops batadv_genl_ops_ | ||||||
|  #define batadv_post_doit(__x, __y, __z) \ |  #define batadv_post_doit(__x, __y, __z) \ | ||||||
|  	batadv_post_doit(const batadv_genl_ops_old *ops, __y, __z) |  	batadv_post_doit(const batadv_genl_ops_old *ops, __y, __z) | ||||||
|   |   | ||||||
| @@ -98,7 +96,7 @@ index 56a9ab22c062b1d0d01ef9d09ce796075d3d6df7..8f542bef10dc0f2682ab2d428c90df9a | |||||||
|  #define genl_family batadv_genl_family |  #define genl_family batadv_genl_family | ||||||
|   |   | ||||||
|  #define genl_register_family(family) \ |  #define genl_register_family(family) \ | ||||||
| @@ -160,6 +150,6 @@ batadv_genl_unregister_family(struct batadv_genl_family *family) | @@ -160,6 +150,6 @@ batadv_genl_unregister_family(struct bat | ||||||
|  	genlmsg_multicast_netns(&(_family)->family, _net, _skb, _portid, \ |  	genlmsg_multicast_netns(&(_family)->family, _net, _skb, _portid, \ | ||||||
|  				_group, _flags) |  				_group, _flags) | ||||||
|   |   | ||||||
| @@ -106,11 +104,9 @@ index 56a9ab22c062b1d0d01ef9d09ce796075d3d6df7..8f542bef10dc0f2682ab2d428c90df9a | |||||||
| +#endif /* LINUX_VERSION_IS_LESS(5, 2, 0) */ | +#endif /* LINUX_VERSION_IS_LESS(5, 2, 0) */ | ||||||
|   |   | ||||||
|  #endif /* _NET_BATMAN_ADV_COMPAT_NET_GENETLINK_H_ */ |  #endif /* _NET_BATMAN_ADV_COMPAT_NET_GENETLINK_H_ */ | ||||||
| diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c |  | ||||||
| index f317d206b411d87b4da2f57e35c3fb78cedfb160..bdac5dbd899a9540d58052fd32c8c89520927390 100644 |  | ||||||
| --- a/net/batman-adv/netlink.c | --- a/net/batman-adv/netlink.c | ||||||
| +++ b/net/batman-adv/netlink.c | +++ b/net/batman-adv/netlink.c | ||||||
| @@ -1351,7 +1351,7 @@ static void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb, | @@ -1351,7 +1351,7 @@ static void batadv_post_doit(const struc | ||||||
|  	} |  	} | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -119,7 +115,7 @@ index f317d206b411d87b4da2f57e35c3fb78cedfb160..bdac5dbd899a9540d58052fd32c8c895 | |||||||
|  	{ |  	{ | ||||||
|  		.cmd = BATADV_CMD_GET_MESH, |  		.cmd = BATADV_CMD_GET_MESH, | ||||||
|  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
| @@ -1485,8 +1485,8 @@ struct genl_family batadv_netlink_family __ro_after_init = { | @@ -1485,8 +1485,8 @@ struct genl_family batadv_netlink_family | ||||||
|  	.pre_doit = batadv_pre_doit, |  	.pre_doit = batadv_pre_doit, | ||||||
|  	.post_doit = batadv_post_doit, |  	.post_doit = batadv_post_doit, | ||||||
|  	.module = THIS_MODULE, |  	.module = THIS_MODULE, | ||||||
|   | |||||||
| @@ -9,9 +9,6 @@ This reverts commit 1810de05310d5c5e9140f870ac21052f38bc06b8. | |||||||
|  |  | ||||||
| Signed-off-by: Sven Eckelmann <sven@narfation.org> | Signed-off-by: Sven Eckelmann <sven@narfation.org> | ||||||
|  |  | ||||||
| diff --git a/compat-include/linux/minmax.h b/compat-include/linux/minmax.h |  | ||||||
| deleted file mode 100644 |  | ||||||
| index 9b7269e8a760361c1650b947c77702f0bdcd73d9..0000000000000000000000000000000000000000 |  | ||||||
| --- a/compat-include/linux/minmax.h | --- a/compat-include/linux/minmax.h | ||||||
| +++ /dev/null | +++ /dev/null | ||||||
| @@ -1,20 +0,0 @@ | @@ -1,20 +0,0 @@ | ||||||
| @@ -35,8 +32,6 @@ index 9b7269e8a760361c1650b947c77702f0bdcd73d9..00000000000000000000000000000000 | |||||||
| -#endif | -#endif | ||||||
| - | - | ||||||
| -#endif /* _NET_BATMAN_ADV_COMPAT_LINUX_MINMAX_H_ */ | -#endif /* _NET_BATMAN_ADV_COMPAT_LINUX_MINMAX_H_ */ | ||||||
| diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c |  | ||||||
| index e1ca2b8c315235f234c9061fc73cde2c1b76aa46..eeb3f6d00d8541b377c9703837ef76b05e8d061e 100644 |  | ||||||
| --- a/net/batman-adv/bat_v.c | --- a/net/batman-adv/bat_v.c | ||||||
| +++ b/net/batman-adv/bat_v.c | +++ b/net/batman-adv/bat_v.c | ||||||
| @@ -15,7 +15,6 @@ | @@ -15,7 +15,6 @@ | ||||||
| @@ -47,8 +42,6 @@ index e1ca2b8c315235f234c9061fc73cde2c1b76aa46..eeb3f6d00d8541b377c9703837ef76b0 | |||||||
|  #include <linux/netdevice.h> |  #include <linux/netdevice.h> | ||||||
|  #include <linux/netlink.h> |  #include <linux/netlink.h> | ||||||
|  #include <linux/rculist.h> |  #include <linux/rculist.h> | ||||||
| diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c |  | ||||||
| index 423c2d17170387bfe89b83c4e20f06d525a36b30..4d8e3fdb4427a431cab903bc8a20edb816079fd7 100644 |  | ||||||
| --- a/net/batman-adv/bat_v_elp.c | --- a/net/batman-adv/bat_v_elp.c | ||||||
| +++ b/net/batman-adv/bat_v_elp.c | +++ b/net/batman-adv/bat_v_elp.c | ||||||
| @@ -18,7 +18,6 @@ | @@ -18,7 +18,6 @@ | ||||||
| @@ -59,8 +52,6 @@ index 423c2d17170387bfe89b83c4e20f06d525a36b30..4d8e3fdb4427a431cab903bc8a20edb8 | |||||||
|  #include <linux/netdevice.h> |  #include <linux/netdevice.h> | ||||||
|  #include <linux/nl80211.h> |  #include <linux/nl80211.h> | ||||||
|  #include <linux/prandom.h> |  #include <linux/prandom.h> | ||||||
| diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c |  | ||||||
| index a0a9636d17406362f879f342300a18e75424efa5..89ba88322c9c11acc49a9dcd9877ad8767fe713b 100644 |  | ||||||
| --- a/net/batman-adv/bat_v_ogm.c | --- a/net/batman-adv/bat_v_ogm.c | ||||||
| +++ b/net/batman-adv/bat_v_ogm.c | +++ b/net/batman-adv/bat_v_ogm.c | ||||||
| @@ -18,7 +18,6 @@ | @@ -18,7 +18,6 @@ | ||||||
| @@ -71,8 +62,6 @@ index a0a9636d17406362f879f342300a18e75424efa5..89ba88322c9c11acc49a9dcd9877ad87 | |||||||
|  #include <linux/mutex.h> |  #include <linux/mutex.h> | ||||||
|  #include <linux/netdevice.h> |  #include <linux/netdevice.h> | ||||||
|  #include <linux/prandom.h> |  #include <linux/prandom.h> | ||||||
| diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c |  | ||||||
| index a5d9d800082bade3a1d52cc040557e41f963fac3..96873d47fac5cb9b4fbfa217eedf1f92818b0e98 100644 |  | ||||||
| --- a/net/batman-adv/fragmentation.c | --- a/net/batman-adv/fragmentation.c | ||||||
| +++ b/net/batman-adv/fragmentation.c | +++ b/net/batman-adv/fragmentation.c | ||||||
| @@ -14,8 +14,8 @@ | @@ -14,8 +14,8 @@ | ||||||
| @@ -85,8 +74,6 @@ index a5d9d800082bade3a1d52cc040557e41f963fac3..96873d47fac5cb9b4fbfa217eedf1f92 | |||||||
|  #include <linux/netdevice.h> |  #include <linux/netdevice.h> | ||||||
|  #include <linux/skbuff.h> |  #include <linux/skbuff.h> | ||||||
|  #include <linux/slab.h> |  #include <linux/slab.h> | ||||||
| diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c |  | ||||||
| index 4a6a25d551a83b1723e80a349e1a655a2152b0ac..eabde547d308438257622879e77d84c24daa2199 100644 |  | ||||||
| --- a/net/batman-adv/hard-interface.c | --- a/net/batman-adv/hard-interface.c | ||||||
| +++ b/net/batman-adv/hard-interface.c | +++ b/net/batman-adv/hard-interface.c | ||||||
| @@ -18,7 +18,6 @@ | @@ -18,7 +18,6 @@ | ||||||
| @@ -97,8 +84,6 @@ index 4a6a25d551a83b1723e80a349e1a655a2152b0ac..eabde547d308438257622879e77d84c2 | |||||||
|  #include <linux/mutex.h> |  #include <linux/mutex.h> | ||||||
|  #include <linux/netdevice.h> |  #include <linux/netdevice.h> | ||||||
|  #include <linux/printk.h> |  #include <linux/printk.h> | ||||||
| diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c |  | ||||||
| index 3ddd66e4c29ef532de33c7182cc0cc470b33fd4f..c552bc4168d0abd7bf6d23e570d583806fb162b1 100644 |  | ||||||
| --- a/net/batman-adv/main.c | --- a/net/batman-adv/main.c | ||||||
| +++ b/net/batman-adv/main.c | +++ b/net/batman-adv/main.c | ||||||
| @@ -23,7 +23,6 @@ | @@ -23,7 +23,6 @@ | ||||||
| @@ -109,8 +94,6 @@ index 3ddd66e4c29ef532de33c7182cc0cc470b33fd4f..c552bc4168d0abd7bf6d23e570d58380 | |||||||
|  #include <linux/module.h> |  #include <linux/module.h> | ||||||
|  #include <linux/netdevice.h> |  #include <linux/netdevice.h> | ||||||
|  #include <linux/printk.h> |  #include <linux/printk.h> | ||||||
| diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c |  | ||||||
| index bdac5dbd899a9540d58052fd32c8c89520927390..b6a703ddd8e97e6a02e8d73c5728802f090ab419 100644 |  | ||||||
| --- a/net/batman-adv/netlink.c | --- a/net/batman-adv/netlink.c | ||||||
| +++ b/net/batman-adv/netlink.c | +++ b/net/batman-adv/netlink.c | ||||||
| @@ -23,7 +23,6 @@ | @@ -23,7 +23,6 @@ | ||||||
| @@ -121,8 +104,6 @@ index bdac5dbd899a9540d58052fd32c8c89520927390..b6a703ddd8e97e6a02e8d73c5728802f | |||||||
|  #include <linux/netdevice.h> |  #include <linux/netdevice.h> | ||||||
|  #include <linux/netlink.h> |  #include <linux/netlink.h> | ||||||
|  #include <linux/printk.h> |  #include <linux/printk.h> | ||||||
| diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c |  | ||||||
| index 789c851732b78ad9d1515f7b171219cc770c7045..46b774c08c947def8f72f260224254b01c3a387d 100644 |  | ||||||
| --- a/net/batman-adv/tp_meter.c | --- a/net/batman-adv/tp_meter.c | ||||||
| +++ b/net/batman-adv/tp_meter.c | +++ b/net/batman-adv/tp_meter.c | ||||||
| @@ -23,7 +23,6 @@ | @@ -23,7 +23,6 @@ | ||||||
|   | |||||||
| @@ -5,11 +5,9 @@ Subject: batman-adv: Fix build of multicast code against Linux < 5.13 | |||||||
| Fixes: 007b4c4b031f ("batman-adv: convert ifmcaddr6 to RCU") | Fixes: 007b4c4b031f ("batman-adv: convert ifmcaddr6 to RCU") | ||||||
| Signed-off-by: Sven Eckelmann <sven@narfation.org> | Signed-off-by: Sven Eckelmann <sven@narfation.org> | ||||||
|  |  | ||||||
| diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c |  | ||||||
| index 1d63c8cbbfe7b16e360e91bcf3bb77ec7b12893b..ece9fb5dd81bfadbdbe15363dfd8fd257dbe942f 100644 |  | ||||||
| --- a/net/batman-adv/multicast.c | --- a/net/batman-adv/multicast.c | ||||||
| +++ b/net/batman-adv/multicast.c | +++ b/net/batman-adv/multicast.c | ||||||
| @@ -454,9 +454,14 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev, | @@ -454,9 +454,14 @@ batadv_mcast_mla_softif_get_ipv6(struct | ||||||
|  		return 0; |  		return 0; | ||||||
|  	} |  	} | ||||||
|   |   | ||||||
| @@ -24,7 +22,7 @@ index 1d63c8cbbfe7b16e360e91bcf3bb77ec7b12893b..ece9fb5dd81bfadbdbe15363dfd8fd25 | |||||||
|  		if (IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) < |  		if (IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) < | ||||||
|  		    IPV6_ADDR_SCOPE_LINKLOCAL) |  		    IPV6_ADDR_SCOPE_LINKLOCAL) | ||||||
|  			continue; |  			continue; | ||||||
| @@ -485,6 +490,9 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev, | @@ -485,6 +490,9 @@ batadv_mcast_mla_softif_get_ipv6(struct | ||||||
|  		hlist_add_head(&new->list, mcast_list); |  		hlist_add_head(&new->list, mcast_list); | ||||||
|  		ret++; |  		ret++; | ||||||
|  	} |  	} | ||||||
|   | |||||||
| @@ -23,11 +23,9 @@ adding a lot of extra overhead in the kernel portion. | |||||||
| Signed-off-by: Sven Eckelmann <sven@narfation.org> | Signed-off-by: Sven Eckelmann <sven@narfation.org> | ||||||
| Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/77c7d62618259f22f36427eaa62668e6e1c43090 | Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/77c7d62618259f22f36427eaa62668e6e1c43090 | ||||||
|  |  | ||||||
| diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c |  | ||||||
| index 789f257be24f36ace3e63628a3381a6d46dcccd9..680def809838097a9949de1dc9861923911f3d04 100644 |  | ||||||
| --- a/net/batman-adv/bat_iv_ogm.c | --- a/net/batman-adv/bat_iv_ogm.c | ||||||
| +++ b/net/batman-adv/bat_iv_ogm.c | +++ b/net/batman-adv/bat_iv_ogm.c | ||||||
| @@ -1849,6 +1849,8 @@ batadv_iv_ogm_orig_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq, | @@ -1849,6 +1849,8 @@ batadv_iv_ogm_orig_dump_subentry(struct | ||||||
|  		    orig_node->orig) || |  		    orig_node->orig) || | ||||||
|  	    nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN, |  	    nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN, | ||||||
|  		    neigh_node->addr) || |  		    neigh_node->addr) || | ||||||
| @@ -36,7 +34,7 @@ index 789f257be24f36ace3e63628a3381a6d46dcccd9..680def809838097a9949de1dc9861923 | |||||||
|  	    nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, |  	    nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, | ||||||
|  			neigh_node->if_incoming->net_dev->ifindex) || |  			neigh_node->if_incoming->net_dev->ifindex) || | ||||||
|  	    nla_put_u8(msg, BATADV_ATTR_TQ, tq_avg) || |  	    nla_put_u8(msg, BATADV_ATTR_TQ, tq_avg) || | ||||||
| @@ -2078,6 +2080,8 @@ batadv_iv_ogm_neigh_dump_neigh(struct sk_buff *msg, u32 portid, u32 seq, | @@ -2078,6 +2080,8 @@ batadv_iv_ogm_neigh_dump_neigh(struct sk | ||||||
|   |   | ||||||
|  	if (nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN, |  	if (nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN, | ||||||
|  		    hardif_neigh->addr) || |  		    hardif_neigh->addr) || | ||||||
| @@ -45,7 +43,7 @@ index 789f257be24f36ace3e63628a3381a6d46dcccd9..680def809838097a9949de1dc9861923 | |||||||
|  	    nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, |  	    nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, | ||||||
|  			hardif_neigh->if_incoming->net_dev->ifindex) || |  			hardif_neigh->if_incoming->net_dev->ifindex) || | ||||||
|  	    nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS, |  	    nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS, | ||||||
| @@ -2459,6 +2463,8 @@ static int batadv_iv_gw_dump_entry(struct sk_buff *msg, u32 portid, | @@ -2459,6 +2463,8 @@ static int batadv_iv_gw_dump_entry(struc | ||||||
|  		    router->addr) || |  		    router->addr) || | ||||||
|  	    nla_put_string(msg, BATADV_ATTR_HARD_IFNAME, |  	    nla_put_string(msg, BATADV_ATTR_HARD_IFNAME, | ||||||
|  			   router->if_incoming->net_dev->name) || |  			   router->if_incoming->net_dev->name) || | ||||||
| @@ -54,11 +52,9 @@ index 789f257be24f36ace3e63628a3381a6d46dcccd9..680def809838097a9949de1dc9861923 | |||||||
|  	    nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_DOWN, |  	    nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_DOWN, | ||||||
|  			gw_node->bandwidth_down) || |  			gw_node->bandwidth_down) || | ||||||
|  	    nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_UP, |  	    nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_UP, | ||||||
| diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c |  | ||||||
| index eeb3f6d00d8541b377c9703837ef76b05e8d061e..fd7f30f5f3033fd1a9e21518a71e66b557212374 100644 |  | ||||||
| --- a/net/batman-adv/bat_v.c | --- a/net/batman-adv/bat_v.c | ||||||
| +++ b/net/batman-adv/bat_v.c | +++ b/net/batman-adv/bat_v.c | ||||||
| @@ -145,6 +145,8 @@ batadv_v_neigh_dump_neigh(struct sk_buff *msg, u32 portid, u32 seq, | @@ -145,6 +145,8 @@ batadv_v_neigh_dump_neigh(struct sk_buff | ||||||
|   |   | ||||||
|  	if (nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN, |  	if (nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN, | ||||||
|  		    hardif_neigh->addr) || |  		    hardif_neigh->addr) || | ||||||
| @@ -67,7 +63,7 @@ index eeb3f6d00d8541b377c9703837ef76b05e8d061e..fd7f30f5f3033fd1a9e21518a71e66b5 | |||||||
|  	    nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, |  	    nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, | ||||||
|  			hardif_neigh->if_incoming->net_dev->ifindex) || |  			hardif_neigh->if_incoming->net_dev->ifindex) || | ||||||
|  	    nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS, |  	    nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS, | ||||||
| @@ -297,6 +299,8 @@ batadv_v_orig_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq, | @@ -297,6 +299,8 @@ batadv_v_orig_dump_subentry(struct sk_bu | ||||||
|  	if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, orig_node->orig) || |  	if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, orig_node->orig) || | ||||||
|  	    nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN, |  	    nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN, | ||||||
|  		    neigh_node->addr) || |  		    neigh_node->addr) || | ||||||
| @@ -76,24 +72,22 @@ index eeb3f6d00d8541b377c9703837ef76b05e8d061e..fd7f30f5f3033fd1a9e21518a71e66b5 | |||||||
|  	    nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, |  	    nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, | ||||||
|  			neigh_node->if_incoming->net_dev->ifindex) || |  			neigh_node->if_incoming->net_dev->ifindex) || | ||||||
|  	    nla_put_u32(msg, BATADV_ATTR_THROUGHPUT, throughput) || |  	    nla_put_u32(msg, BATADV_ATTR_THROUGHPUT, throughput) || | ||||||
| @@ -738,6 +742,12 @@ static int batadv_v_gw_dump_entry(struct sk_buff *msg, u32 portid, | @@ -737,6 +741,12 @@ static int batadv_v_gw_dump_entry(struct | ||||||
|  |  		genlmsg_cancel(msg, hdr); | ||||||
|  		goto out; |  		goto out; | ||||||
|  	} |  	} | ||||||
|   | + | ||||||
| +	if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, | +	if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, | ||||||
| +			router->if_incoming->net_dev->ifindex)) { | +			router->if_incoming->net_dev->ifindex)) { | ||||||
| +		genlmsg_cancel(msg, hdr); | +		genlmsg_cancel(msg, hdr); | ||||||
| +		goto out; | +		goto out; | ||||||
| +	} | +	} | ||||||
| + |   | ||||||
|  	if (nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_DOWN, |  	if (nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_DOWN, | ||||||
|  			gw_node->bandwidth_down)) { |  			gw_node->bandwidth_down)) { | ||||||
|  		genlmsg_cancel(msg, hdr); |  | ||||||
| diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c |  | ||||||
| index b6a703ddd8e97e6a02e8d73c5728802f090ab419..27f78f0c4aea025b964301e20f972031ab8ad478 100644 |  | ||||||
| --- a/net/batman-adv/netlink.c | --- a/net/batman-adv/netlink.c | ||||||
| +++ b/net/batman-adv/netlink.c | +++ b/net/batman-adv/netlink.c | ||||||
| @@ -813,6 +813,10 @@ static int batadv_netlink_hardif_fill(struct sk_buff *msg, | @@ -813,6 +813,10 @@ static int batadv_netlink_hardif_fill(st | ||||||
|  			bat_priv->soft_iface->ifindex)) |  			bat_priv->soft_iface->ifindex)) | ||||||
|  		goto nla_put_failure; |  		goto nla_put_failure; | ||||||
|   |   | ||||||
| @@ -104,7 +98,7 @@ index b6a703ddd8e97e6a02e8d73c5728802f090ab419..27f78f0c4aea025b964301e20f972031 | |||||||
|  	if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, |  	if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, | ||||||
|  			net_dev->ifindex) || |  			net_dev->ifindex) || | ||||||
|  	    nla_put_string(msg, BATADV_ATTR_HARD_IFNAME, |  	    nla_put_string(msg, BATADV_ATTR_HARD_IFNAME, | ||||||
| @@ -1044,6 +1048,10 @@ static int batadv_netlink_vlan_fill(struct sk_buff *msg, | @@ -1044,6 +1048,10 @@ static int batadv_netlink_vlan_fill(stru | ||||||
|  			bat_priv->soft_iface->ifindex)) |  			bat_priv->soft_iface->ifindex)) | ||||||
|  		goto nla_put_failure; |  		goto nla_put_failure; | ||||||
|   |   | ||||||
|   | |||||||
| @@ -0,0 +1,31 @@ | |||||||
|  | From: Sven Eckelmann <sven@narfation.org> | ||||||
|  | Date: Tue, 18 May 2021 21:00:27 +0200 | ||||||
|  | Subject: batman-adv: Avoid WARN_ON timing related checks | ||||||
|  |  | ||||||
|  | The soft/batadv interface for a queued OGM can be changed during the time | ||||||
|  | the OGM was queued for transmission and when the OGM is actually | ||||||
|  | transmitted by the worker. | ||||||
|  |  | ||||||
|  | But WARN_ON must be used to denote kernel bugs and not to print simple | ||||||
|  | warnings. A warning can simply be printed using pr_warn. | ||||||
|  |  | ||||||
|  | Reported-by: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp> | ||||||
|  | Reported-by: syzbot+c0b807de416427ff3dd1@syzkaller.appspotmail.com | ||||||
|  | Fixes: 29b9256e6631 ("batman-adv: consider outgoing interface in OGM sending") | ||||||
|  | Signed-off-by: Sven Eckelmann <sven@narfation.org> | ||||||
|  | Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/5061f9c502d7101912089d8f4a7866e0a926a49a | ||||||
|  |  | ||||||
|  | --- a/net/batman-adv/bat_iv_ogm.c | ||||||
|  | +++ b/net/batman-adv/bat_iv_ogm.c | ||||||
|  | @@ -409,8 +409,10 @@ static void batadv_iv_ogm_emit(struct ba | ||||||
|  |  	if (WARN_ON(!forw_packet->if_outgoing)) | ||||||
|  |  		return; | ||||||
|  |   | ||||||
|  | -	if (WARN_ON(forw_packet->if_outgoing->soft_iface != soft_iface)) | ||||||
|  | +	if (forw_packet->if_outgoing->soft_iface != soft_iface) { | ||||||
|  | +		pr_warn("%s: soft interface switch for queued OGM\n", __func__); | ||||||
|  |  		return; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	if (forw_packet->if_incoming->if_status != BATADV_IF_ACTIVE) | ||||||
|  |  		return; | ||||||
| @@ -0,0 +1,162 @@ | |||||||
|  | From: Pavel Skripkin <paskripkin@gmail.com> | ||||||
|  | Date: Sun, 24 Oct 2021 16:13:56 +0300 | ||||||
|  | Subject: batman-adv: fix error handling | ||||||
|  |  | ||||||
|  | Syzbot reported ODEBUG warning in batadv_nc_mesh_free(). The problem was | ||||||
|  | in wrong error handling in batadv_mesh_init(). | ||||||
|  |  | ||||||
|  | Before this patch batadv_mesh_init() was calling batadv_mesh_free() in case | ||||||
|  | of any batadv_*_init() calls failure. This approach may work well, when | ||||||
|  | there is some kind of indicator, which can tell which parts of batadv are | ||||||
|  | initialized; but there isn't any. | ||||||
|  |  | ||||||
|  | All written above lead to cleaning up uninitialized fields. Even if we hide | ||||||
|  | ODEBUG warning by initializing bat_priv->nc.work, syzbot was able to hit | ||||||
|  | GPF in batadv_nc_purge_paths(), because hash pointer in still NULL. [1] | ||||||
|  |  | ||||||
|  | To fix these bugs we can unwind batadv_*_init() calls one by one. | ||||||
|  | It is good approach for 2 reasons: 1) It fixes bugs on error handling | ||||||
|  | path 2) It improves the performance, since we won't call unneeded | ||||||
|  | batadv_*_free() functions. | ||||||
|  |  | ||||||
|  | So, this patch makes all batadv_*_init() clean up all allocated memory | ||||||
|  | before returning with an error to no call correspoing batadv_*_free() | ||||||
|  | and open-codes batadv_mesh_free() with proper order to avoid touching | ||||||
|  | uninitialized fields. | ||||||
|  |  | ||||||
|  | Link: https://lore.kernel.org/netdev/000000000000c87fbd05cef6bcb0@google.com/ [1] | ||||||
|  | Reported-and-tested-by: syzbot+28b0702ada0bf7381f58@syzkaller.appspotmail.com | ||||||
|  | Fixes: 21e838760727 ("[batman-adv] fix various race conditions during startup & shutdown") | ||||||
|  | Signed-off-by: Pavel Skripkin <paskripkin@gmail.com> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | Signed-off-by: Sven Eckelmann <sven@narfation.org> | ||||||
|  | Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/0631e0825c8129cd3896926da62a09ac00bf13a0 | ||||||
|  |  | ||||||
|  | --- a/net/batman-adv/bridge_loop_avoidance.c | ||||||
|  | +++ b/net/batman-adv/bridge_loop_avoidance.c | ||||||
|  | @@ -1556,10 +1556,14 @@ int batadv_bla_init(struct batadv_priv * | ||||||
|  |  		return 0; | ||||||
|  |   | ||||||
|  |  	bat_priv->bla.claim_hash = batadv_hash_new(128); | ||||||
|  | -	bat_priv->bla.backbone_hash = batadv_hash_new(32); | ||||||
|  | +	if (!bat_priv->bla.claim_hash) | ||||||
|  | +		return -ENOMEM; | ||||||
|  |   | ||||||
|  | -	if (!bat_priv->bla.claim_hash || !bat_priv->bla.backbone_hash) | ||||||
|  | +	bat_priv->bla.backbone_hash = batadv_hash_new(32); | ||||||
|  | +	if (!bat_priv->bla.backbone_hash) { | ||||||
|  | +		batadv_hash_destroy(bat_priv->bla.claim_hash); | ||||||
|  |  		return -ENOMEM; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	batadv_hash_set_lock_class(bat_priv->bla.claim_hash, | ||||||
|  |  				   &batadv_claim_hash_lock_class_key); | ||||||
|  | --- a/net/batman-adv/main.c | ||||||
|  | +++ b/net/batman-adv/main.c | ||||||
|  | @@ -189,29 +189,41 @@ int batadv_mesh_init(struct net_device * | ||||||
|  |   | ||||||
|  |  	bat_priv->gw.generation = 0; | ||||||
|  |   | ||||||
|  | -	ret = batadv_v_mesh_init(bat_priv); | ||||||
|  | -	if (ret < 0) | ||||||
|  | -		goto err; | ||||||
|  | - | ||||||
|  |  	ret = batadv_originator_init(bat_priv); | ||||||
|  | -	if (ret < 0) | ||||||
|  | -		goto err; | ||||||
|  | +	if (ret < 0) { | ||||||
|  | +		atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING); | ||||||
|  | +		goto err_orig; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	ret = batadv_tt_init(bat_priv); | ||||||
|  | -	if (ret < 0) | ||||||
|  | -		goto err; | ||||||
|  | +	if (ret < 0) { | ||||||
|  | +		atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING); | ||||||
|  | +		goto err_tt; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ret = batadv_v_mesh_init(bat_priv); | ||||||
|  | +	if (ret < 0) { | ||||||
|  | +		atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING); | ||||||
|  | +		goto err_v; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	ret = batadv_bla_init(bat_priv); | ||||||
|  | -	if (ret < 0) | ||||||
|  | -		goto err; | ||||||
|  | +	if (ret < 0) { | ||||||
|  | +		atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING); | ||||||
|  | +		goto err_bla; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	ret = batadv_dat_init(bat_priv); | ||||||
|  | -	if (ret < 0) | ||||||
|  | -		goto err; | ||||||
|  | +	if (ret < 0) { | ||||||
|  | +		atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING); | ||||||
|  | +		goto err_dat; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	ret = batadv_nc_mesh_init(bat_priv); | ||||||
|  | -	if (ret < 0) | ||||||
|  | -		goto err; | ||||||
|  | +	if (ret < 0) { | ||||||
|  | +		atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING); | ||||||
|  | +		goto err_nc; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	batadv_gw_init(bat_priv); | ||||||
|  |  	batadv_mcast_init(bat_priv); | ||||||
|  | @@ -221,8 +233,20 @@ int batadv_mesh_init(struct net_device * | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  |   | ||||||
|  | -err: | ||||||
|  | -	batadv_mesh_free(soft_iface); | ||||||
|  | +err_nc: | ||||||
|  | +	batadv_dat_free(bat_priv); | ||||||
|  | +err_dat: | ||||||
|  | +	batadv_bla_free(bat_priv); | ||||||
|  | +err_bla: | ||||||
|  | +	batadv_v_mesh_free(bat_priv); | ||||||
|  | +err_v: | ||||||
|  | +	batadv_tt_free(bat_priv); | ||||||
|  | +err_tt: | ||||||
|  | +	batadv_originator_free(bat_priv); | ||||||
|  | +err_orig: | ||||||
|  | +	batadv_purge_outstanding_packets(bat_priv, NULL); | ||||||
|  | +	atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); | ||||||
|  | + | ||||||
|  |  	return ret; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | --- a/net/batman-adv/network-coding.c | ||||||
|  | +++ b/net/batman-adv/network-coding.c | ||||||
|  | @@ -152,8 +152,10 @@ int batadv_nc_mesh_init(struct batadv_pr | ||||||
|  |  				   &batadv_nc_coding_hash_lock_class_key); | ||||||
|  |   | ||||||
|  |  	bat_priv->nc.decoding_hash = batadv_hash_new(128); | ||||||
|  | -	if (!bat_priv->nc.decoding_hash) | ||||||
|  | +	if (!bat_priv->nc.decoding_hash) { | ||||||
|  | +		batadv_hash_destroy(bat_priv->nc.coding_hash); | ||||||
|  |  		goto err; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	batadv_hash_set_lock_class(bat_priv->nc.decoding_hash, | ||||||
|  |  				   &batadv_nc_decoding_hash_lock_class_key); | ||||||
|  | --- a/net/batman-adv/translation-table.c | ||||||
|  | +++ b/net/batman-adv/translation-table.c | ||||||
|  | @@ -4193,8 +4193,10 @@ int batadv_tt_init(struct batadv_priv *b | ||||||
|  |  		return ret; | ||||||
|  |   | ||||||
|  |  	ret = batadv_tt_global_init(bat_priv); | ||||||
|  | -	if (ret < 0) | ||||||
|  | +	if (ret < 0) { | ||||||
|  | +		batadv_tt_local_table_free(bat_priv); | ||||||
|  |  		return ret; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	batadv_tvlv_handler_register(bat_priv, batadv_tt_tvlv_ogm_handler_v1, | ||||||
|  |  				     batadv_tt_tvlv_unicast_handler_v1, | ||||||
| @@ -0,0 +1,182 @@ | |||||||
|  | From: Linus Lüssing <linus.luessing@c0d3.blue> | ||||||
|  | Date: Mon, 1 Nov 2021 21:46:17 +0100 | ||||||
|  | Subject: batman-adv: allow netlink usage in unprivileged containers | ||||||
|  |  | ||||||
|  | Currently, creating a batman-adv interface in an unprivileged LXD | ||||||
|  | container and attaching secondary interfaces to it with "ip" or "batctl" | ||||||
|  | works fine. However all batctl debug and configuration commands | ||||||
|  | fail: | ||||||
|  |  | ||||||
|  |   root@container:~# batctl originators | ||||||
|  |   Error received: Operation not permitted | ||||||
|  |   root@container:~# batctl orig_interval | ||||||
|  |   1000 | ||||||
|  |   root@container:~# batctl orig_interval 2000 | ||||||
|  |   root@container:~# batctl orig_interval | ||||||
|  |   1000 | ||||||
|  |  | ||||||
|  | To fix this change the generic netlink permissions from GENL_ADMIN_PERM | ||||||
|  | to GENL_UNS_ADMIN_PERM. This way a batman-adv interface is fully | ||||||
|  | maintainable as root from within a user namespace, from an unprivileged | ||||||
|  | container. | ||||||
|  |  | ||||||
|  | All except one batman-adv netlink setting are per interface and do not | ||||||
|  | leak information or change settings from the host system and are | ||||||
|  | therefore save to retrieve or modify as root from within an unprivileged | ||||||
|  | container. | ||||||
|  |  | ||||||
|  | "batctl routing_algo" / BATADV_CMD_GET_ROUTING_ALGOS is the only | ||||||
|  | exception: It provides the batman-adv kernel module wide default routing | ||||||
|  | algorithm. However it is read-only from netlink and an unprivileged | ||||||
|  | container is still not allowed to modify | ||||||
|  | /sys/module/batman_adv/parameters/routing_algo. Instead it is advised to | ||||||
|  | use the newly introduced "batctl if create routing_algo RA_NAME" / | ||||||
|  | IFLA_BATADV_ALGO_NAME to set the routing algorithm on interface | ||||||
|  | creation, which already works fine in an unprivileged container. | ||||||
|  |  | ||||||
|  | Cc: Tycho Andersen <tycho@tycho.pizza> | ||||||
|  | Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue> | ||||||
|  | Signed-off-by: Sven Eckelmann <sven@narfation.org> | ||||||
|  | Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/055fa41b73ca8dae1c1ed41777e32a8f02e80c82 | ||||||
|  |  | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/compat-include/uapi/linux/genetlink.h | ||||||
|  | @@ -0,0 +1,22 @@ | ||||||
|  | +/* SPDX-License-Identifier: GPL-2.0 */ | ||||||
|  | +/* Copyright (C) B.A.T.M.A.N. contributors: | ||||||
|  | + * | ||||||
|  | + * Marek Lindner, Simon Wunderlich | ||||||
|  | + * | ||||||
|  | + * This file contains macros for maintaining compatibility with older versions | ||||||
|  | + * of the Linux kernel. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +#ifndef _NET_BATMAN_ADV_COMPAT_UAPI_LINUX_GENETLINK_H_ | ||||||
|  | +#define _NET_BATMAN_ADV_COMPAT_UAPI_LINUX_GENETLINK_H_ | ||||||
|  | + | ||||||
|  | +#include <linux/version.h> | ||||||
|  | +#include_next <uapi/linux/genetlink.h> | ||||||
|  | + | ||||||
|  | +#if LINUX_VERSION_IS_LESS(4, 6, 0) | ||||||
|  | + | ||||||
|  | +#define GENL_UNS_ADMIN_PERM GENL_ADMIN_PERM | ||||||
|  | + | ||||||
|  | +#endif /* LINUX_VERSION_IS_LESS(4, 6, 0) */ | ||||||
|  | + | ||||||
|  | +#endif /* _NET_BATMAN_ADV_COMPAT_UAPI_LINUX_GENETLINK_H_ */ | ||||||
|  | --- a/net/batman-adv/netlink.c | ||||||
|  | +++ b/net/batman-adv/netlink.c | ||||||
|  | @@ -1369,21 +1369,21 @@ static const struct genl_ops batadv_netl | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_TP_METER, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.doit = batadv_netlink_tp_meter_start, | ||||||
|  |  		.internal_flags = BATADV_FLAG_NEED_MESH, | ||||||
|  |  	}, | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_TP_METER_CANCEL, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.doit = batadv_netlink_tp_meter_cancel, | ||||||
|  |  		.internal_flags = BATADV_FLAG_NEED_MESH, | ||||||
|  |  	}, | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_GET_ROUTING_ALGOS, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.dumpit = batadv_algo_dump, | ||||||
|  |  	}, | ||||||
|  |  	{ | ||||||
|  | @@ -1398,68 +1398,68 @@ static const struct genl_ops batadv_netl | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_GET_TRANSTABLE_LOCAL, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.dumpit = batadv_tt_local_dump, | ||||||
|  |  	}, | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_GET_TRANSTABLE_GLOBAL, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.dumpit = batadv_tt_global_dump, | ||||||
|  |  	}, | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_GET_ORIGINATORS, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.dumpit = batadv_orig_dump, | ||||||
|  |  	}, | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_GET_NEIGHBORS, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.dumpit = batadv_hardif_neigh_dump, | ||||||
|  |  	}, | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_GET_GATEWAYS, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.dumpit = batadv_gw_dump, | ||||||
|  |  	}, | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_GET_BLA_CLAIM, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.dumpit = batadv_bla_claim_dump, | ||||||
|  |  	}, | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_GET_BLA_BACKBONE, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.dumpit = batadv_bla_backbone_dump, | ||||||
|  |  	}, | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_GET_DAT_CACHE, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.dumpit = batadv_dat_cache_dump, | ||||||
|  |  	}, | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_GET_MCAST_FLAGS, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.dumpit = batadv_mcast_flags_dump, | ||||||
|  |  	}, | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_SET_MESH, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.doit = batadv_netlink_set_mesh, | ||||||
|  |  		.internal_flags = BATADV_FLAG_NEED_MESH, | ||||||
|  |  	}, | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_SET_HARDIF, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.doit = batadv_netlink_set_hardif, | ||||||
|  |  		.internal_flags = BATADV_FLAG_NEED_MESH | | ||||||
|  |  				  BATADV_FLAG_NEED_HARDIF, | ||||||
|  | @@ -1475,7 +1475,7 @@ static const struct genl_ops batadv_netl | ||||||
|  |  	{ | ||||||
|  |  		.cmd = BATADV_CMD_SET_VLAN, | ||||||
|  |  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, | ||||||
|  | -		.flags = GENL_ADMIN_PERM, | ||||||
|  | +		.flags = GENL_UNS_ADMIN_PERM, | ||||||
|  |  		.doit = batadv_netlink_set_vlan, | ||||||
|  |  		.internal_flags = BATADV_FLAG_NEED_MESH | | ||||||
|  |  				  BATADV_FLAG_NEED_VLAN, | ||||||
| @@ -0,0 +1,165 @@ | |||||||
|  | From: Linus Lüssing <linus.luessing@c0d3.blue> | ||||||
|  | Date: Sat, 1 Jan 2022 06:27:13 +0100 | ||||||
|  | Subject: batman-adv: mcast: don't send link-local multicast to mcast routers | ||||||
|  |  | ||||||
|  | The addition of routable multicast TX handling introduced a | ||||||
|  | bug/regression for packets with a link-local multicast destination: | ||||||
|  | These packets would be sent to all batman-adv nodes with a multicast | ||||||
|  | router and to all batman-adv nodes with an old version without multicast | ||||||
|  | router detection. | ||||||
|  |  | ||||||
|  | This even disregards the batman-adv multicast fanout setting, which can | ||||||
|  | potentially lead to an unwanted, high number of unicast transmissions or | ||||||
|  | even congestion. | ||||||
|  |  | ||||||
|  | Fixing this by avoiding to send link-local multicast packets to nodes in | ||||||
|  | the multicast router list. | ||||||
|  |  | ||||||
|  | Fixes: 3a8df00cd969 ("batman-adv: mcast: apply optimizations for routable packets, too") | ||||||
|  | Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue> | ||||||
|  | Signed-off-by: Sven Eckelmann <sven@narfation.org> | ||||||
|  | Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/ee013870947b9175847aa46a0686ca01dd480af4 | ||||||
|  |  | ||||||
|  | --- a/net/batman-adv/multicast.c | ||||||
|  | +++ b/net/batman-adv/multicast.c | ||||||
|  | @@ -1380,6 +1380,7 @@ batadv_mcast_forw_rtr_node_get(struct ba | ||||||
|  |   * @bat_priv: the bat priv with all the soft interface information | ||||||
|  |   * @skb: The multicast packet to check | ||||||
|  |   * @orig: an originator to be set to forward the skb to | ||||||
|  | + * @is_routable: stores whether the destination is routable | ||||||
|  |   * | ||||||
|  |   * Return: the forwarding mode as enum batadv_forw_mode and in case of | ||||||
|  |   * BATADV_FORW_SINGLE set the orig to the single originator the skb | ||||||
|  | @@ -1387,17 +1388,16 @@ batadv_mcast_forw_rtr_node_get(struct ba | ||||||
|  |   */ | ||||||
|  |  enum batadv_forw_mode | ||||||
|  |  batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||||||
|  | -		       struct batadv_orig_node **orig) | ||||||
|  | +		       struct batadv_orig_node **orig, int *is_routable) | ||||||
|  |  { | ||||||
|  |  	int ret, tt_count, ip_count, unsnoop_count, total_count; | ||||||
|  |  	bool is_unsnoopable = false; | ||||||
|  |  	unsigned int mcast_fanout; | ||||||
|  |  	struct ethhdr *ethhdr; | ||||||
|  | -	int is_routable = 0; | ||||||
|  |  	int rtr_count = 0; | ||||||
|  |   | ||||||
|  |  	ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable, | ||||||
|  | -					   &is_routable); | ||||||
|  | +					   is_routable); | ||||||
|  |  	if (ret == -ENOMEM) | ||||||
|  |  		return BATADV_FORW_NONE; | ||||||
|  |  	else if (ret < 0) | ||||||
|  | @@ -1410,7 +1410,7 @@ batadv_mcast_forw_mode(struct batadv_pri | ||||||
|  |  	ip_count = batadv_mcast_forw_want_all_ip_count(bat_priv, ethhdr); | ||||||
|  |  	unsnoop_count = !is_unsnoopable ? 0 : | ||||||
|  |  			atomic_read(&bat_priv->mcast.num_want_all_unsnoopables); | ||||||
|  | -	rtr_count = batadv_mcast_forw_rtr_count(bat_priv, is_routable); | ||||||
|  | +	rtr_count = batadv_mcast_forw_rtr_count(bat_priv, *is_routable); | ||||||
|  |   | ||||||
|  |  	total_count = tt_count + ip_count + unsnoop_count + rtr_count; | ||||||
|  |   | ||||||
|  | @@ -1730,6 +1730,7 @@ batadv_mcast_forw_want_rtr(struct batadv | ||||||
|  |   * @bat_priv: the bat priv with all the soft interface information | ||||||
|  |   * @skb: the multicast packet to transmit | ||||||
|  |   * @vid: the vlan identifier | ||||||
|  | + * @is_routable: stores whether the destination is routable | ||||||
|  |   * | ||||||
|  |   * Sends copies of a frame with multicast destination to any node that signaled | ||||||
|  |   * interest in it, that is either via the translation table or the according | ||||||
|  | @@ -1742,7 +1743,7 @@ batadv_mcast_forw_want_rtr(struct batadv | ||||||
|  |   * is neither IPv4 nor IPv6. NET_XMIT_SUCCESS otherwise. | ||||||
|  |   */ | ||||||
|  |  int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||||||
|  | -			   unsigned short vid) | ||||||
|  | +			   unsigned short vid, int is_routable) | ||||||
|  |  { | ||||||
|  |  	int ret; | ||||||
|  |   | ||||||
|  | @@ -1758,12 +1759,16 @@ int batadv_mcast_forw_send(struct batadv | ||||||
|  |  		return ret; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	if (!is_routable) | ||||||
|  | +		goto skip_mc_router; | ||||||
|  | + | ||||||
|  |  	ret = batadv_mcast_forw_want_rtr(bat_priv, skb, vid); | ||||||
|  |  	if (ret != NET_XMIT_SUCCESS) { | ||||||
|  |  		kfree_skb(skb); | ||||||
|  |  		return ret; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +skip_mc_router: | ||||||
|  |  	consume_skb(skb); | ||||||
|  |  	return ret; | ||||||
|  |  } | ||||||
|  | --- a/net/batman-adv/multicast.h | ||||||
|  | +++ b/net/batman-adv/multicast.h | ||||||
|  | @@ -43,7 +43,8 @@ enum batadv_forw_mode { | ||||||
|  |   | ||||||
|  |  enum batadv_forw_mode | ||||||
|  |  batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||||||
|  | -		       struct batadv_orig_node **mcast_single_orig); | ||||||
|  | +		       struct batadv_orig_node **mcast_single_orig, | ||||||
|  | +		       int *is_routable); | ||||||
|  |   | ||||||
|  |  int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv, | ||||||
|  |  				struct sk_buff *skb, | ||||||
|  | @@ -51,7 +52,7 @@ int batadv_mcast_forw_send_orig(struct b | ||||||
|  |  				struct batadv_orig_node *orig_node); | ||||||
|  |   | ||||||
|  |  int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||||||
|  | -			   unsigned short vid); | ||||||
|  | +			   unsigned short vid, int is_routable); | ||||||
|  |   | ||||||
|  |  void batadv_mcast_init(struct batadv_priv *bat_priv); | ||||||
|  |   | ||||||
|  | @@ -68,7 +69,8 @@ void batadv_mcast_purge_orig(struct bata | ||||||
|  |   | ||||||
|  |  static inline enum batadv_forw_mode | ||||||
|  |  batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||||||
|  | -		       struct batadv_orig_node **mcast_single_orig) | ||||||
|  | +		       struct batadv_orig_node **mcast_single_orig, | ||||||
|  | +		       int *is_routable) | ||||||
|  |  { | ||||||
|  |  	return BATADV_FORW_ALL; | ||||||
|  |  } | ||||||
|  | @@ -85,7 +87,7 @@ batadv_mcast_forw_send_orig(struct batad | ||||||
|  |   | ||||||
|  |  static inline int | ||||||
|  |  batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||||||
|  | -		       unsigned short vid) | ||||||
|  | +		       unsigned short vid, int is_routable) | ||||||
|  |  { | ||||||
|  |  	kfree_skb(skb); | ||||||
|  |  	return NET_XMIT_DROP; | ||||||
|  | --- a/net/batman-adv/soft-interface.c | ||||||
|  | +++ b/net/batman-adv/soft-interface.c | ||||||
|  | @@ -198,6 +198,7 @@ static netdev_tx_t batadv_interface_tx(s | ||||||
|  |  	int gw_mode; | ||||||
|  |  	enum batadv_forw_mode forw_mode = BATADV_FORW_SINGLE; | ||||||
|  |  	struct batadv_orig_node *mcast_single_orig = NULL; | ||||||
|  | +	int mcast_is_routable = 0; | ||||||
|  |  	int network_offset = ETH_HLEN; | ||||||
|  |  	__be16 proto; | ||||||
|  |   | ||||||
|  | @@ -300,7 +301,8 @@ static netdev_tx_t batadv_interface_tx(s | ||||||
|  |  send: | ||||||
|  |  		if (do_bcast && !is_broadcast_ether_addr(ethhdr->h_dest)) { | ||||||
|  |  			forw_mode = batadv_mcast_forw_mode(bat_priv, skb, | ||||||
|  | -							   &mcast_single_orig); | ||||||
|  | +							   &mcast_single_orig, | ||||||
|  | +							   &mcast_is_routable); | ||||||
|  |  			if (forw_mode == BATADV_FORW_NONE) | ||||||
|  |  				goto dropped; | ||||||
|  |   | ||||||
|  | @@ -365,7 +367,8 @@ send: | ||||||
|  |  			ret = batadv_mcast_forw_send_orig(bat_priv, skb, vid, | ||||||
|  |  							  mcast_single_orig); | ||||||
|  |  		} else if (forw_mode == BATADV_FORW_SOME) { | ||||||
|  | -			ret = batadv_mcast_forw_send(bat_priv, skb, vid); | ||||||
|  | +			ret = batadv_mcast_forw_send(bat_priv, skb, vid, | ||||||
|  | +						     mcast_is_routable); | ||||||
|  |  		} else { | ||||||
|  |  			if (batadv_dat_snoop_outgoing_arp_request(bat_priv, | ||||||
|  |  								  skb)) | ||||||
							
								
								
									
										36
									
								
								feeds/wifi-ax/hostapd/patches/770-wds-hack.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								feeds/wifi-ax/hostapd/patches/770-wds-hack.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/ap/hostapd.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/hostapd.c | ||||||
|  | @@ -11,6 +11,8 @@ | ||||||
|  |  #include <sqlite3.h> | ||||||
|  |  #endif /* CONFIG_SQLITE */ | ||||||
|  |   | ||||||
|  | +#include <syslog.h> | ||||||
|  | + | ||||||
|  |  #include "utils/common.h" | ||||||
|  |  #include "utils/eloop.h" | ||||||
|  |  #include "common/ieee802_11_defs.h" | ||||||
|  | @@ -1316,6 +1318,22 @@ static int hostapd_setup_bss(struct host | ||||||
|  |  			os_memcpy(hapd->own_addr, if_addr, ETH_ALEN); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	if (conf->wds_sta) { | ||||||
|  | +		char path[128]; | ||||||
|  | +		FILE *fp; | ||||||
|  | + | ||||||
|  | +		sprintf(path, "/sys/kernel/debug/ieee80211/%s/netdev:%s/disable_offload", hostapd_drv_get_radio_name(hapd), conf->iface); | ||||||
|  | + | ||||||
|  | +		fp = fopen(path, "w"); | ||||||
|  | +		if (fp) { | ||||||
|  | +			syslog(0, "WDS: disable encap - %s\n", path); | ||||||
|  | +			fprintf(fp, "1"); | ||||||
|  | +			fclose(fp); | ||||||
|  | +		} else { | ||||||
|  | +			syslog(0, "WDS: failed to disable encap - %s\n", path); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	if (conf->wmm_enabled < 0) | ||||||
|  |  		conf->wmm_enabled = hapd->iconf->ieee80211n | hapd->iconf->ieee80211ax; | ||||||
|  |   | ||||||
| @@ -0,0 +1,29 @@ | |||||||
|  | diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c | ||||||
|  | index ad2aebf..355b4a8 100644 | ||||||
|  | --- a/src/common/hw_features_common.c | ||||||
|  | +++ b/src/common/hw_features_common.c | ||||||
|  | @@ -615,9 +615,21 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, | ||||||
|  |  			    center_segment0 == channel - 6) | ||||||
|  |  				data->center_freq1 = 5000 + center_segment0 * 5; | ||||||
|  |  			else { | ||||||
|  | -				wpa_printf(MSG_ERROR, | ||||||
|  | -					   "Wrong coupling between HT and VHT/HE channel setting"); | ||||||
|  | -				return -1; | ||||||
|  | +				if (channel <= 48) | ||||||
|  | +					center_segment0 = 42; | ||||||
|  | +				else if (channel <= 64) | ||||||
|  | +					center_segment0 = 58; | ||||||
|  | +				else if (channel <= 112) | ||||||
|  | +					center_segment0 = 106; | ||||||
|  | +				else if (channel <= 128) | ||||||
|  | +					center_segment0 = 122; | ||||||
|  | +				else if (channel <= 144) | ||||||
|  | +					center_segment0 = 138; | ||||||
|  | +				else if (channel <= 161) | ||||||
|  | +					center_segment0 = 155; | ||||||
|  | +				else if (channel <= 177) | ||||||
|  | +					center_segment0 = 171; | ||||||
|  | +				data->center_freq1 = 5000 + center_segment0 * 5; | ||||||
|  |  			} | ||||||
|  |  		} | ||||||
|  |  		break; | ||||||
| @@ -132,7 +132,7 @@ mac80211_hostapd_setup_base() { | |||||||
|  |  | ||||||
| 	json_select config | 	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 | 	[ "$auto_channel" -gt 0 ] && json_get_vars acs_exclude_dfs | ||||||
| 	[ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] && | 	[ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] && | ||||||
| @@ -1162,10 +1162,13 @@ drv_mac80211_setup() { | |||||||
| 		if [ "$no_reload" != "0" ]; then | 		if [ "$no_reload" != "0" ]; then | ||||||
| 			add_ap=1 | 			add_ap=1 | ||||||
| 			ubus wait_for hostapd | 			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="$?" | 			ret="$?" | ||||||
|  | 			rm -f /tmp/wifi_fail_test | ||||||
| 			[ "$ret" != 0 -o -z "$hostapd_res" ] && { | 			[ "$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 | 				return | ||||||
| 			} | 			} | ||||||
| 			wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1 | 			wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1 | ||||||
|   | |||||||
							
								
								
									
										74
									
								
								feeds/wifi-ax/mac80211/patches/pending/214-fix-wds.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								feeds/wifi-ax/mac80211/patches/pending/214-fix-wds.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | |||||||
|  | --- a/net/mac80211/debugfs_netdev.c | ||||||
|  | +++ b/net/mac80211/debugfs_netdev.c | ||||||
|  | @@ -300,6 +300,32 @@ static ssize_t ieee80211_if_parse_smps(s | ||||||
|  |  } | ||||||
|  |  IEEE80211_IF_FILE_RW(smps); | ||||||
|  |   | ||||||
|  | +static ssize_t ieee80211_if_fmt_disable_offload(const struct ieee80211_sub_if_data *sdata, | ||||||
|  | +				     char *buf, int buflen) | ||||||
|  | +{ | ||||||
|  | +	return snprintf(buf, buflen, "%u\n", sdata->disable_offload); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static ssize_t ieee80211_if_parse_disable_offload(struct ieee80211_sub_if_data *sdata, | ||||||
|  | +				       const char *buf, int buflen) | ||||||
|  | +{ | ||||||
|  | +	int ret; | ||||||
|  | +	u8 val; | ||||||
|  | + | ||||||
|  | +	ret = kstrtou8(buf, 0, &val); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	if (!val) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  | +	sdata->disable_offload = val; | ||||||
|  | +	ieee80211_recalc_offload(sdata->local); | ||||||
|  | + | ||||||
|  | +	return buflen; | ||||||
|  | +} | ||||||
|  | +IEEE80211_IF_FILE_RW(disable_offload); | ||||||
|  | + | ||||||
|  |  int ieee80211_if_fmt_bmiss_threshold(const struct ieee80211_sub_if_data *sdata, | ||||||
|  |  				     char *buf, int buflen) | ||||||
|  |  { | ||||||
|  | @@ -680,6 +706,7 @@ static void add_common_files(struct ieee | ||||||
|  |  	DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||||||
|  |  	DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_2ghz); | ||||||
|  |  	DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_5ghz); | ||||||
|  | +	DEBUGFS_ADD_MODE(disable_offload, 0600); | ||||||
|  |  	DEBUGFS_ADD(hw_queues); | ||||||
|  |   | ||||||
|  |  	if (sdata->local->ops->wake_tx_queue && | ||||||
|  | --- a/net/mac80211/ieee80211_i.h | ||||||
|  | +++ b/net/mac80211/ieee80211_i.h | ||||||
|  | @@ -942,6 +942,7 @@ struct ieee80211_sub_if_data { | ||||||
|  |  	bool control_port_no_encrypt; | ||||||
|  |  	bool control_port_no_preauth; | ||||||
|  |  	bool control_port_over_nl80211; | ||||||
|  | +	bool disable_offload; | ||||||
|  |  	int encrypt_headroom; | ||||||
|  |   | ||||||
|  |  	atomic_t num_tx_queued; | ||||||
|  | --- a/net/mac80211/iface.c | ||||||
|  | +++ b/net/mac80211/iface.c | ||||||
|  | @@ -909,6 +909,9 @@ static bool ieee80211_set_sdata_offload_ | ||||||
|  |  		flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	if (sdata->disable_offload) | ||||||
|  | +		flags = 0; | ||||||
|  | + | ||||||
|  |  	if (sdata->vif.offload_flags == flags) | ||||||
|  |  		return false; | ||||||
|  |   | ||||||
|  | @@ -939,6 +942,8 @@ static void ieee80211_set_vif_encap_ops( | ||||||
|  |  	if (sdata->wdev.use_4addr && | ||||||
|  |  	    !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR)) | ||||||
|  |  		enabled = false; | ||||||
|  | +	if (bss->disable_offload) | ||||||
|  | +		enabled = false; | ||||||
|  |   | ||||||
|  |  	sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops : | ||||||
|  |  					   &ieee80211_dataif_ops; | ||||||
| @@ -1,21 +0,0 @@ | |||||||
| Index: backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c |  | ||||||
| =================================================================== |  | ||||||
| --- backports-20210222_001-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/mac.c |  | ||||||
| +++ backports-20210222_001-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c |  | ||||||
| @@ -6590,6 +6590,7 @@ static int ath11k_mac_op_update_vif_offl |  | ||||||
|  	u32 param_id, param_value; |  | ||||||
|  	int ret; |  | ||||||
|   |  | ||||||
| +	return 0; |  | ||||||
|  	if (ab->nss.enabled && vif->type == NL80211_IFTYPE_AP_VLAN) |  | ||||||
|  		return 0; |  | ||||||
|   |  | ||||||
| @@ -6835,6 +6836,8 @@ static int ath11k_mac_op_add_interface(s |  | ||||||
|  	else |  | ||||||
|  		param_value = ATH11K_HW_TXRX_NATIVE_WIFI; |  | ||||||
|   |  | ||||||
| +	param_value = ATH11K_HW_TXRX_NATIVE_WIFI; |  | ||||||
| + |  | ||||||
|  	ret = ath11k_nss_vdev_set_cmd(arvif, NSS_WIFI_VDEV_ENCAP_TYPE_CMD, param_value); |  | ||||||
|   |  | ||||||
|  	if(ret) { |  | ||||||
| @@ -0,0 +1,57 @@ | |||||||
|  | --- a/drivers/net/wireless/ath/ath11k/ahb.c | ||||||
|  | +++ b/drivers/net/wireless/ath/ath11k/ahb.c | ||||||
|  | @@ -526,6 +526,7 @@ static int ath11k_ahb_ext_irq_config(str | ||||||
|  |  	int irq; | ||||||
|  |  	int ret; | ||||||
|  |  	bool nss_offload; | ||||||
|  | +	static int devidx = 0; | ||||||
|  |   | ||||||
|  |  	/* TCL Completion, REO Dest, ERR, Exception and h2rxdma rings are offloaded | ||||||
|  |  	 * to nss when its enabled, hence don't enable these interrupts | ||||||
|  | @@ -539,6 +540,9 @@ static int ath11k_ahb_ext_irq_config(str | ||||||
|  |  		irq_grp->ab = ab; | ||||||
|  |  		irq_grp->grp_id = i; | ||||||
|  |  		init_dummy_netdev(&irq_grp->napi_ndev); | ||||||
|  | +		snprintf(irq_grp->napi_ndev.name, sizeof(irq_grp->napi_ndev.name), "%s%d:%d", | ||||||
|  | +			 "ath11k_ahb", devidx, i); | ||||||
|  | +		irq_grp->napi_ndev.threaded = 1; | ||||||
|  |  		netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, | ||||||
|  |  			       ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT); | ||||||
|  |   | ||||||
|  | @@ -604,6 +608,8 @@ static int ath11k_ahb_ext_irq_config(str | ||||||
|  |  		} | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	devidx++; | ||||||
|  | + | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | --- a/drivers/net/wireless/ath/ath11k/pci.c | ||||||
|  | +++ b/drivers/net/wireless/ath/ath11k/pci.c | ||||||
|  | @@ -806,6 +806,7 @@ static int ath11k_pci_ext_irq_config(str | ||||||
|  |  	int i, j, ret, num_vectors = 0; | ||||||
|  |  	u32 user_base_data = 0, base_vector = 0, base_idx; | ||||||
|  |  	u8 domain_id; | ||||||
|  | +	static int devidx = 0; | ||||||
|  |   | ||||||
|  |  	domain_id = ath11k_pci_get_domain_id(ab); | ||||||
|  |  	base_idx = ATH11K_PCI_IRQ_CE0_OFFSET + CE_COUNT_MAX; | ||||||
|  | @@ -822,6 +823,9 @@ static int ath11k_pci_ext_irq_config(str | ||||||
|  |  		irq_grp->ab = ab; | ||||||
|  |  		irq_grp->grp_id = i; | ||||||
|  |  		init_dummy_netdev(&irq_grp->napi_ndev); | ||||||
|  | +		snprintf(irq_grp->napi_ndev.name, sizeof(irq_grp->napi_ndev.name), "%s%d:%d", | ||||||
|  | +			 "ath11k_pci", devidx, i); | ||||||
|  | +		irq_grp->napi_ndev.threaded = 1; | ||||||
|  |  		netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, | ||||||
|  |  			       ath11k_pci_ext_grp_napi_poll, NAPI_POLL_WEIGHT); | ||||||
|  |   | ||||||
|  | @@ -868,6 +872,7 @@ static int ath11k_pci_ext_irq_config(str | ||||||
|  |  		} | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	devidx++; | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
| @@ -0,0 +1,31 @@ | |||||||
|  | From 9ff18b1e8b9417c50566f469d8b3f5f36bef746a Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <john@phrozen.org> | ||||||
|  | Date: Fri, 11 Mar 2022 16:13:41 +0100 | ||||||
|  | Subject: [PATCH] ipq40xx: disable dualboot on ecw5211 | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <john@phrozen.org> | ||||||
|  | --- | ||||||
|  |  target/linux/ipq40xx/base-files/etc/init.d/bootcount | 8 ++++++++ | ||||||
|  |  1 file changed, 8 insertions(+) | ||||||
|  |  | ||||||
|  | diff --git a/target/linux/ipq40xx/base-files/etc/init.d/bootcount b/target/linux/ipq40xx/base-files/etc/init.d/bootcount | ||||||
|  | index d2a4abcadd..36b5d56d0c 100755 | ||||||
|  | --- a/target/linux/ipq40xx/base-files/etc/init.d/bootcount | ||||||
|  | +++ b/target/linux/ipq40xx/base-files/etc/init.d/bootcount | ||||||
|  | @@ -13,5 +13,13 @@ boot() { | ||||||
|  |  	linksys,mr8300) | ||||||
|  |  		mtd resetbc s_env || true | ||||||
|  |  		;; | ||||||
|  | +	edgecore,spw2ac1200|\ | ||||||
|  | +	edgecore,spw2ac1200-lan-poe|\ | ||||||
|  | +	edgecore,ecw5211) | ||||||
|  | +		avail=$(fw_printenv -n upgrade_available) | ||||||
|  | +		[ ${avail} -eq 0 ] || { | ||||||
|  | +			fw_setenv bootcount 0 | ||||||
|  | +			fw_setenv upgrade_available 0 | ||||||
|  | +		} | ||||||
|  |  	esac | ||||||
|  |  } | ||||||
|  | --  | ||||||
|  | 2.25.1 | ||||||
|  |  | ||||||
							
								
								
									
										377
									
								
								patches/ipq40xx/0014-ipq40xx-add-Indio-UM-325AC-support.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										377
									
								
								patches/ipq40xx/0014-ipq40xx-add-Indio-UM-325AC-support.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,377 @@ | |||||||
|  | From 77c7dfe84d6a89a237e34ce24b8fae63a01b6be3 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Sohail Ahmad <sohail@indionetworks.com> | ||||||
|  | Date: Tue, 22 Mar 2022 08:02:50 +0100 | ||||||
|  | Subject: [PATCH] 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> | ||||||
|  | --- | ||||||
|  |  .../ipq40xx/base-files/etc/board.d/02_network |   4 + | ||||||
|  |  .../etc/hotplug.d/firmware/11-ath10k-caldata  |   6 + | ||||||
|  |  .../arm/boot/dts/qcom-ipq4019-um-325ac.dts    |  94 ++++++++++ | ||||||
|  |  .../arm/boot/dts/qcom-ipq4019-um-325ac.dtsi   | 168 ++++++++++++++++++ | ||||||
|  |  target/linux/ipq40xx/image/generic.mk         |  14 ++ | ||||||
|  |  .../911-dts-ipq4019-indio-um-325ac.patch      |  13 ++ | ||||||
|  |  6 files changed, 299 insertions(+) | ||||||
|  |  create mode 100644 target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dts | ||||||
|  |  create mode 100644 target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dtsi | ||||||
|  |  create mode 100644 target/linux/ipq40xx/patches-5.4/911-dts-ipq4019-indio-um-325ac.patch | ||||||
|  |  | ||||||
|  | diff --git a/target/linux/ipq40xx/base-files/etc/board.d/02_network b/target/linux/ipq40xx/base-files/etc/board.d/02_network | ||||||
|  | index f533c39179..f875719400 100755 | ||||||
|  | --- a/target/linux/ipq40xx/base-files/etc/board.d/02_network | ||||||
|  | +++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network | ||||||
|  | @@ -123,6 +123,10 @@ ipq40xx_setup_interfaces() | ||||||
|  |  		ucidef_add_switch "switch0" \ | ||||||
|  |  			"0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan" | ||||||
|  |  		;; | ||||||
|  | +	um-325ac) | ||||||
|  | +		ucidef_set_interface_wan "eth0" | ||||||
|  | +		ucidef_set_interface_lan "eth1" | ||||||
|  | +		;; | ||||||
|  |  	*) | ||||||
|  |  		echo "Unsupported hardware. Network interfaces not initialized" | ||||||
|  |  		;; | ||||||
|  | diff --git a/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata | ||||||
|  | index 99a99801ef..3a22a6faab 100644 | ||||||
|  | --- a/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata | ||||||
|  | +++ b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata | ||||||
|  | @@ -172,6 +172,9 @@ case "$FIRMWARE" in | ||||||
|  |  		caldata_extract "0:ART" 4096 12064 | ||||||
|  |  		ath10k_patch_mac $(mtd_get_mac_ascii 0:ART WLAN0_BASEMAC) | ||||||
|  |  		;; | ||||||
|  | +	um-325ac) | ||||||
|  | +		caldata_extract "ART" 0x1000 0x2f20 | ||||||
|  | +		;; | ||||||
|  |  	esac | ||||||
|  |  	;; | ||||||
|  |  "ath10k/pre-cal-ahb-a800000.wifi.bin") | ||||||
|  | @@ -293,6 +296,9 @@ case "$FIRMWARE" in | ||||||
|  |  		caldata_extract "0:ART" 20480 12064 | ||||||
|  |  		ath10k_patch_mac $(mtd_get_mac_ascii 0:ART WLAN1_BASEMAC) | ||||||
|  |  		;; | ||||||
|  | +	um-325ac) | ||||||
|  | +		caldata_extract "ART" 0x5000 0x2f20 | ||||||
|  | +		;; | ||||||
|  |  	esac | ||||||
|  |  	;; | ||||||
|  |  *) | ||||||
|  | diff --git a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dts b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dts | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..0ab70a68c3 | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dts | ||||||
|  | @@ -0,0 +1,94 @@ | ||||||
|  | +/* Copyright (c) 2015, 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-ipq4019-um-325ac.dtsi" | ||||||
|  | + | ||||||
|  | +/ { | ||||||
|  | +	model = "Indio Networks UM-325AC"; | ||||||
|  | +	compatible = "um-325ac"; | ||||||
|  | + | ||||||
|  | +	memory { | ||||||
|  | +		device_type = "memory"; | ||||||
|  | +		reg = <0x80000000 0x10000000>; | ||||||
|  | +	}; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +&blsp1_spi1 { | ||||||
|  | +	mx25l25635f@0 { | ||||||
|  | +		compatible = "mx25l25635f", "jedec,spi-nor"; | ||||||
|  | +		#address-cells = <1>; | ||||||
|  | +		#size-cells = <1>; | ||||||
|  | +		reg = <0>; | ||||||
|  | +		spi-max-frequency = <24000000>; | ||||||
|  | + | ||||||
|  | +		SBL1@0 { | ||||||
|  | +			label = "SBL1"; | ||||||
|  | +			reg = <0x0 0x40000>; | ||||||
|  | +			read-only; | ||||||
|  | +		}; | ||||||
|  | +		MIBIB@40000 { | ||||||
|  | +			label = "MIBIB"; | ||||||
|  | +			reg = <0x40000 0x20000>; | ||||||
|  | +			read-only; | ||||||
|  | +		}; | ||||||
|  | +		QSEE@60000 { | ||||||
|  | +			label = "QSEE"; | ||||||
|  | +			reg = <0x60000 0x60000>; | ||||||
|  | +			read-only; | ||||||
|  | +		}; | ||||||
|  | +		CDT@c0000 { | ||||||
|  | +			label = "CDT"; | ||||||
|  | +			reg = <0xc0000 0x10000>; | ||||||
|  | +			read-only; | ||||||
|  | +		}; | ||||||
|  | +		DDRPARAMS@d0000 { | ||||||
|  | +			label = "DDRPARAMS"; | ||||||
|  | +			reg = <0xd0000 0x10000>; | ||||||
|  | +			read-only; | ||||||
|  | +		}; | ||||||
|  | +		APPSBLENV@e0000 { | ||||||
|  | +			label = "APPSBLENV"; | ||||||
|  | +			reg = <0xe0000 0x10000>; | ||||||
|  | +			read-only; | ||||||
|  | +		}; | ||||||
|  | +		APPSBL@f0000 { | ||||||
|  | +			label = "APPSBL"; | ||||||
|  | +			reg = <0xf0000 0x80000>; | ||||||
|  | +			read-only; | ||||||
|  | +		}; | ||||||
|  | +		ART@170000 { | ||||||
|  | +			label = "ART"; | ||||||
|  | +			reg = <0x170000 0x10000>; | ||||||
|  | +			read-only; | ||||||
|  | +		}; | ||||||
|  | +		kernel@180000 { | ||||||
|  | +			label = "kernel"; | ||||||
|  | +			reg = <0x180000 0x400000>; | ||||||
|  | +		}; | ||||||
|  | +		rootfs@580000 { | ||||||
|  | +			label = "rootfs"; | ||||||
|  | +			reg = <0x580000 0x15F0000>; | ||||||
|  | +		}; | ||||||
|  | +		certificates@1b80000 { | ||||||
|  | +			label = "certificates"; | ||||||
|  | +			reg = <0x1b80000 0x10000>; | ||||||
|  | +		}; | ||||||
|  | +		firmware@180000 { | ||||||
|  | +			label = "firmware"; | ||||||
|  | +			reg = <0x180000 0x1a00000>; | ||||||
|  | +		}; | ||||||
|  | +	}; | ||||||
|  | +}; | ||||||
|  | diff --git a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dtsi b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dtsi | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..6fccf0d1d8 | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dtsi | ||||||
|  | @@ -0,0 +1,168 @@ | ||||||
|  | +/* Copyright (c) 2015, 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-ipq4019.dtsi" | ||||||
|  | +#include <dt-bindings/soc/qcom,tcsr.h> | ||||||
|  | + | ||||||
|  | +/ { | ||||||
|  | +	model = "Indio Networks UM-325AC"; | ||||||
|  | +	compatible = "um-325ac"; | ||||||
|  | + | ||||||
|  | +	aliases { | ||||||
|  | +		serial0 = &blsp1_uart1; | ||||||
|  | +	}; | ||||||
|  | + | ||||||
|  | +	chosen { | ||||||
|  | +		stdout-path = "serial0:115200n8"; | ||||||
|  | +	}; | ||||||
|  | + | ||||||
|  | +	soc { | ||||||
|  | +		tcsr@194b000 { | ||||||
|  | +			/* select hostmode */ | ||||||
|  | +			compatible = "qcom,tcsr"; | ||||||
|  | +			reg = <0x194b000 0x100>; | ||||||
|  | +			qcom,usb-hsphy-mode-select = <TCSR_USB_HSPHY_HOST_MODE>; | ||||||
|  | +			status = "okay"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		ess_tcsr@1953000 { | ||||||
|  | +			compatible = "qcom,tcsr"; | ||||||
|  | +			reg = <0x1953000 0x1000>; | ||||||
|  | +			qcom,ess-interface-select = <TCSR_ESS_PSGMII>; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		tcsr@1949000 { | ||||||
|  | +			compatible = "qcom,tcsr"; | ||||||
|  | +			reg = <0x1949000 0x100>; | ||||||
|  | +			qcom,wifi_glb_cfg = <TCSR_WIFI_GLB_CFG>; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		tcsr@1957000 { | ||||||
|  | +			compatible = "qcom,tcsr"; | ||||||
|  | +			reg = <0x1957000 0x100>; | ||||||
|  | +			qcom,wifi_noc_memtype_m0_m2 = <TCSR_WIFI_NOC_MEMTYPE_M0_M2>; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		rng@22000 { | ||||||
|  | +			status = "ok"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		pinctrl@1000000 { | ||||||
|  | +			serial_pins: serial_pinmux { | ||||||
|  | +				mux { | ||||||
|  | +					pins = "gpio60", "gpio61"; | ||||||
|  | +					function = "blsp_uart0"; | ||||||
|  | +					bias-disable; | ||||||
|  | +				}; | ||||||
|  | +			}; | ||||||
|  | + | ||||||
|  | +			spi_0_pins: spi_0_pinmux { | ||||||
|  | +				pinmux { | ||||||
|  | +					function = "blsp_spi0"; | ||||||
|  | +					pins = "gpio55", "gpio56", "gpio57"; | ||||||
|  | +				}; | ||||||
|  | +				pinmux_cs { | ||||||
|  | +					function = "gpio"; | ||||||
|  | +					pins = "gpio54"; | ||||||
|  | +				}; | ||||||
|  | +				pinconf { | ||||||
|  | +					pins = "gpio55", "gpio56", "gpio57"; | ||||||
|  | +					drive-strength = <12>; | ||||||
|  | +					bias-disable; | ||||||
|  | +				}; | ||||||
|  | +				pinconf_cs { | ||||||
|  | +					pins = "gpio54"; | ||||||
|  | +					drive-strength = <2>; | ||||||
|  | +					bias-disable; | ||||||
|  | +					output-high; | ||||||
|  | +				}; | ||||||
|  | +			}; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		blsp_dma: dma@7884000 { | ||||||
|  | +			status = "ok"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		spi@78b5000 { | ||||||
|  | +			pinctrl-0 = <&spi_0_pins>; | ||||||
|  | +			pinctrl-names = "default"; | ||||||
|  | +			status = "ok"; | ||||||
|  | +			cs-gpios = <&tlmm 54 0>; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		serial@78af000 { | ||||||
|  | +			pinctrl-0 = <&serial_pins>; | ||||||
|  | +			pinctrl-names = "default"; | ||||||
|  | +			status = "ok"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		cryptobam: dma@8e04000 { | ||||||
|  | +			status = "ok"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		crypto@8e3a000 { | ||||||
|  | +			status = "ok"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		watchdog@b017000 { | ||||||
|  | +			status = "ok"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		wifi@a000000 { | ||||||
|  | +			status = "ok"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		wifi@a800000 { | ||||||
|  | +			status = "ok"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		mdio@90000 { | ||||||
|  | +			status = "okay"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		ess-switch@c000000 { | ||||||
|  | +			status = "okay"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		ess-psgmii@98000 { | ||||||
|  | +			status = "okay"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		edma@c080000 { | ||||||
|  | +			status = "okay"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		usb3_ss_phy: ssphy@9a000 { | ||||||
|  | +			status = "okay"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		usb3_hs_phy: hsphy@a6000 { | ||||||
|  | +			status = "okay"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		usb3: usb3@8af8800 { | ||||||
|  | +			status = "okay"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		usb2_hs_phy: hsphy@a8000 { | ||||||
|  | +			status = "okay"; | ||||||
|  | +		}; | ||||||
|  | + | ||||||
|  | +		usb2: usb2@60f8800 { | ||||||
|  | +			status = "okay"; | ||||||
|  | +		}; | ||||||
|  | +	}; | ||||||
|  | +}; | ||||||
|  | diff --git a/target/linux/ipq40xx/image/generic.mk b/target/linux/ipq40xx/image/generic.mk | ||||||
|  | index fffd8fdd66..5c8f51ad98 100644 | ||||||
|  | --- a/target/linux/ipq40xx/image/generic.mk | ||||||
|  | +++ b/target/linux/ipq40xx/image/generic.mk | ||||||
|  | @@ -890,3 +890,17 @@ define Device/hfcl_ion4 | ||||||
|  |  	DEVICE_PACKAGES := uboot-envtools | ||||||
|  |  endef | ||||||
|  |  TARGET_DEVICES += hfcl_ion4 | ||||||
|  | + | ||||||
|  | +define Device/um-325ac | ||||||
|  | +	DEVICE_VENDOR := Indio Networks | ||||||
|  | +	DEVICE_MODEL := UM-325AC | ||||||
|  | +	BOARD_NAME := um-325ac | ||||||
|  | +	SOC := qcom-ipq4019 | ||||||
|  | +	DEVICE_DTS := qcom-ipq4019-um-325ac | ||||||
|  | +	KERNEL_INSTALL := 1 | ||||||
|  | +	KERNEL_SIZE := 4096k | ||||||
|  | +	IMAGE_SIZE := 26624k | ||||||
|  | +	$(call Device/FitImage) | ||||||
|  | +	IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | append-metadata | ||||||
|  | +endef | ||||||
|  | +TARGET_DEVICES += um-325ac | ||||||
|  | diff --git a/target/linux/ipq40xx/patches-5.4/911-dts-ipq4019-indio-um-325ac.patch b/target/linux/ipq40xx/patches-5.4/911-dts-ipq4019-indio-um-325ac.patch | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..5c591e1a47 | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/target/linux/ipq40xx/patches-5.4/911-dts-ipq4019-indio-um-325ac.patch | ||||||
|  | @@ -0,0 +1,13 @@ | ||||||
|  | +diff -Nurb a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile | ||||||
|  | +--- a/arch/arm/boot/dts/Makefile	2022-03-21 14:59:54.834759752 +0000 | ||||||
|  | ++++ b/arch/arm/boot/dts/Makefile	2022-03-21 15:01:21.535371530 +0000 | ||||||
|  | +@@ -906,7 +906,8 @@ | ||||||
|  | + 	qcom-msm8974-sony-xperia-amami.dtb \ | ||||||
|  | + 	qcom-msm8974-sony-xperia-castor.dtb \ | ||||||
|  | + 	qcom-msm8974-sony-xperia-honami.dtb \ | ||||||
|  | +-	qcom-mdm9615-wp8548-mangoh-green.dtb | ||||||
|  | ++	qcom-mdm9615-wp8548-mangoh-green.dtb \ | ||||||
|  | ++	qcom-ipq4019-um-325ac.dtb | ||||||
|  | + dtb-$(CONFIG_ARCH_RDA) += \ | ||||||
|  | + 	rda8810pl-orangepi-2g-iot.dtb \ | ||||||
|  | + 	rda8810pl-orangepi-i96.dtb | ||||||
|  | --  | ||||||
|  | 2.25.1 | ||||||
|  |  | ||||||
							
								
								
									
										1052
									
								
								patches/ipq40xx/0015-ipq40xx-add-support-for-udaya-a5-id2.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1052
									
								
								patches/ipq40xx/0015-ipq40xx-add-support-for-udaya-a5-id2.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,7 +1,7 @@ | |||||||
| From 2858efa76a021729e068e45675c86f670674aa16 Mon Sep 17 00:00:00 2001 | From a42b4b5273ed91281c046939492d5bb02b0ca3fa Mon Sep 17 00:00:00 2001 | ||||||
| From: John Crispin <john@phrozen.org> | From: John Crispin <john@phrozen.org> | ||||||
| Date: Fri, 7 Jan 2022 10:58:08 +0100 | Date: Fri, 7 Jan 2022 10:58:08 +0100 | ||||||
| Subject: [PATCH] ramips: add support for actiontec web7200 | Subject: [PATCH 06/14] ramips: add support for actiontec web7200 | ||||||
|  |  | ||||||
| Signed-off-by: John Crispin <john@phrozen.org> | Signed-off-by: John Crispin <john@phrozen.org> | ||||||
| --- | --- | ||||||
| @@ -34,7 +34,7 @@ Signed-off-by: John Crispin <john@phrozen.org> | |||||||
|  create mode 100644 target/linux/ramips/patches-5.4/499-mtd-add-nmbm-support.patch |  create mode 100644 target/linux/ramips/patches-5.4/499-mtd-add-nmbm-support.patch | ||||||
|  |  | ||||||
| diff --git a/package/boot/uboot-envtools/files/ramips b/package/boot/uboot-envtools/files/ramips | diff --git a/package/boot/uboot-envtools/files/ramips b/package/boot/uboot-envtools/files/ramips | ||||||
| index 33af86c846..ce389d6ef8 100644 | index 33af86c846..c13ee08103 100644 | ||||||
| --- a/package/boot/uboot-envtools/files/ramips | --- a/package/boot/uboot-envtools/files/ramips | ||||||
| +++ b/package/boot/uboot-envtools/files/ramips | +++ b/package/boot/uboot-envtools/files/ramips | ||||||
| @@ -13,6 +13,9 @@ touch /etc/config/ubootenv | @@ -13,6 +13,9 @@ touch /etc/config/ubootenv | ||||||
| @@ -42,7 +42,7 @@ index 33af86c846..ce389d6ef8 100644 | |||||||
|   |   | ||||||
|  case "$board" in |  case "$board" in | ||||||
| +actiontec,web7200) | +actiontec,web7200) | ||||||
| +	ubootenv_add_uci_config "/dev/mtd2" "0x0" "0x20000" "0x20000" | +	ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x20000" "0x20000" | ||||||
| +	;; | +	;; | ||||||
|  alfa-network,ac1200rm|\ |  alfa-network,ac1200rm|\ | ||||||
|  alfa-network,awusfree1|\ |  alfa-network,awusfree1|\ | ||||||
| @@ -3196,7 +3196,7 @@ index 0000000000..18dfb6adda | |||||||
| +#include "nmbm-debug.inl" | +#include "nmbm-debug.inl" | ||||||
| diff --git a/target/linux/ramips/files/drivers/mtd/nmbm/nmbm-debug.h b/target/linux/ramips/files/drivers/mtd/nmbm/nmbm-debug.h | diff --git a/target/linux/ramips/files/drivers/mtd/nmbm/nmbm-debug.h b/target/linux/ramips/files/drivers/mtd/nmbm/nmbm-debug.h | ||||||
| new file mode 100644 | new file mode 100644 | ||||||
| index 0000000000..582118333e | index 0000000000..7f9dfed9e1 | ||||||
| --- /dev/null | --- /dev/null | ||||||
| +++ b/target/linux/ramips/files/drivers/mtd/nmbm/nmbm-debug.h | +++ b/target/linux/ramips/files/drivers/mtd/nmbm/nmbm-debug.h | ||||||
| @@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2740
									
								
								patches/ramips/0008-ramips-move-mt7621_nand-driver-to-files.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2740
									
								
								patches/ramips/0008-ramips-move-mt7621_nand-driver-to-files.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | From 8ff3f57a88d867d48c2a38876baf9b389d7441df Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Stijn Tintel <stijn@linux-ipv6.be> | ||||||
|  | Date: Wed, 19 Jan 2022 17:59:51 +0200 | ||||||
|  | Subject: [PATCH 09/14] ramips: mt7621_nand: reduce log verbosity | ||||||
|  |  | ||||||
|  | Avoid flooding the log with the message below by increasing the log | ||||||
|  | level to debug: | ||||||
|  |  | ||||||
|  |   mt7621-nand 1e003000.nand: Using programmed access timing: 31c07388 | ||||||
|  |  | ||||||
|  | Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be> | ||||||
|  | --- | ||||||
|  |  target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | 2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | diff --git a/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c b/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | ||||||
|  | index 678295a68d..16493a2e97 100644 | ||||||
|  | --- a/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | ||||||
|  | +++ b/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | ||||||
|  | @@ -759,7 +759,7 @@ static int mt7621_nfc_setup_data_interface(struct nand_chip *nand, int csline, | ||||||
|  |   | ||||||
|  |  	acccon = ACCTIMING(tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt); | ||||||
|  |   | ||||||
|  | -	dev_info(nfc->dev, "Using programmed access timing: %08x\n", acccon); | ||||||
|  | +	dev_dbg(nfc->dev, "Using programmed access timing: %08x\n", acccon); | ||||||
|  |   | ||||||
|  |  	nfi_write32(nfc, NFI_ACCCON, acccon); | ||||||
|  |   | ||||||
|  | --  | ||||||
|  | 2.25.1 | ||||||
|  |  | ||||||
| @@ -0,0 +1,44 @@ | |||||||
|  | From 10d63c9973b9598a065244e9752db7aa3d78a93f Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Felix Fietkau <nbd@nbd.name> | ||||||
|  | Date: Wed, 9 Mar 2022 20:46:21 +0100 | ||||||
|  | Subject: [PATCH 10/14] ramips: mt7621_nand: initialize ECC_FDMADDR | ||||||
|  |  | ||||||
|  | This is needed for the ECC controller to access FDM data | ||||||
|  |  | ||||||
|  | Signed-off-by: Felix Fietkau <nbd@nbd.name> | ||||||
|  | --- | ||||||
|  |  target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | 4 ++++ | ||||||
|  |  1 file changed, 4 insertions(+) | ||||||
|  |  | ||||||
|  | diff --git a/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c b/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | ||||||
|  | index 16493a2e97..0751e59c37 100644 | ||||||
|  | --- a/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | ||||||
|  | +++ b/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | ||||||
|  | @@ -214,6 +214,7 @@ struct mt7621_nfc { | ||||||
|  |  	struct clk *nfi_clk; | ||||||
|  |  	struct device *dev; | ||||||
|  |   | ||||||
|  | +	u32 nfi_base; | ||||||
|  |  	void __iomem *nfi_regs; | ||||||
|  |  	void __iomem *ecc_regs; | ||||||
|  |   | ||||||
|  | @@ -860,6 +861,8 @@ static int mt7621_nfc_ecc_init(struct mt7621_nfc *nfc) | ||||||
|  |  		     (decode_block_size << DEC_CS_S) | | ||||||
|  |  		     (DEC_CON_EL << DEC_CON_S) | DEC_EMPTY_EN; | ||||||
|  |   | ||||||
|  | +	ecc_write32(nfc, ECC_FDMADDR, nfc->nfi_base + NFI_FDML(0)); | ||||||
|  | + | ||||||
|  |  	mt7621_ecc_encoder_op(nfc, false); | ||||||
|  |  	ecc_write32(nfc, ECC_ENCCNFG, ecc_enccfg); | ||||||
|  |   | ||||||
|  | @@ -1277,6 +1280,7 @@ static int mt7621_nfc_probe(struct platform_device *pdev) | ||||||
|  |  	nfc->dev = dev; | ||||||
|  |   | ||||||
|  |  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nfi"); | ||||||
|  | +	nfc->nfi_base = res->start; | ||||||
|  |  	nfc->nfi_regs = devm_ioremap_resource(dev, res); | ||||||
|  |  	if (IS_ERR(nfc->nfi_regs)) { | ||||||
|  |  		ret = PTR_ERR(nfc->nfi_regs); | ||||||
|  | --  | ||||||
|  | 2.25.1 | ||||||
|  |  | ||||||
| @@ -0,0 +1,51 @@ | |||||||
|  | From bee84b6606374bb887e70e263419b19e112f1b5c Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Felix Fietkau <nbd@nbd.name> | ||||||
|  | Date: Thu, 10 Mar 2022 11:45:00 +0100 | ||||||
|  | Subject: [PATCH 11/14] ramips: enable support for mtk_bmt in the nand flash | ||||||
|  |  driver | ||||||
|  |  | ||||||
|  | Signed-off-by: Felix Fietkau <nbd@nbd.name> | ||||||
|  | --- | ||||||
|  |  .../linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | 8 ++++++++ | ||||||
|  |  1 file changed, 8 insertions(+) | ||||||
|  |  | ||||||
|  | diff --git a/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c b/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | ||||||
|  | index 0751e59c37..1072450898 100644 | ||||||
|  | --- a/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | ||||||
|  | +++ b/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | ||||||
|  | @@ -18,6 +18,7 @@ | ||||||
|  |  #include <linux/mtd/mtd.h> | ||||||
|  |  #include <linux/mtd/rawnand.h> | ||||||
|  |  #include <linux/mtd/partitions.h> | ||||||
|  | +#include <linux/mtd/mtk_bmt.h> | ||||||
|  |  #include <linux/platform_device.h> | ||||||
|  |  #include <asm/addrspace.h> | ||||||
|  |   | ||||||
|  | @@ -1254,9 +1255,12 @@ static int mt7621_nfc_init_chip(struct mt7621_nfc *nfc) | ||||||
|  |  	if (ret) | ||||||
|  |  		return ret; | ||||||
|  |   | ||||||
|  | +	mtk_bmt_attach(mtd); | ||||||
|  | + | ||||||
|  |  	ret = mtd_device_register(mtd, NULL, 0); | ||||||
|  |  	if (ret) { | ||||||
|  |  		dev_err(nfc->dev, "Failed to register MTD: %d\n", ret); | ||||||
|  | +		mtk_bmt_detach(mtd); | ||||||
|  |  		nand_release(nand); | ||||||
|  |  		return ret; | ||||||
|  |  	} | ||||||
|  | @@ -1325,7 +1329,11 @@ clk_disable: | ||||||
|  |  static int mt7621_nfc_remove(struct platform_device *pdev) | ||||||
|  |  { | ||||||
|  |  	struct mt7621_nfc *nfc = platform_get_drvdata(pdev); | ||||||
|  | +	struct nand_chip *nand = &nfc->nand; | ||||||
|  | +	struct mtd_info *mtd = nand_to_mtd(nand); | ||||||
|  |   | ||||||
|  | +	mtk_bmt_detach(mtd); | ||||||
|  | +	mtd_device_unregister(mtd); | ||||||
|  |  	nand_release(&nfc->nand); | ||||||
|  |  	clk_disable_unprepare(nfc->nfi_clk); | ||||||
|  |   | ||||||
|  | --  | ||||||
|  | 2.25.1 | ||||||
|  |  | ||||||
							
								
								
									
										29
									
								
								patches/ramips/0012-ramips-skip-bbt-scan-on-mt7621.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								patches/ramips/0012-ramips-skip-bbt-scan-on-mt7621.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | From 806708eed0809c9ee07cbcff1285a64c9767242f Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Felix Fietkau <nbd@nbd.name> | ||||||
|  | Date: Thu, 10 Mar 2022 15:20:29 +0100 | ||||||
|  | Subject: [PATCH 12/14] ramips: skip bbt scan on mt7621 | ||||||
|  |  | ||||||
|  | reduces unnecessary flash reads and speeds up boot time | ||||||
|  |  | ||||||
|  | Signed-off-by: Felix Fietkau <nbd@nbd.name> | ||||||
|  | --- | ||||||
|  |  target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | 3 ++- | ||||||
|  |  1 file changed, 2 insertions(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | diff --git a/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c b/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | ||||||
|  | index 1072450898..f01e1e8a8e 100644 | ||||||
|  | --- a/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | ||||||
|  | +++ b/target/linux/ramips/files/drivers/mtd/nand/raw/mt7621_nand.c | ||||||
|  | @@ -1229,7 +1229,8 @@ static int mt7621_nfc_init_chip(struct mt7621_nfc *nfc) | ||||||
|  |  	nand_set_controller_data(nand, (void *)nfc); | ||||||
|  |  	nand_set_flash_node(nand, nfc->dev->of_node); | ||||||
|  |   | ||||||
|  | -	nand->options |= NAND_USE_BOUNCE_BUFFER | NAND_NO_SUBPAGE_WRITE; | ||||||
|  | +	nand->options |= NAND_USE_BOUNCE_BUFFER | NAND_NO_SUBPAGE_WRITE | | ||||||
|  | +			 NAND_SKIP_BBTSCAN; | ||||||
|  |  	if (!nfc->nfi_clk) | ||||||
|  |  		nand->options |= NAND_KEEP_TIMINGS; | ||||||
|  |   | ||||||
|  | --  | ||||||
|  | 2.25.1 | ||||||
|  |  | ||||||
| @@ -0,0 +1,48 @@ | |||||||
|  | From 9f51c3956a80205006dc6a686d80969bd3b42ecb Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Felix Fietkau <nbd@nbd.name> | ||||||
|  | Date: Thu, 10 Mar 2022 17:32:20 +0100 | ||||||
|  | Subject: [PATCH 13/14] kernel: mtdsplit: support UBI after FIT images | ||||||
|  |  | ||||||
|  | Change the partition name accordingly. Same behavior as mtdsplit_uimage | ||||||
|  |  | ||||||
|  | Signed-off-by: Felix Fietkau <nbd@nbd.name> | ||||||
|  | --- | ||||||
|  |  .../generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c     | 8 ++++++-- | ||||||
|  |  1 file changed, 6 insertions(+), 2 deletions(-) | ||||||
|  |  | ||||||
|  | diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c | ||||||
|  | index 5cc1658dbd..f043428949 100644 | ||||||
|  | --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c | ||||||
|  | +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c | ||||||
|  | @@ -57,6 +57,7 @@ mtdsplit_fit_parse(struct mtd_info *mtd, | ||||||
|  |  	size_t fit_offset, fit_size; | ||||||
|  |  	size_t rootfs_offset, rootfs_size; | ||||||
|  |  	struct mtd_partition *parts; | ||||||
|  | +	enum mtdsplit_part_type type; | ||||||
|  |  	int ret; | ||||||
|  |   | ||||||
|  |  	of_property_read_string(np, "openwrt,cmdline-match", &cmdline_match); | ||||||
|  | @@ -101,7 +102,7 @@ mtdsplit_fit_parse(struct mtd_info *mtd, | ||||||
|  |   | ||||||
|  |  	/* Search for the rootfs partition after the FIT image */ | ||||||
|  |  	ret = mtd_find_rootfs_from(mtd, fit_offset + fit_size, mtd->size, | ||||||
|  | -				   &rootfs_offset, NULL); | ||||||
|  | +				   &rootfs_offset, &type); | ||||||
|  |  	if (ret) { | ||||||
|  |  		pr_info("no rootfs found after FIT image in \"%s\"\n", | ||||||
|  |  			mtd->name); | ||||||
|  | @@ -118,7 +119,10 @@ mtdsplit_fit_parse(struct mtd_info *mtd, | ||||||
|  |  	parts[0].offset = fit_offset; | ||||||
|  |  	parts[0].size = mtd_rounddown_to_eb(fit_size, mtd) + mtd->erasesize; | ||||||
|  |   | ||||||
|  | -	parts[1].name = ROOTFS_PART_NAME; | ||||||
|  | +	if (type == MTDSPLIT_PART_TYPE_UBI) | ||||||
|  | +		parts[1].name = UBI_PART_NAME; | ||||||
|  | +	else | ||||||
|  | +		parts[1].name = ROOTFS_PART_NAME; | ||||||
|  |  	parts[1].offset = rootfs_offset; | ||||||
|  |  	parts[1].size = rootfs_size; | ||||||
|  |   | ||||||
|  | --  | ||||||
|  | 2.25.1 | ||||||
|  |  | ||||||
							
								
								
									
										4429
									
								
								patches/ramips/0014-update-actiontec-web7200-support.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4429
									
								
								patches/ramips/0014-update-actiontec-web7200-support.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | From ca20a7eabdc16821973945a01a7ef340293a0f74 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Chen Minqiang <ptpt52@gmail.com> | ||||||
|  | Date: Fri, 31 Dec 2021 05:37:55 +0800 | ||||||
|  | Subject: [PATCH 1/2] hostapd: Fix ap+sta channel setup issue | ||||||
|  |  | ||||||
|  | Signed-off-by: Chen Minqiang <ptpt52@gmail.com> | ||||||
|  | --- | ||||||
|  |  .../800-fix-ap-sta-channel-setup-failed.patch | 29 +++++++++++++++++++ | ||||||
|  |  1 file changed, 29 insertions(+) | ||||||
|  |  create mode 100644 package/network/services/hostapd/patches/800-fix-ap-sta-channel-setup-failed.patch | ||||||
|  |  | ||||||
|  | diff --git a/package/network/services/hostapd/patches/800-fix-ap-sta-channel-setup-failed.patch b/package/network/services/hostapd/patches/800-fix-ap-sta-channel-setup-failed.patch | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..de7a611587 | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/package/network/services/hostapd/patches/800-fix-ap-sta-channel-setup-failed.patch | ||||||
|  | @@ -0,0 +1,29 @@ | ||||||
|  | +diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c | ||||||
|  | +index ad2aebf..355b4a8 100644 | ||||||
|  | +--- a/src/common/hw_features_common.c | ||||||
|  | ++++ b/src/common/hw_features_common.c | ||||||
|  | +@@ -615,9 +615,21 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, | ||||||
|  | + 			    center_segment0 == channel - 6) | ||||||
|  | + 				data->center_freq1 = 5000 + center_segment0 * 5; | ||||||
|  | + 			else { | ||||||
|  | +-				wpa_printf(MSG_ERROR, | ||||||
|  | +-					   "Wrong coupling between HT and VHT/HE channel setting"); | ||||||
|  | +-				return -1; | ||||||
|  | ++				if (channel <= 48) | ||||||
|  | ++					center_segment0 = 42; | ||||||
|  | ++				else if (channel <= 64) | ||||||
|  | ++					center_segment0 = 58; | ||||||
|  | ++				else if (channel <= 112) | ||||||
|  | ++					center_segment0 = 106; | ||||||
|  | ++				else if (channel <= 128) | ||||||
|  | ++					center_segment0 = 122; | ||||||
|  | ++				else if (channel <= 144) | ||||||
|  | ++					center_segment0 = 138; | ||||||
|  | ++				else if (channel <= 161) | ||||||
|  | ++					center_segment0 = 155; | ||||||
|  | ++				else if (channel <= 177) | ||||||
|  | ++					center_segment0 = 171; | ||||||
|  | ++				data->center_freq1 = 5000 + center_segment0 * 5; | ||||||
|  | + 			} | ||||||
|  | + 		} | ||||||
|  | + 		break; | ||||||
|  | --  | ||||||
|  | 2.25.1 | ||||||
|  |  | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user