blob: 405626d79226812049ef5eed1c095075c9c219e0 [file] [log] [blame]
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -06001/******************************************************************************
2
3 R M N E T C L I . C
4
5Copyright (c) 2013, The Linux Foundation. All rights reserved.
6
7Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are
9met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials provided
15 with the distribution.
16 * Neither the name of The Linux Foundation nor the names of its
17 contributors may be used to endorse or promote products derived
18 from this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32******************************************************************************/
33
34/******************************************************************************
35
36 @file rmnetcli.c
37 @brief command line interface to expose rmnet control API's
38
39 DESCRIPTION
40 File containing implementation of the command line interface to expose the
41 rmnet control configuration .
42
43******************************************************************************/
44
45/*===========================================================================
46 INCLUDE FILES
47===========================================================================*/
48
49#include <sys/socket.h>
50#include <stdint.h>
51#include <linux/netlink.h>
52#include <string.h>
53#include <stdio.h>
54#include <unistd.h>
55#include <stdlib.h>
56#include "rmnetcli.h"
57#include "librmnetctl.h"
58
59#define RMNET_MAX_STR_LEN 16
60
61#define _RMNETCLI_CHECKNULL(X) do { if (!X) { \
62print_rmnet_api_status(RMNETCTL_INVALID_ARG, RMNETCTL_CFG_FAILURE_NO_COMMAND); \
63 rmnetctl_cleanup(handle); \
64 return RMNETCTL_INVALID_ARG; \
65 } } while (0);
66#define _STRTOUI32(X) (uint32_t)strtoul(X, NULL, 0)
67#define _STRTOUI16(X) (uint16_t)strtoul(X, NULL, 0)
68#define _STRTOUI8(X) (uint8_t)strtoul(X, NULL, 0)
69#define _STRTOI32(X) (int32_t)strtol(X, NULL, 0)
70
71#define _5TABS "\n\t\t\t\t\t"
72#define _2TABS "\n\t\t"
73
74/*!
75* @brief Contains a list of error message from CLI
76*/
77char rmnetcfg_error_code_text
78[RMNETCFG_TOTAL_ERR_MSGS][RMNETCTL_ERR_MSG_SIZE] = {
79 "Help option Specified",
80 "ERROR: No\\Invalid command was specified\n",
81 "ERROR: Could not allocate buffer for Egress device\n"
82};
83
84/*!
85* @brief Method to display the syntax for the commands
86* @details Displays the syntax and usage for the commands
87* @param void
88* @return void
89*/
Harout Hedeshian04d69732013-10-02 09:29:11 -060090static void rmnet_api_usage(void)
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -060091{
92 printf("RmNet API Usage:\n\n");
93 printf("rmnetcli help Displays this help\n");
94 printf("\n");
95 printf("rmnetcli assocnetdev <dev_name> Registers the RmNet");
96 printf(_5TABS" data driver on a particular");
97 printf(_5TABS" device.dev_name cannot");
98 printf(_5TABS" be larger than 15");
99 printf(_5TABS" characters. Returns");
100 printf(_5TABS" the status code.\n\n");
101 printf("rmnetcli unassocnetdev <dev_name> Unregisters the");
102 printf(_5TABS" RmNet data driver on a particular");
103 printf(_5TABS" device. dev_name cannot");
104 printf(_5TABS" be larger than 15");
105 printf(_5TABS" characters. Returns");
106 printf(_5TABS" the status code.\n\n");
107 printf("rmnetcli getnetdevassoc <dev_name> Get if the RmNet");
108 printf(_5TABS" data driver is registered on");
109 printf(_5TABS" a particular device.");
110 printf(_5TABS" dev_name cannot be");
111 printf(_5TABS" larger than 15");
112 printf(_5TABS" characters. Returns 1");
113 printf(_5TABS" if is registered and");
114 printf(_5TABS" 0 if it is not");
115 printf(_5TABS" registered\n\n");
116 printf("rmnetcli setledf <egress_flags> Sets the egress data");
117 printf(_2TABS" <agg_size> format for a particular link.");
118 printf(_2TABS" <agg_count> dev_name cannot be larger");
119 printf(_2TABS" <dev_name> than 15 characters.");
120 printf(_5TABS" Returns the status code\n\n");
121 printf("rmnetcli getledf <dev_name> Gets the egress data");
122 printf(_5TABS" format for a particular link.");
123 printf(_5TABS" dev_name cannot be larger");
124 printf(_5TABS" than 15. Returns the 4");
125 printf(_5TABS" byte unsigned integer");
126 printf(_5TABS" egress_flags\n\n");
127 printf("rmnetcli setlidf <ingress_flags> Sets the ingress");
128 printf(_2TABS" <dev_name> data format for a particular");
129 printf(_5TABS" link. egress_flags is 4");
130 printf(_5TABS" byte unsigned integer.");
131 printf(_5TABS" dev_name cannot be");
132 printf(_5TABS" larger than 15.");
133 printf(_5TABS" characters. Returns");
134 printf(_5TABS" the status code\n\n");
135 printf("rmnetcli getlidf <dev_name> Gets the ingress");
136 printf(_5TABS" data format for a particular");
137 printf(_5TABS" link. dev_name cannot be");
138 printf(_5TABS" larger than 15. Returns");
139 printf(_5TABS" the 4 byte unsigned");
140 printf(_5TABS" integer ingress_flags\n\n");
141 printf("rmnetcli setlepc <logical_ep_id> Sets the logical");
142 printf(_2TABS" <rmnet_mode> endpoint configuration for");
143 printf(_2TABS" <dev_name> a particular link.");
144 printf(_2TABS" <egress_dev_name> logical_ep_id are 32bit");
145 printf(_5TABS" integers from -1 to 31.");
146 printf(_5TABS" rmnet_mode is a 1 byte");
147 printf(_5TABS" unsigned integer of");
148 printf(_5TABS" value none, vnd or");
149 printf(_5TABS" bridged. dev_name");
150 printf(_5TABS" and egress_dev_name");
151 printf(_5TABS" cannot be larger");
152 printf(_5TABS" than 15 tcharacters");
153 printf(_5TABS" Returns the status code\n\n");
154 printf("rmnetcli getlepc <logical_ep_id> Sets the logical");
155 printf(_2TABS" <dev_name> enpoint configuration for a");
156 printf(_5TABS" particular link.");
157 printf(_5TABS" logical_ep_id are 32bit");
158 printf(_5TABS" integers from -1 to 31.");
159 printf(_5TABS" Returns the rmnet_mode");
160 printf(_5TABS" and egress_dev_name.");
161 printf(_5TABS" rmnet_mode is a 1");
162 printf(_5TABS" byte unsigned integer");
163 printf(_5TABS" of value none, vnd or");
164 printf(_5TABS" bridged. dev_name and");
165 printf(_5TABS" egress_dev_name cannot be");
166 printf(_5TABS" larger than 15 ");
167 printf(_5TABS" characters. Returns the");
168 printf(_5TABS" status code\n\n");
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600169 printf("rmnetcli newvnd <dev_id> Creates a new");
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600170 printf(_5TABS" virtual network device node.");
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600171 printf(_5TABS" dev_id is an int");
172 printf(_5TABS" less than 32. Returns");
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600173 printf(_5TABS" the status code\n\n");
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600174 printf("rmnetcli newvndprefix <dev_id> <name_prefix> Creates");
175 printf(_5TABS" virtual network device node.");
176 printf(_5TABS" dev_id is an int");
177 printf(_5TABS" less than 32. Prefix");
178 printf(_5TABS" must be less than");
179 printf(_5TABS" 15 chars. Returns");
180 printf(_5TABS" the status code\n\n");
181 printf("rmnetcli getvndname <dev_id> Get name of");
182 printf(_5TABS" network device node from id");
183 printf("rmnetcli freevnd <dev_id> Removes virtual");
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600184 printf(_5TABS" network device node. dev_name");
185 printf(_5TABS" cannot be larger than 15.");
186 printf(_5TABS" Returns the status code\n\n");
187}
188
189static void print_rmnetctl_lib_errors(uint16_t error_number) {
190 if ((error_number > RMNETCTL_API_SUCCESS) &&
191 (error_number < RMNETCTL_API_ERR_ENUM_LENGTH)) {
192 printf("%s", rmnetctl_error_code_text[error_number]);
193 }
194 if ((error_number >= RMNETCFG_ERR_NUM_START) &&
195 (error_number < RMNETCFG_ERR_NUM_START + RMNETCFG_TOTAL_ERR_MSGS)) {
196 printf("%s", rmnetcfg_error_code_text
197 [error_number - RMNETCFG_ERR_NUM_START]);
198 if ((error_number == RMNETCTL_CFG_SUCCESS_HELP_COMMAND) ||
199 (error_number == RMNETCTL_CFG_FAILURE_NO_COMMAND))
200 rmnet_api_usage();
201 }
202}
203
204/*!
205* @brief Method to check the error numbers generated from API calls
206* @details Displays the error messages based on each error code
207* @param error_number Error number returned from the API and the CLI
208* @return void
209*/
210static void print_rmnet_api_status(int return_code, uint16_t error_number)
211{
212 if (return_code == RMNETCTL_SUCCESS)
213 printf("SUCCESS\n");
214 else if (return_code == RMNETCTL_LIB_ERR)
215 printf("LIBRARY ");
216 else if (return_code == RMNETCTL_KERNEL_ERR)
217 printf("KERNEL : Error code %u\n", error_number);
218 else if (return_code == RMNETCTL_INVALID_ARG)
219 printf("INVALID_ARG\n");
220
221 if (return_code == RMNETCTL_LIB_ERR) {
222 print_rmnetctl_lib_errors(error_number);
223 }
224}
225
226/*!
227* @brief Method to make the API calls
228* @details Checks for each type of parameter and calls the appropriate
229* function based on the number of parameters and paramter type
230* @param argc Number of arguments which vary based on the commands
231* @param argv Value of the arguments which vary based on the commands
232* @return RMNETCTL_SUCCESS if successful. Relevant data might be printed
233* based on the message type
234* @return RMNETCTL_LIB_ERR if there was a library error. Error code will be
235* printed
236* @return RMNETCTL_KERNEL_ERR if there was a error in the kernel. Error code will be
237* printed
238* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
239*/
240
241static int rmnet_api_call(int argc, char *argv[])
242{
243 struct rmnetctl_hndl_s *handle = NULL;
244 uint16_t error_number = RMNETCTL_CFG_FAILURE_NO_COMMAND;
245 int return_code = RMNETCTL_LIB_ERR;
246 if ((!argc) || (!*argv)) {
247 print_rmnet_api_status(RMNETCTL_LIB_ERR,
248 RMNETCTL_CFG_FAILURE_NO_COMMAND);
249 return RMNETCTL_LIB_ERR;
250 }
251 if (!strcmp(*argv, "help")) {
252 print_rmnet_api_status(RMNETCTL_LIB_ERR,
253 RMNETCTL_CFG_SUCCESS_HELP_COMMAND);
254 return RMNETCTL_LIB_ERR;
255 }
256 return_code = rmnetctl_init(&handle, &error_number);
257 if (return_code!= RMNETCTL_SUCCESS) {
258 print_rmnet_api_status(return_code, error_number);
259 return RMNETCTL_LIB_ERR;
260 }
261 error_number = RMNETCTL_CFG_FAILURE_NO_COMMAND;
262 return_code = RMNETCTL_LIB_ERR;
263 if (!strcmp(*argv, "assocnetdev")) {
264 return_code = rmnet_associate_network_device(handle,
265 argv[1], &error_number, RMNETCTL_DEVICE_ASSOCIATE);
266 } else if (!strcmp(*argv, "unassocnetdev")) {
267 return_code = rmnet_associate_network_device(handle,
268 argv[1], &error_number, RMNETCTL_DEVICE_UNASSOCIATE);
269 } else if (!strcmp(*argv, "getnetdevassoc")) {
270 int register_status;
271 return_code = rmnet_get_network_device_associated(handle,
272 argv[1], &register_status, &error_number);
273 if (return_code == RMNETCTL_SUCCESS)
274 printf("register_status is %d\n", register_status);
275 } else if (!strcmp(*argv, "getledf")) {
276 uint32_t egress_flags;
277 uint16_t agg_size, agg_count;
278 return_code = rmnet_get_link_egress_data_format(handle,
279 argv[1], &egress_flags, &agg_size, &agg_count, &error_number);
280 if (return_code == RMNETCTL_SUCCESS) {
281 printf("egress_flags is %u\n", egress_flags);
282 printf("agg_size is %u\n", agg_size);
283 printf("agg_count is %u\n", agg_count);
284 }
285 } else if (!strcmp(*argv, "getlidf")) {
286 uint32_t ingress_flags;
287 return_code = rmnet_get_link_ingress_data_format(handle,
288 argv[1], &ingress_flags, &error_number);
289 if (return_code == RMNETCTL_SUCCESS) {
290 printf("ingress_flags is %u\n", ingress_flags);
291 }
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600292 } else if (!strcmp(*argv, "newvndprefix")) {
293 _RMNETCLI_CHECKNULL(argv[1]);
294 _RMNETCLI_CHECKNULL(argv[2]);
295 return_code = rmnet_new_vnd_prefix(handle,
296 _STRTOUI32(argv[1]), &error_number, RMNETCTL_NEW_VND, argv[2]);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600297 } else if (!strcmp(*argv, "newvnd")) {
298 _RMNETCLI_CHECKNULL(argv[1]);
299 return_code = rmnet_new_vnd(handle,
300 _STRTOUI32(argv[1]), &error_number, RMNETCTL_NEW_VND);
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600301 } else if (!strcmp(*argv, "getvndname")) {
302 char buffer[32];
303 memset(buffer, 0, 32);
304 _RMNETCLI_CHECKNULL(argv[1]);
305 return_code = rmnet_get_vnd_name(handle, _STRTOUI32(argv[1]),
306 &error_number, buffer, 32);
307 if (return_code == RMNETCTL_SUCCESS) {
308 printf("VND name: %s\n", buffer);
309 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600310 } else if (!strcmp(*argv, "freevnd")) {
311 _RMNETCLI_CHECKNULL(argv[1]);
312 return_code = rmnet_new_vnd(handle,
313 _STRTOUI32(argv[1]), &error_number, RMNETCTL_FREE_VND);
314 } else if (!strcmp(*argv, "setlidf")) {
315 _RMNETCLI_CHECKNULL(argv[1]);
316 return_code = rmnet_set_link_ingress_data_format(handle,
317 _STRTOUI32(argv[1]), argv[2], &error_number);
318 } else if (!strcmp(*argv, "getlepc")) {
319 _RMNETCLI_CHECKNULL(argv[1]);
320 uint8_t rmnet_mode;
321 char *egress_dev_name;
322 egress_dev_name = NULL;
323 egress_dev_name = (char *)malloc(RMNET_MAX_STR_LEN
324 * sizeof(char));
325 if (!egress_dev_name) {
326 print_rmnet_api_status(RMNETCTL_LIB_ERR,
327 RMNETCTL_CFG_FAILURE_EGRESS_DEV_NAME_NULL);
328 return RMNETCTL_LIB_ERR;
329 }
330 return_code = rmnet_get_logical_ep_config(handle,
331 _STRTOI32(argv[1]), argv[2], &rmnet_mode,
332 &egress_dev_name, &error_number);
333 if (return_code == RMNETCTL_SUCCESS) {
334 printf("rmnet_mode is %u\n", rmnet_mode);
335 printf("egress_dev_name is %s\n", egress_dev_name);
336 }
337 } else if (!strcmp(*argv, "setledf")) {
338 _RMNETCLI_CHECKNULL(argv[1]);
339 _RMNETCLI_CHECKNULL(argv[2]);
340 _RMNETCLI_CHECKNULL(argv[3]);
341 return_code = rmnet_set_link_egress_data_format(handle,
342 _STRTOUI32(argv[1]), _STRTOUI16(argv[2]), _STRTOUI16(argv[3]),
343 argv[4], &error_number);
344 } else if (!strcmp(*argv, "setlepc")) {
345 _RMNETCLI_CHECKNULL(argv[1]);
346 _RMNETCLI_CHECKNULL(argv[2]);
347 return_code = rmnet_set_logical_ep_config(handle,
348 _STRTOI32(argv[1]), _STRTOUI8(argv[2]), argv[3], argv[4],
349 &error_number);
350 }
351 print_rmnet_api_status(return_code, error_number);
352 rmnetctl_cleanup(handle);
353 return return_code;
354}
355
356/*!
357* @brief Method which serves as en entry point to the rmnetcli function
358* @details Entry point for the RmNet Netlink API. This is the command line
359* interface for the RmNet API
360* @param argc Number of arguments which vary based on the commands
361* @param argv Value of the arguments which vary based on the commands
362* @return RMNETCTL_SUCCESS if successful. Relevant data might be printed
363* based on the message type
364* @return RMNETCTL_LIB_ERR if there was a library error. Error code will be
365* printed
366* @return RMNETCTL_KERNEL_ERR if there was a error in the kernel. Error code will be
367* printed
368* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
369*/
370int main(int argc, char *argv[])
371{
372 argc--;
373 argv++;
374 return rmnet_api_call(argc, argv);
375}