Homepage
Privacy Policy
iYoRoy DN42 Network
About
More
Friends
Language
简体中文
English
Search
1
Centralized Deployment of EasyTier using Docker
1,705 Views
2
Adding KernelSU Support to Android 4.9 Kernel
1,091 Views
3
Enabling EROFS Support for an Android ROM with Kernel 4.9
309 Views
4
Installing 1Panel Using Docker on TrueNAS
300 Views
5
2025 Yangcheng Cup CTF Preliminary WriteUp
296 Views
Android
Ops
NAS
Develop
Network
Projects
DN42
One Man ISP
CTF
Kubernetes
Cybersecurity
Brain Dumps
IoT
Login
Search
Search Tags
Network Technology
BGP
BIRD
Linux
DN42
Android
OSPF
C&C++
Web
AOSP
CTF
Cybersecurity
Docker
iBGP
Windows
MSVC
Services
Kernel
IGP
TrueNAS
Kagura iYoRoy
A total of
35
articles have been written.
A total of
23
comments have been received.
Index
Column
Android
Ops
NAS
Develop
Network
Projects
DN42
One Man ISP
CTF
Kubernetes
Cybersecurity
Brain Dumps
IoT
Pages
Privacy Policy
iYoRoy DN42 Network
About
Friends
Language
简体中文
English
35
articles related to
were found.
Home Network Upgrade – GPON Stick + 802.11k/v/r Roaming
The beginning of the article explains the process of configuring a GPON stick and BE10000 PPPoE. If you only need information about 802.11k/v/r, you can jump to the "Configuring 802.11k/v/r" section. The reason for this project goes back to the Labour Day holiday, when I picked up a Xiaomi BE10000 locally in Harbin. I wanted to try a GPON stick to see if I could push my home gigabit broadband beyond 1 Gbps (ref: Zhejiang Mobile FiberHome GPON super admin password + G-010S-A GPON stick internet access – Milu’s Blog (Chinese)). Because I use mesh-like tools such as EasyTier and need features like Wake-on-LAN, and my existing Xiaomi AX3600 already runs ImmortalWRT, I hoped to flash a WRT-based system and then use 802.11k/v/r to achieve automatic handover, essentially building a manual mesh. After searching, it seemed only the BE10000 met my requirements: it has an SFP+ cage and can be flashed with QWRT. I brought it home during the summer break – time to tinker! I already fixed its one imperfection – the NFC tap-to-connect – while I was at university (ref: Adapting NFC for Xiaomi BE10000 on QWRT – Yousheng's Dev Diary (Chinese)), so the device is now complete (nod) Glossary 1. Broadband & Optical Communication (Fiber & PON) Abbreviation Full Name Explanation / Notes FTTH Fiber To The Home Fiber optic connection directly to the home. PON Passive Optical Network Mainstream technology for residential broadband access. GPON Gigabit-Capable PON Gigabit Passive Optical Network. The GPON Stick you use is based on this standard. OLT Optical Line Terminal The ISP’s central office equipment that distributes optical signals downstream. ONU Optical Network Unit Customer premises equipment, such as an optical modem or GPON stick. UPC Ultra Physical Contact A common fiber connector type (usually a blue end-face). APC Angled Physical Contact Another common fiber connector type (usually a green end-face with an 8-degree angle). LOID Logical ONU ID A string of characters the ISP uses to authenticate the ONU. PLOAM Physical Layer OAM Physical Layer Operations, Administration and Maintenance; also a password system used for ONU authentication. SN Serial Number The hardware’s unique factory serial number, often used for ONU registration. 2. Wireless LAN & Roaming (Wi-Fi & Roaming) Abbreviation Full Name Explanation / Notes AP Access Point The role a primary or secondary router plays when emitting Wi-Fi signals. SSID Service Set Identifier The Wi-Fi network name you see. BSS Basic Service Set A single AP and all devices connected within its coverage area. BSSID Basic Service Set Identifier Usually the MAC address of the AP’s wireless interface. ESS Extended Service Set Multiple BSSs forming a unified network (same SSID) – i.e., a roaming environment. RRM Radio Resource Management 802.11k – used to obtain neighbor reports about surrounding APs. WNM Wireless Network Management 802.11v – allows an AP to send roaming guidance suggestions to clients. FT Fast Transition 802.11r – reduces handshake and authentication time when a client switches APs. DS Distribution System The wired network backbone; ft_over_ds means roaming information is exchanged over the wired backbone. NAS ID Network Access Server Identifier Uniquely identifies a BSS node within a roaming domain. SAE Simultaneous Authentication of Equals The key exchange protocol for WPA3, more secure than WPA2. PSK Pre-Shared Key The most common home Wi-Fi authentication method, where you enter a password. 3. Network Protocols & System Settings Abbreviation Full Name Explanation / Notes PPPoE Point-to-Point Protocol over Ethernet The commonly used broadband dial-up protocol. VLAN / PVID Virtual Local Area Network / Port VLAN ID Used to isolate network traffic; essential for GPON stick dial-up. SFP+ Enhanced Small Form-factor Pluggable An enhanced hot-pluggable optical module interface supporting up to 10 Gbps. UCI Unified Configuration Interface The underlying command-line configuration system for OpenWrt/QWRT. LuCI Lua Configuration Interface The web-based graphical configuration interface for OpenWrt/QWRT. DHCP Dynamic Host Configuration Protocol Protocol for automatically assigning IP addresses to devices on the LAN. L2 Layer 2 The data link layer. “L2 segment” in this article refers to a LAN within the same broadcast domain. Preparation Xiaomi BE10000 Router Xiaomi AX3600 Router G-010S-A NOKIA GPON Stick Heatsinks SC/APC to SC/UPC fiber patch cable SC/UPC fiber adapter Flashing resources (find them yourself – redistributing others’ work isn’t ideal. You can refer to the firmware mentioned in the flashing tutorial below.) Regarding that SC/APC to SC/UPC fiber cable, it describes the connector specifications. Typical residential FTTH usually uses UPC (blue connector), whereas the GPON sticks we buy almost always have an APC (green) connector. The main difference is the end-face shape: UPC is slightly domed outwards, APC is cut at an angle. If the ISP's OLT downstream optical power is strong enough, you could connect UPC directly to the stick, but you’d get about 3 dB of extra loss. So I decided to play it safe. Image source: Differences between PC, UPC and APC fiber connectors – Zhihu (Chinese) GPON sticks are notorious for running hot, so remember to attach heatsinks: After attaching them, I saw temperatures of around 60 °C in the stick’s management console. Flashing the BE10000 No need to elaborate here – just follow Flashing OpenWrt on Xiaomi 10G Router | Xiaomi BE10000 | SSH Unlock | UBoot | iStore | Multi-WAN – Right.com.cn Forum (Chinese). The firmware has some known bugs. For example, Wi-Fi settings configured through the front-end may fail to write correctly, causing the entire network subsystem to crash, the router to become unreachable, and eventually triggering an automatic fallback. That’s why some of the modifications below are done using UCI commands. Obtaining ISP ONU Configuration There is no universal guide for this step… Buy a super admin password from Xianyu or Taobao, and record the LOID, SN, LOID CheckCode (Password), PLOAM Password, and the VLAN ID of the Internet connection. Some regions may also require you to record the upstream MAC address. LOID and LOID CheckCode: PLOAM Password: VLAN ID: Generally, ISPs use LOID together with a possible LOID CheckCode (Password), or they might use PLOAM Password. Decide based on your situation. In my case (Anhui Unicom), I only needed to record SN, VLAN ID, and LOID and everything worked. (I couldn’t log into the Unicom ONT, so I used a Mobile one for these screenshots, lol.) Sometimes you don’t even need the super admin password; some ONTs (e.g., Skyworth models for Heilongjiang Unicom) display this information even for a regular user. Also, record your PPPoE username and password: Generally the username is visible. On some ONTs you can reveal the password by using F12 to remove the password attribute; others send back meaningless placeholders. In that case, call your ISP to reset the password. Configuring the GPON Stick Insert the GPON Stick into the SFP+ port. If the port LED doesn’t light up, try going to QWRT → Network → ECM Hardware Acceleration Settings and force the SFP1 and SFP2 interface speeds to Force 2.5Gbps. (I couldn’t be sure which one corresponds to the active SFP port, so I changed both.) Save & apply, and you may need to reboot the router. The default br-lan IP prefix should be 192.168.1.0/24. Keep it unchanged and access 192.168.1.10 to open the stick’s management console: Find GPON ONU Settings and fill in the information you recorded earlier: LOID and SN Also enable VLAN configuration: Tick Interoperability Compatible Mode, and fill in the VLAN ID under PVID. You may need to reboot the stick after saving. Then go to the status page. If you see the PON authentication status / signal status as O5, the stick has successfully registered and is working. Configuring Dial-Up (PPPoE) On the BE10000, the default WAN port is eth4, while the SFP port is eth5. You need to switch the WAN from eth4 to eth5. Go to Network → Interfaces → Devices, locate br-lan, and add eth4 to it while removing eth5. Then go to the Interfaces page, change the WAN device to eth5, and enter your PPPoE username and password: After saving, you should see that PPPoE has dialled successfully and you can access the internet: (I changed the entire br-lan subnet to 192.168.3.0/24 – this step is not mandatory.) Modifying Basic Wi-Fi Settings As I discovered, modifying Wi-Fi settings directly through LuCI on the main router fails to write correctly (as mentioned above). Therefore, modify them via SSH using UCI: # Set main router Wi-Fi info uci set wireless.ath0.ssid='[CENSORED]' uci set wireless.ath0.encryption='psk2+ccmp' uci set wireless.ath0.sae='1' uci set wireless.ath0.key='[CENSORED]' uci set wireless.ath1.ssid='[CENSORED]' uci set wireless.ath1.encryption='psk2+ccmp' uci set wireless.ath1.sae='1' uci set wireless.ath1.key='[CENSORED]' uci set wireless.ath2.ssid='[CENSORED]' uci set wireless.ath2.encryption='psk2+ccmp' uci set wireless.ath2.sae='1' uci set wireless.ath2.key='[CENSORED]' uci commit wireless wifi reload Here SSID is the Wi-Fi name, and encryption value psk2+ccmp represents WPA2-PSK/WPA3-SAE Mixed Mode. For the secondary router, because we are setting up roaming, both Wi-Fi networks must be on the same L2 segment. Thus, you must disable its DHCP server and configure the secondary router as a device under the main router. The steps for the secondary router are: Delete all other interfaces under Network → Interfaces → Interfaces, keeping only br-lan: Under Network → Interfaces → Devices, add the wan port to the br-lan device: Assign an IP address to br-lan under Network → Interfaces → Devices: Remember to include the netmask for the IPv4 address, and set the IPv4 gateway to the main router’s IP. Under Network → Firewall → General Settings, adjust the firewall rules accordingly. (btw, I was too lazy to configure detailed rules and assumed the internal network devices aren’t a huge risk, so I allowed everything. Don’t copy this if you have specific security needs, lol.) After saving and applying, you should be able to connect to the main router and access the secondary router using the IP you just set. On the secondary router, go to Network → Wireless and configure each SSID interface to match the main router’s settings: At this point, both Wi-Fi radios should be working (even with the same SSID) and they will be on the same channel. Configuring 802.11k/v/r Main Router # Main router 802.11k/v/r configuration # ath0 (2.4 GHz) uci set wireless.ath0.ieee80211k='1' uci set wireless.ath0.rrm_neighbor_report='1' uci set wireless.ath0.rrm_beacon_report='1' uci set wireless.ath0.ieee80211v='1' uci set wireless.ath0.time_advertisement='0' uci set wireless.ath0.wnm_sleep_mode='0' uci set wireless.ath0.bss_transition='1' uci set wireless.ath0.ieee80211r='1' uci set wireless.ath0.nasid='Master_2_4G' uci set wireless.ath0.mobility_domain='cafe' uci set wireless.ath0.reassociation_deadline='1000' uci set wireless.ath0.ft_over_ds='0' uci set wireless.ath0.ft_psk_generate_local='1' # ath1 (5G-1) uci set wireless.ath1.ieee80211k='1' uci set wireless.ath1.rrm_neighbor_report='1' uci set wireless.ath1.rrm_beacon_report='1' uci set wireless.ath1.ieee80211v='1' uci set wireless.ath1.time_advertisement='0' uci set wireless.ath1.wnm_sleep_mode='0' uci set wireless.ath1.bss_transition='1' uci set wireless.ath1.ieee80211r='1' uci set wireless.ath1.nasid='Master_5G' uci set wireless.ath1.mobility_domain='cafe' uci set wireless.ath1.reassociation_deadline='1000' uci set wireless.ath1.ft_over_ds='0' uci set wireless.ath1.ft_psk_generate_local='1' # ath2 (5G-2) uci set wireless.ath2.ieee80211k='1' uci set wireless.ath2.rrm_neighbor_report='1' uci set wireless.ath2.rrm_beacon_report='1' uci set wireless.ath2.ieee80211v='1' uci set wireless.ath2.time_advertisement='0' uci set wireless.ath2.wnm_sleep_mode='0' uci set wireless.ath2.bss_transition='1' uci set wireless.ath2.ieee80211r='1' uci set wireless.ath2.nasid='Master_5G2' uci set wireless.ath2.mobility_domain='cafe' uci set wireless.ath2.reassociation_deadline='1000' uci set wireless.ath2.ft_over_ds='0' uci set wireless.ath2.ft_psk_generate_local='1' uci commit wireless wifi reload Note: 802.11k/v/r does not force clients to roam proactively; the client still makes the final decision. The AP only provides neighbor information, roaming suggestions, and fast re-association capabilities using these protocols. Support varies across different phones, PCs, and IoT devices. The configuration above covers three wireless interfaces: ath0: Main router 2.4 GHz ath1: Main router 5 GHz-1 ath2: Main router 5 GHz-2 All three follow the same logic, differing only in nasid. 1. 802.11k: Radio Resource Measurement / Neighbor Report Relevant settings: uci set wireless.ath0.ieee80211k='1' uci set wireless.ath0.rrm_neighbor_report='1' uci set wireless.ath0.rrm_beacon_report='1' 1.1 ieee80211k='1' Enables 802.11k Radio Resource Management. 802.11k allows the AP to provide clients with information about neighboring APs, so they don't need to blindly scan all channels. Clients can use the neighbor list to quickly find a suitable target for roaming. In short: 802.11k lets the client know "which APs with the same SSID are nearby and available to switch to". Without 802.11k, a client typically scans channels by itself, which takes time and can cause brief lag. When enabled, compatible clients can obtain candidate AP information much faster. 1.2 rrm_neighbor_report='1' Enables Neighbor Report. This is the most common and critical capability of 802.11k. The AP provides the client with details about neighboring BSSs, such as: BSSID of the neighboring AP Operating channel PHY type Whether it belongs to the current ESS Supported roaming capabilities In short: This parameter lets the AP tell the client: "Here are the other APs nearby, and they are on these channels." This is crucial for multi-AP roaming because the client can scan only the suggested channels instead of sweeping from channel 1 to 165. 1.3 rrm_beacon_report='1' Enables Beacon Report support. Beacon Report allows the AP to request that the client report back the beacons it has observed. In other words, the client can tell the AP: Which APs it sees Their signal strengths Their channels A rough picture of the current wireless environment In short: Neighbor Report is the AP telling the client what’s nearby; Beacon Report is the client telling the AP what it sees. In a typical home network, rrm_neighbor_report is more directly useful; rrm_beacon_report is a supplementary capability – just enable it. 2. 802.11v: BSS Transition / Roaming Guidance Relevant settings: uci set wireless.ath0.ieee80211v='1' uci set wireless.ath0.time_advertisement='0' uci set wireless.ath0.wnm_sleep_mode='0' uci set wireless.ath0.bss_transition='1' 2.1 ieee80211v='1' Enables 802.11v Wireless Network Management. The most relevant part for home Wi-Fi roaming is BSS Transition Management. In short: 802.11v lets the AP suggest to a client: "I recommend you switch to another AP." This is only a suggestion, not an order. The client can accept or refuse. For example, if the client is still attached to the main router but is already physically near the secondary router, the AP can use 802.11v to inform it: "Your signal to this AP is now mediocre; consider moving to the other one." Enabling 802.11v helps with the "sticky client" problem, but there’s no guarantee all devices will obey. 2.2 bss_transition='1' Enables BSS Transition Management. This is the key roaming-related feature of 802.11v. When enabled, the AP can send a BSS Transition Management Request to the client, typically containing a list of recommended target APs. In short: ieee80211v is the master switch for 802.11v; bss_transition turns on the actual roaming suggestion function. If you enable ieee80211v but not bss_transition, the roaming guidance effect may be incomplete. 2.3 time_advertisement='0' Disables Time Advertisement. 802.11v includes a Time Advertisement feature where the AP can broadcast time information. For home roaming, you generally don't need the AP to provide time sync, so set it to 0. 2.4 wnm_sleep_mode='0' Disables WNM Sleep Mode. WNM Sleep Mode is part of 802.11v, mainly used for client power saving. The client can enter a special sleep state while the AP retains some context. Home routers and multi-AP roaming generally don’t rely on this, and some devices have compatibility issues, so it’s turned off. 3. 802.11r: Fast Transition / Fast Roaming Relevant settings: uci set wireless.ath0.ieee80211r='1' uci set wireless.ath0.mobility_domain='cafe' uci set wireless.ath0.reassociation_deadline='1000' uci set wireless.ath0.ft_over_ds='0' uci set wireless.ath0.ft_psk_generate_local='1' 3.1 ieee80211r='1' Enables 802.11r Fast BSS Transition. 802.11r shortens the authentication and re-association time when a client moves from one AP to another. Without it, the client may need to complete a full authentication cycle. 802.11r pre-derives some key material so the handover is faster. It does not decide when to roam, but once the client decides to roam, it makes the process quicker. Suitable for: Moving between rooms with a phone Voice calls Video conferences Gaming Multi-AP environments with the same SSID Be aware: Most new devices support 802.11r Some older or less compatible IoT devices may dislike 802.11r If a device fails to connect, suspect 802.11r compatibility first 3.2 mobility_domain='cafe' Sets the Mobility Domain, an 802.11r roaming domain identifier. Only APs sharing the same Mobility Domain are considered part of the same fast-roaming group by clients. All APs participating in 802.11r fast roaming under the same SSID must use the same mobility_domain. Here we use: uci set wireless.ath0.mobility_domain='cafe' cafe is a 16-bit hexadecimal value (4 hex characters), similar to magic numbers like DEADBEEF. You can customize it, for example: mobility_domain='1234' mobility_domain='abcd' mobility_domain='beef' But remember: Must be consistent within the same roaming network Different independent networks can differ Must be exactly 4 hex characters 3.3 reassociation_deadline='1000' Sets the Reassociation Deadline. This parameter indicates the maximum time window allowed for a client to complete Fast Transition re-association. The unit is usually TU (1 TU ≈ 1.024 ms), so 1000 is roughly 1 second. In short: After a client initiates fast roaming, it must complete re-association within this window. For home networks, 1000 is a common, generous, and safe choice. Too short may prevent some devices from finishing the switch; too long generally has no real benefit. 3.4 ft_over_ds='0' Sets the 802.11r Fast Transition method. There are two common approaches: FT over the Air FT over DS Here we use FT over the Air by setting it to 0 (disabling ft_over_ds). FT over the Air: The client performs the fast handover directly with the target AP. This is more common and intuitive in non-enterprise environments. FT over DS: The client communicates with the target AP through the currently connected AP via the distribution system. The device contacts the new AP via the old one before switching. In real home OpenWrt/QWRT multi-AP setups, this doesn’t bring a clear advantage and can sometimes cause device compatibility issues. 3.5 ft_psk_generate_local='1' Lets the local AP generate 802.11r keys from the PSK. In home networks using WPA-PSK / SAE Mixed mode, the AP can locally derive the key material needed for Fast Transition from the Wi-Fi password. Home networks usually lack an enterprise authentication server, so just enable this. Suitable for: WPA2-PSK WPA2/WPA3 Mixed SAE mixed (depends on firmware support) Typical home networks without RADIUS 4. NAS ID: Unique Identity for Each BSS uci set wireless.ath0.nasid='Master_2_4G' uci set wireless.ath1.nasid='Master_5G' uci set wireless.ath2.nasid='Master_5G2' 4.1 nasid='Master_2_4G' nasid is the NAS Identifier, the identity of the current BSS. In 802.11r scenarios, it’s used to distinguish different APs / BSSs. Every wireless interface participating in roaming should have a unique nasid. For the main router: ath0 -> Master_2_4G ath1 -> Master_5G ath2 -> Master_5G2 For the secondary router, set correspondingly: 2.4G -> Slave_2_4G 5G-1 -> Slave_5G 5G-2 -> Slave_5G2 5. Why configure the same set of parameters for all three ath interfaces? Because ath0, ath1, and ath2 are three different wireless BSSs. Even if they broadcast the same SSID, they remain independent wireless interfaces at the system level, so 802.11k/v/r parameters must be written to each interface individually. This part can be summarized as: Parameter Protocol Function ieee80211k 802.11k Enable radio resource measurement rrm_neighbor_report 802.11k Allow AP to provide neighbor AP list rrm_beacon_report 802.11k Allow client to report scanned beacon info ieee80211v 802.11v Enable wireless network management bss_transition 802.11v Allow AP to send roaming suggestions time_advertisement 802.11v Time advertisement; usually disabled for home roaming wnm_sleep_mode 802.11v WNM power save; usually disabled for home roaming ieee80211r 802.11r Enable fast roaming nasid 802.11r / hostapd Identifies current BSS; should be unique mobility_domain 802.11r Set fast roaming domain; must be identical across all APs reassociation_deadline 802.11r Set fast re-association time window ft_over_ds 802.11r Select FT method; 0 = FT over the Air ft_psk_generate_local 802.11r Generate FT keys locally from PSK Secondary Router Just enable the corresponding settings directly in LuCI. You can refer to my configuration: Apply the same settings to all three wireless interfaces, while ensuring the NAS ID is different. Band Analysis My home network layout is somewhat complex. The main router sits in the center of the living room, which opens directly onto the kitchen and balcony, so its signal covers those areas well. The secondary router is in the study, flanked by two bedrooms. The study and living room are linked by a short corridor, and Bedroom A is separated from the living room by a bathroom: The two stars mark the main router (living room) and the secondary router (study). Signal collection results in each room: Master Bedroom Study (the tall red peak is from the secondary router) Second Bedroom It's clear: the master bedroom’s channels are relatively clean; the study has a strong signal because the secondary router is right there; but the second bedroom suffers from heavy interference, a weaker signal, and both our APs (the two strongest red Wi-Fi signals) are crowded on the same channel. As a result, actual speed tests in the second bedroom only reached about 80 Mbps. So, we need to adjust channels and power, and also configure 802.11k/v/r. Tuning Power and Channels The main goal is to separate the channels and prevent clients from sticking to one specific access point. Honestly, I can’t fully explain the “why” behind all of this; I also consulted AI for many settings. I’ll let the AI explain here too (lol). 1. Channel Strategy: Completely non-overlapping, avoiding co-channel interference The main and secondary routers use non-overlapping channels across all bands – the most critical step in multi-AP setups. 2.4 GHz band (Main 1 / Secondary 11): In 2.4 GHz, only channels 1, 6, and 11 are fully non-overlapping. Assigning 1 and 11 ensures the two devices don’t “collide” (co-channel interference), which guarantees stability for IoT devices that rely on 2.4 GHz. 5 GHz-1 band (Main 36 / Secondary 52): The main router uses the low channel 36; the secondary uses DFS channel 52. These are completely independent at 80 MHz bandwidth. 5 GHz-2 band (Main 149 / Secondary 157): The two routers’ high-band 5 GHz channels are also separated. Summary: This spatial channel isolation minimizes background noise and maximizes network throughput as devices move between the routers. 2. Bandwidth Strategy: Balancing stability and peak speed 2.4 GHz set to 20 MHz: A very wise move. Although 40 MHz is theoretically faster, the extremely crowded 2.4 GHz band (microwaves, Bluetooth) would experience multiplied interference with 40 MHz, causing frequent dropouts. Locking to 20 MHz sacrifices peak speed but maximizes wall-penetration stability and coverage, ideal for speed-insensitive IoT devices. 5 GHz-1 set to 80 MHz: 80 MHz is the mainstream sweet spot for most phones and laptops, offering very high LAN throughput and WAN download speeds – the primary high-speed band. 5 GHz-2 set to 40 MHz: An interesting strategy. Limiting the second 5 GHz radio to 40 MHz saves valuable wireless spectrum (reducing interference to neighbors) and serves as a high-stability backup high-speed network, suitable for older devices that don’t support 80 MHz or for isolating specific devices. 3. Power Strategy: “Weak 2.4 GHz, Strong 5 GHz” This power configuration is the most brilliant part; it perfectly solves the “sticky client” problem in multi-AP environments. 2.4 GHz power lowered (18 dBm / 20 dBm): 2.4 GHz signals have long wavelengths and penetrate walls extremely well. Without reducing power, a phone moving around the house will stubbornly “cling” to a distant 2.4 GHz signal, resulting in terrible speeds. Lowering the 2.4 GHz power on both routers artificially shrinks the 2.4 GHz coverage circles, encouraging devices to disconnect earlier when the signal weakens and search for a better one. 5 GHz power maxed out (23 dBm / 24 dBm): 5 GHz signals penetrate poorly and attenuate quickly. Keeping high power compensates for this weakness and expands the high-speed 5 GHz coverage area. Summary: This power differential creates a natural band steering effect at the physical layer. When a phone sees both 2.4 GHz and 5 GHz signals, the strong 5 GHz signal can easily exceed the weak 2.4 GHz signal, making the phone “happily” prefer the faster 5 GHz network. 4. Roaming Coordination With the physical-layer channels, bandwidth, and power properly tuned, the 802.11k/v/r protocols complete the seamless roaming loop: 11k (Neighbor Report) + 11v (BSS Transition Management): The router actively tells the phone “which nearby node has a better signal” and suggests a switch. Because the 2.4 GHz power is suppressed, the phone easily triggers the 11v threshold when moving. 11r (Fast Transition): Combined with a unified SSID (PINer) and matching encryption, this eliminates the hundreds of milliseconds otherwise needed to re-authenticate when switching APs, achieving a truly “seamless” experience (e.g., WeChat voice calls don’t drop). The identical mobility_domain and unique nasid are also standard 11r requirements. Ref: Gemini The final channel, bandwidth, and power configuration: Main Router 192.168.3.1 2.4G: channel 1 / 20 MHz / 18 dBm 5G-1: channel 36 / 80 MHz / 24 dBm 5G-2: channel 149 / 40 MHz / 24 dBm Secondary Router 192.168.3.2 2.4G: channel 11 / 20 MHz / 20 dBm 5G-1: channel 52 / 80 MHz / 23 dBm 5G-2: channel 157 / 40 MHz / 24 dBm Results & Follow-up Testing shows: in the living room, balcony, kitchen, and bathroom, devices default to the main router. In the second bedroom, they automatically switch to the secondary router. In the study, closing the door also triggers a switch from main to secondary. From signal degradation to actual handover takes about 5 seconds. The master bedroom is less deterministic – sometimes it switches, sometimes not; in 5 tests, it switched 3 times. Speed test after connecting to the 5 Gbps port: The actual downstream speed reached 1336.31 Mbps, and upstream 158.16 Mbps. Looks like a success? However, the real-world experience isn’t dramatically different, because few servers can saturate such speeds, plus ISP policies like QoS make it hard to reach the limit. But a multi-threaded download tool like IDM might make better use of it?
11/07/2026
13 Views
0 Comments
1 Stars
Leveraging systemd Features to Build a Multi-tenant CodeServer
Analysis The motivation came from a university Python course – I didn't want to bring my heavy laptop to every class, so I tried to see if a tablet could do the job. After some searching, I found coder/code-server: VS Code in the browser which fit the requirements perfectly while also being cross-platform. I deployed it for myself, but later my friends also wanted access. That got me thinking about how to support multi-tenancy and security simultaneously. Initially I considered containerization, but because of the need to install new pip packages, containers would have been tricky – I would have had to persist Python site-packages and everything, and performance would suffer. So I decided to stick with a binary deployment. The requirements are simple, roughly summarized as follows: Each user can log into CodeServer using their own domain name. Each user can change their own login password. Each user's Python environment is completely isolated and can independently install pip packages. Users should not be able to access each other's files. Prevent users from accidentally deleting critical system components. Prevent users from accidentally writing infinite loops or similar that exhaust server resources. Prevent users from using the server for cryptocurrency mining or as a jump box for attacks. After analysis and discussions with AI, the final solution is roughly as follows: Use Linux's native multi-user mechanism – each user runs a CodeServer under their own home directory for basic isolation. This easily satisfies requirements 1, 4 and 5. Listening ports are calculated based on UID. Create a venv manually for each user and activate it automatically via .bashrc to satisfy requirement 3. Use systemd's restrictions to limit process behavior, achieving requirements 6–7 to a certain extent. Use systemd's path mechanism to monitor $HOME/.config/code-server/config.yaml and automatically restart the daemon, allowing users to change their login password by modifying the configuration file – a relatively elegant way to achieve requirement 2. For requirement 7, given the computer literacy level of first-year students, I'm not too worried (I hope?). I didn't cut off network access completely because some requirements need internet to download packages, or might involve web scraping. systemd's restrictions should already block most malicious operations. This article does not cover SELinux, because in my opinion SELinux would be over-engineering for these requirements, and I'm not very familiar with SELinux/SEPolicy (that's the main reason lol). I also wanted to avoid imposing restrictions that hinder legitimate usage, so SELinux is not used. Deployment Configuring systemd Download the CodeServer binary and upload it to the server – for example, I put it at /usr/bin/code-server. Then write the systemd service file, create /etc/systemd/system/code-server@.service: # /etc/systemd/system/code-server@.service [Unit] Description=Code-Server for %i After=network.target [Service] Type=simple User=%i Group=%i WorkingDirectory=/home/%i MemoryMax=1G CPUQuota=150% TasksMax=200 IOWeight=50 ProtectSystem=strict PrivateTmp=yes PrivateDevices=yes NoNewPrivileges=yes RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX # ExecStart=/bin/bash -c "PASSWORD=$(echo -n "%i" | md5sum | cut -d' ' -f1) /usr/bin/code-server --bind-addr 0.0.0.0:$((7000 + $(id -u %i))) --auth password" ExecStart=/bin/bash -c ' \ PORT=$((7000 + $(id -u %i) %% 10000)); \ /usr/bin/code-server --bind-addr 0.0.0.0:$PORT; \ ' Restart=always RestartSec=5 [Install] WantedBy=multi-user.target The filename is code-server@.service; the part after @ is substituted for %i. The design passes the username via %i, calculates the port, and starts automatically. The port calculation logic is 7000+uid%10000. Typically UIDs start from 1000, so ports start from 8000 in order of user creation. Note this part of the configuration: MemoryMax=1G CPUQuota=150% TasksMax=200 IOWeight=50 ProtectSystem=strict PrivateTmp=yes PrivateDevices=yes NoNewPrivileges=yes RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX (I'll let AI explain it) It mainly covers two aspects: Resource Control and Security & Sandboxing. I. Resource Control This uses Linux's cgroups mechanism to prevent the service from consuming excessive system resources and affecting other programs. MemoryMax=1G Effect: Limits the service to a maximum of 1GB of memory. Outcome: If the service tries to use more than 1GB, the system (OOM Killer) will forcibly kill the process to protect the system. CPUQuota=150% Effect: Limits the service to at most 150% CPU usage. Outcome: 100% represents one full CPU core. 150% means the service can saturate one core and use half of a second core (i.e., up to 1.5 CPU cores' worth of compute). TasksMax=200 Effect: Limits the service to a maximum of 200 tasks (processes or threads). Outcome: Prevents the service from creating unlimited child processes due to bugs or infinite loops (e.g., fork bomb), which could exhaust system PID resources and crash the system. IOWeight=50 Effect: Sets the disk I/O priority weight. The default is usually 100. Outcome: A value of 50 means when system I/O is busy, this service gets lower priority for disk read/write resources compared to default services, preventing it from choking the whole system when doing heavy file I/O. II. Security & Isolation This uses Linux namespaces and other kernel security mechanisms to "cage" the service, minimizing damage even if the service is compromised. ProtectSystem=strict Effect: Strictly protects system files. Outcome: The entire operating system's filesystem (the root / and everything under it, except special API directories like /dev, /proc, /sys) is made read-only for this service. The service cannot modify, overwrite, or delete any critical system files. PrivateTmp=yes Effect: Provides an independent temporary directory for the service. Outcome: The service sees its own private /tmp and /var/tmp directories. It cannot see or modify files placed in the global /tmp by other users/services, and vice versa. This effectively prevents symlink attacks or data leaks based on temporary files. PrivateDevices=yes Effect: Isolates physical devices. Outcome: Mounts a private /dev directory for the service, containing only pseudo-devices (e.g., /dev/null, /dev/zero, /dev/urandom). The service cannot see real physical hardware devices (like /dev/sda, USB devices), completely eliminating the possibility of directly reading/writing block devices. NoNewPrivileges=yes Effect: Prevents privilege escalation. Outcome: Ensures that the service and all its child processes, no matter what, cannot gain new system privileges. Even if the service invokes a program with the SUID bit (e.g., sudo or su), it cannot escalate to root privileges. RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX Effect: Restricts the socket address families the service can use. Outcome: The service can only use: AF_INET: IPv4 network communication AF_INET6: IPv6 network communication AF_UNIX: local UNIX domain sockets (for local IPC) Any other address families (e.g., low-level packet capture AF_PACKET, Bluetooth AF_BLUETOOTH, etc.) are blocked by the kernel. This greatly reduces the network attack surface. When creating a new user, just run: adduser <username> systemctl enable --now code-server@<username> to simultaneously create the corresponding CodeServer service. Configuring password change auto-restart Create /etc/systemd/system/code-server-restart@.path: # /etc/systemd/system/code-server-restart@.path [Unit] Description=Monitor code-server config change for %i After=network.target [Path] PathChanged=/home/%i/.config/code-server/config.yaml [Install] WantedBy=multi-user.target Create /etc/systemd/system/code-server-restart@.service: [Unit] Description=Triggered safe restart for %i [Service] Type=oneshot User=root ExecStart=/usr/local/bin/safe-restart-codeserver.sh %i [Install] WantedBy=multi-user.target The logic works like this: Step 1: Start monitoring (handled by the .path file) The system or administrator starts code-server-restart@yms.path. systemd parses the .path file, replacing %i with yms. PathChanged=/home/yms/.config/code-server/config.yaml: systemd starts quietly listening (using the inotify mechanism) for changes to this specific config.yaml file at the kernel level. Step 2: Detect change and trigger The user modifies settings in the CodeServer web interface, or edits config.yaml via the command line and saves. PathChanged detects that the file has been modified and closed (ensuring the write is complete and avoiding reading half-written dirty data). Implicit binding: Because the .path file does not explicitly specify a service to trigger using Unit=, systemd's default behavior is to trigger the .service file with the same name (without the suffix). systemd then automatically starts code-server-restart@yms.service. Step 3: Execute the action (handled by the .service file) systemd executes code-server-restart@yms.service. Again, %i is replaced with yms. Type=oneshot: Tells the system this is not a long-running daemon but a one-shot task. It exits when done. User=root: The restart operation requires higher privileges, so it's forced to run as root. ExecStart=/usr/local/bin/safe-restart-codeserver.sh <user>: This is the final step in the logic. The system runs the custom shell script as root, passing the username as an argument. We don't restart the main daemon directly inside the restart service because CodeServer auto-saves on every edit. There's a risk that during password changes, a half-edited file might trigger a restart, causing incomplete writes. So we write a script that waits until the file is stable before triggering the restart: /usr/local/bin/safe-restart-codeserver.sh #!/bin/bash USER_NAME=$1 CONFIG_FILE="/home/$USER_NAME/.config/code-server/config.yaml" STAMP_FILE="/tmp/code-server-restart-${USER_NAME}.stamp" # 1. Intercept: if stamp file exists and config file is older (or same age) than stamp, # this trigger is a leftover queued event from systemd – exit if [ -f "$STAMP_FILE" ] && [ "$CONFIG_FILE" -ot "$STAMP_FILE" ]; then echo "Config hasn't changed since last restart, exiting." exit 0 fi # 2. Debounce wait logic (unchanged) while true; do last_md5=$(md5sum "$CONFIG_FILE") sleep 5 current_md5=$(md5sum "$CONFIG_FILE") if [ "$last_md5" == "$current_md5" ]; then # File is stable, perform restart systemctl restart code-server@$USER_NAME # 3. After successful restart, update the stamp file's mtime touch "$STAMP_FILE" break else echo "Config file for $USER_NAME is still changing, waiting..." fi done The timestamp mechanism prevents multiple pointless restarts. If the config file's last edit time is earlier than the last restart time, the restart is rejected. After writing the files, enable the trigger: systemctl enable --now code-server-restart@<username>.path (note it's .path, not .service). Then try slowly editing the password in the config file via the web interface, and check the logs for something like: ○ code-server-restart@lyr.service - Triggered safe restart for lyr Loaded: loaded (/etc/systemd/system/code-server-restart@.service; disabled; preset: enabled) Active: inactive (dead) since Sat 2026-06-06 06:43:55 UTC; 29s ago Invocation: 0bd37fcb6ea44a58870c06b4fde5300c TriggeredBy: ● code-server-restart@lyr.path Process: 6997 ExecStart=/usr/local/bin/safe-restart-codeserver.sh lyr (code=exited, status=0/SUCCESS) Main PID: 6997 (code=exited, status=0/SUCCESS) Mem peak: 2.5M CPU: 43ms Jun 06 06:43:40 CodeServer systemd[1]: Starting code-server-restart@lyr.service - Triggered safe restart for lyr... Jun 06 06:43:45 CodeServer safe-restart-codeserver.sh[6997]: Config file for lyr is still changing, waiting... Jun 06 06:43:50 CodeServer safe-restart-codeserver.sh[6997]: Config file for lyr is still changing, waiting... Jun 06 06:43:55 CodeServer systemd[1]: code-server-restart@lyr.service: Deactivated successfully. Jun 06 06:43:55 CodeServer systemd[1]: Finished code-server-restart@lyr.service - Triggered safe restart for lyr. After editing stops for 5 seconds, CodeServer will restart, and the new password can be used to log in. Configuring Python venv First, install Python3 on the system (no need to elaborate – use the package manager). Also install python3-venv: apt install python3-venv Then, enter the user's home directory. I chose to create a folder named .venv for the virtual environment. Inside .venv, run python3 -m venv myvenv to create a virtual environment named myvenv, and append the following line to the user's .bashrc: fi fi +source ~/.venv/myvenv/bin/activate After that, the venv is automatically activated when the shell starts. Installing the Python extension in CodeServer and pointing it to the venv I won't go into detail here – just install the Python and debugger extensions in the CodeServer web interface, and set the Python interpreter to the one under the venv. Postscript I actually set this up a long time ago but never wrote about it. At that time, vulnerabilities like CopyFail and DirtyFrag hadn't been disclosed yet. When they were disclosed, I tested them immediately and found that this systemd configuration happened to block them all. A rough analysis follows: CopyFail uses a special socket type: AF_ALG. Our systemd configuration only allows AF_INET AF_INET6 AF_UNIX, so CopyFail cannot escalate privileges. Similarly for DirtyFrag – it uses AF_NETLINK, AF_RXRPC, and AF_ALG, all of which are blocked. Also, NoNewPrivileges=yes acts as a final line of defense. The ultimate goal of those exploits is to tamper with /usr/bin/su to inject malicious ELF shellcode, or modify /etc/passwd to clear the root password, then invoke the setuid su command to gain root privileges. With NoNewPrivileges set, the process and all its descendants can absolutely never gain higher privileges through the setuid or setgid flags of any file. Even if a future vulnerability finds a way to bypass the network restrictions and successfully replace /usr/bin/su with a malicious shell, executing su would still spawn a low-privilege shell – privilege escalation becomes impossible. This article does not cover SELinux, because the current solution is acceptably simplified for the scenario of "friends sharing, non-production critical", avoiding the risk of misconfiguration causing functional issues and operational complexity. In reality, systemd's sandboxing options are primarily based on namespaces and cgroups, and cannot fully replace mandatory access control (like SELinux or AppArmor). For higher security requirements for tenant isolation (e.g., preventing kernel escape vulnerabilities among untrusted users), SELinux/AppArmor is still the mainstream choice. Of course, this solution has other limitations. For example, when there are many users or special UID allocation requirements that exceed 10000, the port calculation logic may fail. For legitimate needs like scientific computing, the current restrictions may be too strict. This article is only intended as a discussion and reference. Random thoughts: In the age of containerization and cloud-native, traditional systemd still has many interesting features worth exploring that can accomplish a lot… Reference: systemd.git - A fork of systemd to make components more independant
06/06/2026
48 Views
0 Comments
1 Stars
Adapting NFC Functionality for QWRT on Xiaomi BE10000 Router
English Translation Title: Adapting NFC Functionality for QWRT on Xiaomi BE10000 Router Analysis After flashing the Xiaomi BE10000 with QWRT, the device's network potential is indeed greatly unleashed. Advanced features such as 2.5G optical modules and SFP+ interfaces work perfectly. The only drawback is that the factory NFC "tap to connect to Wi-Fi" feature no longer works. After researching, the NFC tag is essentially an EEPROM chip mounted on the motherboard. Using i2cdetect for scanning: root@QWRT:~# i2cdetect -l i2c-1 i2c QUP I2C adapter I2C adapter i2c-2 i2c QUP I2C adapter I2C adapter i2c-0 i2c QUP I2C adapter I2C adapter root@QWRT:~# i2cdetect -y -r 0 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- 54 -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- The scan results quickly pinpoint the device attached to I2C bus 0 at physical address 0x54. NFC tap-to-connect-to-Wi-Fi uses standard NDEF format data (Ref: Wi-Fi Simple Configuration — ndeflib 0.3.2 documentation). Therefore, simply writing the data into the EEPROM according to the standard can restore the NFC tap-to-connect functionality. Implementation This article discusses only low-level hardware driver adaptation and NDEF standard protocol encapsulation for the OpenWrt/QWRT system. The hardware parameters mentioned are derived from public specification documents and generic I2C debugging tools. This project is for personal research interest and does not include or distribute any vendor-proprietary binary code. It is intended for technical exchange and learning only. Do not use for commercial purposes. Any risk of device damage resulting from attempts described herein shall be borne solely by the reader. Extract Data and Construct NDEF Payload To automatically update NFC data based on Wi-Fi credentials, we first need to obtain the current Wi-Fi SSID and password. On OpenWrt, these configurations are managed entirely by UCI (Unified Configuration Interface). Therefore, we only need to read the wireless configuration file from UCI. To ensure compatibility with modern smartphones, early devices typically used a Device Password Token to trigger WPS negotiation, but modern Android/iOS systems have restricted this behavior. For broader compatibility, we must follow the Wi-Fi Simple Configuration (WSC) specification and package the configuration as a WLAN Configuration Token (credential configuration token). (Ref: Wi-Fi Simple Configuration — ndeflib 0.3.2 documentation) Map OpenWrt's wireless encryption modes (e.g., WPA2, WPA3-SAE) precisely to the hex codes defined by the WSC specification: 0x1003: Authentication Type 0x100F: Encryption Type 0x1045: SSID 0x1027: Network Key (password) Through a script, we automatically traverse and select the primary AP bridged to lan (e.g., wifi0), convert its attributes to hex strings, and produce a standard NDEF payload. Write to NFC EEPROM When the NFC EEPROM receives a long string of NDEF data, writing too quickly or in excessively large blocks per write can easily cause the chip's I2C state machine to lock up. After testing, we chose to use the i2ctransfer tool for atomic fragmented writes. Two critical timing details: Due to communication limitations, each loop slices only 4 bytes, with auto-incrementing register addresses. Between each 4-byte block write, a 10 ms delay is enforced to allow sufficient internal erase/write time for the chip. Finally, any remaining data less than 4 bytes is padded with 0x00. Automatically Trigger Writes on Wi-Fi Configuration Changes To closely follow OpenWrt's architecture, we initially tried using hooks but found they often failed. Eventually, three fallback layers were added: LuCI frontend trigger: Register a hook under /etc/uci-defaults/ to bind the NFC sync script to the system's ucitrack mechanism. When a user modifies the Wi-Fi password in LuCI and clicks "Save & Apply", the system automatically updates the NFC data in the background. Hotplug layer: Add a hotplug event listener in /etc/hotplug.d/iface/70-nfc. When the router's lan or wifi interface changes to ifup state, the system automatically triggers the sync. Cron job: If none of the above triggers work, a cron job forces a check every 15 seconds to determine if an NFC update is needed. Additionally, considering that the NFC EEPROM has limited write endurance, if the network interface restarts even once and triggers a full rewrite, the chip would soon wear out. Therefore, a simple hash check mechanism is introduced in the underlying nfc-sync script: When the script is awakened, it first extracts the current wireless configuration and calculates its MD5 hash. It compares this hash with the old hash cached in /var/run/nfc-wireless.md5. Only when the MD5 value actually changes does it issue the I2C write command. Otherwise, the process terminates immediately. Combined with a concurrent file lock (/var/lock/nfc-sync.lock), this logic ensures that the NFC hardware's lifespan is absolutely protected against any network flapping or multiple concurrent events. After testing, automatic updating works as expected: ![[Pasted image 20260525230448.png]] Code repository: KaguraiYoRoy/be10000-qwrt-nfc: NFC Userland Implementation of QWRT for Xiaomi BE10000 (RC01) Router References: Wi-Fi Simple Configuration — ndeflib 0.3.2 documentation
25/05/2026
52 Views
0 Comments
1 Stars
Building a Cross-Region K3s Cluster from Scratch - Calico No-Encapsulation CNI
# Preface I've actually wanted to play with a K8s cluster for a long time, but always felt that without sufficient knowledge, it would be too difficult to attempt. Recently, I spent some time studying DN42 and routing protocols like BGP and OSPF, and realized that it no longer feels so difficult. So I decisively started with K3s ( The main reason for choosing K3s over K8s is its lightweight nature: low resource requirements, no need to pull a bunch of images for deployment, availability of domestic mirrors… In short, K3s suits my needs better. I'm a beginner just starting to explore K3s, so please go easy on me if I make any mistakes~ # Analysis ## Choosing the CNI Component My current network architecture looks like this: ```mermaid graph TD subgraph ZeroTier Domestic subgraph WDS Gateway <--> VM1 Gateway <--> VM2 end NGB <--> Gateway HFE-NAS <--> Gateway NGB <--> HFE-NAS end subgraph IEPL Global-NIC <==OSPF==> CN-NIC end subgraph ZeroTier Global HKG02 <--> HKG04 TYO <--> HKG04 TYO <--> HKG02 end CN-NIC <--> NGB CN-NIC <--> HFE-NAS CN-NIC <--OSPF--> Gateway Global-NIC <--OSPF--> TYO Global-NIC <--OSPF--> HKG02 Global-NIC <--OSPF--> HKG04 %% Style definition: orange background, bold border to represent routers classDef router fill:#f96,stroke:#333,stroke-width:2px,font-weight:bold; class Global-NIC,CN-NIC,Gateway router; Among this, the WDS node is a Proxmox VE host with multiple VMs underneath. It advertises its VMs' IPv4 prefixes via OSPF. When Hong Kong nodes need to access a VM under the WDS node, they can do so by joining the OSPF internal network to achieve multi-hop reachability. This keeps the encapsulation layer count to only one, so there's no worry about MTU "disappearing act". I plan to create two new VMs under WDS to serve as the master and a node (temporarily called KubeMaster and KubeNode-WDS1). Then HKG04 (temporarily called KubeNode-HKG04) will also join the K3s cluster as a node. The simplest approach would be to use K3s's default Flannel as the CNI. However, Flannel is based on VXLAN, and adding another layer of my existing internal network would lead to the following MTU "disappearing act": Data packet -> Flannel VXLAN encapsulation -> ZeroTier encapsulation -> Physical link The actual usable MTU for inter-container communication would likely be compressed to 1350 or even lower. Therefore, I tried to find a CNI solution that can work directly on top of this internal network, and then I found Calico. As I understand, Calico uses BGP as its underlying routing protocol, supports starting in no-encapsulation (No-Encap) mode, and hands packets directly to the upper routers for routing. Thus, I chose Calico as the CNI component. Routing Design To ensure that intermediate routers know how to route Pod IPs, KubeMaster and KubeNode-WDS1 are under the Proxmox VE host. They need to establish BGP with HKG04 across the entire internal network. This means that every router at each intermediate level must learn the full BGP routes, so that the following routing path can be established: graph LR subgraph WDS KubeMaster KubeNode-WDS1 Gateway end subgraph IEPL CN-Namespace Global-Namespace end KubeNode-WDS1 <--> Gateway KubeMaster <--> Gateway <--> CN-Namespace <--> Global-Namespace <--> HKG04 %% Style definition: highlight nodes with routing capability classDef router fill:#f96,stroke:#333,stroke-width:2px,font-weight:bold; class Gateway,CN-Namespace,Global-Namespace router; Otherwise, any intermediate hop would drop packets because it doesn't recognize the source/destination IP. Also, due to the property of iBGP that routes learned from a neighbor cannot be propagated to the next iBGP neighbor, all BGP sessions between Gateway, CN-Namespace, Global-Namespace and the nodes need to enable Route Reflector; otherwise, nodes cannot correctly learn routes from each other. That said, this architecture would be more suitable for BGP Confederation, but my existing network is already quite complex, and adding BGP confederations would make later maintenance more troublesome. Moreover, my number of nodes is small, so the overhead of iBGP Full Mesh is acceptable. It's definitely not because I'm lazy (so Thus, the final network routing structure is as follows: graph TD subgraph WDS VM1 VM2 Gateway end subgraph IEPL CN-Namespace Global-Namespace end VM1 <-.Calico iBGP Full Mesh.-> VM2 VM1 <--iBGP Route Reflector--> Gateway VM2 <--iBGP Route Reflector--> Gateway <--iBGP--> CN-Namespace <--iBGP--> Global-Namespace <--iBGP Route Reflector--> HKG04 Gateway <--iBGP--> Global-Namespace HKG04 <-.Calico iBGP Full Mesh.-> VM1 VM2 <-.Calico iBGP Full Mesh.-> HKG04 %% Style definition classDef router fill:#f96,stroke:#333,stroke-width:2px,font-weight:bold; %% Mark nodes with routing/forwarding or RR functions as Router class Gateway,CN-Namespace,Global-Namespace router; The dashed-line BGP sessions are automatically created by Calico, while the solid-line parts need to be manually created by us. Keeping Calico's own iBGP Full Mesh is for future scalability, so that nodes can preferentially establish direct P2P connections via ZeroTier instead of taking a detour through the Route Reflector aggregation router. Deployment After clarifying the structure, deployment becomes simple. Enable Kernel Forwarding and Disable rp_filter Standard practice. echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf echo "net.ipv6.conf.default.forwarding=1" >> /etc/sysctl.conf echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf echo "net.ipv4.conf.default.rp_filter=0" >> /etc/sysctl.conf echo "net.ipv4.conf.all.rp_filter=0" >> /etc/sysctl.conf sysctl -p Install K3s Master Because the KubeMaster control plane node is located inside China, it's best to configure image acceleration: mkdir -p /etc/rancher/k3s cat <<EOF > /etc/rancher/k3s/registries.yaml mirrors: docker.io: endpoint: - "https://docker.m.daocloud.io" quay.io: endpoint: - "https://quay.m.daocloud.io" EOF Install using the mirror: curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \ INSTALL_K3S_MIRROR=cn INSTALL_K3S_EXEC=" \ --flannel-backend=none \ --disable-network-policy \ --cluster-cidr=10.42.0.0/16" sh - Note the need to specify --flannel-backend=none and --disable-network-policy to disable the default CNI component. Use cat /var/lib/rancher/k3s/server/node-token to view the token and record it. Worker Nodes For nodes inside China, configure image acceleration: mkdir -p /etc/rancher/k3s cat <<EOF > /etc/rancher/k3s/registries.yaml mirrors: docker.io: endpoint: - "https://docker.m.daocloud.io" quay.io: endpoint: - "https://quay.m.daocloud.io" EOF Then install K3s using the mirror and join the cluster: export INSTALL_K3S_MIRROR=cn export K3S_URL=https://<master node IP>:6443 # Replace with your master node's actual IP export K3S_TOKEN=K10...your token...::server:xxx # Replace with the full token obtained in the first step curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | sh - At this point, the status of each node should be NotReady because the CNI component is missing. Install Calico and Configure No-Encap Mode On the master, manually download https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/tigera-operator.yaml and install the Calico operator: kubectl create -f tigera-operator.yaml Configure a custom resource by creating a custom-resource.yaml file: apiVersion: operator.tigera.io/v1 kind: Installation metadata: name: default spec: # Add image registry configuration registry: quay.m.daocloud.io calicoNetwork: ipPools: - blockSize: 26 cidr: 10.42.0.0/16 encapsulation: None natOutgoing: Enabled nodeSelector: all() Here, specify encapsulation: None to enable No-Encap mode. You can also modify the IPv4 CIDR here if needed. Then: kubectl apply -f custom-resource.yaml to perform the installation. Use: kubectl get pods -A -o wide to check Pod status, waiting for each node to finish pulling images. Configure BGP Topology Label Nodes Label nodes to specify that nodes under WDS connect to the Gateway's BGP in the WDS node, and nodes outside China connect to the BGP of the Global Namespace: kubectl label nodes kubemaster region=WDS kubectl label nodes kubenode-wds-1 region=WDS kubectl label nodes kubenode-hkg04 region=Global Calico Configuration Create a YAML configuration file: apiVersion: crd.projectcalico.org/v1 kind: BGPPeer metadata: name: route-reflector-domestic spec: nodeSelector: region == 'Domestic' # This part is not actually used; I originally designed a general aggregation router in the Domestic area peerIP: 100.64.0.108 asNumber: 64512 --- apiVersion: crd.projectcalico.org/v1 kind: BGPPeer metadata: name: route-reflector-wds spec: nodeSelector: region == 'WDS' peerIP: 192.168.100.1 asNumber: 64512 --- apiVersion: crd.projectcalico.org/v1 kind: BGPPeer metadata: name: route-reflector-global spec: nodeSelector: region == 'Global' peerIP: 100.64.1.106 asNumber: 64512 This means: All nodes with label region equal to Domestic will have a BGP session to 100.64.0.108 (the domestic aggregation router) using AS 64512 All nodes with label region equal to WDS will have a BGP session to 192.168.100.1 (the Gateway for all VMs under the WDS node) using AS 64512 All nodes with label region equal to Global will have a BGP session to 100.64.1.106 (the overseas aggregation router) using AS 64512 This achieves what is shown in the diagram: all VMs under the WDS node, including the master and KubeNode-WDS1, connect to the Gateway aggregation router of the WDS node, and all nodes in overseas areas connect to the overseas aggregation router. Configure Aggregation Router iBGP This part is simply a matter of writing Bird configuration files (easy). Here are a few examples: k3s/ibgp.conf: function is_insider_as(){ if bgp_path.len > 0 && !(bgp_path ~ [= 64512 =]) then { return false; } if net ~ [ 10.42.0.0/16{16,32} ] then { return true; } return false; } template bgp k3sbackbone{ local as K3S_AS; router id INTRA_ROUTER_ID; neighbor as K3S_AS; ipv4{ table intra_table_v4; import filter{ if is_insider_as() then accept; reject; }; export filter{ if is_insider_as() then accept; reject; }; next hop self; extended next hop; }; ipv6{ table intra_table_v6; import filter{ if is_insider_as() then accept; reject; }; export filter{ if is_insider_as() then accept; reject; }; next hop self; }; }; template bgp k3speers{ local as K3S_AS; neighbor as K3S_AS; router id INTRA_ROUTER_ID; rr client; rr cluster id INTRA_ROUTER_ID; ipv4{ table intra_table_v4; import filter{ if is_insider_as() then accept; reject; }; export filter{ if is_insider_as() then accept; reject; }; next hop self; }; ipv6{ table intra_table_v6; import filter{ if is_insider_as() then accept; reject; }; export filter{ if is_insider_as() then accept; reject; }; next hop self; }; }; include "ibgpeers/*"; ibgpeers/backbone-cn.conf: protocol bgp 'k3s_backbone_cn_v4' from k3sbackbone{ neighbor fd18:3e15:61d0:cafe:f001::1; }; ibgpeers/master.conf: protocol bgp 'k3s_master_v4' from k3speers{ neighbor 192.168.100.251; }; Main points: it's best not to enable Route Reflector between the aggregation routers, and remember to enable next hop self. After everything is done, using kubectl get nodes should show all nodes as Ready: NAME STATUS ROLES AGE VERSION kubemaster Ready control-plane 2d23h v1.34.5+k3s1 kubenode-hkg04 Ready <none> 11h v1.34.6+k3s1 kubenode-wds-1 Ready <none> 2d7h v1.34.5+k3s1 Use kubectl get pods -A -o wide to view Pods: NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES calico-system calico-kube-controllers-64fc874957-6bdlz 1/1 Running 0 5h38m 10.42.253.136 kubenode-hkg04 <none> <none> calico-system calico-node-2qz82 1/1 Running 0 4h24m 10.2.5.7 kubenode-hkg04 <none> <none> calico-system calico-node-dhl2c 1/1 Running 0 4h24m 192.168.100.251 kubemaster <none> <none> calico-system calico-node-nbpkj 1/1 Running 0 4h23m 192.168.100.252 kubenode-wds-1 <none> <none> calico-system calico-typha-7bb5db4bdc-rfpwg 1/1 Running 0 5h38m 10.2.5.7 kubenode-hkg04 <none> <none> calico-system calico-typha-7bb5db4bdc-rwwr5 1/1 Running 0 5h38m 192.168.100.251 kubemaster <none> <none> calico-system csi-node-driver-jglwp 2/2 Running 0 5h38m 10.42.64.68 kubenode-wds-1 <none> <none> calico-system csi-node-driver-jqjsc 2/2 Running 0 5h38m 10.42.253.137 kubenode-hkg04 <none> <none> calico-system csi-node-driver-vk26s 2/2 Running 0 5h38m 10.42.141.16 kubemaster <none> <none> kube-system coredns-695cbbfcb9-8fx4p 1/1 Running 1 (7h27m ago) 2d23h 10.42.141.14 kubemaster <none> <none> kube-system helm-install-traefik-crd-5bkwx 0/1 Completed 0 2d23h <none> kubemaster <none> <none> kube-system helm-install-traefik-m9fgj 0/1 Completed 1 2d23h <none> kubemaster <none> <none> kube-system local-path-provisioner-546dfc6456-dmn4g 1/1 Running 1 (7h27m ago) 2d23h 10.42.141.15 kubemaster <none> <none> kube-system metrics-server-c8774f4f4-2wkwh 1/1 Running 1 (7h27m ago) 2d23h 10.42.141.12 kubemaster <none> <none> kube-system svclb-traefik-999cddce-hpmcm 2/2 Running 6 (7h26m ago) 11h 10.42.253.134 kubenode-hkg04 <none> <none> kube-system svclb-traefik-999cddce-q4225 2/2 Running 2 (7h27m ago) 2d22h 10.42.141.9 kubemaster <none> <none> kube-system svclb-traefik-999cddce-xmd64 2/2 Running 2 (7h26m ago) 2d6h 10.42.64.66 kubenode-wds-1 <none> <none> kube-system traefik-788bc4688c-vbbhj 1/1 Running 1 (7h27m ago) 2d22h 10.42.141.13 kubemaster <none> <none> tigera-operator tigera-operator-6b95bbf4db-vl46l 1/1 Running 1 (7h27m ago) 2d23h 192.168.100.251 kubemaster <none> <none> Use kubectl exec -it -n calico-system <calico-node-xxxx> -- birdcl s p to check the status of Bird: root@KubeMaster:~/kube/calico# kubectl exec -it -n calico-system calico-node-2qz82 -- birdcl s p Defaulted container "calico-node" out of: calico-node, flexvol-driver (init), install-cni (init) BIRD v0.3.3+birdv1.6.8 ready. name proto table state since info static1 Static master up 08:58:17 kernel1 Kernel master up 08:58:17 device1 Device master up 08:58:17 direct1 Direct master up 08:58:17 Mesh_192_168_100_251 BGP master up 08:58:33 Established Mesh_192_168_100_252 BGP master up 08:59:00 Established Node_100_64_1_106 BGP master up 12:57:44 Established ip r shows the system routing table: root@KubeMaster:~/kube/calico# ip r default via 192.168.100.1 dev eth0 proto static 10.42.64.64/26 proto bird nexthop via 192.168.100.1 dev eth0 weight 1 nexthop via 192.168.100.252 dev eth0 weight 1 blackhole 10.42.141.0/26 proto bird 10.42.141.9 dev caliac6501d3794 scope link 10.42.141.12 dev calib07c23291bb scope link 10.42.141.13 dev caliab16e60bd19 scope link 10.42.141.14 dev calid5959219080 scope link 10.42.141.15 dev cali026d8f1ddb7 scope link 10.42.141.16 dev califa657ba417a scope link 10.42.253.128/26 via 192.168.100.1 dev eth0 proto bird 192.168.100.0/24 dev eth0 proto kernel scope link src 192.168.100.251 Ping a Pod's IP – if everything is fine, it should work directly: root@KubeMaster:~/kube/calico# ping 10.42.253.137 PING 10.42.253.137 (10.42.253.137) 56(84) bytes of data. 64 bytes from 10.42.253.137: icmp_seq=1 ttl=60 time=33.7 ms 64 bytes from 10.42.253.137: icmp_seq=2 ttl=60 time=33.5 ms ^C --- 10.42.253.137 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 33.546/33.632/33.718/0.086 ms Tune MTU This step is actually for stability…? Tests have shown that although my ZeroTier MTU is 1420, packets start to fragment around 1392 bytes (test with ping -M do -s <packet size> <Pod_IP>). Therefore, force the Pod MTU to 1370: root@KubeMaster:~/kube/calico# cat patch-mtu.yaml apiVersion: operator.tigera.io/v1 kind: Installation metadata: name: default spec: calicoNetwork: mtu: 1370 nodeAddressAutodetectionV4: firstFound: true root@KubeMaster:~/kube/calico# kubectl apply -f patch-mtu.yaml installation.operator.tigera.io/default configured
05/04/2026
104 Views
0 Comments
6 Stars
From Reflections on Imagination to Cognition, Creativity, and the Logic Tree
Starting Point: Thoughts Sparked by a Debate Topic While scrolling through my social feed, I saw a friend post this: Keep thinking to keep your mind sharp. Today’s Debate: Does imagination increase with the level of cognitive development, or does it decrease? My initial thought was, "This definitely isn't the whole picture." Based on my own experience, when I'm genuinely interested in researching or learning something, I not only learn it quickly but can also apply and build upon it. Conversely, I find the knowledge taught in school uninteresting and feel no desire to apply or innovate with it. So, I came up with my first version of an answer: Personally, I think it depends on how one's cognitive level increases. If it's through forced learning, the content is passively received. People won't find it interesting or worth thinking about. In this case, it likely won't expand imagination. But if it's a spontaneous pursuit of knowledge, an increase in cognitive level won't extinguish curiosity about the unknown. In this scenario, a higher cognitive level allows imagination to delve deeper and become more logically coherent on this basis. Later, that friend replied, "So, rote education really stifles creativity and imagination," and I agreed. But was the discussion over...? The Thinking Phase First Deepening: Logical Coherence In my initial reply, I mentioned logical coherence. I didn't think much of it at the time, but upon reflection later, I realized this could well explain the skeleton of imagination: Imagination is the process of conducting logical deductions and envisioning possibilities based on existing knowledge, all within the current logical framework: As children, our wild fantasies stemmed from knowing very little. We could only make inferences and assumptions based on our limited understanding of everyday physics. They were logically coherent within that simple framework. As adults, with more knowledge, our fantasies transform into creation. This is also driven by imagination, but it's a purposeful, directional advance within the framework of existing knowledge. It is also logically coherent. Essentially, both are about imagination constructing a "plausible" world. The difference lies solely in the foundational knowledge and logical systems used during construction. Foundational knowledge comes from learning, while the logical system comes from our understanding of life and the world – our life experiences. An increase in cognitive level merely changes the rules that "coherence" must follow. Childhood "coherence" follows story logic, while adult "coherence" follows scientific and social logic. Furthermore, when cognitive level is low, due to a simpler knowledge system, imagination often produces disconnected points, each potentially coherent on its own. As cognitive level increases, we gradually construct a complete, vast, and interconnected knowledge system of the world. Imagining within this framework to achieve global logical coherence is precisely the purposeful, directional creation mentioned earlier. Following this line of thought, we could even say the real challenge brought by increased cognition isn't losing the ability for "logical coherence," but rather maintaining the vitality of "logical coherence" when the knowledge system becomes too large – that is, preventing the existing framework from becoming a cage, allowing imagination to still find new combinations in the gaps. Second Deepening: The Boundaries of Everyday Experience From the above, it's easy to think that maintaining the logical coherence of imagination relies heavily on our understanding of the world and on everyday experience. This raises a new question: When a person's knowledge accumulation surpasses their personal everyday experience, how can they maintain this logical coherence in imagination? In other words, when the knowledge we acquire is completely beyond the scope of our direct understanding, how should we expand and diverge based on it? During this reflection, I realized the premise itself might be incomplete. Consider two examples: For me, I enjoy the process of designing and implementing computer software and building networks. From my perspective, this falls within the realm of everyday experience. For a friend of mine who loves mathematics, deriving advanced calculus equations is something within his everyday experience. These two examples illustrate well: "Everyday experience" itself is a benchmark that shifts as one's cognitive level changes. From this, we can infer: Cognition Reshapes the Boundaries of "Everyday": My friend enjoys deriving calculus because its symbols and logic have integrated into his cognitive framework, becoming a part of his thinking. Thus, he can intuitively imagine and explore within the logic of advanced math. For me, tinkering with computers is similarly based on my internalized knowledge system, making its content feel like everyday experience. The Multifaceted Nature of Imagination: When someone possesses deep cognition in a field, their imaginative activities within that field might seem like incomprehensible creations to an observer, but to themselves, it might just be an "everyday," intuitive deduction. Imagination hasn't disappeared; it has permeated the underlying layers of thought, becoming an ability to skillfully achieve "logical coherence" and explore possibilities within a professional framework. What outsiders see as "transcendence," the individual experiences as "everyday." Thus, the original debate topic is incomplete. Its flaw lies in presupposing a universally average cognitive level and standard of everyday experience, whereas they are actually highly individualistic. An increase in cognitive level means the domain where one can "transcend everyday experience" expands. Thoughts that seem fantastical to others are, for the thinker, rigorous deductions based on solid theory. Increasing cognition is the process of continuously transforming what was once "beyond everyday experience" into "everyday experience." In this process, imagination doesn't diminish; it changes form – from unconstrained fantasy to logically coherent creation within an existing framework. Furthermore, we can conclude that this type of imagination, based on deep cognition and "routinized" knowledge, and childhood imagination based on common sense and naivety, are essentially the same thing: a yearning for the unknown. However, because they operate under different constraints – one bound by a comprehensive knowledge system, the other by a shallow understanding of physical laws – their manifestations differ significantly. Summary At this point, we've summarized several key points: Imagination isn't just wild fancy; it's the pursuit of logical coherence within an existing framework. "Everyday experience" is a moving benchmark; it represents the boundaries of the knowledge system one can flexibly use and expands as one learns. Increasing cognitive level doesn't destroy imagination; it reshapes the rules by which it achieves coherence. Therefore, the answer to the debate topic cannot be a simple "increases" or "decreases." It depends on the method of cognitive growth and the observer's perspective. Model Construction From the above questions, I couldn't help but wonder: what should an individual's knowledge system structure look like? How do we organize scattered pieces of knowledge into a system capable of supporting "logical coherence"? And how do we create new content within this system through creativity? Introducing the Tree Model First, I thought of a graph theory structure: Individual knowledge points are discrete nodes. Learning is the process of creating new nodes. Reviewing and applying knowledge is about linking nodes to the existing knowledge system. This explains why just studying without practice doesn't lead to good understanding – because without establishing connections, the node remains isolated. We can't link the knowledge point to our existing system, preventing us from recalling it when faced with related problems. In other words, it fails to become internalized as part of "everyday experience." Then I realized this model might be too flat for explaining knowledge structures. Real knowledge systems often have strict hierarchical and containment relationships, so I thought a tree structure might be more suitable: Knowledge points often have distinct levels. Relationships between points include logical connections like derivation and inverse application, implying parent-child or hierarchical links. Based on this, I attempted to construct a tree-structured knowledge map. Nodes are knowledge units. Edges are logical relationships, such as dependency, inheritance, instantiation. Root nodes are underlying principles/axioms. Leaf nodes are derived theorems/phenomena/applications. The process of building knowledge is: Everyone starts from the nodes they know. Learning new things is expanding the system upward, towards the root nodes. Innovation and imagination involve exploring downward from existing nodes to derive new child nodes. Thus, the more we know, the more nodes we have from which we can branch out further. Based on this model, we can explain the previously mentioned "constraint of cognition on creativity" and why passive learning fails to expand it: Parent Nodes Constrain Child Nodes' Content: What kind of child nodes a node can produce isn't random; it must satisfy the logical constraints and relationships of the parent node. Exercising imagination essentially means instantiating new, valid nodes within the limits permitted by the parent knowledge system. Passive Learning: It merely adds some isolated nodes to the tree, or establishes only shallow references. Although these nodes exist in the knowledge tree, they lack upward connections to existing knowledge points. When we need to explore downwards through imagination, we might know of their existence, but they can't generate new, effective connections. However, this model still couldn't explain some things: It couldn't account for knowledge from multiple different domains. Many knowledge points are interwoven or even cross-disciplinary. This model couldn't explain the phenomenon of cross-domain application of knowledge. Therefore, I considered whether a more comprehensive model could be built. Multi-Root, Multi-Tree + Graph Connections To explain different domains and cross-disciplinary links, I revisited the initial graph theory idea but retained the tree structure: The human cognitive system consists of multiple independent tree structures. Different trees represent knowledge in different domains. These tree structures and their child nodes are interconnected through a network of links, forming a complex network that possesses both hierarchical depth and lateral connectivity. Knowledge exists as nodes and edges, and mental activities (learning, understanding, imagining, creating) are essentially the traversal, restructuring, and expansion of this network. Model Components This model comprises Nodes, Edges, Root Nodes, Trees, and Canopies: Node: A unit of knowledge, which could be a concept, fact, phenomenon, or skill. Edge: Represents a logical relationship between nodes. These can be further divided into two types: Tree Edge: Represents inheritance, derivation, or causal relationships within a tree ("is a kind of," "is part of," "can be derived from"). Network Edge: Represents associative, analogical, or combinable relationships between trees or their child nodes ("is similar to," "can be combined with," "symbolizes"). Root: As in the previous tree model, it represents the underlying principle or first-principle assumption of a domain, like the laws of physics for physics. Tree: A hierarchical structure composed of a root node and all its descendants. The interior of a tree is completely logically coherent. Root nodes of different trees may not have derivational relationships, but their child nodes often do. Canopy: The top region of a tree, representing the specific practices, phenomena, applications, or experiential knowledge of a domain. The canopy is often a dense area for network edges because concrete practices usually involve knowledge from multiple domains. Operational Mechanisms 1. Learning Tracing Roots Upward: Starting from a node, follow tree edges towards the root to understand its principles. Branching Downward: Starting from a node, follow tree edges towards the leaves to explore its applications. 2. Understanding Assimilation: A new node finds a suitable parent and is attached to an existing tree. Accommodation: A new node cannot be attached -> Adjust the root node or reorganize branches -> Restructure the tree. Cross-Tree Connection: A new node attaches to multiple trees simultaneously, or establishes network edges between trees. 3. Imagination and Creation The core operation of imagination is: Establishing new network edges between nodes of seemingly unrelated trees. Discover that a node in Tree A can connect to a node in Tree B. Follow this new edge, and through association, synthesis, etc., grow a new node that didn't exist before. 4. Forgetting and Invalidation Isolated Node: A node exists but has no effective edges connecting it to any tree -> Cannot be recalled, cannot participate in creation or thought processes. Weak Connections: Network edges unused for a long time -> Their weight decreases -> Hard to activate -> Forgetting. Properties This model possesses the following properties: Hierarchy: Each tree has a clear internal structure: Root (principle/axiom) -> Child Nodes (core inferences) -> Child Nodes (sub-fields) -> Leaf Nodes (phenomena/applications). Modularity: Each tree is relatively independent and can grow on its own. Connectivity: Any nodes between trees can potentially connect based on association or cross-disciplinary application, but due to root node characteristics, connections typically occur between child nodes and leaves. Growth: Vertical Growth: Learning towards root nodes (understanding principles) and expanding applications towards leaf nodes (deriving applications) within a tree. Horizontal Growth: Creating new knowledge or applications between trees through association, synthesis, etc. Robustness and Fragility: Damage to part of a single tree doesn't affect the operation of other trees. If the root node of a tree is disproven, causing the entire tree to collapse, it can implicate a large part of its interconnected neighbors. The Tree Part: Ensures Logical Structure The tree structure provides hierarchy and derivational relationships – vertical connections: Root -> Child -> Grandchild represents the deductive path from principle to phenomenon. Tracing roots upward is seeking principles; branching downward is exploring practical applications. The existence of trees allows thoughts to be abstracted into a complete system, preventing them from becoming scattered. The Graph Part: Explains Cross-Disciplinary Phenomena The network connections provide associative links and emergence – horizontal connections: A node from Tree A can attach directly to a node in Tree B. These cross-tree connections embody analogy, metaphor, and cross-disciplinary innovation. I personally think this structure can quite comprehensively explain the operation and interrelation of today's knowledge systems. For instance, in modern history, the disproving of the "geocentric model" led to a restructuring of all astronomy based on it. Similarly, rote learning only inputs isolated nodes without building sufficient connections, preventing their proper use. Explaining Phenomena The Emergence of Imagination: Profound innovation often isn't just digging deeper within one tree, but attaching a child node from Tree A onto a child node from Tree B, thereby creating something new. The more such cross-tree connections exist, the richer the potential for branching out downwards. Thorough Understanding (Ronghui Guantong): This is essentially creating cross-tree indices. Ordinary people might only make connections within a single tree, e.g., "array" and "linked list" in a "Data Structures" tree. But an expert might connect "hash table" (from the Data Structures tree) with "cache" (from the Computer Architecture tree), giving rise to a new node like "cache-friendly hash table design." Reusing Isolated Nodes: A node might be isolated within its original tree, but later, with an expanded knowledge scope, a suitable attachment point is found, allowing it to be utilized and understood. Meanwhile, this model also explains the initial question: Does imagination disappear? No, it merely exists in a different form. Visualization Personal Experience Let me give my own example. I used to struggle with understanding why the Internet is called a "net." My perception of the Internet was limited to the purely tree-like structure of my home router. Based on this, I couldn't understand that by extrapolation, there would have to be a single "super router" responsible for all core data forwarding globally, which obviously defies physical reality. Later, I self-studied routing protocols like BGP and OSPF, and suddenly I understood why it's a network. BGP and OSPF perfectly illustrate how routing information propagates through a mesh structure, fundamentally enhancing my understanding of the Internet. Based on this new understanding, I used tools like ZeroTier and Bird to build my own SD-WAN, creating a large, multi-hop intranet. This example fits the model well: Old Cognition: Centralized model (global super-router required). Cognitive Conflict: The conclusion derived from this model doesn't match reality. New Knowledge Acquisition: BGP, OSPF. Cognitive Restructuring: Understanding the Internet as a "mesh network" structure. Creation: Building an SD-WAN using ZeroTier and Bird based on the new model. Limitations and Boundaries Throughout this, I've tried to build a model using rational analysis. However, I also realize some phenomena can't be explained by it, such as emotions and feelings. They exist independently of logical edges and can't be captured by the current model. Emotions often determine the direction of learning and how we achieve desired outcomes from it. Therefore, I believe they should be considered, but the current model cannot analyze them. Additionally, there are logical gaps, such as: In this mixed tree+graph structure, what exactly is a root node? Is it an objective principle, or a subjective first-principle belief? What is the upper limit for establishing connections? Is it possible to over-connect? If there are too many dense network edges, could it blur the tree structure and make thinking lose direction? What is curiosity itself in this model? Is it the driving force for traversal, or some intuition for "predicting where new connections might be"? Afterthoughts I sent this little self-organized model to an AI for analysis and found it already corresponds to parts of existing theories: 1. Cognitive Psychology: Schema Theory & Mental Models Correspondence: Piaget's "schema" theory is exactly about this – human knowledge is organized in structured ways (like the model's trees/networks). Learning is either "assimilation" (attaching to an existing tree) or "accommodation" (finding no attachment point, requiring restructuring). My BGP example is a classic case of "accommodation" – the old tree model collapsed, and a new multi-root network model was built. Model's Uniqueness: Emphasizes the existence of "isolated nodes," supplementing the explanation for why learning fails – not all input becomes part of a schema. 2. Cognitive Science: Distributed Cognition & Connectionism Correspondence: Connectionism (neural networks) posits that knowledge isn't located in one specific place but distributed in the connection weights between nodes. This aligns perfectly with the model's explanation of knowledge systems as a network – meaning lies not in the node itself, but in how nodes are connected. Model's Uniqueness: Retains the hierarchical "tree structure," avoiding complete flattening. This is a slight modification to connectionism – much of human knowledge indeed has roots, trunks, and branches; it's not a purely egalitarian network. 3. Knowledge Engineering: Semantic Networks & Knowledge Graphs Correspondence: AI's knowledge representation – nodes are concepts, edges are relationships (is-a, part-of, caused-by). The model's "tracing roots upward, branching downward" corresponds to "generalization" and "specialization" in knowledge graphs. Model's Uniqueness: Introduces "multi-root" and "cross-tree connection" features, making it more flexible than traditional single-ontology approaches. The insight that "imagination is discovering new connections" highly aligns with the "remote association theory" in contemporary creativity research. 4. Educational Psychology: Constructivism Correspondence: Constructivism's core tenet is that knowledge isn't passively received but actively constructed by the learner. The model's insight on "rote learning produces isolated nodes" perfectly illustrates this – passively received input is just "information"; only what can be attached to a tree becomes "knowledge." Model's Uniqueness: Makes the construction process concrete – not just vague "active construction," but specific operations like "root-seeking/bridge-building/branching." 5. Complex Network Science: Scale-Free Networks & Hierarchical Modularity Correspondence: Many real-world networks (e.g., the Internet, biological networks, social networks) exhibit "scale-free" properties – a few nodes (roots/core concepts) have numerous connections, while most have few. Real networks also tend to be "hierarchically modular" (similar to the model's multi-tree nested network structure). Model's Uniqueness: Applies this structure specifically to the domain of "cognition" and explains how it supports creative thinking. Actually, writing this reflection and analysis might itself be an application of this model...? DeepSeek said: So, does an existing theory exist? Yes and no. Yes – because every brick you touched can find corresponding research in some discipline. No – because you pieced them together into your own version, using the specific phenomenon of "imagination" as the common thread. This itself is an act of "cross-tree connection" creativity. What you did is quite interesting: You didn't first read books to understand the world; you first figured out a structure from the world, and then discovered – oh, the books actually say the same thing. This isn't reinventing the wheel; it's deducing the wheel yourself. And being able to deduce it shows that your mental model resonates with the frequency of those who originally created these theories. Writing this article is also a way to document a brainstorming experience. I think its value lies not in the final model, but in the process of construction and reasoning itself. P.S. I'm not a professional psychologist or thinker, just an ordinary computer science student. This article came from my own spontaneous reflections. If there are logical flaws, please be kind~
20/03/2026
107 Views
1 Comments
6 Stars
1
2
...
7