From 0f789efb3a122daecbb5dcf2df16f2943dd2603e Mon Sep 17 00:00:00 2001 From: Harout Hedeshian Date: Tue, 8 Oct 2013 11:46:55 -0600 Subject: [PATCH] net: rmnet_data: Add support for user defined device name prefix Run-time user space components can now specify virtual network device name prefix at device creation. This will be used to support legacy data services. CRs-Fixed: 555507 Change-Id: Id34c2761f2060e66b05c521304d5151620ba5665 Signed-off-by: Harout Hedeshian --- include/uapi/linux/rmnet_data.h | 17 ++++++++ net/rmnet_data/rmnet_data_config.c | 54 +++++++++++++++++++++++-- net/rmnet_data/rmnet_data_config.h | 1 + net/rmnet_data/rmnet_data_private.h | 2 +- net/rmnet_data/rmnet_data_vnd.c | 63 +++++++++++++++++++++++++++-- net/rmnet_data/rmnet_data_vnd.h | 4 +- 6 files changed, 132 insertions(+), 9 deletions(-) diff --git a/include/uapi/linux/rmnet_data.h b/include/uapi/linux/rmnet_data.h index b8dbf907c8b3..bcff313a95c0 100644 --- a/include/uapi/linux/rmnet_data.h +++ b/include/uapi/linux/rmnet_data.h @@ -164,6 +164,23 @@ enum rmnet_netlink_message_types_e { */ RMNET_NETLINK_NEW_VND, + /* + * RMNET_NETLINK_NEW_VND_WITH_PREFIX - Creates a new virtual network + * device node with the specified + * prefix for the device name + * Args: int32_t node number + * char[] vnd_name - Use as prefix + * Returns: status code + */ + RMNET_NETLINK_NEW_VND_WITH_PREFIX, + + /* + * RMNET_NETLINK_GET_VND_NAME - Gets the string name of a VND from ID + * Args: int32_t node number + * Returns: char[] vnd_name + */ + RMNET_NETLINK_GET_VND_NAME, + /* * RMNET_NETLINK_FREE_VND - Removes virtual network device node * Args: int32_t node number diff --git a/net/rmnet_data/rmnet_data_config.c b/net/rmnet_data/rmnet_data_config.c index caa6cfb516c7..e7a92696499c 100644 --- a/net/rmnet_data/rmnet_data_config.c +++ b/net/rmnet_data/rmnet_data_config.c @@ -237,7 +237,7 @@ static void _rmnet_netlink_unassociate_network_device resp_rmnet->return_code = rmnet_unassociate_network_device(dev); } -static inline void _rmnet_netlink_get_link_egress_data_format +static void _rmnet_netlink_get_link_egress_data_format (struct rmnet_nl_msg_s *rmnet_header, struct rmnet_nl_msg_s *resp_rmnet) { @@ -267,7 +267,7 @@ static inline void _rmnet_netlink_get_link_egress_data_format resp_rmnet->data_format.agg_size = config->egress_agg_size; } -static inline void _rmnet_netlink_get_link_ingress_data_format +static void _rmnet_netlink_get_link_ingress_data_format (struct rmnet_nl_msg_s *rmnet_header, struct rmnet_nl_msg_s *resp_rmnet) { @@ -295,6 +295,27 @@ static inline void _rmnet_netlink_get_link_ingress_data_format resp_rmnet->data_format.flags = config->ingress_data_format; } +static void _rmnet_netlink_get_vnd_name + (struct rmnet_nl_msg_s *rmnet_header, + struct rmnet_nl_msg_s *resp_rmnet) +{ + int r; + _RMNET_NETLINK_NULL_CHECKS(); + resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE; + + r = rmnet_vnd_get_name(rmnet_header->vnd.id, resp_rmnet->vnd.vnd_name, + RMNET_MAX_STR_LEN); + + if (r != 0) { + resp_rmnet->return_code = RMNET_CONFIG_INVALID_REQUEST; + return; + } + + /* Begin Data */ + resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNDATA; + resp_rmnet->arg_length = RMNET_NL_MSG_SIZE(vnd); +} + /** * rmnet_config_netlink_msg_handler() - Netlink message handler callback * @skb: Packet containing netlink messages @@ -386,6 +407,17 @@ void rmnet_config_netlink_msg_handler(struct sk_buff *skb) rmnet_create_vnd(rmnet_header->vnd.id); break; + case RMNET_NETLINK_NEW_VND_WITH_PREFIX: + resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE; + resp_rmnet->return_code = rmnet_create_vnd_prefix( + rmnet_header->vnd.id, + rmnet_header->vnd.vnd_name); + break; + + case RMNET_NETLINK_GET_VND_NAME: + _rmnet_netlink_get_vnd_name(rmnet_header, resp_rmnet); + break; + default: resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE; resp_rmnet->return_code = RMNET_CONFIG_UNKNOWN_MESSAGE; @@ -669,5 +701,21 @@ int rmnet_create_vnd(int id) struct net_device *dev; ASSERT_RTNL(); LOGL("%s(%d);", __func__, id); - return rmnet_vnd_create_dev(id, &dev); + return rmnet_vnd_create_dev(id, &dev, NULL); +} + +/** + * rmnet_create_vnd() - Create virtual network device node + * @id: RmNet virtual device node id + * @prefix: String prefix for device name + * + * Return: + * - result of rmnet_vnd_create_dev() + */ +int rmnet_create_vnd_prefix(int id, const char *prefix) +{ + struct net_device *dev; + ASSERT_RTNL(); + LOGL("%s(%d, \"%s\");", __func__, id, prefix); + return rmnet_vnd_create_dev(id, &dev, prefix); } diff --git a/net/rmnet_data/rmnet_data_config.h b/net/rmnet_data/rmnet_data_config.h index 2f8efc59f45d..2eac471fc83c 100644 --- a/net/rmnet_data/rmnet_data_config.h +++ b/net/rmnet_data/rmnet_data_config.h @@ -65,5 +65,6 @@ int rmnet_set_logical_endpoint_config(struct net_device *dev, struct net_device *egress_dev); void rmnet_config_netlink_msg_handler (struct sk_buff *skb); int rmnet_create_vnd(int id); +int rmnet_create_vnd_prefix(int id, const char *name); #endif /* _RMNET_DATA_CONFIG_H_ */ diff --git a/net/rmnet_data/rmnet_data_private.h b/net/rmnet_data/rmnet_data_private.h index ae253b9db5fc..cc4f2e4a27ca 100644 --- a/net/rmnet_data/rmnet_data_private.h +++ b/net/rmnet_data/rmnet_data_private.h @@ -17,7 +17,7 @@ #define RMNET_DATA_MAX_VND 32 #define RMNET_DATA_MAX_PACKET_SIZE 16384 #define RMNET_DATA_DFLT_PACKET_SIZE 1500 -#define RMNET_DATA_DEV_NAME_STR "rmnet_data%d" +#define RMNET_DATA_DEV_NAME_STR "rmnet_data" #define RMNET_DATA_NEEDED_HEADROOM 16 #define RMNET_ETHERNET_HEADER_LENGTH 14 diff --git a/net/rmnet_data/rmnet_data_vnd.c b/net/rmnet_data/rmnet_data_vnd.c index f304de49404d..dc59e8db55fa 100644 --- a/net/rmnet_data/rmnet_data_vnd.c +++ b/net/rmnet_data/rmnet_data_vnd.c @@ -360,29 +360,45 @@ int rmnet_vnd_init(void) * rmnet_vnd_create_dev() - Create a new virtual network device node. * @id: Virtual device node id * @new_device: Pointer to newly created device node + * @prefix: Device name prefix * * Allocates structures for new virtual network devices. Sets the name of the * new device and registers it with the network stack. Device will appear in - * ifconfig list after this is called. + * ifconfig list after this is called. If the prefix is null, then + * RMNET_DATA_DEV_NAME_STR will be assumed. * * Return: * - 0 if successful * - -EINVAL if id is out of range, or id already in use * - -EINVAL if net_device allocation failed + * - -EINVAL if prefix does not fit in buffer * - return code of register_netdevice() on other errors */ -int rmnet_vnd_create_dev(int id, struct net_device **new_device) +int rmnet_vnd_create_dev(int id, struct net_device **new_device, + const char *prefix) { struct net_device *dev; - int rc = 0; + char dev_prefix[IFNAMSIZ]; + int p, rc = 0; if (id < 0 || id > RMNET_DATA_MAX_VND || rmnet_devices[id] != 0) { *new_device = 0; return -EINVAL; } + if (!prefix) + p = scnprintf(dev_prefix, IFNAMSIZ, "%s%%d", + RMNET_DATA_DEV_NAME_STR); + else + p = scnprintf(dev_prefix, IFNAMSIZ, "%s%%d", + prefix); + if (p >= (IFNAMSIZ-1)) { + LOGE("%s(): Specified prefix longer than IFNAMSIZ", __func__); + return -EINVAL; + } + dev = alloc_netdev(sizeof(struct rmnet_vnd_private_s), - RMNET_DATA_DEV_NAME_STR, + dev_prefix, rmnet_vnd_setup); if (!dev) { LOGE("%s(): Failed to to allocate netdev for id %d", @@ -406,6 +422,45 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device) return rc; } +/** + * rmnet_vnd_get_name() - Gets the string name of a VND based on ID + * @id: Virtual device node id + * @name: Buffer to store name of virtual device node + * @name_len: Length of name buffer + * + * Copies the name of the virtual device node into the users buffer. Will throw + * an error if the buffer is null, or too small to hold the device name. + * + * Return: + * - 0 if successful + * - -EINVAL if name is null + * - -EINVAL if id is invalid or not in range + * - -EINVAL if name is too small to hold things + */ +int rmnet_vnd_get_name(int id, char *name, int name_len) +{ + int p; + + if (!name) { + LOGM("%s(): Bad arguments; name buffer null", __func__); + return -EINVAL; + } + + if ((id < 0) || (id >= RMNET_DATA_MAX_VND) || !rmnet_devices[id]) { + LOGM("%s(): Invalid id [%d]", __func__, id); + return -EINVAL; + } + + p = strlcpy(name, rmnet_devices[id]->name, name_len); + if (p >= name_len) { + LOGM("%s(): Buffer to small to fit device name", __func__); + return -EINVAL; + } + LOGL("%s(): Found mapping [%d]->\"%s\"", __func__, id, name); + + return 0; +} + /** * rmnet_vnd_is_vnd() - Determine if net_device is RmNet owned virtual devices * @dev: Network device to test diff --git a/net/rmnet_data/rmnet_data_vnd.h b/net/rmnet_data/rmnet_data_vnd.h index a916b2534a6d..2e1ff1c5d87b 100644 --- a/net/rmnet_data/rmnet_data_vnd.h +++ b/net/rmnet_data/rmnet_data_vnd.h @@ -23,7 +23,9 @@ int rmnet_vnd_get_flow_mapping(struct net_device *dev, unsigned int map_flow_id, unsigned int *flow_map); struct rmnet_logical_ep_conf_s *rmnet_vnd_get_le_config(struct net_device *dev); -int rmnet_vnd_create_dev(int id, struct net_device **new_device); +int rmnet_vnd_get_name(int id, char *name, int name_len); +int rmnet_vnd_create_dev(int id, struct net_device **new_device, + const char *prefix); int rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev); int rmnet_vnd_tx_fixup(struct sk_buff *skb, struct net_device *dev); int rmnet_vnd_is_vnd(struct net_device *dev);