Re: [PATCH net-next 1/1 v3] drivers: net: rmnet: Initial implementation
+ */ +void rmnet_egress_handler(struct sk_buff *skb, + struct rmnet_logical_ep_conf_s *ep) +{ + struct rmnet_phys_ep_conf_s *config; + struct net_device *orig_dev; + int rc; + + orig_dev = skb->dev; + skb->dev = ep->egress_dev; + + config = (struct rmnet_phys_ep_conf_s *) + rcu_dereference(skb->dev->rx_handler_data); This is certainly a misuse of dev->rx_handler_data. Dev private of a function arg to carry the pointer around. Hi Jiri Sorry for the delay in posting a new series. I have an additional query regarding this comment. This dev (from skb->dev->rx_handler_data) corresponds to the real_dev to which the rmnet devices are attached to. I had earlier setup a rx_handler on this real_dev netdevice in rmnet_associate_network_device(). Would it still be incorrect to use rx_handler_data of real_dev to have rmnet specific config information? Bridge is similarly storing the bridge information on the real_dev rx_handler_data and retrieving it through br_port_get_rcu(). I am using that as a reference. -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH net-next 1/1 v3] drivers: net: rmnet: Initial implementation
+https://source.codeaurora.org/quic/la/platform/vendor/qcom-opensource/\ +dataservices/tree/rmnetctl Don't split URL better to have long line. diff --git a/drivers/net/rmnet/Kconfig b/drivers/net/rmnet/Kconfig Since this is Qualcomm and Ethernet specific, maybe better to put in drivers/net/ethernet/qualcom/rmnet +config RMNET_DEBUG Please use network device standard debug mechanism. netif_msg_XXX + buffloc += snprintf(&buffer[buffloc], sizeof(buffer) - buffloc, + " %02x", skb->data[i]); If you really have to do this. Use hex_dump_bytes API. + skb->mac_header = 0; + skb->mac_len = 0; +} Why not use sbk_set_mac_header(skb, 0)? +static inline struct rmnet_phys_ep_conf_s *_rmnet_get_phys_ep_config + (struct net_device *dev) awkward line break. dev could be const + config = (struct rmnet_phys_ep_conf_s *) + rcu_dereference(dev->rx_handler_data); Please don't directly reference rx_handler. There is already functions like netdev_is_rx_handler_busy() to abstract that API. + * @epconfig:endpoint configuration structure to set + */ You are using docbook format here, but this is not a docbook comment. ie. /** * function - This is a docbook comment * @dev: this is a param */ Plus these are static functions so there is no point in documentating internal API with docbook. + ASSERT_RTNL(); + + if (!dev || config_id < RMNET_LOCAL_LOGICAL_ENDPOINT || + config_id >= RMNET_MAX_LOGICAL_EP) + return -EINVAL; For internal API's you should validate parmeters at the external entry point not in each call. Otherwise you have a multitude of impossible error checks and dead code paths. + .next = 0, + .priority = 0 +}; Don't initialize fields that are not used or should be zero. Hi Stephen I'll make these changes. Could just be: static inline int _rmnet_is_physical_endpoint_associated(const struct net_device *dev) { rx_handler_func_t *rx_handler = rcu_dereference(dev->rx_handler); return rx_handler == rmet_rx_handler; } But standard practice is to use ndo_ops to identify self in network drivers. I.e return dev->netdev_ops == &rmnet_device_ops; The netdevice which is associated is the physical (real_dev). This device can vary based on hardware and will have its own netdev_ops associated with it. rmnet_device_ops applies to the rmnet devices only. I'll use the first option you have suggested. + if (!data[IFLA_RMNET_MUX_ID]) + return -EINVAL; So you are inventing private link netlink attributes. Why? Why can't you use device switch, bridge, or other master/slave model. I would like to eventually add more configuration options for the ingress & egress data formats as well as the endpoint configuration (VND mode vs BRIDGE mode). I was able to re-use IFLA_VLAN_ID for IFLA_RMNET_MUX_ID and test but it wasn't sufficient for the additional parameters. I'll check the bridge attributes and try to reuse it. -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH net-next 1/1 v3] drivers: net: rmnet: Initial implementation
On Fri, 14 Apr 2017 15:57:22 -0600 Subash Abhinov Kasiviswanathan wrote: > >> + rmnet_kfree_skb > >> + (skb, > >> + RMNET_STATS_SKBFREE_INGRESS_NOT_EXPECT_MAPD); > > > > very odd formatting. Please fix. > > > Checkpatch complains if it is over 80 chars in a line, so I had to do > this. > I'll change to a single line. Either ignore checkpatch, it is only a dumb script; or better yet refactor the code so it isn't indented so much.
Re: [PATCH net-next 1/1 v3] drivers: net: rmnet: Initial implementation
No, please use standard facilities in order to do debug logging. +static struct rmnet_logical_ep_conf_s *_rmnet_get_logical_ep Dont use "_" at the start of a name without purpose +static int rmnet_associate_network_device(struct net_device *dev) I would expect to see here you making connection between real_dev and rmnet dev. I don't see such thing. Name of the function is misleading. + + config = kmalloc(sizeof(*config), GFP_ATOMIC); kzalloc, and you don't have to zero the memory. +static struct notifier_block rmnet_dev_notifier = { You should add "__read_mostly" + .notifier_call = rmnet_config_notify_cb, + .next = 0, + .priority = 0 This initialization of 0s is not needed. +/* rmnet_vnd_is_vnd() gives mux_id + 1, so subtract 1 to get the correct mux_id + */ Fix this comment format. +void rmnet_print_packet(const struct sk_buff *skb, const char *dev, char dir) No reason to have this function. One can use P_ALL tap to get skbs to userspace. +/* rmnet_bridge_handler() - Bridge related functionality + */ Fix the comment format (you have it on multiple places) +static rx_handler_result_t rmnet_bridge_handler + (struct sk_buff *skb, struct rmnet_logical_ep_conf_s *ep) The formatting is incorrect: static rx_handler_result_t rmnet_bridge_handler(struct sk_buff *skb, struct rmnet_logical_ep_conf_s *ep) + config = (struct rmnet_phys_ep_conf_s *) + rcu_dereference(skb->dev->rx_handler_data); + + if (!config) { Cannot happen. Please remove this. + .ndo_set_mac_address = 0, + .ndo_validate_addr = 0, These are NULL by default. No need to init. + if ((id < 0) || (id >= RMNET_MAX_VND) || !rmnet_devices[id]) Unneeded inner "()"s. I see you have it on multiple places. + + dev_conf = (struct rmnet_vnd_private_s *)netdev_priv(dev); The typecast is not needed since netdev_priv is void*. You have it all over the code. +#define ETH_P_MAP 0xDA1A /* Multiplexing and Aggregation Protocol +* NOT AN OFFICIALLY REGISTERED ID ] Please push this and ARPHRD_RAWIP as separate patches, to increase the visibility. +enum { + IFLA_RMNET_UNSPEC, + IFLA_RMNET_MUX_ID, + __IFLA_RMNET_MAX, +}; This belongs to include/uapi/linux/if_link.h Please see IFLA_BOND_* as example +#define RMNET_INIT_OK 0 +#define RMNET_INIT_ERROR 1 Please use common error codes (0/-ENOMEM/-EINVAL/...) + static u32 rmnet_mod_mask = X Don't use this custom helpers. Use existing loggign facilities. + pr_notice("[RMNET:LOW] %s(): " fmt "\n", __func__, \ + ##__VA_ARGS__); \ + } while (0) These look scarry. Please use netdev_err, dev_err and others instead. +unsigned int rmnet_log_module_mask; +module_param(rmnet_log_module_mask, uint, 0644); +MODULE_PARM_DESC(rmnet_log_module_mask, "Logging module mask"); No module options please. + config = (struct rmnet_phys_ep_conf_s *) + rcu_dereference(skb->dev->rx_handler_data); This is certainly a misuse of dev->rx_handler_data. Dev private of a function arg to carry the pointer around. +struct net_device *rmnet_devices[RMNET_MAX_VND]; Avoid this global variable. Hi Jiri I'll make these changes. + if (!data[IFLA_RMNET_MUX_ID]) + return -EINVAL; + + mux_id = nla_get_u16(data[IFLA_VLAN_ID]); This is a bug I believe... ^^^ I'm pretty sure that you did not test this code. Since both IFLA_VLAN_ID and IFLA_RMNET_MUX_ID are 1 from enum, this actually works. I was using VLAN as a reference, so I missed to change this to IFLA_RMNET_MUX_ID. + rmnet_kfree_skb + (skb, +RMNET_STATS_SKBFREE_INGRESS_NOT_EXPECT_MAPD); very odd formatting. Please fix. Checkpatch complains if it is over 80 chars in a line, so I had to do this. I'll change to a single line. -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH net-next 1/1 v3] drivers: net: rmnet: Initial implementation
On Thu, 13 Apr 2017 23:05:29 -0600 Subash Abhinov Kasiviswanathan wrote: > RmNet driver provides a transport agnostic MAP (multiplexing and > aggregation protocol) support in embedded module. Module provides > virtual network devices which can be attached to any IP-mode > physical device. This will be used to provide all MAP functionality > on future hardware in a single consistent location. > > Signed-off-by: Subash Abhinov Kasiviswanathan > > diff --git a/Documentation/networking/rmnet.txt > b/Documentation/networking/rmnet.txt > new file mode 100644 > index 000..58d3ea2 > --- /dev/null > +++ b/Documentation/networking/rmnet.txt > ... > +3. Userspace configuration > + > +rmnet userspace configuration is done through netlink library librmnetctl > +and command line utility rmnetcli. Utility is hosted in codeaurora forum git. > +The driver uses rtnl_link_ops for communication. > + > +https://source.codeaurora.org/quic/la/platform/vendor/qcom-opensource/\ > +dataservices/tree/rmnetctl Don't split URL better to have long line. > diff --git a/drivers/net/Makefile b/drivers/net/Makefile > index 98ed4d9..29b3945 100644 > --- a/drivers/net/Makefile > +++ b/drivers/net/Makefile > @@ -74,3 +74,4 @@ obj-$(CONFIG_HYPERV_NET) += hyperv/ > obj-$(CONFIG_NTB_NETDEV) += ntb_netdev.o > > obj-$(CONFIG_FUJITSU_ES) += fjes/ > +obj-$(CONFIG_RMNET) += rmnet/ > diff --git a/drivers/net/rmnet/Kconfig b/drivers/net/rmnet/Kconfig Since this is Qualcomm and Ethernet specific, maybe better to put in drivers/net/ethernet/qualcom/rmnet > new file mode 100644 > index 000..63cd477 > --- /dev/null > +++ b/drivers/net/rmnet/Kconfig > @@ -0,0 +1,23 @@ > +# > +# RMNET MAP driver > +# > + > +menuconfig RMNET > + depends on NETDEVICES > + bool "RmNet MAP driver" > + default n > + ---help--- > + If you say Y here, then the rmnet module will be statically > + compiled into the kernel. The rmnet module provides MAP > + functionality for embedded and bridged traffic. > +if RMNET > + > +config RMNET_DEBUG > + bool "RmNet Debug Logging" > + default n > + ---help--- > + Say Y here if you want RmNet to be able to log packets in main > + system log. This should not be enabled on production builds as it can > + impact system performance. Note that simply enabling it here will not > + enable the logging; it must be enabled at run-time as well. Please use network device standard debug mechanism. netif_msg_XXX > +endif # RMNET > diff --git a/drivers/net/rmnet/Makefile b/drivers/net/rmnet/Makefile > new file mode 100644 > index 000..2b6c9cf > --- /dev/null > +++ b/drivers/net/rmnet/Makefile > @@ -0,0 +1,14 @@ > +# > +# Makefile for the RMNET module > +# > + > +rmnet-y := rmnet_main.o > +rmnet-y += rmnet_config.o > +rmnet-y += rmnet_vnd.o > +rmnet-y += rmnet_handlers.o > +rmnet-y += rmnet_map_data.o > +rmnet-y += rmnet_map_command.o > +rmnet-y += rmnet_stats.o > +obj-$(CONFIG_RMNET) += rmnet.o > + > +CFLAGS_rmnet_main.o := -I$(src) > diff --git a/drivers/net/rmnet/rmnet_config.c > b/drivers/net/rmnet/rmnet_config.c > new file mode 100644 > index 000..a4bc76b > --- /dev/null > +++ b/drivers/net/rmnet/rmnet_config.c > @@ -0,0 +1,592 @@ > +/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 and > + * only version 2 as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * RMNET configuration engine > + * > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "rmnet_config.h" > +#include "rmnet_handlers.h" > +#include "rmnet_vnd.h" > +#include "rmnet_private.h" > + > +RMNET_LOG_MODULE(RMNET_LOGMASK_CONFIG); > + > +/* Local Definitions and Declarations */ > +#define RMNET_LOCAL_LOGICAL_ENDPOINT -1 > + > +/* _rmnet_is_physical_endpoint_associated() - Determines if device is > associated > + * @dev: Device to get check > + * > + * Compares device rx_handler callback pointer against known function > + */ > +static inline int _rmnet_is_physical_endpoint_associated(struct net_device > *dev) > +{ > + rx_handler_func_t *rx_handler; > + > + rx_handler = rcu_dereference(dev->rx_handler); > + > + if (rx_handler == rmnet_rx_handler) > + return 1; > + else > + return 0; > +} Could just be: static inline int _rmnet_is_physical_endpoint_associated(const struct net_device *dev) { rx_handler_func_t *rx_handler = rcu_deref
Re: [PATCH net-next 1/1 v3] drivers: net: rmnet: Initial implementation
Fri, Apr 14, 2017 at 07:05:29AM CEST, subas...@codeaurora.org wrote: >RmNet driver provides a transport agnostic MAP (multiplexing and >aggregation protocol) support in embedded module. Module provides >virtual network devices which can be attached to any IP-mode >physical device. This will be used to provide all MAP functionality >on future hardware in a single consistent location. > >Signed-off-by: Subash Abhinov Kasiviswanathan >--- > Documentation/networking/rmnet.txt| 83 + > drivers/net/Kconfig | 2 + > drivers/net/Makefile | 1 + > drivers/net/rmnet/Kconfig | 23 ++ > drivers/net/rmnet/Makefile| 14 + > drivers/net/rmnet/rmnet_config.c | 592 ++ > drivers/net/rmnet/rmnet_config.h | 79 + > drivers/net/rmnet/rmnet_handlers.c| 517 + > drivers/net/rmnet/rmnet_handlers.h| 24 ++ > drivers/net/rmnet/rmnet_main.c| 52 +++ > drivers/net/rmnet/rmnet_map.h | 100 ++ > drivers/net/rmnet/rmnet_map_command.c | 180 +++ > drivers/net/rmnet/rmnet_map_data.c| 145 + > drivers/net/rmnet/rmnet_private.h | 76 + > drivers/net/rmnet/rmnet_stats.c | 86 + > drivers/net/rmnet/rmnet_stats.h | 61 > drivers/net/rmnet/rmnet_vnd.c | 353 > drivers/net/rmnet/rmnet_vnd.h | 34 ++ > include/uapi/linux/Kbuild | 1 + > include/uapi/linux/if_arp.h | 1 + > include/uapi/linux/if_ether.h | 4 +- > include/uapi/linux/rmnet.h| 34 ++ > 22 files changed, 2461 insertions(+), 1 deletion(-) > create mode 100644 Documentation/networking/rmnet.txt > create mode 100644 drivers/net/rmnet/Kconfig > create mode 100644 drivers/net/rmnet/Makefile > create mode 100644 drivers/net/rmnet/rmnet_config.c > create mode 100644 drivers/net/rmnet/rmnet_config.h > create mode 100644 drivers/net/rmnet/rmnet_handlers.c > create mode 100644 drivers/net/rmnet/rmnet_handlers.h > create mode 100644 drivers/net/rmnet/rmnet_main.c > create mode 100644 drivers/net/rmnet/rmnet_map.h > create mode 100644 drivers/net/rmnet/rmnet_map_command.c > create mode 100644 drivers/net/rmnet/rmnet_map_data.c > create mode 100644 drivers/net/rmnet/rmnet_private.h > create mode 100644 drivers/net/rmnet/rmnet_stats.c > create mode 100644 drivers/net/rmnet/rmnet_stats.h > create mode 100644 drivers/net/rmnet/rmnet_vnd.c > create mode 100644 drivers/net/rmnet/rmnet_vnd.h > create mode 100644 include/uapi/linux/rmnet.h > >diff --git a/Documentation/networking/rmnet.txt >b/Documentation/networking/rmnet.txt >new file mode 100644 >index 000..58d3ea2 >--- /dev/null >+++ b/Documentation/networking/rmnet.txt >@@ -0,0 +1,83 @@ >+1. Introduction >+ >+rmnet driver is used for supporting the Multiplexing and aggregation >+Protocol (MAP). This protocol is used by all recent chipsets using Qualcomm >+Technologies, Inc. modems. >+ >+This driver can be used to register onto any physical network device in >+IP mode. Physical transports include USB, HSIC, PCIe and IP accelerator. >+ >+Multiplexing allows for creation of logical netdevices (rmnet devices) to >+handle multiple private data networks (PDN) like a default internet, >tethering, >+multimedia messaging service (MMS) or IP media subsystem (IMS). Hardware sends >+packets with MAP headers to rmnet. Based on the multiplexer id, rmnet >+routes to the appropriate PDN after removing the MAP header. >+ >+Aggregation is required to achieve high data rates. This involves hardware >+sending aggregated bunch of MAP frames. rmnet driver will de-aggregate >+these MAP frames and send them to appropriate PDN's. >+ >+2. Packet format >+ >+a. MAP packet (data / control) >+ >+MAP header has the same endianness of the IP packet. >+ >+Packet format - >+ >+Bit 0 1 2-7 8 - 15 16 - 31 >+Function Command / Data Reserved Pad Multiplexer IDPayload >length >+Bit32 - x >+Function Raw Bytes >+ >+Command (1)/ Data (0) bit value is to indicate if the packet is a MAP command >+or data packet. Control packet is used for transport level flow control. Data >+packets are standard IP packets. >+ >+Reserved bits are usually zeroed out and to be ignored by receiver. >+ >+Padding is number of bytes to be added for 4 byte alignment if required by >+hardware. >+ >+Multiplexer ID is to indicate the PDN on which data has to be sent. >+ >+Payload length includes the padding length but does not include MAP header >+length. >+ >+b. MAP packet (command specific) >+ >+Bit 0 1 2-7 8 - 15 16 - 31 >+Function Command Reserved Pad Multiplexer IDPayload length >+Bit 32 - 3940 - 4546 - 47 48 - 63 >+Function Command nameReserved Command Type Reserved >+Bit 64 - 95 >+Function Transaction ID >+Bit
[PATCH net-next 1/1 v3] drivers: net: rmnet: Initial implementation
RmNet driver provides a transport agnostic MAP (multiplexing and aggregation protocol) support in embedded module. Module provides virtual network devices which can be attached to any IP-mode physical device. This will be used to provide all MAP functionality on future hardware in a single consistent location. Signed-off-by: Subash Abhinov Kasiviswanathan --- Documentation/networking/rmnet.txt| 83 + drivers/net/Kconfig | 2 + drivers/net/Makefile | 1 + drivers/net/rmnet/Kconfig | 23 ++ drivers/net/rmnet/Makefile| 14 + drivers/net/rmnet/rmnet_config.c | 592 ++ drivers/net/rmnet/rmnet_config.h | 79 + drivers/net/rmnet/rmnet_handlers.c| 517 + drivers/net/rmnet/rmnet_handlers.h| 24 ++ drivers/net/rmnet/rmnet_main.c| 52 +++ drivers/net/rmnet/rmnet_map.h | 100 ++ drivers/net/rmnet/rmnet_map_command.c | 180 +++ drivers/net/rmnet/rmnet_map_data.c| 145 + drivers/net/rmnet/rmnet_private.h | 76 + drivers/net/rmnet/rmnet_stats.c | 86 + drivers/net/rmnet/rmnet_stats.h | 61 drivers/net/rmnet/rmnet_vnd.c | 353 drivers/net/rmnet/rmnet_vnd.h | 34 ++ include/uapi/linux/Kbuild | 1 + include/uapi/linux/if_arp.h | 1 + include/uapi/linux/if_ether.h | 4 +- include/uapi/linux/rmnet.h| 34 ++ 22 files changed, 2461 insertions(+), 1 deletion(-) create mode 100644 Documentation/networking/rmnet.txt create mode 100644 drivers/net/rmnet/Kconfig create mode 100644 drivers/net/rmnet/Makefile create mode 100644 drivers/net/rmnet/rmnet_config.c create mode 100644 drivers/net/rmnet/rmnet_config.h create mode 100644 drivers/net/rmnet/rmnet_handlers.c create mode 100644 drivers/net/rmnet/rmnet_handlers.h create mode 100644 drivers/net/rmnet/rmnet_main.c create mode 100644 drivers/net/rmnet/rmnet_map.h create mode 100644 drivers/net/rmnet/rmnet_map_command.c create mode 100644 drivers/net/rmnet/rmnet_map_data.c create mode 100644 drivers/net/rmnet/rmnet_private.h create mode 100644 drivers/net/rmnet/rmnet_stats.c create mode 100644 drivers/net/rmnet/rmnet_stats.h create mode 100644 drivers/net/rmnet/rmnet_vnd.c create mode 100644 drivers/net/rmnet/rmnet_vnd.h create mode 100644 include/uapi/linux/rmnet.h diff --git a/Documentation/networking/rmnet.txt b/Documentation/networking/rmnet.txt new file mode 100644 index 000..58d3ea2 --- /dev/null +++ b/Documentation/networking/rmnet.txt @@ -0,0 +1,83 @@ +1. Introduction + +rmnet driver is used for supporting the Multiplexing and aggregation +Protocol (MAP). This protocol is used by all recent chipsets using Qualcomm +Technologies, Inc. modems. + +This driver can be used to register onto any physical network device in +IP mode. Physical transports include USB, HSIC, PCIe and IP accelerator. + +Multiplexing allows for creation of logical netdevices (rmnet devices) to +handle multiple private data networks (PDN) like a default internet, tethering, +multimedia messaging service (MMS) or IP media subsystem (IMS). Hardware sends +packets with MAP headers to rmnet. Based on the multiplexer id, rmnet +routes to the appropriate PDN after removing the MAP header. + +Aggregation is required to achieve high data rates. This involves hardware +sending aggregated bunch of MAP frames. rmnet driver will de-aggregate +these MAP frames and send them to appropriate PDN's. + +2. Packet format + +a. MAP packet (data / control) + +MAP header has the same endianness of the IP packet. + +Packet format - + +Bit 0 1 2-7 8 - 15 16 - 31 +Function Command / Data Reserved Pad Multiplexer IDPayload length +Bit32 - x +Function Raw Bytes + +Command (1)/ Data (0) bit value is to indicate if the packet is a MAP command +or data packet. Control packet is used for transport level flow control. Data +packets are standard IP packets. + +Reserved bits are usually zeroed out and to be ignored by receiver. + +Padding is number of bytes to be added for 4 byte alignment if required by +hardware. + +Multiplexer ID is to indicate the PDN on which data has to be sent. + +Payload length includes the padding length but does not include MAP header +length. + +b. MAP packet (command specific) + +Bit 0 1 2-7 8 - 15 16 - 31 +Function Command Reserved Pad Multiplexer IDPayload length +Bit 32 - 3940 - 4546 - 47 48 - 63 +Function Command nameReserved Command Type Reserved +Bit 64 - 95 +Function Transaction ID +Bit 96 - 127 +Function Command data + +Command 1 indicates disabling flow while 2 is enabling flow + +Command types - +0 for MAP command request +1 is to acknowledge the receipt of a co