rmnetcfg: Initial commit
RmNet configuration library and command line utility for configuring
the RmNet Data kernel module.
CRs-Fixed: 525675
Acked-by: Subash Abhinov Kasiviswanathan <subashab@qti.qualcomm.com>
Change-Id: I4c15e2f0e32082077c189cf316f845699aef5f13
diff --git a/rmnetctl/cli/Android.mk b/rmnetctl/cli/Android.mk
new file mode 100644
index 0000000..27281ff
--- /dev/null
+++ b/rmnetctl/cli/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := rmnetcli.c
+LOCAL_CFLAGS := -Wall -Werror
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/../inc
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../src
+LOCAL_C_INCLUDES += $(LOCAL_PATH)
+
+LOCAL_MODULE := rmnetcli
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := librmnetctl
+include $(BUILD_EXECUTABLE)
diff --git a/rmnetctl/cli/rmnetcli.c b/rmnetctl/cli/rmnetcli.c
new file mode 100644
index 0000000..2c4d099
--- /dev/null
+++ b/rmnetctl/cli/rmnetcli.c
@@ -0,0 +1,352 @@
+/******************************************************************************
+
+ R M N E T C L I . C
+
+Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+
+ @file rmnetcli.c
+ @brief command line interface to expose rmnet control API's
+
+ DESCRIPTION
+ File containing implementation of the command line interface to expose the
+ rmnet control configuration .
+
+******************************************************************************/
+
+/*===========================================================================
+ INCLUDE FILES
+===========================================================================*/
+
+#include <sys/socket.h>
+#include <stdint.h>
+#include <linux/netlink.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "rmnetcli.h"
+#include "librmnetctl.h"
+
+#define RMNET_MAX_STR_LEN 16
+
+#define _RMNETCLI_CHECKNULL(X) do { if (!X) { \
+print_rmnet_api_status(RMNETCTL_INVALID_ARG, RMNETCTL_CFG_FAILURE_NO_COMMAND); \
+ rmnetctl_cleanup(handle); \
+ return RMNETCTL_INVALID_ARG; \
+ } } while (0);
+#define _STRTOUI32(X) (uint32_t)strtoul(X, NULL, 0)
+#define _STRTOUI16(X) (uint16_t)strtoul(X, NULL, 0)
+#define _STRTOUI8(X) (uint8_t)strtoul(X, NULL, 0)
+#define _STRTOI32(X) (int32_t)strtol(X, NULL, 0)
+
+#define _5TABS "\n\t\t\t\t\t"
+#define _2TABS "\n\t\t"
+
+/*!
+* @brief Contains a list of error message from CLI
+*/
+char rmnetcfg_error_code_text
+[RMNETCFG_TOTAL_ERR_MSGS][RMNETCTL_ERR_MSG_SIZE] = {
+ "Help option Specified",
+ "ERROR: No\\Invalid command was specified\n",
+ "ERROR: Could not allocate buffer for Egress device\n"
+};
+
+/*!
+* @brief Method to display the syntax for the commands
+* @details Displays the syntax and usage for the commands
+* @param void
+* @return void
+*/
+static void rmnet_api_usage()
+{
+ printf("RmNet API Usage:\n\n");
+ printf("rmnetcli help Displays this help\n");
+ printf("\n");
+ printf("rmnetcli assocnetdev <dev_name> Registers the RmNet");
+ printf(_5TABS" data driver on a particular");
+ printf(_5TABS" device.dev_name cannot");
+ printf(_5TABS" be larger than 15");
+ printf(_5TABS" characters. Returns");
+ printf(_5TABS" the status code.\n\n");
+ printf("rmnetcli unassocnetdev <dev_name> Unregisters the");
+ printf(_5TABS" RmNet data driver on a particular");
+ printf(_5TABS" device. dev_name cannot");
+ printf(_5TABS" be larger than 15");
+ printf(_5TABS" characters. Returns");
+ printf(_5TABS" the status code.\n\n");
+ printf("rmnetcli getnetdevassoc <dev_name> Get if the RmNet");
+ printf(_5TABS" data driver is registered on");
+ printf(_5TABS" a particular device.");
+ printf(_5TABS" dev_name cannot be");
+ printf(_5TABS" larger than 15");
+ printf(_5TABS" characters. Returns 1");
+ printf(_5TABS" if is registered and");
+ printf(_5TABS" 0 if it is not");
+ printf(_5TABS" registered\n\n");
+ printf("rmnetcli setledf <egress_flags> Sets the egress data");
+ printf(_2TABS" <agg_size> format for a particular link.");
+ printf(_2TABS" <agg_count> dev_name cannot be larger");
+ printf(_2TABS" <dev_name> than 15 characters.");
+ printf(_5TABS" Returns the status code\n\n");
+ printf("rmnetcli getledf <dev_name> Gets the egress data");
+ printf(_5TABS" format for a particular link.");
+ printf(_5TABS" dev_name cannot be larger");
+ printf(_5TABS" than 15. Returns the 4");
+ printf(_5TABS" byte unsigned integer");
+ printf(_5TABS" egress_flags\n\n");
+ printf("rmnetcli setlidf <ingress_flags> Sets the ingress");
+ printf(_2TABS" <dev_name> data format for a particular");
+ printf(_5TABS" link. egress_flags is 4");
+ printf(_5TABS" byte unsigned integer.");
+ printf(_5TABS" dev_name cannot be");
+ printf(_5TABS" larger than 15.");
+ printf(_5TABS" characters. Returns");
+ printf(_5TABS" the status code\n\n");
+ printf("rmnetcli getlidf <dev_name> Gets the ingress");
+ printf(_5TABS" data format for a particular");
+ printf(_5TABS" link. dev_name cannot be");
+ printf(_5TABS" larger than 15. Returns");
+ printf(_5TABS" the 4 byte unsigned");
+ printf(_5TABS" integer ingress_flags\n\n");
+ printf("rmnetcli setlepc <logical_ep_id> Sets the logical");
+ printf(_2TABS" <rmnet_mode> endpoint configuration for");
+ printf(_2TABS" <dev_name> a particular link.");
+ printf(_2TABS" <egress_dev_name> logical_ep_id are 32bit");
+ printf(_5TABS" integers from -1 to 31.");
+ printf(_5TABS" rmnet_mode is a 1 byte");
+ printf(_5TABS" unsigned integer of");
+ printf(_5TABS" value none, vnd or");
+ printf(_5TABS" bridged. dev_name");
+ printf(_5TABS" and egress_dev_name");
+ printf(_5TABS" cannot be larger");
+ printf(_5TABS" than 15 tcharacters");
+ printf(_5TABS" Returns the status code\n\n");
+ printf("rmnetcli getlepc <logical_ep_id> Sets the logical");
+ printf(_2TABS" <dev_name> enpoint configuration for a");
+ printf(_5TABS" particular link.");
+ printf(_5TABS" logical_ep_id are 32bit");
+ printf(_5TABS" integers from -1 to 31.");
+ printf(_5TABS" Returns the rmnet_mode");
+ printf(_5TABS" and egress_dev_name.");
+ printf(_5TABS" rmnet_mode is a 1");
+ printf(_5TABS" byte unsigned integer");
+ printf(_5TABS" of value none, vnd or");
+ printf(_5TABS" bridged. dev_name and");
+ printf(_5TABS" egress_dev_name cannot be");
+ printf(_5TABS" larger than 15 ");
+ printf(_5TABS" characters. Returns the");
+ printf(_5TABS" status code\n\n");
+ printf("rmnetcli newvnd <dev_name> Creates a new");
+ printf(_5TABS" virtual network device node.");
+ printf(_5TABS" dev_name cannot be");
+ printf(_5TABS" larger than 15. Returns");
+ printf(_5TABS" the status code\n\n");
+ printf("rmnetcli freevnd <dev_name> Removes virtual");
+ printf(_5TABS" network device node. dev_name");
+ printf(_5TABS" cannot be larger than 15.");
+ printf(_5TABS" Returns the status code\n\n");
+}
+
+static void print_rmnetctl_lib_errors(uint16_t error_number) {
+ if ((error_number > RMNETCTL_API_SUCCESS) &&
+ (error_number < RMNETCTL_API_ERR_ENUM_LENGTH)) {
+ printf("%s", rmnetctl_error_code_text[error_number]);
+ }
+ if ((error_number >= RMNETCFG_ERR_NUM_START) &&
+ (error_number < RMNETCFG_ERR_NUM_START + RMNETCFG_TOTAL_ERR_MSGS)) {
+ printf("%s", rmnetcfg_error_code_text
+ [error_number - RMNETCFG_ERR_NUM_START]);
+ if ((error_number == RMNETCTL_CFG_SUCCESS_HELP_COMMAND) ||
+ (error_number == RMNETCTL_CFG_FAILURE_NO_COMMAND))
+ rmnet_api_usage();
+ }
+}
+
+/*!
+* @brief Method to check the error numbers generated from API calls
+* @details Displays the error messages based on each error code
+* @param error_number Error number returned from the API and the CLI
+* @return void
+*/
+static void print_rmnet_api_status(int return_code, uint16_t error_number)
+{
+ if (return_code == RMNETCTL_SUCCESS)
+ printf("SUCCESS\n");
+ else if (return_code == RMNETCTL_LIB_ERR)
+ printf("LIBRARY ");
+ else if (return_code == RMNETCTL_KERNEL_ERR)
+ printf("KERNEL : Error code %u\n", error_number);
+ else if (return_code == RMNETCTL_INVALID_ARG)
+ printf("INVALID_ARG\n");
+
+ if (return_code == RMNETCTL_LIB_ERR) {
+ print_rmnetctl_lib_errors(error_number);
+ }
+}
+
+/*!
+* @brief Method to make the API calls
+* @details Checks for each type of parameter and calls the appropriate
+* function based on the number of parameters and paramter type
+* @param argc Number of arguments which vary based on the commands
+* @param argv Value of the arguments which vary based on the commands
+* @return RMNETCTL_SUCCESS if successful. Relevant data might be printed
+* based on the message type
+* @return RMNETCTL_LIB_ERR if there was a library error. Error code will be
+* printed
+* @return RMNETCTL_KERNEL_ERR if there was a error in the kernel. Error code will be
+* printed
+* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
+*/
+
+static int rmnet_api_call(int argc, char *argv[])
+{
+ struct rmnetctl_hndl_s *handle = NULL;
+ uint16_t error_number = RMNETCTL_CFG_FAILURE_NO_COMMAND;
+ int return_code = RMNETCTL_LIB_ERR;
+ if ((!argc) || (!*argv)) {
+ print_rmnet_api_status(RMNETCTL_LIB_ERR,
+ RMNETCTL_CFG_FAILURE_NO_COMMAND);
+ return RMNETCTL_LIB_ERR;
+ }
+ if (!strcmp(*argv, "help")) {
+ print_rmnet_api_status(RMNETCTL_LIB_ERR,
+ RMNETCTL_CFG_SUCCESS_HELP_COMMAND);
+ return RMNETCTL_LIB_ERR;
+ }
+ return_code = rmnetctl_init(&handle, &error_number);
+ if (return_code!= RMNETCTL_SUCCESS) {
+ print_rmnet_api_status(return_code, error_number);
+ return RMNETCTL_LIB_ERR;
+ }
+ error_number = RMNETCTL_CFG_FAILURE_NO_COMMAND;
+ return_code = RMNETCTL_LIB_ERR;
+ if (!strcmp(*argv, "assocnetdev")) {
+ return_code = rmnet_associate_network_device(handle,
+ argv[1], &error_number, RMNETCTL_DEVICE_ASSOCIATE);
+ } else if (!strcmp(*argv, "unassocnetdev")) {
+ return_code = rmnet_associate_network_device(handle,
+ argv[1], &error_number, RMNETCTL_DEVICE_UNASSOCIATE);
+ } else if (!strcmp(*argv, "getnetdevassoc")) {
+ int register_status;
+ return_code = rmnet_get_network_device_associated(handle,
+ argv[1], ®ister_status, &error_number);
+ if (return_code == RMNETCTL_SUCCESS)
+ printf("register_status is %d\n", register_status);
+ } else if (!strcmp(*argv, "getledf")) {
+ uint32_t egress_flags;
+ uint16_t agg_size, agg_count;
+ return_code = rmnet_get_link_egress_data_format(handle,
+ argv[1], &egress_flags, &agg_size, &agg_count, &error_number);
+ if (return_code == RMNETCTL_SUCCESS) {
+ printf("egress_flags is %u\n", egress_flags);
+ printf("agg_size is %u\n", agg_size);
+ printf("agg_count is %u\n", agg_count);
+ }
+ } else if (!strcmp(*argv, "getlidf")) {
+ uint32_t ingress_flags;
+ return_code = rmnet_get_link_ingress_data_format(handle,
+ argv[1], &ingress_flags, &error_number);
+ if (return_code == RMNETCTL_SUCCESS) {
+ printf("ingress_flags is %u\n", ingress_flags);
+ }
+ } else if (!strcmp(*argv, "newvnd")) {
+ _RMNETCLI_CHECKNULL(argv[1]);
+ return_code = rmnet_new_vnd(handle,
+ _STRTOUI32(argv[1]), &error_number, RMNETCTL_NEW_VND);
+ } else if (!strcmp(*argv, "freevnd")) {
+ _RMNETCLI_CHECKNULL(argv[1]);
+ return_code = rmnet_new_vnd(handle,
+ _STRTOUI32(argv[1]), &error_number, RMNETCTL_FREE_VND);
+ } else if (!strcmp(*argv, "setlidf")) {
+ _RMNETCLI_CHECKNULL(argv[1]);
+ return_code = rmnet_set_link_ingress_data_format(handle,
+ _STRTOUI32(argv[1]), argv[2], &error_number);
+ } else if (!strcmp(*argv, "getlepc")) {
+ _RMNETCLI_CHECKNULL(argv[1]);
+ uint8_t rmnet_mode;
+ char *egress_dev_name;
+ egress_dev_name = NULL;
+ egress_dev_name = (char *)malloc(RMNET_MAX_STR_LEN
+ * sizeof(char));
+ if (!egress_dev_name) {
+ print_rmnet_api_status(RMNETCTL_LIB_ERR,
+ RMNETCTL_CFG_FAILURE_EGRESS_DEV_NAME_NULL);
+ return RMNETCTL_LIB_ERR;
+ }
+ return_code = rmnet_get_logical_ep_config(handle,
+ _STRTOI32(argv[1]), argv[2], &rmnet_mode,
+ &egress_dev_name, &error_number);
+ if (return_code == RMNETCTL_SUCCESS) {
+ printf("rmnet_mode is %u\n", rmnet_mode);
+ printf("egress_dev_name is %s\n", egress_dev_name);
+ }
+ } else if (!strcmp(*argv, "setledf")) {
+ _RMNETCLI_CHECKNULL(argv[1]);
+ _RMNETCLI_CHECKNULL(argv[2]);
+ _RMNETCLI_CHECKNULL(argv[3]);
+ return_code = rmnet_set_link_egress_data_format(handle,
+ _STRTOUI32(argv[1]), _STRTOUI16(argv[2]), _STRTOUI16(argv[3]),
+ argv[4], &error_number);
+ } else if (!strcmp(*argv, "setlepc")) {
+ _RMNETCLI_CHECKNULL(argv[1]);
+ _RMNETCLI_CHECKNULL(argv[2]);
+ return_code = rmnet_set_logical_ep_config(handle,
+ _STRTOI32(argv[1]), _STRTOUI8(argv[2]), argv[3], argv[4],
+ &error_number);
+ }
+ print_rmnet_api_status(return_code, error_number);
+ rmnetctl_cleanup(handle);
+ return return_code;
+}
+
+/*!
+* @brief Method which serves as en entry point to the rmnetcli function
+* @details Entry point for the RmNet Netlink API. This is the command line
+* interface for the RmNet API
+* @param argc Number of arguments which vary based on the commands
+* @param argv Value of the arguments which vary based on the commands
+* @return RMNETCTL_SUCCESS if successful. Relevant data might be printed
+* based on the message type
+* @return RMNETCTL_LIB_ERR if there was a library error. Error code will be
+* printed
+* @return RMNETCTL_KERNEL_ERR if there was a error in the kernel. Error code will be
+* printed
+* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
+*/
+int main(int argc, char *argv[])
+{
+ argc--;
+ argv++;
+ return rmnet_api_call(argc, argv);
+}
diff --git a/rmnetctl/cli/rmnetcli.h b/rmnetctl/cli/rmnetcli.h
new file mode 100644
index 0000000..503a86e
--- /dev/null
+++ b/rmnetctl/cli/rmnetcli.h
@@ -0,0 +1,61 @@
+/******************************************************************************
+
+ R M N E T C L I . H
+
+Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+
+ @file rmnetcli.h
+ @brief headers for the command line interface to expose rmnet control API's
+
+ DESCRIPTION
+ Header file containing definition for the command line interface to expose
+ rmnet control API's
+
+******************************************************************************/
+
+#ifndef RMNETCLI_H
+#define RMNETCLI_H
+
+/* Print the help for the commands since the help flag was used. */
+#define RMNETCTL_CFG_SUCCESS_HELP_COMMAND 100
+/* No/invalid API call was specified. So return an error. */
+#define RMNETCTL_CFG_FAILURE_NO_COMMAND 101
+/* The buffer for egress device name was NULL */
+#define RMNETCTL_CFG_FAILURE_EGRESS_DEV_NAME_NULL 102
+
+/* This should always be the value of the starting element */
+#define RMNETCFG_ERR_NUM_START 100
+
+/* This should always be the total number of error message from CLI */
+#define RMNETCFG_TOTAL_ERR_MSGS 3
+
+#endif /* not defined RMNETCLI_H */