source: mainline/uspace/app/nic/nic.c@ 184b600

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 184b600 was f9b2cb4c, checked in by Martin Decky <martin@…>, 10 years ago

unify interface API

  • introduce new interfaces
  • unify location service clients to always expect service ID as the second argument
  • remove obsolete methods that take explicit exchange management arguments (first phase)
  • use interfaces in device drivers, devman, location service, logger, inet
  • Property mode set to 100644
File size: 13.3 KB
Line 
1/*
2 * Copyright (c) 2014 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup nic
30 * @{
31 */
32/** @file NIC configuration utility.
33 *
34 */
35
36#include <errno.h>
37#include <loc.h>
38#include <nic_iface.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <str_error.h>
42#include <sys/types.h>
43
44#define NAME "nic"
45
46typedef struct {
47 nic_device_info_t device_info;
48 nic_address_t address;
49 nic_cable_state_t link_state;
50 nic_channel_mode_t duplex;
51 nic_unicast_mode_t unicast_mode;
52 nic_multicast_mode_t multicast_mode;
53 nic_broadcast_mode_t broadcast_mode;
54 int speed;
55} nic_info_t;
56
57static void print_syntax(void)
58{
59 printf("syntax:\n");
60 printf("\t" NAME " [<index> <cmd> [<args...>]]\n");
61 printf("\t<index> is NIC index number reported by the tool\n");
62 printf("\t<cmd> is:\n");
63 printf("\taddr <mac_address> - set MAC address\n");
64 printf("\tspeed <10|100|1000> - set NIC speed\n");
65 printf("\tduplex <half|full|simplex> - set duplex mode\n");
66 printf("\tauto - enable autonegotiation\n");
67 printf("\tunicast <block|default|list|promisc> - set unicast receive filtering\n");
68 printf("\tmulticast <block|list|promisc> - set multicast receive filtering\n");
69 printf("\tbroadcast <block|allow> - block or allow incoming broadcast frames\n");
70}
71
72static async_sess_t *get_nic_by_index(size_t i)
73{
74 int rc;
75 size_t count;
76 char *svc_name;
77 category_id_t nic_cat;
78 service_id_t *nics = NULL;
79 async_sess_t *sess;
80
81 rc = loc_category_get_id("nic", &nic_cat, 0);
82 if (rc != EOK) {
83 printf("Error resolving category 'nic'.\n");
84 goto error;
85 }
86
87 rc = loc_category_get_svcs(nic_cat, &nics, &count);
88 if (rc != EOK) {
89 printf("Error getting list of NICs.\n");
90 goto error;
91 }
92
93 rc = loc_service_get_name(nics[i], &svc_name);
94 if (rc != EOK) {
95 printf("Error getting service name.\n");
96 goto error;
97 }
98
99 printf("Using device: %s\n", svc_name);
100
101 sess = loc_service_connect(nics[i], INTERFACE_DDF, 0);
102 if (sess == NULL) {
103 printf("Error connecting to service.\n");
104 goto error;
105 }
106
107 return sess;
108error:
109 return NULL;
110}
111
112static int nic_get_info(service_id_t svc_id, char *svc_name,
113 nic_info_t *info)
114{
115 async_sess_t *sess;
116 nic_role_t role;
117 int rc;
118
119 sess = loc_service_connect(svc_id, INTERFACE_DDF, 0);
120 if (sess == NULL) {
121 printf("Error connecting to service.\n");
122 goto error;
123 }
124
125 rc = nic_get_address(sess, &info->address);
126 if (rc != EOK) {
127 printf("Error getting NIC address.\n");
128 rc = EIO;
129 goto error;
130 }
131
132 rc = nic_get_device_info(sess, &info->device_info);
133 if (rc != EOK) {
134 printf("Error getting NIC device info.\n");
135 rc = EIO;
136 goto error;
137 }
138
139 rc = nic_get_cable_state(sess, &info->link_state);
140 if (rc != EOK) {
141 printf("Error getting link state.\n");
142 rc = EIO;
143 goto error;
144 }
145
146 rc = nic_get_operation_mode(sess, &info->speed, &info->duplex, &role);
147 if (rc != EOK) {
148 printf("Error getting NIC speed and duplex mode.\n");
149 rc = EIO;
150 goto error;
151 }
152
153 rc = nic_unicast_get_mode(sess, &info->unicast_mode, 0, NULL, NULL);
154 if (rc != EOK) {
155 printf("Error gettinc NIC unicast receive mode.\n");
156 rc = EIO;
157 goto error;
158 }
159
160 rc = nic_multicast_get_mode(sess, &info->multicast_mode, 0, NULL, NULL);
161 if (rc != EOK) {
162 printf("Error gettinc NIC multicast receive mode.\n");
163 rc = EIO;
164 goto error;
165 }
166
167 rc = nic_broadcast_get_mode(sess, &info->broadcast_mode);
168 if (rc != EOK) {
169 printf("Error gettinc NIC broadcast receive mode.\n");
170 rc = EIO;
171 goto error;
172 }
173
174 return EOK;
175error:
176 return rc;
177}
178
179static const char *nic_link_state_str(nic_cable_state_t link_state)
180{
181 switch (link_state) {
182 case NIC_CS_UNKNOWN: return "unknown";
183 case NIC_CS_PLUGGED: return "up";
184 case NIC_CS_UNPLUGGED: return "down";
185 default: assert(false); return NULL;
186 }
187}
188
189static const char *nic_duplex_mode_str(nic_channel_mode_t mode)
190{
191 switch (mode) {
192 case NIC_CM_FULL_DUPLEX: return "full-duplex";
193 case NIC_CM_HALF_DUPLEX: return "half-duplex";
194 case NIC_CM_SIMPLEX: return "simplex";
195 default: assert(false); return NULL;
196 }
197}
198
199static const char *nic_unicast_mode_str(nic_unicast_mode_t mode)
200{
201 switch (mode) {
202 case NIC_UNICAST_UNKNOWN: return "unknown";
203 case NIC_UNICAST_BLOCKED: return "blocked";
204 case NIC_UNICAST_DEFAULT: return "default";
205 case NIC_UNICAST_LIST: return "list";
206 case NIC_UNICAST_PROMISC: return "promisc";
207 default: assert(false); return NULL;
208 }
209}
210
211static const char *nic_multicast_mode_str(nic_unicast_mode_t mode)
212{
213 switch (mode) {
214 case NIC_MULTICAST_UNKNOWN: return "unknown";
215 case NIC_MULTICAST_BLOCKED: return "blocked";
216 case NIC_MULTICAST_LIST: return "list";
217 case NIC_MULTICAST_PROMISC: return "promisc";
218 default: assert(false); return NULL;
219 }
220}
221
222static const char *nic_broadcast_mode_str(nic_unicast_mode_t mode)
223{
224 switch (mode) {
225 case NIC_BROADCAST_UNKNOWN: return "unknown";
226 case NIC_BROADCAST_BLOCKED: return "blocked";
227 case NIC_BROADCAST_ACCEPTED: return "accepted";
228 default: assert(false); return NULL;
229 }
230}
231
232static char *nic_addr_format(nic_address_t *a)
233{
234 int rc;
235 char *s;
236
237 rc = asprintf(&s, "%02x:%02x:%02x:%02x:%02x:%02x",
238 a->address[0], a->address[1], a->address[2],
239 a->address[3], a->address[4], a->address[5]);
240 if (rc < 0)
241 return NULL;
242
243 return s;
244}
245
246static int nic_list(void)
247{
248 category_id_t nic_cat;
249 service_id_t *nics = NULL;
250 nic_info_t nic_info;
251 size_t count, i;
252 char *svc_name;
253 char *addr_str;
254 int rc;
255
256 rc = loc_category_get_id("nic", &nic_cat, 0);
257 if (rc != EOK) {
258 printf("Error resolving category 'nic'.\n");
259 goto error;
260 }
261
262 rc = loc_category_get_svcs(nic_cat, &nics, &count);
263 if (rc != EOK) {
264 printf("Error getting list of NICs.\n");
265 goto error;
266 }
267
268 printf("[Index]: [Service Name]\n");
269 for (i = 0; i < count; i++) {
270 rc = loc_service_get_name(nics[i], &svc_name);
271 if (rc != EOK) {
272 printf("Error getting service name.\n");
273 goto error;
274 }
275
276 rc = nic_get_info(nics[i], svc_name, &nic_info);
277 if (rc != EOK)
278 goto error;
279
280 addr_str = nic_addr_format(&nic_info.address);
281 if (addr_str == NULL) {
282 printf("Out of memory.\n");
283 rc = ENOMEM;
284 goto error;
285 }
286
287 printf("%zu: %s\n", i, svc_name);
288 printf("\tMAC address: %s\n", addr_str);
289 printf("\tVendor name: %s\n",
290 nic_info.device_info.vendor_name);
291 printf("\tModel name: %s\n",
292 nic_info.device_info.model_name);
293 printf("\tLink state: %s\n",
294 nic_link_state_str(nic_info.link_state));
295 printf("\tUnicast receive mode: %s\n",
296 nic_unicast_mode_str(nic_info.unicast_mode));
297 printf("\tMulticast receive mode: %s\n",
298 nic_multicast_mode_str(nic_info.multicast_mode));
299 printf("\tBroadcast receive mode: %s\n",
300 nic_broadcast_mode_str(nic_info.broadcast_mode));
301
302 if (nic_info.link_state == NIC_CS_PLUGGED) {
303 printf("\tSpeed: %dMbps %s\n", nic_info.speed,
304 nic_duplex_mode_str(nic_info.duplex));
305 }
306
307 free(svc_name);
308 free(addr_str);
309 }
310
311 return EOK;
312error:
313 free(nics);
314 return rc;
315}
316
317static int nic_set_speed(int i, char *str)
318{
319 async_sess_t *sess;
320 uint32_t speed;
321 int oldspeed;
322 nic_channel_mode_t oldduplex;
323 nic_role_t oldrole;
324 int rc;
325
326 rc = str_uint32_t(str, NULL, 10, false, &speed);
327 if (rc != EOK) {
328 printf("Speed must be a numeric value.\n");
329 return rc;
330 }
331
332 if (speed != 10 && speed != 100 && speed != 1000) {
333 printf("Speed must be one of: 10, 100, 1000.\n");
334 return EINVAL;
335 }
336
337 sess = get_nic_by_index(i);
338 if (sess == NULL) {
339 printf("Specified NIC doesn't exist or cannot connect to it.\n");
340 return EINVAL;
341 }
342
343 rc = nic_get_operation_mode(sess, &oldspeed, &oldduplex, &oldrole);
344 if (rc != EOK) {
345 printf("Error getting NIC speed and duplex mode.\n");
346 return EIO;
347 }
348
349 return nic_set_operation_mode(sess, speed, oldduplex, oldrole);
350}
351
352static int nic_set_duplex(int i, char *str)
353{
354 async_sess_t *sess;
355 int oldspeed;
356 nic_channel_mode_t duplex = NIC_CM_UNKNOWN;
357 nic_channel_mode_t oldduplex;
358 nic_role_t oldrole;
359 int rc;
360
361 if (!str_cmp(str, "half"))
362 duplex = NIC_CM_HALF_DUPLEX;
363
364 if (!str_cmp(str, "full"))
365 duplex = NIC_CM_FULL_DUPLEX;
366
367 if (!str_cmp(str, "simplex"))
368 duplex = NIC_CM_SIMPLEX;
369
370 if (duplex == NIC_CM_UNKNOWN) {
371 printf("Invalid duplex specification.\n");
372 return EINVAL;
373 }
374
375 sess = get_nic_by_index(i);
376 if (sess == NULL) {
377 printf("Specified NIC doesn't exist or cannot connect to it.\n");
378 return EINVAL;
379 }
380
381 rc = nic_get_operation_mode(sess, &oldspeed, &oldduplex, &oldrole);
382 if (rc != EOK) {
383 printf("Error getting NIC speed and duplex mode.\n");
384 return EIO;
385 }
386
387 return nic_set_operation_mode(sess, oldspeed, duplex, oldrole);
388}
389
390static int nic_set_autoneg(int i)
391{
392 async_sess_t *sess;
393 int rc;
394
395 sess = get_nic_by_index(i);
396 if (sess == NULL) {
397 printf("Specified NIC doesn't exist or cannot connect to it.\n");
398 return EINVAL;
399 }
400
401 rc = nic_autoneg_restart(sess);
402 if (rc != EOK) {
403 printf("Error restarting NIC autonegotiation.\n");
404 return EIO;
405 }
406
407 return EOK;
408}
409
410static int nic_set_addr(int i, char *str)
411{
412 async_sess_t *sess;
413 nic_address_t addr;
414 int rc, idx;
415
416 sess = get_nic_by_index(i);
417 if (sess == NULL) {
418 printf("Specified NIC doesn't exist or cannot connect to it.\n");
419 return EINVAL;
420 }
421
422 if (str_size(str) != 17) {
423 printf("Invalid MAC address specified");
424 return EINVAL;
425 }
426
427 for (idx = 0; idx < 6; idx++) {
428 rc = str_uint8_t(&str[idx * 3], NULL, 16, false, &addr.address[idx]);
429 if (rc != EOK) {
430 printf("Invalid MAC address specified");
431 return EINVAL;
432 }
433 }
434
435 return nic_set_address(sess, &addr);
436}
437
438static int nic_set_rx_unicast(int i, char *str)
439{
440 async_sess_t *sess;
441
442 sess = get_nic_by_index(i);
443 if (sess == NULL) {
444 printf("Specified NIC doesn't exist or cannot connect to it.\n");
445 return EINVAL;
446 }
447
448 if (!str_cmp(str, "block")) {
449 nic_unicast_set_mode(sess, NIC_UNICAST_BLOCKED, NULL, 0);
450 return EOK;
451 }
452
453 if (!str_cmp(str, "default")) {
454 nic_unicast_set_mode(sess, NIC_UNICAST_DEFAULT, NULL, 0);
455 return EOK;
456 }
457
458 if (!str_cmp(str, "list")) {
459 nic_unicast_set_mode(sess, NIC_UNICAST_LIST, NULL, 0);
460 return EOK;
461 }
462
463 if (!str_cmp(str, "promisc")) {
464 nic_unicast_set_mode(sess, NIC_UNICAST_PROMISC, NULL, 0);
465 return EOK;
466 }
467
468
469 printf("Invalid pameter - should be one of: block, default, promisc\n");
470 return EINVAL;
471}
472
473static int nic_set_rx_multicast(int i, char *str)
474{
475 async_sess_t *sess;
476
477 sess = get_nic_by_index(i);
478 if (sess == NULL) {
479 printf("Specified NIC doesn't exist or cannot connect to it.\n");
480 return EINVAL;
481 }
482
483 if (!str_cmp(str, "block")) {
484 nic_multicast_set_mode(sess, NIC_MULTICAST_BLOCKED, NULL, 0);
485 return EOK;
486 }
487
488 if (!str_cmp(str, "list")) {
489 nic_multicast_set_mode(sess, NIC_MULTICAST_LIST, NULL, 0);
490 return EOK;
491 }
492
493 if (!str_cmp(str, "promisc")) {
494 nic_multicast_set_mode(sess, NIC_MULTICAST_PROMISC, NULL, 0);
495 return EOK;
496 }
497
498 printf("Invalid pameter - should be one of: block, promisc\n");
499 return EINVAL;
500}
501
502static int nic_set_rx_broadcast(int i, char *str)
503{
504 async_sess_t *sess;
505
506 sess = get_nic_by_index(i);
507 if (sess == NULL) {
508 printf("Specified NIC doesn't exist or cannot connect to it.\n");
509 return EINVAL;
510 }
511
512 if (!str_cmp(str, "block")) {
513 nic_broadcast_set_mode(sess, NIC_BROADCAST_BLOCKED);
514 return EOK;
515 }
516
517 if (!str_cmp(str, "accept")) {
518 nic_broadcast_set_mode(sess, NIC_BROADCAST_ACCEPTED);
519 return EOK;
520 }
521
522 printf("Invalid pameter - should be 'block' or 'accept'\n");
523 return EINVAL;
524}
525
526int main(int argc, char *argv[])
527{
528 int rc;
529 uint32_t index;
530
531 if (argc == 1) {
532 rc = nic_list();
533 if (rc != EOK)
534 return 1;
535 } else if (argc >= 3) {
536 rc = str_uint32_t(argv[1], NULL, 10, false, &index);
537 if (rc != EOK) {
538 printf(NAME ": Invalid argument.\n");
539 print_syntax();
540 return 1;
541 }
542
543 if (!str_cmp(argv[2], "addr"))
544 return nic_set_addr(index, argv[3]);
545
546 if (!str_cmp(argv[2], "speed"))
547 return nic_set_speed(index, argv[3]);
548
549 if (!str_cmp(argv[2], "duplex"))
550 return nic_set_duplex(index, argv[3]);
551
552 if (!str_cmp(argv[2], "auto"))
553 return nic_set_autoneg(index);
554
555 if (!str_cmp(argv[2], "unicast"))
556 return nic_set_rx_unicast(index, argv[3]);
557
558 if (!str_cmp(argv[2], "multicast"))
559 return nic_set_rx_multicast(index, argv[3]);
560
561 if (!str_cmp(argv[2], "broadcast"))
562 return nic_set_rx_broadcast(index, argv[3]);
563
564 } else {
565 printf(NAME ": Invalid argument.\n");
566 print_syntax();
567 return 1;
568 }
569
570 return 0;
571}
572
573/** @}
574 */
Note: See TracBrowser for help on using the repository browser.