cli.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * swconfig.c: Switch configuration utility
  3. *
  4. * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
  5. * Copyright (C) 2010 Martin Mares <mj@ucw.cz>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * version 2 as published by the Free Software Foundatio.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <inttypes.h>
  20. #include <errno.h>
  21. #include <stdbool.h>
  22. #include <stdint.h>
  23. #include <getopt.h>
  24. #include <sys/types.h>
  25. #include <sys/socket.h>
  26. #include <linux/types.h>
  27. #include <linux/netlink.h>
  28. #include <linux/genetlink.h>
  29. #include <netlink/netlink.h>
  30. #include <netlink/genl/genl.h>
  31. #include <netlink/genl/ctrl.h>
  32. #include <linux/switch.h>
  33. #include "swlib.h"
  34. enum {
  35. CMD_NONE,
  36. CMD_GET,
  37. CMD_SET,
  38. CMD_LOAD,
  39. CMD_HELP,
  40. CMD_SHOW,
  41. CMD_PORTMAP,
  42. };
  43. static void
  44. print_attrs(const struct switch_attr *attr)
  45. {
  46. int i = 0;
  47. while (attr) {
  48. const char *type;
  49. switch(attr->type) {
  50. case SWITCH_TYPE_INT:
  51. type = "int";
  52. break;
  53. case SWITCH_TYPE_STRING:
  54. type = "string";
  55. break;
  56. case SWITCH_TYPE_PORTS:
  57. type = "ports";
  58. break;
  59. case SWITCH_TYPE_NOVAL:
  60. type = "none";
  61. break;
  62. default:
  63. type = "unknown";
  64. break;
  65. }
  66. printf("\tAttribute %d (%s): %s (%s)\n", ++i, type, attr->name, attr->description);
  67. attr = attr->next;
  68. }
  69. }
  70. static void
  71. list_attributes(struct switch_dev *dev)
  72. {
  73. printf("%s: %s(%s), ports: %d (cpu @ %d), vlans: %d\n", dev->dev_name, dev->alias, dev->name, dev->ports, dev->cpu_port, dev->vlans);
  74. printf(" --switch\n");
  75. print_attrs(dev->ops);
  76. printf(" --vlan\n");
  77. print_attrs(dev->vlan_ops);
  78. printf(" --port\n");
  79. print_attrs(dev->port_ops);
  80. }
  81. static void
  82. print_attr_val(const struct switch_attr *attr, const struct switch_val *val)
  83. {
  84. int i;
  85. switch (attr->type) {
  86. case SWITCH_TYPE_INT:
  87. printf("%d", val->value.i);
  88. break;
  89. case SWITCH_TYPE_STRING:
  90. printf("%s", val->value.s);
  91. break;
  92. case SWITCH_TYPE_PORTS:
  93. for(i = 0; i < val->len; i++) {
  94. printf("%d%s ",
  95. val->value.ports[i].id,
  96. (val->value.ports[i].flags &
  97. SWLIB_PORT_FLAG_TAGGED) ? "t" : "");
  98. }
  99. break;
  100. default:
  101. printf("?unknown-type?");
  102. }
  103. }
  104. static void
  105. show_attrs(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
  106. {
  107. while (attr) {
  108. if (attr->type != SWITCH_TYPE_NOVAL) {
  109. printf("\t%s: ", attr->name);
  110. if (swlib_get_attr(dev, attr, val) < 0)
  111. printf("???");
  112. else
  113. print_attr_val(attr, val);
  114. putchar('\n');
  115. }
  116. attr = attr->next;
  117. }
  118. }
  119. static void
  120. show_global(struct switch_dev *dev)
  121. {
  122. struct switch_val val;
  123. printf("Global attributes:\n");
  124. show_attrs(dev, dev->ops, &val);
  125. }
  126. static void
  127. show_port(struct switch_dev *dev, int port)
  128. {
  129. struct switch_val val;
  130. printf("Port %d:\n", port);
  131. val.port_vlan = port;
  132. show_attrs(dev, dev->port_ops, &val);
  133. }
  134. static void
  135. show_vlan(struct switch_dev *dev, int vlan, bool all)
  136. {
  137. struct switch_val val;
  138. struct switch_attr *attr;
  139. val.port_vlan = vlan;
  140. if (all) {
  141. attr = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_VLAN, "ports");
  142. if (swlib_get_attr(dev, attr, &val) < 0)
  143. return;
  144. if (!val.len)
  145. return;
  146. }
  147. printf("VLAN %d:\n", vlan);
  148. show_attrs(dev, dev->vlan_ops, &val);
  149. }
  150. static void
  151. print_usage(void)
  152. {
  153. printf("swconfig list\n");
  154. printf("swconfig dev <dev> [port <port>|vlan <vlan>] (help|set <key> <value>|get <key>|load <config>|show)\n");
  155. exit(1);
  156. }
  157. int main(int argc, char **argv)
  158. {
  159. int retval = 0;
  160. struct switch_dev *dev;
  161. struct switch_attr *a;
  162. struct switch_val val;
  163. int i;
  164. int cmd = CMD_NONE;
  165. char *cdev = NULL;
  166. int cport = -1;
  167. int cvlan = -1;
  168. char *ckey = NULL;
  169. char *cvalue = NULL;
  170. char *csegment = NULL;
  171. if((argc == 2) && !strcmp(argv[1], "list")) {
  172. swlib_list();
  173. return 0;
  174. }
  175. if(argc < 4)
  176. print_usage();
  177. if(strcmp(argv[1], "dev"))
  178. print_usage();
  179. cdev = argv[2];
  180. for(i = 3; i < argc; i++)
  181. {
  182. char *arg = argv[i];
  183. if (cmd != CMD_NONE) {
  184. print_usage();
  185. } else if (!strcmp(arg, "port") && i+1 < argc) {
  186. cport = atoi(argv[++i]);
  187. } else if (!strcmp(arg, "vlan") && i+1 < argc) {
  188. cvlan = atoi(argv[++i]);
  189. } else if (!strcmp(arg, "help")) {
  190. cmd = CMD_HELP;
  191. } else if (!strcmp(arg, "set") && i+1 < argc) {
  192. cmd = CMD_SET;
  193. ckey = argv[++i];
  194. if (i+1 < argc)
  195. cvalue = argv[++i];
  196. } else if (!strcmp(arg, "get") && i+1 < argc) {
  197. cmd = CMD_GET;
  198. ckey = argv[++i];
  199. } else if (!strcmp(arg, "load") && i+1 < argc) {
  200. if ((cport >= 0) || (cvlan >= 0))
  201. print_usage();
  202. cmd = CMD_LOAD;
  203. ckey = argv[++i];
  204. } else if (!strcmp(arg, "portmap")) {
  205. if (i + 1 < argc)
  206. csegment = argv[++i];
  207. cmd = CMD_PORTMAP;
  208. } else if (!strcmp(arg, "show")) {
  209. cmd = CMD_SHOW;
  210. } else {
  211. print_usage();
  212. }
  213. }
  214. if (cmd == CMD_NONE)
  215. print_usage();
  216. if (cport > -1 && cvlan > -1)
  217. print_usage();
  218. dev = swlib_connect(cdev);
  219. if (!dev) {
  220. fprintf(stderr, "Failed to connect to the switch. Use the \"list\" command to see which switches are available.\n");
  221. return 1;
  222. }
  223. swlib_scan(dev);
  224. if (cmd == CMD_GET || cmd == CMD_SET) {
  225. if(cport > -1)
  226. a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_PORT, ckey);
  227. else if(cvlan > -1)
  228. a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_VLAN, ckey);
  229. else
  230. a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_GLOBAL, ckey);
  231. if(!a)
  232. {
  233. fprintf(stderr, "Unknown attribute \"%s\"\n", ckey);
  234. retval = -1;
  235. goto out;
  236. }
  237. }
  238. switch(cmd)
  239. {
  240. case CMD_SET:
  241. if ((a->type != SWITCH_TYPE_NOVAL) &&
  242. (cvalue == NULL))
  243. print_usage();
  244. if(cvlan > -1)
  245. cport = cvlan;
  246. if(swlib_set_attr_string(dev, a, cport, cvalue) < 0)
  247. {
  248. fprintf(stderr, "failed\n");
  249. retval = -1;
  250. goto out;
  251. }
  252. break;
  253. case CMD_GET:
  254. if(cvlan > -1)
  255. val.port_vlan = cvlan;
  256. if(cport > -1)
  257. val.port_vlan = cport;
  258. if(swlib_get_attr(dev, a, &val) < 0)
  259. {
  260. fprintf(stderr, "failed\n");
  261. retval = -1;
  262. goto out;
  263. }
  264. print_attr_val(a, &val);
  265. putchar('\n');
  266. break;
  267. case CMD_HELP:
  268. list_attributes(dev);
  269. break;
  270. case CMD_PORTMAP:
  271. swlib_print_portmap(dev, csegment);
  272. break;
  273. case CMD_SHOW:
  274. if (cport >= 0 || cvlan >= 0) {
  275. if (cport >= 0)
  276. show_port(dev, cport);
  277. else
  278. show_vlan(dev, cvlan, false);
  279. } else {
  280. show_global(dev);
  281. for (i=0; i < dev->ports; i++)
  282. show_port(dev, i);
  283. for (i=0; i < dev->vlans; i++)
  284. show_vlan(dev, i, true);
  285. }
  286. break;
  287. }
  288. out:
  289. swlib_free_all(dev);
  290. return retval;
  291. }