On Mon, 2021-01-25 at 00:33 -0700, Subash Abhinov Kasiviswanathan
wrote:
> Pass through mode is to allow packets in MAP format to be passed
> on to the stack. rmnet driver can be used to process and demultiplex
> these packets.
> 
> Pass through mode can be enabled when the device is in raw ip mode
> only.
> Conversely, raw ip mode cannot be disabled when pass through mode is
> enabled.
> 
> Userspace can use pass through mode in conjunction with rmnet driver
> through the following steps-
> 
> 1. Enable raw ip mode on qmi_wwan device
> 2. Enable pass through mode on qmi_wwan device
> 3. Create a rmnet device with qmi_wwan device as real device using
> netlink

This option is module-wide, right?

eg, if there are multiple qmi_wwan-driven devices on the system, *all*
of them must use MAP + passthrough, or none of them can, right?

There are users that run 2+ devices on the same system, and different
cards. I'm not sure I would assume that all can/would run in the same
mode, unfortunately.

Dan

> Signed-off-by: Subash Abhinov Kasiviswanathan <
> subas...@codeaurora.org>
> ---
> v1->v2: Update commit text and fix the following comments from Bjorn-
> Remove locking as no netdev state change is requried since all the
> configuration is already done in raw_ip_store.
> Check the inverse relationship between raw_ip mode and pass_through
> mode.
> pass_through_mode just sets/resets the flag now.
> raw_ip check is not needed when queueing pass_through mode packets as
> that is enforced already during the mode configuration.
> 
>  drivers/net/usb/qmi_wwan.c | 58
> ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 58 insertions(+)
> 
> diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
> index 7ea113f5..e58a80a 100644
> --- a/drivers/net/usb/qmi_wwan.c
> +++ b/drivers/net/usb/qmi_wwan.c
> @@ -57,6 +57,7 @@ struct qmi_wwan_state {
>  enum qmi_wwan_flags {
>       QMI_WWAN_FLAG_RAWIP = 1 << 0,
>       QMI_WWAN_FLAG_MUX = 1 << 1,
> +     QMI_WWAN_FLAG_PASS_THROUGH = 1 << 2,
>  };
>  
>  enum qmi_wwan_quirks {
> @@ -326,6 +327,13 @@ static ssize_t raw_ip_store(struct device
> *d,  struct device_attribute *attr, co
>       if (enable == (info->flags & QMI_WWAN_FLAG_RAWIP))
>               return len;
>  
> +     /* ip mode cannot be cleared when pass through mode is set */
> +     if (!enable && (info->flags & QMI_WWAN_FLAG_PASS_THROUGH)) {
> +             netdev_err(dev->net,
> +                        "Cannot clear ip mode on pass through
> device\n");
> +             return -EINVAL;
> +     }
> +
>       if (!rtnl_trylock())
>               return restart_syscall();
>  
> @@ -456,14 +464,59 @@ static ssize_t del_mux_store(struct device
> *d,  struct device_attribute *attr, c
>       return ret;
>  }
>  
> +static ssize_t pass_through_show(struct device *d,
> +                              struct device_attribute *attr, char
> *buf)
> +{
> +     struct usbnet *dev = netdev_priv(to_net_dev(d));
> +     struct qmi_wwan_state *info;
> +
> +     info = (void *)&dev->data;
> +     return sprintf(buf, "%c\n",
> +                    info->flags & QMI_WWAN_FLAG_PASS_THROUGH ? 'Y' :
> 'N');
> +}
> +
> +static ssize_t pass_through_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;
> +     bool enable;
> +
> +     if (strtobool(buf, &enable))
> +             return -EINVAL;
> +
> +     info = (void *)&dev->data;
> +
> +     /* no change? */
> +     if (enable == (info->flags & QMI_WWAN_FLAG_PASS_THROUGH))
> +             return len;
> +
> +     /* pass through mode can be set for raw ip devices only */
> +     if (!(info->flags & QMI_WWAN_FLAG_RAWIP)) {
> +             netdev_err(dev->net,
> +                        "Cannot set pass through mode on non ip
> device\n");
> +             return -EINVAL;
> +     }
> +
> +     if (enable)
> +             info->flags |= QMI_WWAN_FLAG_PASS_THROUGH;
> +     else
> +             info->flags &= ~QMI_WWAN_FLAG_PASS_THROUGH;
> +
> +     return len;
> +}
> +
>  static DEVICE_ATTR_RW(raw_ip);
>  static DEVICE_ATTR_RW(add_mux);
>  static DEVICE_ATTR_RW(del_mux);
> +static DEVICE_ATTR_RW(pass_through);
>  
>  static struct attribute *qmi_wwan_sysfs_attrs[] = {
>       &dev_attr_raw_ip.attr,
>       &dev_attr_add_mux.attr,
>       &dev_attr_del_mux.attr,
> +     &dev_attr_pass_through.attr,
>       NULL,
>  };
>  
> @@ -510,6 +563,11 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev,
> struct sk_buff *skb)
>       if (info->flags & QMI_WWAN_FLAG_MUX)
>               return qmimux_rx_fixup(dev, skb);
>  
> +     if (info->flags & QMI_WWAN_FLAG_PASS_THROUGH) {
> +             skb->protocol = htons(ETH_P_MAP);
> +             return (netif_rx(skb) == NET_RX_SUCCESS);
> +     }
> +
>       switch (skb->data[0] & 0xf0) {
>       case 0x40:
>               proto = htons(ETH_P_IP);

Reply via email to