User Tools

Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
playground:mission-log-template1 [2015/07/07 11:57] – [Power Consumption Analysis] chronoplayground:mission-log-template1 [2015/07/15 13:59] (current) chrono
Line 1: Line 1:
-====== Review: Managed Low-Power Switch DGS-1100-8 ======+====== Fixing Kernel drivers for Huawei E3372s LTE/4G Stick======
  
-In a past Mission-Log, we've [[mission:log:2012:01:13:dlink-green-ethernet-switch-review|reviewed the power consumption of "green" Ethernet Switches]] (consumer-grade/unmanaged) that could be used in off-grid environments and they performed really well. Compliant with IEEE 802.3az Energy Efficient Ethernet, these switches consume less energy by cutting down on power consumption when the traffic volume is low and automatically measure the length of the connected cables to adjust power usage, when cables are shorter than 20 metersIn additionthey monitor the link status of every port and drastically reduce power consumption when a port has no link. With more technology and infrastructure, the need increased for more Ethernet features like VLANstrunks and many other features, usually  offered only by expensive, loud and very power hungry managed/enterprise switches+In order to mitigate the problem of having no internet at all, we got a SIM-Card for LTE/4Ǵ. At the same time the Telekom Speedstick V LTE (which is basically a rebranded Huawei 3372sbecame available and not too expensive. A little research showed that it should be really easy to deploy this stick, when flashing a Non-HiLink Firmware (<=21.xxx), when the Stick could be used just like old modemswith at commands but without the dependency to run pppd/wvdial like in the old modem or even 3G daysYou just have to 
  
-Luckily this situation has changed and we could test and already deploy a new pair of managed but very low power and fanless (silent) switches: The [[http://us.dlink.com/products/business-solutions/easysmart-8-port-gigabit-switch/|D-Link DGS-1100 Family]], which also come in a sturdy metal case and with the benefit of a (limited - due to legal issues on a per country basis) lifetime warranty.+<code> 
 +$ echo "AT^NDISDUP=1,1,"internet.eplus.de" > /dev/ttyUSB1 
 +$ udhcpc wwan0 
 +</code>
  
-====== ======+and should be done with it. In reality this became quite a quest but with combined efforts we managed to get it to work and created a patch for current kernels (tested 3.18.[11-18]. If you also have this stick and are unable to get an IP via dhcp, this patch might be for you.
  
-===== Power Consumption Analysis =====+<code> 
 +$ make clean 
 +$ make target/linux/{clean,prepare} V=s QUILT=
 +$ cd build_dir/target-mips_34kc_musl-1.1.10/linux-ar71xx_generic/linux-3.18.18/ 
 +$ patch -p1 -i /path/to/patchfile/fix-cdc-ncm-huawei-3372s.patch 
 +</code>
  
-For better comparison all measurement results have been put togetherA couple of people have been bit unhappy, that we've only documented power consumption on the DC side in the past review (which is all we care about for off-grid usage)As a result, this time we've documented DC and Wall-Power consumption (with the original D-Link AC/DC plug).+<sxh c> 
 +diff -u a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c 
 +--- a/drivers/net/usb/cdc_mbim.c 2015-06-28 17:40:40.000000000 +0000 
 ++++ b/drivers/net/usb/cdc_mbim.c 2015-07-04 15:05:14.546901702 +0000 
 +@@ -158,7 +158,7 @@ 
 +  if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)
 +  goto err;
  
-==== Test-Setup ====+- ret cdc_ncm_bind_common(dev, intf, data_altsetting); 
 ++ ret cdc_ncm_bind_common(dev, intf, data_altsetting, 0); 
 +  if (ret) 
 +  goto err;
  
 +diff -u a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
 +--- a/drivers/net/usb/cdc_ncm.c 2015-06-28 17:40:40.000000000 +0000
 ++++ b/drivers/net/usb/cdc_ncm.c 2015-07-09 08:43:01.658770535 +0000
 +@@ -684,10 +684,11 @@
 +  ctx->tx_curr_skb = NULL;
 +  }
  
-==== Results ====++ kfree(ctx->delayed_ndp16); 
 +  kfree(ctx); 
 + }
  
-| ||  DGS-1008D G2  ||  DGS-1008D G3  || DGS-1100-8 Rev A1 ||| +-int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting) 
-| || {{:blog:2012-02-10:d-link-dgs-1008d.jpg?235|}}||{{:blog:2012-02-10:dlink-ds1008v2.jpg?235|}}||{{:blog:2012-02-10:dlink-ds1008v2.jpg?235|}}||| ++int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting, int drvflags) 
-| Clients |Mode| 5V DC Current | 5V DC Power | 5V DC Current | 5V DC Power | 5V DC Current | 5V DC Power| 230V AC Power | + { 
-| 0 | Switch only | 66-93mA | 0.33-0.46W | 67-111mA | 0.33-0.55W | 105mA | 0.52W | 0.8W | +  const struct usb_cdc_union_desc *union_desc = NULL; 
-| 1 | Client Stdby | 100-160mA | 0.5-0.8W | 109-124mA | 0.54-0.62W | 131mA | 0.65W | 1W | +  struct cdc_ncm_ctx *ctx; 
-| 2 | Client Stdby | 141-194mA | 0.70-0.97W | 153-161mA | 0.76-0.80W | 154mA | 0.77W | 1.1W | +@@ -855,6 +856,17 @@ 
-| 2 | Client Idle | 160-200mA | 0.8-1W | 170mA | 0.85W | 212mA | 1.06W | 1.5W | +  /* finish setting up the device specific data */ 
-| 3 | Client SCP | 250mA | 1.25W | 210-220mA | 1.07W | 238mA | 1.2W | 1.7W | +  cdc_ncm_setup(dev);
-| 4 | Client SCP | 250mA | 1.25W | 210-220mA | 1.07W | 264mA | 1.32W | 1.9W |+
  
 ++ /* Device-specific flags */
 ++ ctx->drvflags = drvflags;
 ++
 ++ /* Allocate the delayed NDP if needed. */
 ++ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
 ++ ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL);
 ++ if (!ctx->delayed_ndp16)
 ++ goto error2;
 ++ dev_info(&intf->dev, "NDP will be placed at end of frame for this device.");
 ++ }
 ++
 +  /* override ethtool_ops */
 +  dev->net->ethtool_ops = &cdc_ncm_ethtool_ops;
 +@@ -954,8 +966,11 @@
 +  if (cdc_ncm_select_altsetting(intf) != CDC_NCM_COMM_ALTSETTING_NCM)
 +  return -ENODEV;
  
-===== Reliability & Performance =====+- /* The NCM data altsetting is fixed */ 
 +- ret cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM); 
 ++ /* The NCM data altsetting is fixed, so we hard-coded it. 
 ++ * Additionally, generic NCM devices are assumed to accept arbitrarily 
 ++ * placed NDP. 
 ++ */ 
 ++ ret cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM, 0);
  
-The DGS-1100-8 test candidates have been up and running 24x7 for more than 365 days now without any glitch or the necessity to power cycle. +  /* 
 +  * We should get an event when network connection is "connected" or 
 +@@ -986,6 +1001,14 @@ 
 +  struct usb_cdc_ncm_nth16 *nth16 = (void *)skb->data; 
 +  size_t ndpoffset = le16_to_cpu(nth16->wNdpIndex);
  
-<WRAP round tip> ++ /* If NDP should be moved to the end of the NCM packagewe can't follow the 
-When you make changes to the configuration in the web-interfacemake sure to click the **"Save Configuration"** button in the top left menu to actually save your changes to non-volatile RAMOtherwise the next power cycle will wipe your config changes :++ * NTH16 header as we would normally do. NDP isn't written to the SKB yet, and 
-</WRAP>++ the wNdpIndex field in the header is actually not consistent with realityIt will be later. 
 ++ */ 
 ++ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END
 ++ if (ctx->delayed_ndp16->dwSignature == sign) 
 ++ return ctx->delayed_ndp16; 
 +
 +  /* follow the chain of NDPs, looking for a match */ 
 +  while (ndpoffset) { 
 +  ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset); 
 +@@ -995,7 +1018,8 @@ 
 +  }
  
-===== Conclusion =====+  /* align new NDP */ 
 +- cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_max); 
 ++ if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)) 
 ++ cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_max);
  
-Grid powered devices still have the luxury to be able to consume more power than absolutely necessary, since the limiting factor is money and not power itself. Off-Grid scenarios change that point of view on costs, as the value is no longer moneybut the painfully finite element of power itself.+  /* verify that there is room for the NDP and the datagram (reserve) */ 
 +  if ((ctx->tx_max - skb->len - reserve) < ctx->max_ndp_size) 
 +@@ -1008,7 +1032,11 @@ 
 +  nth16->wNdpIndex = cpu_to_le16(skb->len); 
 + 
 +  /* push a new empty NDP */ 
 +- ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, ctx->max_ndp_size), 0, ctx->max_ndp_size); 
 ++ if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)) 
 ++ ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, ctx->max_ndp_size), 0, ctx->max_ndp_size); 
 ++ else 
 ++ ndp16 = ctx->delayed_ndp16; 
 +
 +  ndp16->dwSignature = sign; 
 +  ndp16->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16)); 
 +  return ndp16; 
 +@@ -1023,6 +1051,15 @@ 
 +  struct sk_buff *skb_out; 
 +  u16 n = 0, index, ndplen; 
 +  u8 ready2send = 0; 
 ++ u32 delayed_ndp_size; 
 +
 ++ /* When our NDP gets written in cdc_ncm_ndp(), then skb_out->len gets updated 
 ++ * accordingly. Otherwise, we should check here. 
 ++ */ 
 ++ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) 
 ++ delayed_ndp_size = ctx->max_ndp_size; 
 ++ else 
 ++ delayed_ndp_size = 0; 
 + 
 +  /* if there is a remaining skb, it gets priority */ 
 +  if (skb != NULL) { 
 +@@ -1077,7 +1114,7 @@ 
 +  cdc_ncm_align_tail(skb_out,  ctx->tx_modulus, ctx->tx_remainder, ctx->tx_max); 
 + 
 +  /* check if we had enough room left for both NDP and frame */ 
 +- if (!ndp16 || skb_out->len + skb->len > ctx->tx_max) { 
 ++ if (!ndp16 || skb_out->len + skb->len + delayed_ndp_size > ctx->tx_max) { 
 +  if (n == 0) { 
 +  /* won't fit, MTU problem? */ 
 +  dev_kfree_skb_any(skb); 
 + 
 +@@ -1150,6 +1187,17 @@ 
 +  /* variables will be reset at next call */ 
 +  } 
 + 
 ++ /* If requested, put NDP at end of frame. */ 
 ++ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) { 
 ++ nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data; 
 ++ cdc_ncm_align_tail(skb_outctx->tx_ndp_modulus, 0, ctx->tx_max); 
 ++ nth16->wNdpIndex = cpu_to_le16(skb_out->len); 
 ++ memcpy(skb_put(skb_out, ctx->max_ndp_size), ctx->delayed_ndp16, ctx->max_ndp_size); 
 +
 ++ /* Zero out delayed NDP - signature checking will naturally fail. */ 
 ++ ndp16 = memset(ctx->delayed_ndp16, 0, ctx->max_ndp_size); 
 ++ } 
 +
 +  /* If collected data size is less or equal ctx->min_tx_pkt 
 +  * bytes, we send buffers as it is. If we get more datait 
 +  * would be more efficient for USB HS mobile device with DMA 
 +diff -u a/drivers/net/usb/huawei_cdc_ncm.c b/drivers/net/usb/huawei_cdc_ncm.c 
 +--- a/drivers/net/usb/huawei_cdc_ncm.c 2015-06-28 17:40:40.000000000 +0000 
 ++++ b/drivers/net/usb/huawei_cdc_ncm.c 2015-07-04 15:23:25.779014586 +0000 
 +@@ -73,11 +73,14 @@ 
 +  struct usb_driver *subdriver = ERR_PTR(-ENODEV); 
 +  int ret = -ENODEV; 
 +  struct huawei_cdc_ncm_state *drvstate = (void *)&usbnet_dev->data; 
 ++ int drvflags = 0; 
 + 
 +  /* altsetting should always be 1 for NCM devices - so we hard-coded 
 +- * it here 
 ++ * it here. Some huawei devices will need the NDP part of the NCM package to 
 ++ * be at the end of the frame. 
 +  */ 
 +- ret = cdc_ncm_bind_common(usbnet_dev, intf, 1); 
 ++ drvflags |= CDC_NCM_FLAG_NDP_TO_END; 
 ++ ret = cdc_ncm_bind_common(usbnet_dev, intf, 1, drvflags); 
 +  if (ret) 
 +  goto err; 
 + 
 +diff -u a/include/linux/usb/cdc_ncm.h b/include/linux/usb/cdc_ncm.h 
 +--- a/include/linux/usb/cdc_ncm.h 2015-06-28 17:40:40.000000000 +0000 
 ++++ b/include/linux/usb/cdc_ncm.h 2015-07-04 15:27:52.171388014 +0000 
 +@@ -80,6 +80,9 @@ 
 + #define CDC_NCM_TIMER_INTERVAL_MIN 5UL 
 + #define CDC_NCM_TIMER_INTERVAL_MAX (U32_MAX / NSEC_PER_USEC) 
 + 
 ++/* Driver flags */ 
 ++#define CDC_NCM_FLAG_NDP_TO_END 0x02 /* NDP is placed at end of frame */ 
 +
 + #define cdc_ncm_comm_intf_is_mbim(x)  ((x)->desc.bInterfaceSubClass == USB_CDC_SUBCLASS_MBIM && \ 
 +         (x)->desc.bInterfaceProtocol == USB_CDC_PROTO_NONE) 
 + #define cdc_ncm_data_intf_is_mbim(x)  ((x)->desc.bInterfaceProtocol == USB_CDC_MBIM_PROTO_NTB) 
 +@@ -103,9 +106,11 @@ 
 + 
 +  spinlock_t mtx; 
 +  atomic_t stop; 
 ++ int drvflags; 
 + 
 +  u32 timer_interval; 
 +  u32 max_ndp_size; 
 ++ struct usb_cdc_ncm_ndp16 *delayed_ndp16; 
 + 
 +  u32 tx_timer_pending; 
 +  u32 tx_curr_frame_num; 
 +@@ -133,7 +138,7 @@ 
 + }; 
 + 
 + u8 cdc_ncm_select_altsetting(struct usb_interface *intf); 
 +-int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting); 
 ++int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting, int drvflags); 
 + void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf); 
 + struct sk_buff *cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign); 
 + int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in); 
 +</sxh>
  
-There are still a lot of devices out there with a standby-consumption of well above 10W, the DGS-1008D G3 connects 4 clients, actively transfers a lot of data and consumes about 1W. D-link obviously did a good job with this, although there is a little curiosity in StandBy: The G2 consumes a little less power in StandBy, when no clients are connected but the G3 saves considerably more power when active so overall the G3 is a very good evolutionary step in low-power consumption Gigabit-Ethernet technology. 
  
-The only drawback of these switches is their un-managed nature. Hopefully, in the future even managed switches can operate with this kind of power consumption profile. 
  
-Other manufacturers, who also build similar products, may always send us their products for hardcore real live evaluation as well :) 
  
 {{tag>ethernet switch review hardware test energy}} {{tag>ethernet switch review hardware test energy}}
  
 ~~DISCUSSION~~ ~~DISCUSSION~~