blob: 8f4d582546c465a76a9a221a370facc28b9dc6b4 [file] [log] [blame]
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -06001/******************************************************************************
2
3 R M N E T C L I . C
4
Harout Hedeshiana9731652014-01-06 18:00:23 +02005Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -06006
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");
Harout Hedeshiana9731652014-01-06 18:00:23 +0200154 printf("rmnetcli unsetlepc <logical_ep_id> Un-sets the logical");
155 printf(_2TABS" <dev_name> endpoint configuration for");
156 printf(_5TABS" a particular link.");
157 printf(_5TABS" integers from -1 to 31.");
158 printf(_5TABS" dev_name cannot be larger");
159 printf(_5TABS" than 15 tcharacters");
160 printf(_5TABS" Returns the status code\n\n");
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600161 printf("rmnetcli getlepc <logical_ep_id> Sets the logical");
162 printf(_2TABS" <dev_name> enpoint configuration for a");
163 printf(_5TABS" particular link.");
164 printf(_5TABS" logical_ep_id are 32bit");
165 printf(_5TABS" integers from -1 to 31.");
166 printf(_5TABS" Returns the rmnet_mode");
167 printf(_5TABS" and egress_dev_name.");
168 printf(_5TABS" rmnet_mode is a 1");
169 printf(_5TABS" byte unsigned integer");
170 printf(_5TABS" of value none, vnd or");
171 printf(_5TABS" bridged. dev_name and");
172 printf(_5TABS" egress_dev_name cannot be");
173 printf(_5TABS" larger than 15 ");
174 printf(_5TABS" characters. Returns the");
175 printf(_5TABS" status code\n\n");
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600176 printf("rmnetcli newvnd <dev_id> Creates a new");
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600177 printf(_5TABS" virtual network device node.");
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600178 printf(_5TABS" dev_id is an int");
179 printf(_5TABS" less than 32. Returns");
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600180 printf(_5TABS" the status code\n\n");
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600181 printf("rmnetcli newvndprefix <dev_id> <name_prefix> Creates");
182 printf(_5TABS" virtual network device node.");
183 printf(_5TABS" dev_id is an int");
184 printf(_5TABS" less than 32. Prefix");
185 printf(_5TABS" must be less than");
186 printf(_5TABS" 15 chars. Returns");
187 printf(_5TABS" the status code\n\n");
188 printf("rmnetcli getvndname <dev_id> Get name of");
Harout Hedeshiana9731652014-01-06 18:00:23 +0200189 printf(_5TABS" network device node from id\n\n");
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600190 printf("rmnetcli freevnd <dev_id> Removes virtual");
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600191 printf(_5TABS" network device node. dev_name");
192 printf(_5TABS" cannot be larger than 15.");
193 printf(_5TABS" Returns the status code\n\n");
Harout Hedeshian97a1e982013-11-08 09:28:53 -0700194 printf("rmnetcli addvnctcflow <dev_id> Add a modem flow");
195 printf(_2TABS" <mdm_flow_hndl> handle - tc flow handle");
196 printf(_2TABS" <tc_flow_hndl> mapping for a virtual network");
197 printf(_2TABS" device node\n\n");
198 printf("rmnetcli delvnctcflow <dev_id> Delete a modem flow");
199 printf(_2TABS" <mdm_flow_hndl> handle - tc flow handle");
200 printf(_2TABS" <tc_flow_hndl> mapping for a virtual network");
201 printf(_2TABS" device node\n\n");
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600202}
203
204static void print_rmnetctl_lib_errors(uint16_t error_number) {
205 if ((error_number > RMNETCTL_API_SUCCESS) &&
206 (error_number < RMNETCTL_API_ERR_ENUM_LENGTH)) {
207 printf("%s", rmnetctl_error_code_text[error_number]);
208 }
209 if ((error_number >= RMNETCFG_ERR_NUM_START) &&
210 (error_number < RMNETCFG_ERR_NUM_START + RMNETCFG_TOTAL_ERR_MSGS)) {
211 printf("%s", rmnetcfg_error_code_text
212 [error_number - RMNETCFG_ERR_NUM_START]);
213 if ((error_number == RMNETCTL_CFG_SUCCESS_HELP_COMMAND) ||
214 (error_number == RMNETCTL_CFG_FAILURE_NO_COMMAND))
215 rmnet_api_usage();
216 }
217}
218
219/*!
220* @brief Method to check the error numbers generated from API calls
221* @details Displays the error messages based on each error code
222* @param error_number Error number returned from the API and the CLI
223* @return void
224*/
225static void print_rmnet_api_status(int return_code, uint16_t error_number)
226{
227 if (return_code == RMNETCTL_SUCCESS)
228 printf("SUCCESS\n");
229 else if (return_code == RMNETCTL_LIB_ERR)
230 printf("LIBRARY ");
231 else if (return_code == RMNETCTL_KERNEL_ERR)
232 printf("KERNEL : Error code %u\n", error_number);
233 else if (return_code == RMNETCTL_INVALID_ARG)
234 printf("INVALID_ARG\n");
235
236 if (return_code == RMNETCTL_LIB_ERR) {
237 print_rmnetctl_lib_errors(error_number);
238 }
239}
240
241/*!
242* @brief Method to make the API calls
243* @details Checks for each type of parameter and calls the appropriate
244* function based on the number of parameters and paramter type
245* @param argc Number of arguments which vary based on the commands
246* @param argv Value of the arguments which vary based on the commands
247* @return RMNETCTL_SUCCESS if successful. Relevant data might be printed
248* based on the message type
249* @return RMNETCTL_LIB_ERR if there was a library error. Error code will be
250* printed
251* @return RMNETCTL_KERNEL_ERR if there was a error in the kernel. Error code will be
252* printed
253* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
254*/
255
256static int rmnet_api_call(int argc, char *argv[])
257{
258 struct rmnetctl_hndl_s *handle = NULL;
259 uint16_t error_number = RMNETCTL_CFG_FAILURE_NO_COMMAND;
260 int return_code = RMNETCTL_LIB_ERR;
261 if ((!argc) || (!*argv)) {
262 print_rmnet_api_status(RMNETCTL_LIB_ERR,
263 RMNETCTL_CFG_FAILURE_NO_COMMAND);
264 return RMNETCTL_LIB_ERR;
265 }
266 if (!strcmp(*argv, "help")) {
267 print_rmnet_api_status(RMNETCTL_LIB_ERR,
268 RMNETCTL_CFG_SUCCESS_HELP_COMMAND);
269 return RMNETCTL_LIB_ERR;
270 }
271 return_code = rmnetctl_init(&handle, &error_number);
272 if (return_code!= RMNETCTL_SUCCESS) {
273 print_rmnet_api_status(return_code, error_number);
274 return RMNETCTL_LIB_ERR;
275 }
276 error_number = RMNETCTL_CFG_FAILURE_NO_COMMAND;
277 return_code = RMNETCTL_LIB_ERR;
278 if (!strcmp(*argv, "assocnetdev")) {
279 return_code = rmnet_associate_network_device(handle,
280 argv[1], &error_number, RMNETCTL_DEVICE_ASSOCIATE);
281 } else if (!strcmp(*argv, "unassocnetdev")) {
282 return_code = rmnet_associate_network_device(handle,
283 argv[1], &error_number, RMNETCTL_DEVICE_UNASSOCIATE);
284 } else if (!strcmp(*argv, "getnetdevassoc")) {
285 int register_status;
286 return_code = rmnet_get_network_device_associated(handle,
287 argv[1], &register_status, &error_number);
288 if (return_code == RMNETCTL_SUCCESS)
289 printf("register_status is %d\n", register_status);
290 } else if (!strcmp(*argv, "getledf")) {
291 uint32_t egress_flags;
292 uint16_t agg_size, agg_count;
293 return_code = rmnet_get_link_egress_data_format(handle,
294 argv[1], &egress_flags, &agg_size, &agg_count, &error_number);
295 if (return_code == RMNETCTL_SUCCESS) {
296 printf("egress_flags is %u\n", egress_flags);
297 printf("agg_size is %u\n", agg_size);
298 printf("agg_count is %u\n", agg_count);
299 }
300 } else if (!strcmp(*argv, "getlidf")) {
301 uint32_t ingress_flags;
302 return_code = rmnet_get_link_ingress_data_format(handle,
303 argv[1], &ingress_flags, &error_number);
304 if (return_code == RMNETCTL_SUCCESS) {
305 printf("ingress_flags is %u\n", ingress_flags);
306 }
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600307 } else if (!strcmp(*argv, "newvndprefix")) {
308 _RMNETCLI_CHECKNULL(argv[1]);
309 _RMNETCLI_CHECKNULL(argv[2]);
310 return_code = rmnet_new_vnd_prefix(handle,
311 _STRTOUI32(argv[1]), &error_number, RMNETCTL_NEW_VND, argv[2]);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600312 } else if (!strcmp(*argv, "newvnd")) {
313 _RMNETCLI_CHECKNULL(argv[1]);
314 return_code = rmnet_new_vnd(handle,
315 _STRTOUI32(argv[1]), &error_number, RMNETCTL_NEW_VND);
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600316 } else if (!strcmp(*argv, "getvndname")) {
317 char buffer[32];
318 memset(buffer, 0, 32);
319 _RMNETCLI_CHECKNULL(argv[1]);
320 return_code = rmnet_get_vnd_name(handle, _STRTOUI32(argv[1]),
321 &error_number, buffer, 32);
322 if (return_code == RMNETCTL_SUCCESS) {
323 printf("VND name: %s\n", buffer);
324 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600325 } else if (!strcmp(*argv, "freevnd")) {
326 _RMNETCLI_CHECKNULL(argv[1]);
327 return_code = rmnet_new_vnd(handle,
328 _STRTOUI32(argv[1]), &error_number, RMNETCTL_FREE_VND);
329 } else if (!strcmp(*argv, "setlidf")) {
330 _RMNETCLI_CHECKNULL(argv[1]);
331 return_code = rmnet_set_link_ingress_data_format(handle,
332 _STRTOUI32(argv[1]), argv[2], &error_number);
Harout Hedeshian97a1e982013-11-08 09:28:53 -0700333 } else if (!strcmp(*argv, "delvnctcflow")) {
334 _RMNETCLI_CHECKNULL(argv[1]);
335 _RMNETCLI_CHECKNULL(argv[2]);
336 _RMNETCLI_CHECKNULL(argv[3]);
337 return_code = rmnet_add_del_vnd_tc_flow(handle,
338 _STRTOUI32(argv[1]), _STRTOUI32(argv[2]), _STRTOUI32(argv[3]),
339 RMNETCTL_DEL_FLOW, &error_number);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600340 } else if (!strcmp(*argv, "getlepc")) {
341 _RMNETCLI_CHECKNULL(argv[1]);
342 uint8_t rmnet_mode;
343 char *egress_dev_name;
344 egress_dev_name = NULL;
345 egress_dev_name = (char *)malloc(RMNET_MAX_STR_LEN
346 * sizeof(char));
347 if (!egress_dev_name) {
348 print_rmnet_api_status(RMNETCTL_LIB_ERR,
349 RMNETCTL_CFG_FAILURE_EGRESS_DEV_NAME_NULL);
350 return RMNETCTL_LIB_ERR;
351 }
352 return_code = rmnet_get_logical_ep_config(handle,
353 _STRTOI32(argv[1]), argv[2], &rmnet_mode,
354 &egress_dev_name, &error_number);
355 if (return_code == RMNETCTL_SUCCESS) {
356 printf("rmnet_mode is %u\n", rmnet_mode);
357 printf("egress_dev_name is %s\n", egress_dev_name);
358 }
Harout Hedeshian97a1e982013-11-08 09:28:53 -0700359 } else if (!strcmp(*argv, "addvnctcflow")) {
360 _RMNETCLI_CHECKNULL(argv[1]);
361 _RMNETCLI_CHECKNULL(argv[2]);
362 _RMNETCLI_CHECKNULL(argv[3]);
363 return_code = rmnet_add_del_vnd_tc_flow(handle,
364 _STRTOUI32(argv[1]), _STRTOUI32(argv[2]), _STRTOUI32(argv[3]),
365 RMNETCTL_ADD_FLOW, &error_number);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600366 } else if (!strcmp(*argv, "setledf")) {
367 _RMNETCLI_CHECKNULL(argv[1]);
368 _RMNETCLI_CHECKNULL(argv[2]);
369 _RMNETCLI_CHECKNULL(argv[3]);
370 return_code = rmnet_set_link_egress_data_format(handle,
371 _STRTOUI32(argv[1]), _STRTOUI16(argv[2]), _STRTOUI16(argv[3]),
372 argv[4], &error_number);
373 } else if (!strcmp(*argv, "setlepc")) {
374 _RMNETCLI_CHECKNULL(argv[1]);
375 _RMNETCLI_CHECKNULL(argv[2]);
376 return_code = rmnet_set_logical_ep_config(handle,
377 _STRTOI32(argv[1]), _STRTOUI8(argv[2]), argv[3], argv[4],
378 &error_number);
Harout Hedeshiana9731652014-01-06 18:00:23 +0200379 } else if (!strcmp(*argv, "unsetlepc")) {
380 _RMNETCLI_CHECKNULL(argv[1]);
381 return_code = rmnet_unset_logical_ep_config(handle,
382 _STRTOI32(argv[1]), argv[2], &error_number);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600383 }
384 print_rmnet_api_status(return_code, error_number);
385 rmnetctl_cleanup(handle);
386 return return_code;
387}
388
389/*!
390* @brief Method which serves as en entry point to the rmnetcli function
391* @details Entry point for the RmNet Netlink API. This is the command line
392* interface for the RmNet API
393* @param argc Number of arguments which vary based on the commands
394* @param argv Value of the arguments which vary based on the commands
395* @return RMNETCTL_SUCCESS if successful. Relevant data might be printed
396* based on the message type
397* @return RMNETCTL_LIB_ERR if there was a library error. Error code will be
398* printed
399* @return RMNETCTL_KERNEL_ERR if there was a error in the kernel. Error code will be
400* printed
401* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
402*/
403int main(int argc, char *argv[])
404{
405 argc--;
406 argv++;
407 return rmnet_api_call(argc, argv);
408}