🚀 Sync 2026-06-07 17:45:31

This commit is contained in:
github-actions[bot] 2026-06-07 17:45:31 +08:00
parent a9100725c5
commit 9c74cc341d
13 changed files with 6 additions and 3779 deletions

View File

@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=26.6.2
PKG_RELEASE:=155
PKG_RELEASE:=156
PKG_PO_VERSION:=$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \

File diff suppressed because one or more lines are too long

View File

@ -1,22 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=quectel-qmi-wwan
PKG_VERSION:=1.2.9
PKG_RELEASE:=1
include $(INCLUDE_DIR)/kernel.mk
include $(INCLUDE_DIR)/package.mk
define KernelPackage/usb-net-qmi-wwan-quectel
SUBMENU:=USB Support
TITLE:=QMI WWAN driver for Quectel modules
DEPENDS:=+kmod-usb-net +kmod-usb-wdm
FILES:=$(PKG_BUILD_DIR)/qmi_wwan_q.ko
AUTOLOAD:=$(call AutoLoad,81,qmi_wwan_q)
endef
define Build/Compile
+$(KERNEL_MAKE) M="$(PKG_BUILD_DIR)" modules
endef
$(eval $(call KernelPackage,usb-net-qmi-wwan-quectel))

View File

@ -1,13 +0,0 @@
--- a/qmi_wwan_q.c
+++ b/qmi_wwan_q.c
@@ -62,9 +62,8 @@ struct rmnet_nss_cb {
int (*nss_tx)(struct sk_buff *skb);
};
static struct rmnet_nss_cb __read_mostly *nss_cb = NULL;
-#if defined(CONFIG_PINCTRL_IPQ807x) || defined(CONFIG_PINCTRL_IPQ5018) || defined(CONFIG_PINCTRL_IPQ8074)
+#if defined(CONFIG_QCA_NSS_DRV)
//#ifdef CONFIG_RMNET_DATA //spf12.x none, not effect for spf11.x
-#define CONFIG_QCA_NSS_DRV
/* define at qsdk/qca/src/linux-4.4/net/rmnet_data/rmnet_data_main.c */ //for spf11.x
/* define at qsdk/qca/src/datarmnet/core/rmnet_config.c */ //for spf12.x
/* set at qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c */

View File

@ -1,44 +0,0 @@
--- a/qmi_wwan_q.c
+++ b/qmi_wwan_q.c
@@ -896,7 +896,7 @@ static void usbnet_bh(unsigned long data
struct tasklet_struct *t = &pQmapDev->usbnet_bh;
bool use_callback = false;
-#if (LINUX_VERSION_CODE > KERNEL_VERSION( 5,8,0 )) //c955e329bb9d44fab75cf2116542fcc0de0473c5
+#if (LINUX_VERSION_CODE > KERNEL_VERSION( 5,8,0 )) && (LINUX_VERSION_CODE < KERNEL_VERSION( 6,17,0 ))
use_callback = t->use_callback;
if (use_callback)
t->callback(&pQmapDev->mpNetDev->bh);
@@ -1368,8 +1368,12 @@ static int qmap_register_device(sQmiWwan
#endif
priv->agg_skb = NULL;
priv->agg_count = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,18,0)
hrtimer_init(&priv->agg_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
priv->agg_hrtimer.function = rmnet_usb_tx_agg_timer_cb;
+#else
+ hrtimer_setup(&priv->agg_hrtimer, rmnet_usb_tx_agg_timer_cb, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+#endif
INIT_WORK(&priv->agg_wq, rmnet_usb_tx_agg_work);
ktime_get_ts64(&priv->agg_time);
spin_lock_init(&priv->agg_lock);
@@ -1472,7 +1476,7 @@ typedef struct {
} BRMAC_SETTING;
#endif
-int qma_setting_store(struct device *dev, QMAP_SETTING *qmap_settings, size_t size) {
+static int qma_setting_store(struct device *dev, QMAP_SETTING *qmap_settings, size_t size) {
struct net_device *netdev = to_net_dev(dev);
struct usbnet * usbnetdev = netdev_priv( netdev );
struct qmi_wwan_state *info = (void *)&usbnetdev->data;
@@ -2266,8 +2270,10 @@ static int qmi_wwan_bind(struct usbnet *
}
if (pQmapDev->use_rmnet_usb && !one_card_mode) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION( 6,17,0 ))
pQmapDev->usbnet_bh = dev->bh;
tasklet_init(&dev->bh, usbnet_bh, (unsigned long)pQmapDev);
+#endif
}
}
}

View File

@ -1,28 +0,0 @@
From 85990e155cb684ec6380bcf70f588255ec41dc69 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=80=AC=E5=90=8D=E7=94=B1=E5=B8=8C?=
<wanglei199909210927@gmail.com>
Date: Wed, 5 Nov 2025 14:16:56 +0800
Subject: [PATCH] qmi_wwan: return correct tx/rx stats in kernel 6.10+ (#130)
---
driver/fibocom_QMI_WWAN/src/qmi_wwan_f.c | 9 ++++++++-
driver/quectel_QMI_WWAN/src/qmi_wwan_q.c | 7 +++++++
2 files changed, 15 insertions(+), 1 deletion(-)
--- a/qmi_wwan_q.c
+++ b/qmi_wwan_q.c
@@ -2153,7 +2153,14 @@ static int qmi_wwan_bind(struct usbnet *
#endif
}
if (!_usbnet_get_stats64)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION( 6,10,0 ))
_usbnet_get_stats64 = dev->net->netdev_ops->ndo_get_stats64;
+#else
+ /* From kernel 6.10+, usbnet sets pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS (352f5b3282), but removed ndo_get_stats64 (9cb3d523c1) */
+ /* Use dev_get_tstats64 to read per-CPU stats when NETDEV_PCPU_STAT_TSTATS was set */
+ if (dev->net->pcpu_stat_type == NETDEV_PCPU_STAT_TSTATS)
+ _usbnet_get_stats64 = dev_get_tstats64;
+#endif
dev->net->netdev_ops = &qmi_wwan_netdev_ops;
ql_net_ethtool_ops = *dev->net->ethtool_ops;

View File

@ -1,16 +0,0 @@
--- a/qmi_wwan_q.c
+++ b/qmi_wwan_q.c
@@ -2563,6 +2563,13 @@ static const struct usb_device_id produc
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0800, 4, sdx55) }, /* Quectel RG500 */
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0801, 4, sdx55) }, /* Quectel RG520 */
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0122, 4, sdx55) }, /* Quectel RG650 */
+ { QMI_FIXED_RAWIP_INTF(0x05c6, 0x90d5, 3, sdx55) }, /* Foxconn T99W240T00 */
+ { QMI_FIXED_RAWIP_INTF(0x05c6, 0x90db, 2, sdx55) }, /* SIM8200 */
+ { QMI_FIXED_RAWIP_INTF(0x02dee, 0x4d22, 5, sdx55) }, /* Meige SRM815 */
+ { QMI_FIXED_RAWIP_INTF(0x305a, 0x1421, 3, sdx55) }, /* gm800 */
+ { QMI_FIXED_RAWIP_INTF(0x305a, 0x1403, 3, sdx55) }, /* gm800 */
+ { QMI_FIXED_RAWIP_INTF(0x05C6, 0x9025, 4, sdx55) },
+ { QMI_FIXED_RAWIP_INTF(0x05C6, 0x9091, 2, sdx55) },
{ } /* END */
};
MODULE_DEVICE_TABLE(usb, products);

View File

@ -1,36 +0,0 @@
obj-m += qmi_wwan_q.o
DIR := $(shell pwd)
OUTPUTDIR=/lib/modules/`uname -r`/kernel/drivers/net/usb/
ifeq ($(ARCH),)
ARCH := $(shell uname -m)
endif
ifeq ($(CROSS_COMPILE),)
CROSS_COMPILE :=
endif
ifeq ($(KDIR),)
KDIR := /lib/modules/$(shell uname -r)/build
ifeq ($(ARCH),i686)
ifeq ($(wildcard $KDIR/arch/$ARCH),)
ARCH=i386
endif
endif
endif
ifneq ($(findstring &,${DIR}),)
$(warning "${DIR}")
$(warning "current directory contain special char '&' !")
$(error "please remove it!")
endif
default:
$(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(DIR) modules
install: default
cp $(DIR)/qmi_wwan_q.ko /lib/modules/$(shell uname -r)/kernel/drivers/net/usb/
depmod
clean:
rm -rf *~ .tmp_versions modules.order Module.symvers
find . -type f -name "*~" -o -name "*.o" -o -name "*.ko" -o -name "*.cmd" -o -name "*.mod.c" | xargs rm -rf

View File

@ -1,177 +0,0 @@
Release Notes
[V1.2.7]
Date: 1/12/2024
enhancement:
1. support SDX35 platform
fix:
[V1.2.6]
Date: 5/25/2023
enhancement:
1. support Linux 6.1
fix:
[V1.2.5]
Date: 5/4/2023
enhancement:
1. support Linux 5.19
2. NSS not effect on SPF12.x and support SFE on 9574
fix:
[V1.2.4]
Date: 4/14/2023
enhancement:
1. support SDX7X platform
fix:
[V1.2.3]
Date: 9/20/2022
enhancement:
1. support 9x07(pid 0x030E) platform
fix:
[V1.2.2]
Date: 9/7/2022
enhancement:
1. Optimization, the network card send queue wakeup is changed from callback to tasklet
2. Add the function of returning LAN packets in bridge mode
3. support ndo ioctl on kernel>5.14
4. Allow setting MTU greater than 1500
fix:
[V1.2.1]
Date: 9/26/2021
enhancement:
1. support IPQ5018's NSS
2. use 'qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c' instead myself rmnet_nss.c
and qmi_wwan_q.ko must load after rmnet_nss.ko
fix:
[V1.2.0.25]
Date: 9/17/2021
enhancement:
fix:
1. add sdx6x platfrom support
[V1.2.0.24]
Date: 9/6/2021
enhancement:
fix:
1. add BG95 support
2. support Linux 5.14.0
[V1.2.0.23]
Date: 3/23/2021
enhancement:
fix:
1. add sdx12 platfrom support
[V1.2.0.22]
Date: 2/5/2021
enhancement:
fix:
1. fix panic (memory-access-after-free) when do modem reboot stress test
[V1.2.0.21]
Date: 2/4/2021
enhancement:
1. Code refactoring - QMAP and rmnet
fix:
1. qmap_qmi_wwan_rx_fixup: change skb_dequeue to __skb_dequeue
[V1.2.0.20]
Date: 11/2/2020
enhancement:
fix:
1. LTE-A modems can not obtain IP by DHCP
[V1.2.0.19]
Date: 10/9/2020
enhancement:
fix:
1. X55 can not access internet after usb resume
[V1.2.0.18]
Date: 10/9/2020
enhancement:
fix:
1. X55: rename rmnet_usb0.1 to wwan0_1
1.1 if there is '.', openwrt will think it is vlan, and auto create vlan
1.2 if there is '.', android will think it is not vaild
1.3 if named as rmnet_usb0, and SOC is QCOM, QCOM's netmgr will auto manager it
[V1.2.0.17]
Date: 9/14/2020
enhancement:
1. Code refactoring - QMAP size and version
fix:
[V1.2.0.16]
Date: 9/14/2020
enhancement:
1. rx_fixup() check if this is enough skb_headroom() to fill ethernet header
fix:
1. fix "WARNING: suspicious RCU usage"
[V1.2.0.15]
Date: 9/10/2020
enhancement:
fix:
1. fix compile errors on kernel 3.10~3.13
[V1.2.0.14]
Date: 7/24/2020
enhancement:
fix:
1. fix QMAP V5 bug on Big Endian CPU
[V1.2.0.13]
Date: 6/22/2020
enhancement:
fix:
1. fix no data traffic when do Upload TPUT test
[V1.2.0.12]
Date: 5/29/2020
enhancement:
fix:
1. IPQ8074: when enable hyfi, quectel-CM will crash system crash
[V1.2.0.9]
Date: 5/13/2020
enhancement:
fix:
1. IPQ8074: enable CONFIG_QCA_NSS_DRV by CONFIG_PINCTRL_IPQ807x (from CONFIG_ARCH_IPQ807x)
[V1.2.0.8]
Date: 5/9/2020
enhancement:
fix:
1. fix compile errors on kernel V3.10
[V1.2.0.7]
Date: 4/25/2020
enhancement:
1. X55 support bridge mode
fix:
[V1.2.0.6]
Date: 4/20/2020
enhancement:
1. add stat64, or the rx/tx statics will become to 0 when data > 4G
2. do not use skb_clone, will make QCOM's NSS and SFE 's cpu loading very high
fix:
[V1.2.0.5]
Date: 4/8/2020
enhancement:
1. add attrite link_state, change carrier state accoring link_state
quectel-CM will set link_state to 1 when QMI setup call success.
fix:
[V1.2.0.4]
Date: 4/8/2020
enhancement:
1. support X55's QMAP V5
fix:

View File

@ -1,68 +0,0 @@
1. Enable QUECTEL_BRIDGE_MODE in qmi_wwan_q.c
2. Guide to use ....
Welcome to Buildroot for the Orange Pi Zero
OrangePi_Zero login: root
# insmod qmi_wwan_q.ko
[ 90.591841] qmi_wwan_q 3-1:1.4: cdc-wdm0: USB WDM device
[ 90.597185] qmi_wwan_q 3-1:1.4: Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&EG12&EP12&EM12&EG16&EG18&BG96&AG35 work on RawIP mode
[ 90.610176] qmi_wwan_q 3-1:1.4: rx_urb_size = 32768
[ 90.620589] qmi_wwan_q 3-1:1.4 wwan0: register 'qmi_wwan_q' at usb-1c1b000.usb-1, WWAN/QMI device, 96:42:59:a9:f5:e4
[ 90.631293] usbcore: registered new interface driver qmi_wwan_q
# brctl addbr br0
# brctl addif br0 eth0
[ 100.413071] br0: port 1(eth0) entered blocking state
[ 100.418081] br0: port 1(eth0) entered disabled state
[ 100.423356] device eth0 entered promiscuous mode
# brctl addif br0 wwan0
[ 102.696724] br0: port 2(wwan0) entered blocking state
[ 102.701823] br0: port 2(wwan0) entered disabled state
[ 102.707182] device wwan0 entered promiscuous mode
# ifconfig br0 up
[ 110.405561] br0: port 1(eth0) entered blocking state
[ 110.410567] br0: port 1(eth0) entered forwarding state
# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.0242b22e80d8 no eth0
wwan0
# ./quectel-CM &
# [01-01_06:37:02:386] Quectel_QConnectManager_Linux_V1.4.3
[01-01_06:37:02:388] Find /sys/bus/usb/devices/3-1 idVendor=0x2c7c idProduct=0x512
[01-01_06:37:02:388] Auto find qmichannel = /dev/cdc-wdm0
[01-01_06:37:02:388] Auto find usbnet_adapter = wwan0
[01-01_06:37:02:389] qmap_mode = 1, muxid = 0x81, qmap_netcard = wwan0
[01-01_06:37:02:389] Modem works in QMI mode
[01-01_06:37:02:389] qmap_mode = 1, muxid = 0x81, qmap_netcard = wwan0
[01-01_06:37:02:394] cdc_wdm_fd = 7
[01-01_06:37:02:561] Get clientWDS = 18
[01-01_06:37:02:633] Get clientDMS = 1
[01-01_06:37:02:689] Get clientNAS = 2
[01-01_06:37:02:753] Get clientUIM = 1
[01-01_06:37:02:817] Get clientWDA = 1
[01-01_06:37:02:881] requestBaseBandVersion EM12GBATE1127
[01-01_06:37:02:945] qmap_settings.rx_urb_size = 16384
[01-01_06:37:03:201] requestGetSIMStatus SIMStatus: SIM_READY
[01-01_06:37:03:265] requestGetProfile[1] ctnet///0
[01-01_06:37:03:329] requestRegistrationState2 MCC: 460, MNC: 11, PS: Attached, DataCap: LTE
[01-01_06:37:03:393] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[01-01_06:37:03:457] requestSetupDataCall WdsConnectionIPv4Handle: 0x192a5ed0
[01-01_06:37:03:717] ifconfig wwan0 up
[01-01_06:37:03:747] echo '0x64b69855' > /sys/module/qmi_wwan_q/parameters/bridge_ipv4
[ 117.030116] net wwan0: link_state 0x0 -> 0x1
[ 117.041259] br0: port 2(wwan0) entered blocking state
[ 117.046326] br0: port 2(wwan0) entered forwarding state
[ 117.336688] net wwan0: sip = 100.182.152.85, tip=100.182.152.86, ipv4=100.182.152.85
[ 121.612281] random: crng init done
[ 128.143645] net wwan0: PC Mac Address: 5e:6b:82:fa:ab:c3
[ 128.151936] net wwan0: rx_pkts=1, rx_len=312
[ 128.203578] net wwan0: PC Mac Address: 5e:6b:82:fa:ab:c3
[ 131.012891] net wwan0: sip = 100.182.152.85, tip=100.182.152.86, ipv4=100.182.152.85
[ 131.341780] net wwan0: rx_pkts=1, rx_len=316
[ 131.434642] net wwan0: rx_pkts=1, rx_len=1404
[ 131.439416] net wwan0: rx_pkts=3, rx_len=4212
[ 131.512782] net wwan0: rx_pkts=4, rx_len=5616
[ 131.535345] net wwan0: rx_pkts=7, rx_len=9828
[ 133.778699] net wwan0: rx_pkts=8, rx_len=11232
[ 134.143941] net wwan0: rx_pkts=9, rx_len=12636
[ 140.053957] net wwan0: rx_pkts=11, rx_len=15444

View File

@ -1,234 +0,0 @@
1. Enable QUECTEL_BRIDGE_MODE in qmi_wwan_q.c
2. set qmap_mode to 4
3. if you want add wwan0.2 to br2, wwan0.3 to br3
set bridge_mode to BIT(1)|BIT(2)
4. Guide to use ....
# insmod qmi_wwan_q.ko qmap_mode=4 bridge_mode=6
[243467.331669] qmi_wwan_q 3-1:1.4: cdc-wdm0: USB WDM device
[243467.337136] qmi_wwan_q 3-1:1.4: Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&EG12&EP12&EM12&EG16&EG18&BG96&AG35 work on RawIP mode
[243467.349471] qmi_wwan_q 3-1:1.4: rx_urb_size = 32768
[243467.364803] qmi_wwan_q 3-1:1.4 wwan0: register 'qmi_wwan_q' at usb-1c1b000.usb-1, WWAN/QMI device, 96:42:59:a9:f5:e4
[243467.376025] net wwan0: qmap_register_device wwan0.1
[243467.381658] net wwan0: qmap_register_device wwan0.2
[243467.387281] net wwan0: qmap_register_device wwan0.3
[243467.392851] net wwan0: qmap_register_device wwan0.4
[243467.398106] usbcore: registered new interface driver qmi_wwan_q
# cat /sys/class/net/wwan0.2/bridge_mode
1
# cat /sys/class/net/wwan0.3/bridge_mode
1
# brctl addbr br2
# brctl addif br2 wwan0.2
[243492.518563] br2: port 1(wwan0.2) entered blocking state
[243492.523888] br2: port 1(wwan0.2) entered disabled state
[243492.535948] device wwan0.2 entered promiscuous mode
# brctl addbr br3
# brctl addif br3 wwan0.3
[243507.486717] br3: port 1(wwan0.3) entered blocking state
[243507.492248] br3: port 1(wwan0.3) entered disabled state
[243507.497982] device wwan0.3 entered promiscuous mode
# brctl show
bridge name bridge id STP enabled interfaces
br2 8000.964259a9f5e4 no wwan0.2
br3 8000.964259a9f5e4 no wwan0.3
# ./quectel-qmi-proxy &
# Find /sys/bus/usb/devices/3-1 idVendor=2c7c idProduct=0512
Find /sys/bus/usb/devices/3-1:1.4/usbmisc/cdc-wdm0
Will use cdc-wdm /dev/cdc-wdm0
qmi_proxy_init enter
qmi_proxy_loop enter
link_prot 2
ul_data_aggregation_protocol 5
dl_data_aggregation_protocol 5
dl_data_aggregation_max_datagrams 32
dl_data_aggregation_max_size 16384
ul_data_aggregation_max_datagrams 16
ul_data_aggregation_max_size 3072
qmi_proxy_init finished, rx_urb_size is 16384
local server: quectel-qmi-proxy sockfd = 4
qmi_start_server: qmi_proxy_server_fd = 4
# ./quectel-CM -n 2 &
# [01-04_02:13:53:053] Quectel_QConnectManager_Linux_V1.4.3
[01-04_02:13:53:056] Find /sys/bus/usb/devices/3-1 idVendor=0x2c7c idProduct=0x512
[01-04_02:13:53:056] Auto find qmichannel = /dev/cdc-wdm0
[01-04_02:13:53:056] Auto find usbnet_adapter = wwan0
[01-04_02:13:53:056] qmap_mode = 4, muxid = 0x82, qmap_netcard = wwan0.2
[01-04_02:13:53:057] Modem works in QMI mode
[01-04_02:13:53:057] qmap_mode = 4, muxid = 0x82, qmap_netcard = wwan0.2
+++ ClientFd=5
[01-04_02:13:53:058] connect to quectel-qmi-proxy sockfd = 7
[01-04_02:13:53:058] cdc_wdm_fd = 7
+++ ClientFd=5 QMIType=1 ClientId=18
[01-04_02:13:53:130] Get clientWDS = 18
+++ ClientFd=5 QMIType=2 ClientId=1
[01-04_02:13:53:194] Get clientDMS = 1
+++ ClientFd=5 QMIType=3 ClientId=2
[01-04_02:13:53:258] Get clientNAS = 2
+++ ClientFd=5 QMIType=11 ClientId=2
[01-04_02:13:53:333] Get clientUIM = 2
[01-04_02:13:53:386] requestBaseBandVersion EM12GBATE1127
[01-04_02:13:53:642] requestGetSIMStatus SIMStatus: SIM_READY
[01-04_02:13:53:706] requestGetProfile[2] IMS///0
[01-04_02:13:53:770] requestRegistrationState2 MCC: 460, MNC: 11, PS: Attached, DataCap: LTE
[01-04_02:13:53:841] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[01-04_02:13:54:058] requestSetupDataCall WdsConnectionIPv4Handle: 0x78a3aba0
[243527.630628] net wwan0: link_state 0x0 -> 0x2
[01-04_02:13:54:319] ifconfig wwan0 up
[01-04_02:13:54:325] ifconfig wwan0.2 up
[01-04_02:13:54:330] echo '0x645026c8' > /sys/class/net/wwan0.2/bridge_ipv4
# udhcpc -i br2
udhcpc: started, v1.29.3
[243532.653027] br2: port 1(wwan0.2) entered blocking state
[243532.658384] br2: port 1(wwan0.2) entered forwarding state
udhcpc: sending discover
[243532.784337] wwan0.2 PC Mac Address: 96:42:59:a9:f5:e4
[243532.794813] net wwan0: rx_pkts=1, rx_len=312
udhcpc: sending select for 100.80.38.200
[243532.894325] wwan0.2 PC Mac Address: 96:42:59:a9:f5:e4
udhcpc: lease of 100.80.38.200 obtained, lease time 7200
deleting routers
adding dns 202.102.213.68
adding dns 61.132.163.68
# ./quectel-CM -n 3 &
# [01-04_02:14:03:645] Quectel_QConnectManager_Linux_V1.4.3
[01-04_02:14:03:648] Find /sys/bus/usb/devices/3-1 idVendor=0x2c7c idProduct=0x512
[01-04_02:14:03:648] Auto find qmichannel = /dev/cdc-wdm0
[01-04_02:14:03:648] Auto find usbnet_adapter = wwan0
[01-04_02:14:03:649] qmap_mode = 4, muxid = 0x83, qmap_netcard = wwan0.3
[01-04_02:14:03:649] Modem works in QMI mode
[01-04_02:14:03:649] qmap_mode = 4, muxid = 0x83, qmap_netcard = wwan0.3
[01-04_02:14:03:650] connect to quectel-qmi-proxy sockfd = 7
+++ ClientFd=6
[01-04_02:14:03:650] cdc_wdm_fd = 7
+++ ClientFd=6 QMIType=1 ClientId=19
[01-04_02:14:03:722] Get clientWDS = 19
+++ ClientFd=6 QMIType=2 ClientId=2
[01-04_02:14:03:786] Get clientDMS = 2
+++ ClientFd=6 QMIType=3 ClientId=3
[01-04_02:14:03:850] Get clientNAS = 3
+++ ClientFd=6 QMIType=11 ClientId=3
[01-04_02:14:03:914] Get clientUIM = 3
[01-04_02:14:03:978] requestBaseBandVersion EM12GBATE1127
[01-04_02:14:04:235] requestGetSIMStatus SIMStatus: SIM_READY
[01-04_02:14:04:298] requestGetProfile[3] lte///0
[01-04_02:14:04:362] requestRegistrationState2 MCC: 460, MNC: 11, PS: Attached, DataCap: LTE
[01-04_02:14:04:426] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[01-04_02:14:04:555] requestSetupDataCall WdsConnectionIPv4Handle: 0x78a5c850
[243538.126755] net wwan0: link_state 0x2 -> 0x6
[01-04_02:14:04:815] ifconfig wwan0 up
[01-04_02:14:04:824] ifconfig wwan0.3 up
[01-04_02:14:04:829] echo '0x64548ae0' > /sys/class/net/wwan0.3/bridge_ipv4
# udhcpc -i br3
udhcpc: started, v1.29.3
[243541.850178] br3: port 1(wwan0.3) entered blocking state
[243541.855509] br3: port 1(wwan0.3) entered forwarding state
udhcpc: sending discover
[243541.976693] wwan0.3 PC Mac Address: 96:42:59:a9:f5:e4
udhcpc: sending select for 100.84.138.224
[243542.056668] wwan0.3 PC Mac Address: 96:42:59:a9:f5:e4
udhcpc: lease of 100.84.138.224 obtained, lease time 7200
deleting routers
adding dns 202.102.213.68
adding dns 61.132.163.68
# ./quectel-CM -n 1 &
# [01-04_02:14:12:742] Quectel_QConnectManager_Linux_V1.4.3
[01-04_02:14:12:744] Find /sys/bus/usb/devices/3-1 idVendor=0x2c7c idProduct=0x512
[01-04_02:14:12:745] Auto find qmichannel = /dev/cdc-wdm0
[01-04_02:14:12:745] Auto find usbnet_adapter = wwan0
[01-04_02:14:12:745] qmap_mode = 4, muxid = 0x81, qmap_netcard = wwan0.1
[01-04_02:14:12:745] Modem works in QMI mode
[01-04_02:14:12:746] qmap_mode = 4, muxid = 0x81, qmap_netcard = wwan0.1
[01-04_02:14:12:746] connect to quectel-qmi-proxy sockfd = 7
+++ ClientFd=7
[01-04_02:14:12:746] cdc_wdm_fd = 7
+++ ClientFd=7 QMIType=1 ClientId=20
[01-04_02:14:12:842] Get clientWDS = 20
+++ ClientFd=7 QMIType=2 ClientId=3
[01-04_02:14:12:906] Get clientDMS = 3
+++ ClientFd=7 QMIType=3 ClientId=4
[01-04_02:14:12:970] Get clientNAS = 4
+++ ClientFd=7 QMIType=11 ClientId=4
[01-04_02:14:13:034] Get clientUIM = 4
[01-04_02:14:13:098] requestBaseBandVersion EM12GBATE1127
[01-04_02:14:13:354] requestGetSIMStatus SIMStatus: SIM_READY
[01-04_02:14:13:418] requestGetProfile[1] ctnet///0
[01-04_02:14:13:483] requestRegistrationState2 MCC: 460, MNC: 11, PS: Attached, DataCap: LTE
[01-04_02:14:13:546] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[01-04_02:14:13:610] requestSetupDataCall WdsConnectionIPv4Handle: 0x78a92b30
[243547.182801] net wwan0: link_state 0x6 -> 0x7
[01-04_02:14:13:874] ifconfig wwan0 up
[01-04_02:14:13:880] ifconfig wwan0.1 up
[01-04_02:14:13:885] busybox udhcpc -f -n -q -t 5 -i wwan0.1
udhcpc: started, v1.29.3
udhcpc: sending discover
udhcpc: sending select for 10.175.212.85
udhcpc: lease of 10.175.212.85 obtained, lease time 7200
[01-04_02:14:14:175] deleting routers
[01-04_02:14:14:194] adding dns 202.102.213.68
[01-04_02:14:14:195] adding dns 61.132.163.68
# ifconfig
br2 Link encap:Ethernet HWaddr 96:42:59:A9:F5:E4
inet addr:100.80.38.200 Bcast:100.80.38.207 Mask:255.255.255.240
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:612 (612.0 B) TX bytes:684 (684.0 B)
br3 Link encap:Ethernet HWaddr 96:42:59:A9:F5:E4
inet addr:100.84.138.224 Bcast:100.84.138.255 Mask:255.255.255.192
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:612 (612.0 B) TX bytes:684 (684.0 B)
wwan0 Link encap:Ethernet HWaddr 96:42:59:A9:F5:E4
UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
wwan0.1 Link encap:Ethernet HWaddr 96:42:59:A9:F5:E4
inet addr:10.175.212.85 Bcast:10.175.212.87 Mask:255.255.255.252
UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:612 (612.0 B) TX bytes:664 (664.0 B)
wwan0.2 Link encap:Ethernet HWaddr 96:42:59:A9:F5:E4
UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:612 (612.0 B) TX bytes:664 (664.0 B)
wwan0.3 Link encap:Ethernet HWaddr 96:42:59:A9:F5:E4
UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:612 (612.0 B) TX bytes:664 (664.0 B)

File diff suppressed because it is too large Load Diff

View File

@ -1,428 +0,0 @@
/*
Copyright (c) 2023, The Linux Foundation. All rights reserved.
This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General
Public licenseas published byFree Software Foundation; either version 2theof the License,(at your option)
any later version.O1
This program isdistributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the
implied warranty ofOr FITNESS FOR A PARTICULAR PURPOSE.MERCHANTABILITYSee theGNU General Public License
for more details.
You should have received a copy of the GNU General Public licensealong withthis program; if not, write to
the Free SoftwareFoundation, Inc.r51 Franklin Street,Fifth Floor,Boston,MA 02110-1301,USA.
Based on version modification, the author is Quectel <fae-support@quectel.com>
*/
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/hashtable.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <qca-nss-drv/nss_api_if.h>
#include <linux/rmnet_nss.h>
#define RMNET_NSS_HASH_BITS 8
#define hash_add_ptr(table, node, key) \
hlist_add_head(node, &table[hash_ptr(key, HASH_BITS(table))])
static DEFINE_HASHTABLE(rmnet_nss_ctx_hashtable, RMNET_NSS_HASH_BITS);
struct rmnet_nss_ctx {
struct hlist_node hnode;
struct net_device *rmnet_dev;
struct nss_rmnet_rx_handle *nss_ctx;
};
enum __rmnet_nss_stat {
RMNET_NSS_RX_ETH,
RMNET_NSS_RX_FAIL,
RMNET_NSS_RX_NON_ETH,
RMNET_NSS_RX_BUSY,
RMNET_NSS_TX_NO_CTX,
RMNET_NSS_TX_SUCCESS,
RMNET_NSS_TX_FAIL,
RMNET_NSS_TX_NONLINEAR,
RMNET_NSS_TX_BAD_IP,
RMNET_NSS_EXCEPTIONS,
RMNET_NSS_EX_BAD_HDR,
RMNET_NSS_EX_BAD_IP,
RMNET_NSS_EX_SUCCESS,
RMNET_NSS_TX_BAD_FRAGS,
RMNET_NSS_TX_LINEARIZE_FAILS,
RMNET_NSS_TX_NON_ZERO_HEADLEN_FRAGS,
RMNET_NSS_TX_BUSY_LOOP,
RMNET_NSS_NUM_STATS,
};
static unsigned long rmnet_nss_stats[RMNET_NSS_NUM_STATS];
#define RMNET_NSS_STAT(name, counter, desc) \
module_param_named(name, rmnet_nss_stats[counter], ulong, 0444); \
MODULE_PARM_DESC(name, desc)
RMNET_NSS_STAT(rmnet_nss_rx_ethernet, RMNET_NSS_RX_ETH,
"Number of Ethernet headers successfully removed");
RMNET_NSS_STAT(rmnet_nss_rx_fail, RMNET_NSS_RX_FAIL,
"Number of Ethernet headers that could not be removed");
RMNET_NSS_STAT(rmnet_nss_rx_non_ethernet, RMNET_NSS_RX_NON_ETH,
"Number of non-Ethernet packets received");
RMNET_NSS_STAT(rmnet_nss_rx_busy, RMNET_NSS_RX_BUSY,
"Number of packets dropped decause rmnet_data device was busy");
RMNET_NSS_STAT(rmnet_nss_tx_slow, RMNET_NSS_TX_NO_CTX,
"Number of packets sent over non-NSS-accelerated rmnet device");
RMNET_NSS_STAT(rmnet_nss_tx_fast, RMNET_NSS_TX_SUCCESS,
"Number of packets sent over NSS-accelerated rmnet device");
RMNET_NSS_STAT(rmnet_nss_tx_fail, RMNET_NSS_TX_FAIL,
"Number of packets that NSS could not transmit");
RMNET_NSS_STAT(rmnet_nss_tx_nonlinear, RMNET_NSS_TX_NONLINEAR,
"Number of non linear sent over NSS-accelerated rmnet device");
RMNET_NSS_STAT(rmnet_nss_tx_invalid_ip, RMNET_NSS_TX_BAD_IP,
"Number of ingress packets with invalid IP headers");
RMNET_NSS_STAT(rmnet_nss_tx_invalid_frags, RMNET_NSS_TX_BAD_FRAGS,
"Number of ingress packets with invalid frag format");
RMNET_NSS_STAT(rmnet_nss_tx_linearize_fail, RMNET_NSS_TX_LINEARIZE_FAILS,
"Number of ingress packets where linearize in tx fails");
RMNET_NSS_STAT(rmnet_nss_tx_exceptions, RMNET_NSS_EXCEPTIONS,
"Number of times our DL exception handler was invoked");
RMNET_NSS_STAT(rmnet_nss_exception_non_ethernet, RMNET_NSS_EX_BAD_HDR,
"Number of non-Ethernet exception packets");
RMNET_NSS_STAT(rmnet_nss_exception_invalid_ip, RMNET_NSS_EX_BAD_IP,
"Number of exception packets with invalid IP headers");
RMNET_NSS_STAT(rmnet_nss_exception_success, RMNET_NSS_EX_SUCCESS,
"Number of exception packets handled successfully");
RMNET_NSS_STAT(rmnet_nss_tx_non_zero_headlen_frags, RMNET_NSS_TX_NON_ZERO_HEADLEN_FRAGS,
"Number of packets with non zero headlen");
RMNET_NSS_STAT(rmnet_nss_tx_busy_loop, RMNET_NSS_TX_BUSY_LOOP,
"Number of times tx packets busy looped");
static void rmnet_nss_inc_stat(enum __rmnet_nss_stat stat)
{
if (stat >= 0 && stat < RMNET_NSS_NUM_STATS)
rmnet_nss_stats[stat]++;
}
static struct rmnet_nss_ctx *rmnet_nss_find_ctx(struct net_device *dev)
{
struct rmnet_nss_ctx *ctx;
struct hlist_head *bucket;
u32 hash;
hash = hash_ptr(dev, HASH_BITS(rmnet_nss_ctx_hashtable));
bucket = &rmnet_nss_ctx_hashtable[hash];
hlist_for_each_entry(ctx, bucket, hnode) {
if (ctx->rmnet_dev == dev)
return ctx;
}
return NULL;
}
static void rmnet_nss_free_ctx(struct rmnet_nss_ctx *ctx)
{
if (ctx) {
hash_del(&ctx->hnode);
nss_rmnet_rx_xmit_callback_unregister(ctx->nss_ctx);
nss_rmnet_rx_destroy_sync(ctx->nss_ctx);
kfree(ctx);
}
}
/* Pull off an ethernet header, if possible */
static int rmnet_nss_ethhdr_pull(struct sk_buff *skb)
{
if (!skb->protocol || skb->protocol == htons(ETH_P_802_3)) {
void *ret = skb_pull(skb, sizeof(struct ethhdr));
rmnet_nss_inc_stat((ret) ? RMNET_NSS_RX_ETH :
RMNET_NSS_RX_FAIL);
return !ret;
}
rmnet_nss_inc_stat(RMNET_NSS_RX_NON_ETH);
return -1;
}
/* Copy headers to linear section for non linear packets */
static int rmnet_nss_adjust_header(struct sk_buff *skb)
{
struct iphdr *iph;
skb_frag_t *frag;
int bytes = 0;
u8 transport;
if (skb_shinfo(skb)->nr_frags != 1) {
rmnet_nss_inc_stat(RMNET_NSS_TX_BAD_FRAGS);
return -EINVAL;
}
if (skb_headlen(skb)) {
rmnet_nss_inc_stat(RMNET_NSS_TX_NON_ZERO_HEADLEN_FRAGS);
return 0;
}
frag = &skb_shinfo(skb)->frags[0];
iph = (struct iphdr *)(skb_frag_address(frag));
if (iph->version == 4) {
bytes = iph->ihl*4;
transport = iph->protocol;
} else if (iph->version == 6) {
struct ipv6hdr *ip6h = (struct ipv6hdr *)iph;
bytes = sizeof(struct ipv6hdr);
/* Dont have to account for extension headers yet */
transport = ip6h->nexthdr;
} else {
rmnet_nss_inc_stat(RMNET_NSS_TX_BAD_IP);
return -EINVAL;
}
if (transport == IPPROTO_TCP) {
struct tcphdr *th;
th = (struct tcphdr *)((u8 *)iph + bytes);
bytes += th->doff * 4;
} else if (transport == IPPROTO_UDP) {
bytes += sizeof(struct udphdr);
} else {
/* cant do anything else here unfortunately so linearize */
if (skb_linearize(skb)) {
rmnet_nss_inc_stat(RMNET_NSS_TX_LINEARIZE_FAILS);
return -EINVAL;
} else {
return 0;
}
}
if (bytes > skb_frag_size(frag)) {
rmnet_nss_inc_stat(RMNET_NSS_TX_BAD_FRAGS);
return -EINVAL;
}
skb_push(skb, bytes);
memcpy(skb->data, iph, bytes);
/* subtract to account for skb_push */
skb->len -= bytes;
frag->page_offset += bytes;
skb_frag_size_sub(frag, bytes);
/* subtract to account for skb_frag_size_sub */
skb->data_len -= bytes;
return 0;
}
/* Main downlink handler
* Looks up NSS contex associated with the device. If the context is found,
* we add a dummy ethernet header with the approriate protocol field set,
* the pass the packet off to NSS for hardware acceleration.
*/
int rmnet_nss_tx(struct sk_buff *skb)
{
struct ethhdr *eth;
struct rmnet_nss_ctx *ctx;
struct net_device *dev = skb->dev;
nss_tx_status_t rc;
unsigned int len;
u8 version;
if (skb_is_nonlinear(skb)) {
if (rmnet_nss_adjust_header(skb))
goto fail;
else
rmnet_nss_inc_stat(RMNET_NSS_TX_NONLINEAR);
}
version = ((struct iphdr *)skb->data)->version;
ctx = rmnet_nss_find_ctx(dev);
if (!ctx) {
rmnet_nss_inc_stat(RMNET_NSS_TX_NO_CTX);
return -EINVAL;
}
eth = (struct ethhdr *)skb_push(skb, sizeof(*eth));
memset(&eth->h_dest, 0, ETH_ALEN * 2);
if (version == 4) {
eth->h_proto = htons(ETH_P_IP);
} else if (version == 6) {
eth->h_proto = htons(ETH_P_IPV6);
} else {
rmnet_nss_inc_stat(RMNET_NSS_TX_BAD_IP);
goto fail;
}
skb->protocol = htons(ETH_P_802_3);
/* Get length including ethhdr */
len = skb->len;
transmit:
rc = nss_rmnet_rx_tx_buf(ctx->nss_ctx, skb);
if (rc == NSS_TX_SUCCESS) {
/* Increment rmnet_data device stats.
* Don't call rmnet_data_vnd_rx_fixup() to do this, as
* there's no guarantee the skb pointer is still valid.
*/
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
rmnet_nss_inc_stat(RMNET_NSS_TX_SUCCESS);
return 0;
} else if (rc == NSS_TX_FAILURE_QUEUE) {
rmnet_nss_inc_stat(RMNET_NSS_TX_BUSY_LOOP);
goto transmit;
}
fail:
rmnet_nss_inc_stat(RMNET_NSS_TX_FAIL);
kfree_skb(skb);
return 1;
}
/* Called by NSS in the DL exception case.
* Since the packet cannot be sent over the accelerated path, we need to
* handle it. Remove the ethernet header and pass it onward to the stack
* if possible.
*/
void rmnet_nss_receive(struct net_device *dev, struct sk_buff *skb,
struct napi_struct *napi)
{
rmnet_nss_inc_stat(RMNET_NSS_EXCEPTIONS);
if (!skb)
return;
if (rmnet_nss_ethhdr_pull(skb)) {
rmnet_nss_inc_stat(RMNET_NSS_EX_BAD_HDR);
goto drop;
}
/* reset header pointers */
skb_reset_transport_header(skb);
skb_reset_network_header(skb);
skb_reset_mac_header(skb);
/* reset packet type */
skb->pkt_type = PACKET_HOST;
skb->dev = dev;
/* reset protocol type */
switch (skb->data[0] & 0xF0) {
case 0x40:
skb->protocol = htons(ETH_P_IP);
break;
case 0x60:
skb->protocol = htons(ETH_P_IPV6);
break;
default:
rmnet_nss_inc_stat(RMNET_NSS_EX_BAD_IP);
goto drop;
}
rmnet_nss_inc_stat(RMNET_NSS_EX_SUCCESS);
/* Set this so that we dont loop around netif_receive_skb */
skb->cb[0] = 1;
netif_receive_skb(skb);
return;
drop:
kfree_skb(skb);
}
/* Called by NSS in the UL acceleration case.
* We are guaranteed to have an ethernet packet here from the NSS hardware,
* We need to pull the header off and invoke our ndo_start_xmit function
* to handle transmitting the packet to the network stack.
*/
void rmnet_nss_xmit(struct net_device *dev, struct sk_buff *skb)
{
netdev_tx_t ret;
skb_pull(skb, sizeof(struct ethhdr));
rmnet_nss_inc_stat(RMNET_NSS_RX_ETH);
/* NSS takes care of shaping, so bypassing Qdiscs like this is OK */
ret = dev->netdev_ops->ndo_start_xmit(skb, dev);
if (unlikely(ret == NETDEV_TX_BUSY)) {
dev_kfree_skb_any(skb);
rmnet_nss_inc_stat(RMNET_NSS_RX_BUSY);
}
}
/* Create and register an NSS context for an rmnet_data device */
int rmnet_nss_create_vnd(struct net_device *dev)
{
struct rmnet_nss_ctx *ctx;
ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
if (!ctx)
return -ENOMEM;
ctx->rmnet_dev = dev;
ctx->nss_ctx = nss_rmnet_rx_create_sync_nexthop(dev, NSS_N2H_INTERFACE,
NSS_C2C_TX_INTERFACE);
if (!ctx->nss_ctx) {
kfree(ctx);
return -1;
}
nss_rmnet_rx_register(ctx->nss_ctx, rmnet_nss_receive, dev);
nss_rmnet_rx_xmit_callback_register(ctx->nss_ctx, rmnet_nss_xmit);
hash_add_ptr(rmnet_nss_ctx_hashtable, &ctx->hnode, dev);
return 0;
}
/* Unregister and destroy the NSS context for an rmnet_data device */
int rmnet_nss_free_vnd(struct net_device *dev)
{
struct rmnet_nss_ctx *ctx;
ctx = rmnet_nss_find_ctx(dev);
rmnet_nss_free_ctx(ctx);
return 0;
}
static const struct rmnet_nss_cb rmnet_nss = {
.nss_create = rmnet_nss_create_vnd,
.nss_free = rmnet_nss_free_vnd,
.nss_tx = rmnet_nss_tx,
};
int __init rmnet_nss_init(void)
{
pr_err("%s(): initializing rmnet_nss\n", __func__);
RCU_INIT_POINTER(rmnet_nss_callbacks, &rmnet_nss);
return 0;
}
void __exit rmnet_nss_exit(void)
{
struct hlist_node *tmp;
struct rmnet_nss_ctx *ctx;
int bkt;
pr_err("%s(): exiting rmnet_nss\n", __func__);
RCU_INIT_POINTER(rmnet_nss_callbacks, NULL);
/* Tear down all NSS contexts */
hash_for_each_safe(rmnet_nss_ctx_hashtable, bkt, tmp, ctx, hnode)
rmnet_nss_free_ctx(ctx);
}
#if 0
MODULE_LICENSE("GPL v2");
module_init(rmnet_nss_init);
module_exit(rmnet_nss_exit);
#endif