All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next] cdc_ether: Improve ZTE MF823/831/910 handling
@ 2016-07-18 12:24 Kristian Evensen
  2016-07-18 13:01 ` Oliver Neukum
  0 siblings, 1 reply; 22+ messages in thread
From: Kristian Evensen @ 2016-07-18 12:24 UTC (permalink / raw)
  To: oliver, linux-usb, netdev, linux-kernel; +Cc: Kristian Evensen

The firmware in the ZTE MF823/831/910 modems/mifis use OS fingerprinting to
determine which type of device to export. In addition, these devices export
a REST API which can also be used to control the type of device. So far, on
Linux, the devices have been seen as RNDIS or CDC Ether.

When CDC Ether is used, devices of the same type are, as with RNDIS,
exported with the same, bogus random MAC address. In addition, the devices
(at least on all firmware revisions I have found) use this MAC when sending
traffic routed from external networks. And as a final feature, the devices
sometimes export the link state incorrectly.

This patch tries to improve the handling of these devices by doing the
following:

* If a random MAC is read from device, then generate a new random MAC
address. This fix will apply to all devices using cdc_ether, but that
should be ok as we will also fix similar mistakes from other
manufacturers.

* The MF823/MF832/MF910 sometimes export cdc carrier on twice on connect
(the correct behavior is off then on). Work around this by manually setting
carrier to off if an on-notification is received and the NOCARRIER-bit is
not set.

This change will also affect all devices, but as with the MAC-fix it should
take care of similar mistakes. I tried to think of/look/test for
problems/regressions that could be introduced by this behavior, but could
not find any. However, my familiarity with this code path is not that
great, so there could be something I have overlooked.

* Add an rx_fixup-function (and a new driver info-struct) which is used by
these three devices (identified either as PID 0x1405 or 0x1408). The
rx_fixup-function replaces the destination MAC address in the skb with that
of the device. I have not seen a revision of these three device that
behaves correctly (i.e., sets the right destination MAC), so I chose not to
do any comparison with for example the known, bogus addresses.

I have tested this patch with multiple revisions of all three devices, and
they behave as expected. In other words, they all got a valid, random MAC,
the correct operational state and I can receive/sent traffic without
problems. I also tested with some other cdc_ether devices I have and did
not find any problems/regressions caused by the two general changes.

Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
---
 drivers/net/usb/cdc_ether.c | 53 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 7cba2c3..2325097 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -388,6 +388,12 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
 	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
 		netif_dbg(dev, timer, dev->net, "CDC: carrier %s\n",
 			  event->wValue ? "on" : "off");
+
+		/* Work-around for devices with broken off-notifications */
+		if (event->wValue &&
+		    !test_bit(__LINK_STATE_NOCARRIER, &dev->net->state))
+			usbnet_link_change(dev, 0, 0);
+
 		usbnet_link_change(dev, !!event->wValue, 0);
 		break;
 	case USB_CDC_NOTIFY_SPEED_CHANGE:	/* tx/rx rates */
@@ -428,10 +434,34 @@ int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
 		return status;
 	}
 
+	if (dev->net->dev_addr[0] & 0x02)
+		eth_hw_addr_random(dev->net);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(usbnet_cdc_bind);
 
+/* Make sure packets have correct destination MAC address
+ *
+ * A firmware bug observed on some devices (ZTE MF823/831/910) is that the
+ * device sends packets with a static, bogus, random MAC address (event if
+ * device MAC address has been updated). Always set MAC address to that of the
+ * device.
+ */
+static int usbnet_cdc_zte_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+	u8 num_buggy_hwaddrs;
+	u8 buggy_hwaddrs_idx = 0;
+
+	if (skb->len < ETH_HLEN || !(skb->data[0] & 0x02))
+		return 1;
+
+	skb_reset_mac_header(skb);
+	ether_addr_copy(eth_hdr(skb)->h_dest, dev->net->dev_addr);
+
+	return 1;
+}
+
 static const struct driver_info	cdc_info = {
 	.description =	"CDC Ethernet Device",
 	.flags =	FLAG_ETHER | FLAG_POINTTOPOINT,
@@ -442,6 +472,17 @@ static const struct driver_info	cdc_info = {
 	.manage_power =	usbnet_manage_power,
 };
 
+static const struct driver_info	zte_cdc_info = {
+	.description =	"ZTE MF823/831/910 CDC Ethernet Device",
+	.flags =	FLAG_ETHER | FLAG_POINTTOPOINT,
+	.bind =		usbnet_cdc_bind,
+	.unbind =	usbnet_cdc_unbind,
+	.status =	usbnet_cdc_status,
+	.set_rx_mode =	usbnet_cdc_update_filter,
+	.manage_power =	usbnet_manage_power,
+	.rx_fixup = usbnet_cdc_zte_rx_fixup,
+};
+
 static const struct driver_info wwan_info = {
 	.description =	"Mobile Broadband Network Device",
 	.flags =	FLAG_WWAN,
@@ -697,6 +738,18 @@ static const struct usb_device_id	products[] = {
 				      USB_CDC_PROTO_NONE),
 	.driver_info = (unsigned long)&wwan_info,
 }, {
+	/* ZTE MF823/831/910 */
+	USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1405, USB_CLASS_COMM,
+				      USB_CDC_SUBCLASS_ETHERNET,
+				      USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long)&zte_cdc_info,
+}, {
+	/* ZTE MF823/831/910 */
+	USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1408, USB_CLASS_COMM,
+				      USB_CDC_SUBCLASS_ETHERNET,
+				      USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long)&zte_cdc_info,
+}, {
 	/* Telit modules */
 	USB_VENDOR_AND_INTERFACE_INFO(0x1bc7, USB_CLASS_COMM,
 			USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread
* Re: [PATCH net-next] cdc_ether: Improve ZTE MF823/831/910 handling
@ 2016-07-19 12:14 Andrey Melnikov
  0 siblings, 0 replies; 22+ messages in thread
From: Andrey Melnikov @ 2016-07-19 12:14 UTC (permalink / raw)
  To: Kristian Evensen, linux-kernel

> On Tue, Jul 19, 2016 at 10:30 AM, Lars Melin <larsm17@gmail.com> wrote:
> > On 2016-07-19 13:40, Kristian Evensen wrote:
> >
> >> I guess I can match on the VID/PID in usbnet, but won't it be cleaner
> >> to add a new bind() function (in cdc_ether) which matches the two PIDs
> >> and leave usbnet as is? Or am I misunderstanding how to add this
> >> functionality to usbnet?
> >>
> >
> > Matching on the usb id is probably not a great idea, there is more id's
> > than the two you have found and there is also more than two non-unique mac
> > addresses.
> >
> > Example:
> >
> > 0200FFAAAAAA  19d2:1589/1592/1595
> > 020CE70B0102  19d2:1040/1048/1405
> >
> > You can easily find them by googling them, without colon separators you
> > will find them in verbose lsusb listings, with colons you will find them in
> > dmesg pastings.
> >
> > I would probably have found more dupes if users had refrained from using the
> > stupid usbdevices cmd which removes almost all interesting info from device
> > listings in internet foras.

> Thanks for letting me know. It seems that the static MAC behaviour is
> the default behaviour of ZTE-devices that use cdc_ether. Unless anyone
> objects, I will make the following changes for v2:

> * Create a ZTE-specific bind method in cdc_ether that checks for a
> random MAC and generates a new MAC if found.
> * Use the ZTE-specific bind + rx fixup for all ZTE cdc_ether devices
> by default, and add exceptions if we find any devices not displaying
> this behaviour. I see there are already five ZTE devices with separate
> entries in the products-array in cdc_ether.

This is not only ZTE specific bug. Huawei (balong based) modems use
predefined MAC 0a:5b:8f:27:9a:64.
I think - better detect this devices by MAC address, not by VID/PID.

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2016-08-18  8:08 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-18 12:24 [PATCH net-next] cdc_ether: Improve ZTE MF823/831/910 handling Kristian Evensen
2016-07-18 13:01 ` Oliver Neukum
2016-07-18 13:23   ` Kristian Evensen
2016-07-18 13:50     ` Oliver Neukum
2016-07-18 14:10       ` Kristian Evensen
2016-07-18 14:14         ` Oliver Neukum
2016-07-18 14:14           ` Oliver Neukum
2016-07-18 14:27           ` Kristian Evensen
2016-07-18 15:04           ` Kristian Evensen
2016-07-18 15:04             ` Kristian Evensen
2016-07-19  6:20             ` Oliver Neukum
2016-07-19  6:20               ` Oliver Neukum
2016-07-19  6:40               ` Kristian Evensen
2016-07-19  7:17                 ` Oliver Neukum
2016-07-19  8:30                 ` Lars Melin
2016-07-19 11:06                   ` Kristian Evensen
2016-08-08 12:44           ` Bjørn Mork
2016-08-08 13:57             ` Oliver Neukum
2016-08-08 18:30               ` Bjørn Mork
2016-08-18  8:03                 ` Oliver Neukum
2016-08-18  8:03                   ` Oliver Neukum
2016-07-19 12:14 Andrey Melnikov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.