#!/bin/bash # Usage: ./init_adhoc.sh # Example: ./init_adhoc.sh phy0 wlan0 adhocnet 149 200 -95 # set -e set -xv ### === INPUT ARGUMENTS === PHYNAME=$1 DEVNAME=$2 SSID=$3 CHANNEL=$4 TXPOWER=$5 NOISEFLOOR=$6 shift 6 NODES=("$@") # dev_number="${2//[!0-9]/}" dev_number=$(echo "$DEVNAME" | grep -o '[0-9]\+$') echo "dev_number is: $dev_number" if [ -z "$PHYNAME" ] || [ -z "$DEVNAME" ] || [ -z "$SSID" ] || [ -z "$CHANNEL" ] || [ -z "$TXPOWER" ] || [ -z "$NOISEFLOOR" ]; then echo "Usage: $0 " exit 1 fi ### === PATHS === devPath="/sys/class/net/" phyPath="/sys/kernel/debug/ieee80211/" ### === SYSTEM TUNING === echo "[*] Applying system TCP/UDP/queue optimizations..." sysctl -w net.core.rmem_max=8388608 sysctl -w net.core.wmem_max=8388608 sysctl -w net.core.rmem_default=8388608 sysctl -w net.core.wmem_default=8388608 sysctl -w net.core.optmem_max=8388608 sysctl -w net.ipv4.tcp_mem="8388608 8388608 8388608" sysctl -w net.ipv4.tcp_rmem="4096 87380 8388608" sysctl -w net.ipv4.tcp_wmem="4096 65536 8388608" sysctl -w net.ipv4.udp_mem="8388608 8388608 8388608" sysctl -w net.ipv4.udp_rmem_min=4096 sysctl -w net.ipv4.udp_wmem_min=4096 sysctl -w net.core.netdev_max_backlog=5000 sysctl -w net.ipv4.tcp_max_syn_backlog=5000 sysctl -w net.ipv4.tcp_syn_retries=9 sysctl -w net.ipv4.tcp_synack_retries=9 sysctl -w net.ipv4.tcp_no_metrics_save=1 sysctl -w net.ipv4.route.flush=1 echo 0 > /sys/module/tcp_cubic/parameters/hystart echo 0 > /sys/module/tcp_cubic/parameters/hystart_detect sysctl -w net.ipv4.neigh.default.base_reachable_time_ms=1200000 sysctl -w net.ipv4.neigh.default.mcast_solicit=25 sysctl -w net.ipv4.neigh.default.ucast_solicit=25 ### === DEVICE SETUP === echo "[*] Checking and cleaning wireless devices..." # Remove existing device if needed if [ -e "$devPath$DEVNAME" ]; then echo "[*] Removing existing interface $DEVNAME" ip link set $DEVNAME down || true iw dev $DEVNAME del || true fi # Check if PHY exists if [ ! -e "$phyPath$PHYNAME" ]; then echo "[!] PHY $PHYNAME not found! Exiting." exit 1 fi # Remove current devs from PHY if needed current_dev_on_phy=$(iw dev | awk -v phy="${PHYNAME//[!0-9]/}" '$0 ~ "phy#"phy {getline; while ($1 == "Interface") {print $2; getline}}') if [ ! -z "$current_dev_on_phy" ]; then echo "[*] Removing device $current_dev_on_phy on $PHYNAME" ip link set $current_dev_on_phy down || true iw dev $current_dev_on_phy del || true fi echo "[*] Creating new IBSS interface $DEVNAME..." iw phy ${PHYNAME} interface add ${DEVNAME} type ibss # Set device parameters ip link set ${DEVNAME} down iw dev ${DEVNAME} set type ibss iw phy ${PHYNAME} set antenna 3 3 iw phy ${PHYNAME} set retry short 7 long 4 iw phy ${PHYNAME} set rts off iw dev ${DEVNAME} set power_save off iw dev ${DEVNAME} set txpower fixed ${TXPOWER} ip link set ${DEVNAME} up sleep 1 # --- Clean DHCP/ARP spam on adhoc interface --- echo "[*] Suppressing unsolicited ARP on $DEVNAME" sysctl -w net.ipv4.conf.${DEVNAME}.arp_ignore=1 sysctl -w net.ipv4.conf.${DEVNAME}.arp_announce=2 echo "[*] Stopping potential DHCP client on $DEVNAME" pkill -f "dhclient.*$DEVNAME" || true ### === FREQUENCY LOOKUP === source /opt/scripts/mesh/freq.sh FREQ=${chan[$CHANNEL]} if [[ -z "$FREQ" ]]; then echo "[!] Error: Channel $CHANNEL not found in freq.sh mapping!" exit 1 fi echo "Joining IBSS network SSID='$SSID' on ${FREQ} MHz (channel ${CHANNEL})..." BSSID="02:11:87:7B:5E:01" # Locally administered MAC address iw dev ${DEVNAME} ibss join ${SSID} ${FREQ} HT40+ fixed-freq ${BSSID} # iw dev ${DEVNAME} ibss join ${SSID} ${FREQ} HT20 ### === IP ADDRESS ASSIGNMENT === echo "[*] Setting IP address based on node identity..." source /opt/scripts/mesh/node_addresses.sh # Find hostname and corresponding IP HOSTNAME=$(uname -n) echo "HOSTNAME is: '$HOSTNAME'" NODE_NAME=$(echo $HOSTNAME | sed 's/\..*//') # strip domain if present echo "NODE_NAME is: '$NODE_NAME'" # IP_ADDR=${phy0IP["$NODE_NAME"]} # NODE_ID=$(echo "$NODE_NAME" | grep -o '[0-9]\+' | sed 's/^0*//') # Extract numeric ID NODE_ID=$(echo "$NODE_NAME" | sed -E 's/[^0-9]*([0-9]+)$/\1/') NODE_ID=$((10#$NODE_ID)) # Converts to decimal safely echo "NODEID: $NODE_ID" NODE_INDEX=-1 for idx in "${!NODES[@]}"; do if [[ "${NODES[$idx]}" -eq "$NODE_ID" ]]; then NODE_INDEX=$idx break fi done if [[ "$NODE_INDEX" -lt 0 ]]; then echo "Error: Node ID $NODE_ID not found in node list." exit 1 fi # get the dev corresponding IP if [[ "$dev_number" -eq 0 ]]; then IP_ADDR=${phy0IP["$NODE_NAME"]} BROADCAST_IP=${phy0IP["broadcast"]} fi if [[ "$dev_number" -eq 1 ]]; then IP_ADDR=${phy1IP["$NODE_NAME"]} BROADCAST_IP=${phy1IP["broadcast"]} fi if [[ -z "$IP_ADDR" ]]; then echo "[!] Error: No IP address found for $NODE_NAME in phy0IP." exit 1 fi # Remove any existing IPs ip addr flush dev ${DEVNAME} # Set IP address # ip addr add ${IP_ADDR}/24 dev ${DEVNAME} ip addr add ${IP_ADDR}/24 broadcast $BROADCAST_IP dev ${DEVNAME} echo "Assigned IP ${IP_ADDR}/24 to ${DEVNAME} with broadcast $BROADCAST_IP" # Set the interface up if (( NODE_INDEX > 0 && NODE_INDEX < ${#NODES[@]} - 1 )); then echo "[*] Enabling IP forwarding..." sysctl -w net.ipv4.ip_forward=1 fi # Set static routes to other nodes for target_idx in "${!NODES[@]}"; do target_node="${NODES[$target_idx]}" if [[ "$target_node" -eq "$NODE_ID" ]]; then continue; fi if (( target_idx < NODE_INDEX )); then # Left neighbor next_hop="${NODES[$((NODE_INDEX - 1))]}" else # Right neighbor next_hop="${NODES[$((NODE_INDEX + 1))]}" fi target_ip=${phy0IP["apu$(printf "%02d" $target_node)"]} next_ip=${phy0IP["apu$(printf "%02d" $next_hop)"]} echo "[*] Adding route to $target_ip via $next_ip" ip route add "$target_ip/32" via "$next_ip" dev "$DEVNAME" 2>/dev/null || true done ### === NOISE FLOOR SETTING === echo "Setting manual noise floor and ani..." echo 0 > /sys/kernel/debug/ieee80211/${PHYNAME}/ath9k/ani echo ${NOISEFLOOR} > /sys/kernel/debug/ieee80211/${PHYNAME}/ath9k/nf_override echo 198 > /sys/kernel/debug/ieee80211/${PHYNAME}/rc/fixed_rate_idx echo "IBSS Ad-Hoc wireless initialization complete." set +x