Bjørn Mork <[email protected]> writes:
> But I believe I implemented it the last time this was discussed. I'll
> see if I can dig up the old code for a demo. Not going to rush this
> anyway. I'd like everyone to be happy with the result. And it's going
> to be immutable once it's in.
git is a wonderful tool. Nothing is ever lost :)
I found my example code in an old v3.2 based branch, and turned it into
a demo on the bus to job. Note that this requires a minor change to
usbnet.c as well, to prevent it from doing eth_type_trans() on the rx
skbs we pass on to it. Therefore two, eh.. three, patches.
Warning: Trying the qmi_wwan raw-ip feature without the usbnet patch is
a sure path to an oops.
Works for me(tm). Only tested on an E392 for now:
nemi:/tmp# ifconfig wwan1
wwan1 Link encap:Ethernet HWaddr 92:b9:2a:c0:4f:96
BROADCAST 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)
nemi:/tmp# cat /sys/class/net/wwan1/qmi/raw_ip
N
nemi:/tmp# echo 1 >/sys/class/net/wwan1/qmi/raw_ip
nemi:/tmp# ifconfig wwan1
wwan1 Link encap:UNSPEC HWaddr
00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
POINTOPOINT 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)
nemi:/tmp# cat /sys/class/net/wwan1/qmi/raw_ip
Y
bjorn@nemi:~$ qmicli -d /dev/cdc-wdm1
--device-open-net='net-raw-ip|net-no-qos-header'
--wds-start-network=apn=telenor --wds-follow-network
[/dev/cdc-wdm1] Network started
Packet data handle: '34967784'
Ctrl+C will stop the network
[/dev/cdc-wdm1] Connection status: 'connected'
bjorn@nemi:~$ qmicli -d /dev/cdc-wdm1 --client-cid=1 --client-no-release-cid
--wds-get-current-settings
[/dev/cdc-wdm1] Current settings retrieved:
IP Family: IPv4
IPv4 address: 46.157.38.113
IPv4 subnet mask: 255.255.255.252
IPv4 gateway address: 46.157.38.114
IPv4 primary DNS: 193.213.112.4
IPv4 secondary DNS: 130.67.15.198
MTU: 1500
Domains: none
[/dev/cdc-wdm1] Client ID not released:
Service: 'wds'
CID: '1'
nemi:/tmp# ifconfig wwan1 46.157.38.113
nemi:/tmp# ifconfig wwan1
wwan1 Link encap:UNSPEC HWaddr
00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:46.157.38.113 P-t-P:46.157.38.113 Mask:255.255.255.255
UP POINTOPOINT 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)
nemi:/tmp# ip route add 148.122.171.130 dev wwan1
nemi:/tmp# ping -c3 148.122.171.130
PING 148.122.171.130 (148.122.171.130) 56(84) bytes of data.
64 bytes from 148.122.171.130: icmp_seq=1 ttl=58 time=156 ms
64 bytes from 148.122.171.130: icmp_seq=2 ttl=58 time=24.5 ms
64 bytes from 148.122.171.130: icmp_seq=3 ttl=58 time=27.5 ms
--- 148.122.171.130 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 24.568/69.492/156.345/61.426 ms
nemi:/tmp# tshark -nxxi wwan1
tshark: Lua: Error during loading:
[string "/usr/share/wireshark/init.lua"]:46: dofile has been disabled due to
running Wireshark as superuser. See
http://wiki.wireshark.org/CaptureSetup/CapturePrivileges for help in running
Wireshark as an unprivileged user.
Running as user "root" and group "root". This could be dangerous.
Capturing on 'wwan1'
0000 45 00 00 54 75 99 40 00 40 01 30 05 2e 9d 26 71 E..Tu.@[email protected]...&q
0010 94 7a ab 82 08 00 4d e4 6e c0 00 01 6e 77 55 56 .z....M.n...nwUV
0020 00 00 00 00 ad b9 0b 00 00 00 00 00 10 11 12 13 ................
0030 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 ............ !"#
0040 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 $%&'()*+,-./0123
0050 34 35 36 37 4567
0000 45 04 00 54 01 98 00 00 3a 01 ea 02 94 7a ab 82 E..T....:....z..
0010 2e 9d 26 71 00 00 55 e4 6e c0 00 01 6e 77 55 56 ..&q..U.n...nwUV
0020 00 00 00 00 ad b9 0b 00 00 00 00 00 10 11 12 13 ................
0030 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 ............ !"#
0040 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 $%&'()*+,-./0123
0050 34 35 36 37 4567
0000 45 00 00 54 76 2f 40 00 40 01 2f 6f 2e 9d 26 71 E..Tv/@.@./o..&q
0010 94 7a ab 82 08 00 73 dc 6e c0 00 02 6f 77 55 56 .z....s.n...owUV
0020 00 00 00 00 86 c0 0b 00 00 00 00 00 10 11 12 13 ................
0030 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 ............ !"#
0040 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 $%&'()*+,-./0123
0050 34 35 36 37 4567
0000 45 04 00 54 01 f6 00 00 3a 01 e9 a4 94 7a ab 82 E..T....:....z..
0010 2e 9d 26 71 00 00 7b dc 6e c0 00 02 6f 77 55 56 ..&q..{.n...owUV
0020 00 00 00 00 86 c0 0b 00 00 00 00 00 10 11 12 13 ................
0030 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 ............ !"#
0040 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 $%&'()*+,-./0123
0050 34 35 36 37 4567
0000 45 00 00 54 76 7f 40 00 40 01 2f 1f 2e 9d 26 71 E..Tv.@.@./...&q
0010 94 7a ab 82 08 00 b7 d8 6e c0 00 03 70 77 55 56 .z......n...pwUV
0020 00 00 00 00 41 c3 0b 00 00 00 00 00 10 11 12 13 ....A...........
0030 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 ............ !"#
0040 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 $%&'()*+,-./0123
0050 34 35 36 37 4567
0000 45 04 00 54 02 bb 00 00 3a 01 e8 df 94 7a ab 82 E..T....:....z..
0010 2e 9d 26 71 00 00 bf d8 6e c0 00 03 70 77 55 56 ..&q....n...pwUV
0020 00 00 00 00 41 c3 0b 00 00 00 00 00 10 11 12 13 ....A...........
0030 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 ............ !"#
0040 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 $%&'()*+,-./0123
0050 34 35 36 37 4567
Judgement time coming up :) What do you think? Yes, this might not be
the correct forum for kernel patches, but I believe it is where this has
any meaning. The load is on userspace here, and there is absolutely no
reason to submit this to the kernel unless it is going to be used by
NM/MM.
Bjørn
>From 0e92dffbb40964af4798790312201f014d88e561 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <[email protected]>
Date: Fri, 10 Feb 2012 15:58:00 +0100
Subject: [PATCH 1/3] usbnet: allow mini-drivers to consume L2 headers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Assume the minidriver has taken care of all L2 header parsing
if it sets skb->protocol. This allows the minidriver to
support non-ethernet L2 headers, and even operate without
any L2 header at all.
Signed-off-by: Bjørn Mork <[email protected]>
---
drivers/net/usb/usbnet.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 0744bf2ef2d6..0b0ba7ef14e4 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -324,7 +324,10 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
return;
}
- skb->protocol = eth_type_trans (skb, dev->net);
+ /* only update if unset to allow minidriver rx_fixup override */
+ if (skb->protocol == 0)
+ skb->protocol = eth_type_trans (skb, dev->net);
+
dev->net->stats.rx_packets++;
dev->net->stats.rx_bytes += skb->len;
--
2.1.4
>From 569185b5902d7c554349583eecd55dd527180059 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <[email protected]>
Date: Tue, 14 Feb 2012 13:40:10 +0100
Subject: [PATCH 2/3] net: qmi_wwan: support "raw IP" mode
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
QMI wwan devices have traditionally emulated ethernet devices
by default. But they have always had the capability of operating
without any L2 header at all, transmitting and receiving "raw"
IP packets over the USB link. This firmware feature used to be
configurable through the QMI management protocol.
Traditionally there was no way to verify the firmware mode
without attempting to change it. And the firmware would often
disallow changes anyway, i.e. due to a session already being
established. In some cases, this could be a hidden firmware
internal session, completely outside host control. For these
reasons, sticking with the "well known" default mode was safest.
But newer generations of QMI hardware and firmware have moved
towards defaulting to "raw IP" mode instead, followed by an
increasing number of bugs in the already buggy "802.3" firmware
implementation. At the same time, the QMI management protocol
gained the ability to detect the current mode. This has enabled
the userspace QMI management application to verify the current
firmware mode without trying to modify it.
Following this development, the latest QMI hardware and firmware
(the MDM9x30 generation) has dropped support for "802.3" mode
entirely. Support for "raw IP" framing in the driver is therefore
necessary for these devices, and to a certain degree to work
around problems with the previous generation,
This patch adds support for "raw IP" framing for QMI devices,
changing the netdev from an ethernet device to an ARPHRD_NONE
p-t-p device when "raw IP" framing is enabled.
The firmware setup is fully delegated to the QMI userspace
management application, through simple tunneling of the QMI
protocol. The driver will therefore not know which mode has been
"negotiated" between firmware and userspace. Allowing userspace
to inform the driver of the result through a sysfs switch is
considered a better alternative than to change the well established
clean delegation of firmware management to userspace.
Signed-off-by: Bjørn Mork <[email protected]>
---
drivers/net/usb/qmi_wwan.c | 84 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 83 insertions(+), 1 deletion(-)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index af1267fb1139..2da6bdd35bac 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -14,6 +14,7 @@
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/usb/cdc.h>
@@ -48,11 +49,79 @@
struct qmi_wwan_state {
struct usb_driver *subdriver;
atomic_t pmcount;
- unsigned long unused;
+ unsigned long flags;
struct usb_interface *control;
struct usb_interface *data;
};
+enum qmi_wwan_flags {
+ QMI_WWAN_FLAG_RAWIP = 1 << 0,
+};
+
+static void qmi_wwan_netdev_setup(struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct qmi_wwan_state *info = (void *)&dev->data;
+
+ /* ether_setup() has already set sane ethernet settings for us */
+ if (info->flags & QMI_WWAN_FLAG_RAWIP) {
+ net->header_ops = NULL; /* No header */
+ net->type = ARPHRD_NONE;
+ net->hard_header_len = 0;
+ net->addr_len = 0;
+ net->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
+ netdev_dbg(net, "mode: raw IP\n");
+ } else if (!net->header_ops) { /* don't bother if already set */
+ ether_setup(net);
+ netdev_dbg(net, "mode: Ethernet\n");
+ }
+}
+
+static ssize_t raw_ip_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+ struct usbnet *dev = netdev_priv(to_net_dev(d));
+ struct qmi_wwan_state *info = (void *)&dev->data;
+
+ return sprintf(buf, "%c\n", info->flags & QMI_WWAN_FLAG_RAWIP ? 'Y' : 'N');
+}
+
+static ssize_t raw_ip_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct usbnet *dev = netdev_priv(to_net_dev(d));
+ struct qmi_wwan_state *info = (void *)&dev->data;
+ bool enable;
+
+ if (strtobool(buf, &enable))
+ return -EINVAL;
+
+ /* no change? */
+ if (enable == (info->flags & QMI_WWAN_FLAG_RAWIP))
+ return len;
+
+ /* we don't want to modify a running netdev */
+ if (netif_running(dev->net))
+ return -EBUSY;
+
+ if (enable)
+ info->flags |= QMI_WWAN_FLAG_RAWIP;
+ else
+ info->flags &= ~QMI_WWAN_FLAG_RAWIP;
+ qmi_wwan_netdev_setup(dev->net);
+ return len;
+}
+
+static DEVICE_ATTR_RW(raw_ip);
+
+static struct attribute *qmi_wwan_sysfs_attrs[] = {
+ &dev_attr_raw_ip.attr,
+ NULL,
+};
+
+static struct attribute_group qmi_wwan_sysfs_attr_group = {
+ .name = "qmi",
+ .attrs = qmi_wwan_sysfs_attrs,
+};
+
/* default ethernet address used by the modem */
static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3};
@@ -80,6 +149,8 @@ static const u8 buggy_fw_addr[ETH_ALEN] = {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00};
*/
static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
{
+ struct qmi_wwan_state *info = (void *)&dev->data;
+ bool rawip = info->flags & QMI_WWAN_FLAG_RAWIP;
__be16 proto;
/* This check is no longer done by usbnet */
@@ -94,15 +165,25 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
proto = htons(ETH_P_IPV6);
break;
case 0x00:
+ if (rawip)
+ return 0;
if (is_multicast_ether_addr(skb->data))
return 1;
/* possibly bogus destination - rewrite just in case */
skb_reset_mac_header(skb);
goto fix_dest;
default:
+ if (rawip)
+ return 0;
/* pass along other packets without modifications */
return 1;
}
+ if (rawip) {
+ skb->dev = dev->net; /* normally set by eth_type_trans */
+ skb->protocol = proto;
+ return 1;
+ }
+
if (skb_headroom(skb) < ETH_HLEN)
return 0;
skb_push(skb, ETH_HLEN);
@@ -312,6 +393,7 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
dev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */
}
dev->net->netdev_ops = &qmi_wwan_netdev_ops;
+ dev->net->sysfs_groups[0] = &qmi_wwan_sysfs_attr_group;
err:
return status;
}
--
2.1.4
>From 2410262f335be017eea21791db443d428a1550dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <[email protected]>
Date: Wed, 25 Nov 2015 11:07:55 +0100
Subject: [PATCH 3/3] net: qmi_wwan: document the qmi/raw_ip sysfs file
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Bjørn Mork <[email protected]>
---
Documentation/ABI/testing/sysfs-class-net-qmi | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-class-net-qmi
diff --git a/Documentation/ABI/testing/sysfs-class-net-qmi b/Documentation/ABI/testing/sysfs-class-net-qmi
new file mode 100644
index 000000000000..d240b7bf6587
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-net-qmi
@@ -0,0 +1,23 @@
+What: /sys/class/net/<iface>/qmi/raw_ip
+Date: Nov 2015
+KernelVersion: 4.4
+Contact: Bjørn Mork <[email protected]>
+Description:
+ Boolean. Default: 'N'
+
+ Set this to 'Y' to change the network device link
+ framing from '802.3' to 'raw-ip'.
+
+ The netdev will change to reflect the link framing
+ mode. The netdev is an ordinary ethernet device in
+ '802.3' mode, and the driver expects to exchange
+ frames with an ethernet header over the USB link. The
+ netdev is a headerless p-t-p device in 'raw-ip' mode,
+ and the driver expects to echange IPv4 or IPv6 packets
+ without any L2 header over the USB link.
+
+ Userspace is in full control of firmware configuration
+ through the delegation of the QMI protocol. Userspace
+ is responsible for coordination of driver and firmware
+ link framing mode, changing this setting to 'Y' if the
+ firmware is configured for 'raw-ip' mode.
--
2.1.4
_______________________________________________
networkmanager-list mailing list
[email protected]
https://mail.gnome.org/mailman/listinfo/networkmanager-list