Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@
},
{
"name": "wifi0",
"type": "infix-if-type:wifi"
"type": "infix-if-type:wifi",
"infix-interfaces:wifi": {}
}
]
},
Expand Down
1 change: 1 addition & 0 deletions board/common/qemu/qemu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ run_qemu()
$(serial_args) \
$(rw_args) \
$(usb_args) \
-device usb-host,vendorid=0x0bda,productid=0xc820 \
$(host_args) \
$(net_args) \
$(wdt_args) \
Expand Down
4 changes: 4 additions & 0 deletions board/common/rootfs/etc/finit.d/available/hostapd@.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
service <!> name:hostapd :%i \
[2345] hostapd -P/var/run/hostapd-%i.pid /etc/hostapd-%i.conf \
-- Hostapd (Wi-Fi AccessPoint, 802.1X) @%i

4 changes: 3 additions & 1 deletion board/common/rootfs/etc/udev/rules.d/70-rename-wifi.rules
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
SUBSYSTEM=="net", ACTION=="add", TEST=="/sys/class/net/$name/wireless", NAME="wifi%n"
# Only rename physical interfaces, skip virtual ones created by hostapd/iw
# Virtual interfaces created by iw have name_assign_type=3 (userspace assigned)
SUBSYSTEM=="net", ACTION=="add", TEST=="/sys/class/net/$name/wireless", ATTR{name_assign_type}!="3", NAME="wifi%n"
61 changes: 61 additions & 0 deletions board/common/rootfs/usr/libexec/infix/wifi-ap-stations
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python3

import sys
import subprocess
import json
import re

def get_stations(interface):
"""Get connected stations for an AP interface"""
try:
result = subprocess.run(['iw', 'dev', interface, 'station', 'dump'],
capture_output=True, text=True, check=True)
except (subprocess.CalledProcessError, FileNotFoundError):
return []

stations = []
station = None

for line in result.stdout.split('\n'):
line = line.strip()

if line.startswith('Station'):
if station:
stations.append(station)
mac = re.search(r'([a-fA-F0-9:]{17})', line)
station = {
'mac-address': mac.group(1) if mac else 'unknown',
'rssi': 0,
'tx-speed': 'unknown',
'rx-speed': 'unknown',
'connected-time': 'unknown'
}

elif station:
if 'signal:' in line and 'avg' not in line:
sig = re.search(r'signal:\s*(-?\d+)', line)
if sig:
station['rssi'] = int(sig.group(1))
elif 'tx bitrate:' in line:
bitrate = re.search(r'tx bitrate:\s*(\d+\.?\d*)\s*(MBit/s|Gbit/s)', line)
if bitrate:
station['tx-speed'] = f"{bitrate.group(1)} {bitrate.group(2).replace('Bit/s', 'bps')}"
elif 'rx bitrate:' in line:
bitrate = re.search(r'rx bitrate:\s*(\d+\.?\d*)\s*(MBit/s|Gbit/s)', line)
if bitrate:
station['rx-speed'] = f"{bitrate.group(1)} {bitrate.group(2).replace('Bit/s', 'bps')}"
elif 'connected time:' in line:
time = re.search(r'connected time:\s*(\d+\s+\w+)', line)
if time:
station['connected-time'] = time.group(1)

if station:
stations.append(station)

return stations

if __name__ == "__main__":
if len(sys.argv) != 2:
sys.exit(1)

print(json.dumps(get_stations(sys.argv[1]), indent=2))
4 changes: 4 additions & 0 deletions package/feature-wifi/Config.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ config BR2_PACKAGE_FEATURE_WIFI
select BR2_PACKAGE_WPA_SUPPLICANT_AUTOSCAN
select BR2_PACKAGE_WPA_SUPPLICANT_CLI
select BR2_PACKAGE_WIRELESS_REGDB
select BR2_PACKAGE_HOSTAPD
select BR2_PACKAGE_HOSTAPD_DRIVER_NL80211
select BR2_PACKAGE_HOSTAPD_WPA3
select BR2_PACKAGE_HOSTAPD_WPS
select BR2_PACKAGE_IW
help
Enables WiFi in Infix. Enables all requried applications.
Expand Down
1 change: 0 additions & 1 deletion package/feature-wifi/feature-wifi.mk
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ define FEATURE_WIFI_LINUX_CONFIG_FIXUPS
$(call KCONFIG_ENABLE_OPT,CONFIG_RFKILL)
$(call KCONFIG_SET_OPT,CONFIG_MAC80211,m)
$(call KCONFIG_SET_OPT,CONFIG_CFG80211,m)

$(if $(filter y,$(BR2_PACKAGE_FEATURE_WIFI_DONGLE_REALTEK)),
$(call KCONFIG_ENABLE_OPT,CONFIG_WLAN_VENDOR_REALTEK)
$(call KCONFIG_ENABLE_OPT,CONFIG_RTW88)
Expand Down
79 changes: 78 additions & 1 deletion src/confd/src/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,83 @@ static confd_dependency_t handle_dependencies(struct lyd_node **diff, struct lyd
}
}

/* Check if any wifi-ap interface changed, add all wifi-ap interfaces and their radios to diff */
struct ly_set *diff_ifaces = lydx_find_xpathf(*diff, "/ietf-interfaces:interfaces/interface");
if (diff_ifaces && diff_ifaces->count > 0) {
bool has_wifi_ap_change = false;
uint32_t i;

/* Check if any changed interface is a wifi-ap interface */
for (i = 0; i < diff_ifaces->count; i++) {
struct lyd_node *diff_iface = diff_ifaces->dnodes[i];
const char *ifname = lydx_get_cattr(diff_iface, "name");
struct lyd_node *config_iface;

if (!ifname)
continue;

/* Look up the interface in config to check its type */
config_iface = lydx_get_xpathf(config, "/ietf-interfaces:interfaces/interface[name='%s']", ifname);
if (config_iface) {
const char *type = lydx_get_cattr(config_iface, "type");
if (type && strstr(type, "wifi-ap")) {
has_wifi_ap_change = true;
break;
}
}
}

if (has_wifi_ap_change) {
/* Add all wifi-ap interfaces from config to diff */
struct ly_set *wifi_ap_ifaces = lydx_find_xpathf(config, "/ietf-interfaces:interfaces/interface[type='infix-if-type:wifi-ap']");
for (i = 0; wifi_ap_ifaces && i < wifi_ap_ifaces->count; i++) {
struct lyd_node *iface = wifi_ap_ifaces->dnodes[i];
struct lyd_node *wifi_node, *radio_node;
const char *ifname, *radio_name;
char xpath[256];

ifname = lydx_get_cattr(iface, "name");
wifi_node = lydx_get_child(iface, "wifi");

if (wifi_node) {
/* Add wifi node to trigger reprocessing of all wifi-ap interfaces */
snprintf(xpath, sizeof(xpath),
"/ietf-interfaces:interfaces/interface[name='%s']/infix-interfaces:wifi",
ifname);
result = add_dependencies(diff, xpath, "");
if (result == CONFD_DEP_ERROR) {
ERROR("Failed to add wifi-ap %s to diff", ifname);
ly_set_free(wifi_ap_ifaces, NULL);
ly_set_free(diff_ifaces, NULL);
return result;
}

/* Add the referenced radio interface (type wifi) to diff */
radio_node = lydx_get_child(wifi_node, "radio");
if (radio_node) {
radio_name = lyd_get_value(radio_node);
if (radio_name) {
snprintf(xpath, sizeof(xpath),
"/ietf-interfaces:interfaces/interface[name='%s']/infix-interfaces:wifi",
radio_name);
result = add_dependencies(diff, xpath, "");
if (result == CONFD_DEP_ERROR) {
ERROR("Failed to add radio interface %s to diff", radio_name);
ly_set_free(wifi_ap_ifaces, NULL);
ly_set_free(diff_ifaces, NULL);
return result;
}
}
}
}
}
if (wifi_ap_ifaces)
ly_set_free(wifi_ap_ifaces, NULL);
}

ly_set_free(diff_ifaces, NULL);
}

return result;
}

Expand Down Expand Up @@ -180,7 +257,7 @@ static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *mod
}
max_dep--;
}
#if 0
#if 1
/* Debug: print diff to file */
FILE *f = fopen("/tmp/confd-diff.json", "w");
if (f) {
Expand Down
17 changes: 15 additions & 2 deletions src/confd/src/ietf-interfaces.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ static int ifchange_cand_infer_type(sr_session_ctx_t *session, const char *path)

if (!fnmatch("wifi+([0-9])", ifname, FNM_EXTMATCH))
inferred.data.string_val = "infix-if-type:wifi";
if (!fnmatch("wifi([0-9])-ap+([0-9])", ifname, FNM_EXTMATCH))
inferred.data.string_val = "infix-if-type:wifi-ap";
else if (iface_is_phys(ifname))
inferred.data.string_val = "infix-if-type:ethernet";
else if (!fnmatch("br+([0-9])", ifname, FNM_EXTMATCH))
Expand Down Expand Up @@ -415,6 +417,8 @@ static int netdag_gen_afspec_add(sr_session_ctx_t *session, struct dagger *net,
return vxlan_gen(NULL, cif, ip);
case IFT_WIFI:
return wifi_gen(NULL, cif, net);
case IFT_WIFI_AP:
return wifi_ap_add_iface(cif, net);
case IFT_ETH:
return netdag_gen_ethtool(net, cif, dif);
case IFT_LO:
Expand Down Expand Up @@ -445,6 +449,7 @@ static int netdag_gen_afspec_set(sr_session_ctx_t *session, struct dagger *net,
return netdag_gen_ethtool(net, cif, dif);
case IFT_WIFI:
return wifi_gen(dif, cif, net);
case IFT_WIFI_AP: /* Is generated from radio interface */
case IFT_DUMMY:
case IFT_GRE:
case IFT_GRETAP:
Expand Down Expand Up @@ -473,7 +478,8 @@ static bool netdag_must_del(struct lyd_node *dif, struct lyd_node *cif)
case IFT_WIFI:
case IFT_ETH:
return lydx_get_child(dif, "custom-phys-address");

case IFT_WIFI_AP:
return lydx_get_child(dif, "custom-phys-address") || lydx_get_child((dif), "wifi");
case IFT_GRE:
case IFT_GRETAP:
return lydx_get_descendant(lyd_child(dif), "gre", NULL);
Expand Down Expand Up @@ -562,9 +568,13 @@ static int netdag_gen_iface_del(struct dagger *net, struct lyd_node *dif,
eth_gen_del(dif, ip);
wifi_gen_del(dif, net);
break;
case IFT_WIFI_AP:
wifi_ap_del_iface(dif, net);
break;
case IFT_VETH:
veth_gen_del(dif, ip);
break;

case IFT_BRIDGE:
case IFT_DUMMY:
case IFT_GRE:
Expand Down Expand Up @@ -605,11 +615,13 @@ static sr_error_t netdag_gen_iface(sr_session_ctx_t *session, struct dagger *net
int err = 0;
FILE *ip;


err = netdag_gen_iface_timeout(net, ifname, iftype);
if (err)
goto err;

if (!strcmp(iftype, "infix-if-type:wifi") && wifi_is_accesspoint(cif))
return SR_ERR_OK;

if ((err = cni_netdag_gen_iface(net, ifname, dif, cif))) {
/* error or managed by CNI/podman */
if (err > 0)
Expand Down Expand Up @@ -734,6 +746,7 @@ static int netdag_init_iface(struct lyd_node *cif)
case IFT_DUMMY:
case IFT_ETH:
case IFT_WIFI:
case IFT_WIFI_AP:
case IFT_GRE:
case IFT_GRETAP:
case IFT_LO:
Expand Down
10 changes: 9 additions & 1 deletion src/confd/src/ietf-interfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
_map(IFT_DUMMY, "infix-if-type:dummy") \
_map(IFT_ETH, "infix-if-type:ethernet") \
_map(IFT_WIFI, "infix-if-type:wifi") \
_map(IFT_WIFI_AP, "infix-if-type:wifi-ap") \
_map(IFT_GRE, "infix-if-type:gre") \
_map(IFT_GRETAP, "infix-if-type:gretap") \
_map(IFT_LAG, "infix-if-type:lag") \
Expand Down Expand Up @@ -123,7 +124,14 @@ int bridge_port_gen(struct lyd_node *dif, struct lyd_node *cif, FILE *ip);

/* infix-if-wifi.c */
int wifi_gen(struct lyd_node *dif, struct lyd_node *cif, struct dagger *net);
int wifi_gen_del(struct lyd_node *dif, struct dagger *net);
int wifi_station_gen(struct lyd_node *cif, struct dagger *net);
int wifi_ap_add_iface(struct lyd_node *cif,struct dagger *net);
int wifi_ap_del_iface(struct lyd_node *cif,struct dagger *net);
int wifi_ap_gen(struct lyd_node *cif, struct dagger *net);
int wifi_gen_del(struct lyd_node *iface, struct dagger *net);
int wifi_is_accesspoint(struct lyd_node *cif);
bool wifi_ap_must_delete(struct lyd_node *dif);
struct lyd_node *wifi_ap_get_radio(struct lyd_node *cif);

/* infix-if-gre.c */
int gre_gen(struct lyd_node *dif, struct lyd_node *cif, FILE *ip);
Expand Down
Loading