From acba8da49fd887089b9bc5733ca289eb4f8cc7aa Mon Sep 17 00:00:00 2001 From: Harout Hedeshian Date: Tue, 1 Apr 2014 06:24:25 -0600 Subject: [PATCH] net: rmnet_data: Support for NETLINK getters Added support for RMNET_NETLINK_GET_LOGICAL_EP_CONFIG and RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED in the rmnet_data configuration module. CRs-fixed: 599231 Change-Id: Ib5eeb4a37f80a4df19cb3c1ef02ec477f5445740 Acked-by: David Arinzon Signed-off-by: Harout Hedeshian --- net/rmnet_data/rmnet_data_config.c | 127 ++++++++++++++++++++++++++++- net/rmnet_data/rmnet_data_config.h | 8 ++ net/rmnet_data/rmnet_data_vnd.c | 24 ++++-- 3 files changed, 146 insertions(+), 13 deletions(-) diff --git a/net/rmnet_data/rmnet_data_config.c b/net/rmnet_data/rmnet_data_config.c index 907db1c801b5..c2749185d11d 100644 --- a/net/rmnet_data/rmnet_data_config.c +++ b/net/rmnet_data/rmnet_data_config.c @@ -251,7 +251,7 @@ static void _rmnet_netlink_set_logical_ep_config rmnet_header->local_ep_config.next_dev); - if (dev != 0 && dev2 != 0) + if (dev && dev2) resp_rmnet->return_code = rmnet_set_logical_endpoint_config( dev, @@ -261,9 +261,9 @@ static void _rmnet_netlink_set_logical_ep_config else resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE; - if (dev != 0) + if (dev) dev_put(dev); - if (dev2 != 0) + if (dev2) dev_put(dev2); } @@ -284,7 +284,7 @@ static void _rmnet_netlink_unset_logical_ep_config dev = dev_get_by_name(&init_net, rmnet_header->local_ep_config.dev); - if (dev != 0) { + if (dev) { resp_rmnet->return_code = rmnet_unset_logical_endpoint_config( dev, @@ -295,6 +295,44 @@ static void _rmnet_netlink_unset_logical_ep_config } } +static void _rmnet_netlink_get_logical_ep_config + (struct rmnet_nl_msg_s *rmnet_header, + struct rmnet_nl_msg_s *resp_rmnet) +{ + struct net_device *dev; + _RMNET_NETLINK_NULL_CHECKS(); + + resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE; + if (rmnet_header->local_ep_config.ep_id < -1 + || rmnet_header->local_ep_config.ep_id > 254) { + resp_rmnet->return_code = RMNET_CONFIG_BAD_ARGUMENTS; + return; + } + + dev = dev_get_by_name(&init_net, + rmnet_header->local_ep_config.dev); + + if (dev) + resp_rmnet->return_code = + rmnet_get_logical_endpoint_config( + dev, + rmnet_header->local_ep_config.ep_id, + &resp_rmnet->local_ep_config.operating_mode, + resp_rmnet->local_ep_config.next_dev, + sizeof(resp_rmnet->local_ep_config.next_dev)); + else { + resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE; + return; + } + + if (resp_rmnet->return_code == RMNET_CONFIG_OK) { + /* Begin Data */ + resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNDATA; + resp_rmnet->arg_length = RMNET_NL_MSG_SIZE(local_ep_config); + } + dev_put(dev); +} + static void _rmnet_netlink_associate_network_device (struct rmnet_nl_msg_s *rmnet_header, struct rmnet_nl_msg_s *resp_rmnet) @@ -331,6 +369,26 @@ static void _rmnet_netlink_unassociate_network_device dev_put(dev); } +static void _rmnet_netlink_get_network_device_associated + (struct rmnet_nl_msg_s *rmnet_header, + struct rmnet_nl_msg_s *resp_rmnet) +{ + struct net_device *dev; + + _RMNET_NETLINK_NULL_CHECKS(); + resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE; + + dev = dev_get_by_name(&init_net, rmnet_header->data); + if (!dev) { + resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE; + return; + } + + resp_rmnet->return_code = _rmnet_is_physical_endpoint_associated(dev); + resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNDATA; + dev_put(dev); +} + static void _rmnet_netlink_get_link_egress_data_format (struct rmnet_nl_msg_s *rmnet_header, struct rmnet_nl_msg_s *resp_rmnet) @@ -509,6 +567,11 @@ void rmnet_config_netlink_msg_handler(struct sk_buff *skb) (rmnet_header, resp_rmnet); break; + case RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED: + _rmnet_netlink_get_network_device_associated + (rmnet_header, resp_rmnet); + break; + case RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT: _rmnet_netlink_set_link_egress_data_format (rmnet_header, resp_rmnet); @@ -538,6 +601,10 @@ void rmnet_config_netlink_msg_handler(struct sk_buff *skb) resp_rmnet); break; + case RMNET_NETLINK_GET_LOGICAL_EP_CONFIG: + _rmnet_netlink_get_logical_ep_config(rmnet_header, resp_rmnet); + break; + case RMNET_NETLINK_NEW_VND: resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE; resp_rmnet->return_code = @@ -927,6 +994,58 @@ int rmnet_unset_logical_endpoint_config(struct net_device *dev, return _rmnet_unset_logical_endpoint_config(dev, config_id); } +/** + * rmnet_get_logical_endpoint_config() - Gets logical endpoing configuration + * for a device + * @dev: Device to get endpoint configuration on + * @config_id: logical endpoint id on device + * @rmnet_mode: (I/O) logical endpoint mode + * @egress_dev_name: (I/O) logical endpoint egress device name + * @egress_dev_name_size: The maximal size of the I/O egress_dev_name + * + * Retrieves the logical_endpoint_config structure. + * Network device must already have association with RmNet Data driver + * + * Return: + * - RMNET_CONFIG_OK if successful + * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null + * - RMNET_CONFIG_NO_SUCH_DEVICE device is not associated + * - RMNET_CONFIG_BAD_ARGUMENTS if logical endpoint id is out of range or + * if the provided buffer size for egress dev name is too short + */ +int rmnet_get_logical_endpoint_config(struct net_device *dev, + int config_id, + uint8_t *rmnet_mode, + uint8_t *egress_dev_name, + size_t egress_dev_name_size) +{ + struct rmnet_logical_ep_conf_s *epconfig_l = 0; + size_t strlcpy_res = 0; + + LOGL("(%s, %d);", dev->name, config_id); + + if (!egress_dev_name || !rmnet_mode) + return RMNET_CONFIG_BAD_ARGUMENTS; + if (config_id < RMNET_LOCAL_LOGICAL_ENDPOINT + || config_id >= RMNET_DATA_MAX_LOGICAL_EP) + return RMNET_CONFIG_BAD_ARGUMENTS; + + epconfig_l = _rmnet_get_logical_ep(dev, config_id); + + if (!epconfig_l || !epconfig_l->refcount) + return RMNET_CONFIG_NO_SUCH_DEVICE; + + *rmnet_mode = epconfig_l->rmnet_mode; + + strlcpy_res = strlcpy(egress_dev_name, epconfig_l->egress_dev->name, + egress_dev_name_size); + + if (strlcpy_res >= egress_dev_name_size) + return RMNET_CONFIG_BAD_ARGUMENTS; + + return RMNET_CONFIG_OK; +} + /** * rmnet_create_vnd() - Create virtual network device node * @id: RmNet virtual device node id diff --git a/net/rmnet_data/rmnet_data_config.h b/net/rmnet_data/rmnet_data_config.h index e6b5481bdcb0..777d7308ede9 100644 --- a/net/rmnet_data/rmnet_data_config.h +++ b/net/rmnet_data/rmnet_data_config.h @@ -69,6 +69,14 @@ int _rmnet_unset_logical_endpoint_config(struct net_device *dev, int config_id); int rmnet_unset_logical_endpoint_config(struct net_device *dev, int config_id); +int _rmnet_get_logical_endpoint_config(struct net_device *dev, + int config_id, + struct rmnet_logical_ep_conf_s *epconfig); +int rmnet_get_logical_endpoint_config(struct net_device *dev, + int config_id, + uint8_t *rmnet_mode, + uint8_t *egress_dev_name, + size_t egress_dev_name_size); void rmnet_config_netlink_msg_handler (struct sk_buff *skb); int rmnet_config_notify_cb(struct notifier_block *nb, unsigned long event, void *data); diff --git a/net/rmnet_data/rmnet_data_vnd.c b/net/rmnet_data/rmnet_data_vnd.c index 2c662af13065..338e2ce07fdb 100644 --- a/net/rmnet_data/rmnet_data_vnd.c +++ b/net/rmnet_data/rmnet_data_vnd.c @@ -541,10 +541,10 @@ int rmnet_vnd_init(void) * * 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 + * - RMNET_CONFIG_BAD_ARGUMENTS if id is out of range or prefix is too long + * - RMNET_CONFIG_DEVICE_IN_USE if id already in use + * - RMNET_CONFIG_NOMEM if net_device allocation failed + * - RMNET_CONFIG_UNKNOWN_ERROR if register_netdevice() fails */ int rmnet_vnd_create_dev(int id, struct net_device **new_device, const char *prefix) @@ -553,9 +553,14 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device, char dev_prefix[IFNAMSIZ]; int p, rc = 0; - if (id < 0 || id >= RMNET_DATA_MAX_VND || rmnet_devices[id] != 0) { + if (id < 0 || id > RMNET_DATA_MAX_VND) { *new_device = 0; - return -EINVAL; + return RMNET_CONFIG_BAD_ARGUMENTS; + } + + if (rmnet_devices[id] != 0) { + *new_device = 0; + return RMNET_CONFIG_DEVICE_IN_USE; } if (!prefix) @@ -565,8 +570,8 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device, p = scnprintf(dev_prefix, IFNAMSIZ, "%s%%d", prefix); if (p >= (IFNAMSIZ-1)) { - LOGE("Specified prefix (%d) longer than IFNAMSIZ", p); - return -EINVAL; + LOGE("Specified prefix longer than IFNAMSIZ"); + return RMNET_CONFIG_BAD_ARGUMENTS; } dev = alloc_netdev(sizeof(struct rmnet_vnd_private_s), @@ -575,7 +580,7 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device, if (!dev) { LOGE("Failed to to allocate netdev for id %d", id); *new_device = 0; - return -EINVAL; + return RMNET_CONFIG_NOMEM; } rc = register_netdevice(dev); @@ -583,6 +588,7 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device, LOGE("Failed to to register netdev [%s]", dev->name); free_netdev(dev); *new_device = 0; + return RMNET_CONFIG_UNKNOWN_ERROR; } else { rmnet_devices[id] = dev; *new_device = dev;