]> git.ipfire.org Git - people/ms/rstp.git/blame - rstplib/mngr.c
Use new RSTP library.
[people/ms/rstp.git] / rstplib / mngr.c
CommitLineData
ad02a0eb
SH
1/************************************************************************
2 * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
3 * Copyright (C) 2001-2003 Optical Access
4 * Author: Alex Rozin
5 *
6 * This file is part of RSTP library.
7 *
8 * RSTP library is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by the
10 * Free Software Foundation; version 2.1
11 *
12 * RSTP library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with RSTP library; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 **********************************************************************/
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <time.h>
26#include <string.h>
27#include <sys/wait.h>
28#include <sys/time.h>
29#include <sys/types.h>
30#include <signal.h>
31#include <unistd.h>
32#include <errno.h>
33#include <readline/readline.h>
34
35#include "cli.h"
36#include "bitmap.h"
37#include "uid.h"
38
39UID_SOCKET_T main_sock;
40
41typedef struct port_s {
42 int port;
43 struct bridge_s *bridge_partner;
44 int port_partner;
45} PORT_T;
46
47typedef struct bridge_s {
48 long pid;
49 long number_of_ports;
50 PORT_T* ports;
51 UID_SOCKET_T sock;
52 struct bridge_s* next;
53} BRIDGE_T;
54
55static BRIDGE_T* br_lst = 0;
56
57int disconnect_port (PORT_T* port, char reset_myself)
58{
59 UID_MSG_T msg;
60 if (! port->bridge_partner) {
61 printf ("can't disconnect from port p%02d: it has not a partner\n",
62 port->port_partner);
63 return -1;
64 }
65
66 printf ("disconnect from port p%02d for bridge B%ld\n",
67 port->port_partner, port->bridge_partner->pid);
68
69 msg.header.sender_pid = getpid ();
70 msg.header.cmd_type = UID_CNTRL;
71 msg.body.cntrl.cmd = UID_PORT_DISCONNECT;
72
73 msg.header.destination_port = port->port_partner;
74 UiD_SocketSendto (&port->bridge_partner->sock, &msg, sizeof (UID_MSG_T));
75
76 if (reset_myself)
77 port->bridge_partner = NULL;
78 else {
79 port = port->bridge_partner->ports + port->port_partner - 1;
80 port->bridge_partner = NULL;
81 }
82
83 return 0;
84}
85
86int register_bridge (UID_MSG_T* msg, UID_SOCKET_T* socket_4_reply)
87{
88 register BRIDGE_T* newbr;
89
90 /* check if such bridge has just been registered */
91 for (newbr = br_lst; newbr; newbr = newbr->next)
92 if (newbr->pid == msg->header.sender_pid) {
93 printf ("Sorry, such bridge has just been registered\n");
94 /* TBT: may be send him SHUTDOWN ? */
95 }
96
97 newbr = (BRIDGE_T*) malloc (sizeof (BRIDGE_T));
98 if (! newbr) {
99 printf ("Sorry, there is no memory for it :(\n");
100 return 0;
101 }
102
103 newbr->pid = msg->header.sender_pid;
104 newbr->ports = (PORT_T*) calloc (msg->body.cntrl.param1, sizeof (PORT_T));
105 if (! newbr->ports) {
106 printf ("Sorry, there is no memory for its ports :(\n");
107 free (newbr);
108 return 0;
109 }
110 newbr->number_of_ports = msg->body.cntrl.param1;
111 memcpy (&newbr->sock, socket_4_reply, sizeof (UID_SOCKET_T));
112
113 /* bind it to the begin of list */
114 newbr->next = br_lst;
115 br_lst = newbr;
116
117 return 0;
118}
119
120int unregister_bridge (UID_MSG_T* msg)
121{
122 register BRIDGE_T* oldbr;
123 register BRIDGE_T* prev = NULL;
124 register PORT_T* port;
125 register int indx;
126
127 /* check if such bridge has just been registered */
128 for (oldbr = br_lst; oldbr; oldbr = oldbr->next)
129 if (oldbr->pid == msg->header.sender_pid) {
130 break;
131 } else
132 prev = oldbr;
133
134 if (! oldbr) {
135 printf ("Sorry, this bridge has not yet been registered ? :(\n");
136 return 0;
137 }
138
139 /* disconnect all its connceted ports */
140 for (indx = 0; indx < oldbr->number_of_ports; indx++) {
141 port = oldbr->ports + indx;
142 if (port->bridge_partner) {
143 disconnect_port (port, 0);
144 }
145 }
146
147 /* delete from the list & free */
148 if (prev)
149 prev->next = oldbr->next;
150 else
151 br_lst = oldbr->next;
152
153 free (oldbr->ports);
154 free (oldbr);
155 return 0;
156}
157
158static long scan_br_name (char* param)
159{
160 if ('B' == param[0])
161 return strtoul(param + 1, 0, 10);
162 else
163 return strtoul(param, 0, 10);
164}
165
166static int show_bridge (int argc, char** argv)
167{
168 long pid = 0;
169 register BRIDGE_T* br = NULL;
170 register PORT_T* port;
171 register int indx, cnt = 0;
172
173 if (argc > 1) {
174 pid = scan_br_name (argv[1]);
175 printf ("You wanted to see B%ld, didn't you ?\n", pid);
176 }
177
178 for (br = br_lst; br; br = br->next)
179 if (! pid || pid == br->pid) {
180 printf ("%2d. Bridge B%ld has %ld ports:\n",
181 ++cnt,
182 (long) br->pid, br->number_of_ports);
183 for (indx = 0; indx < br->number_of_ports; indx++) {
184 port = br->ports + indx;
185 if (port->bridge_partner) {
186 printf ("port p%02d ", (int) indx + 1);
187 printf ("connected to B%ld port p%02d\n",
188 port->bridge_partner->pid,
189 port->port_partner);
190 }
191 }
192 }
193
194 if (! cnt) {
195 printf ("There are no such bridges :(\n");
196 }
197 return 0;
198}
199
200static void _link_two_ports (BRIDGE_T* br1, PORT_T* port1, int indx1,
201 BRIDGE_T* br2, PORT_T* port2, int indx2)
202{
203 UID_MSG_T msg;
204
205 port1->bridge_partner = br2;
206 port1->port_partner = indx2;
207 port2->bridge_partner = br1;
208 port2->port_partner = indx1;
209
210 msg.header.sender_pid = getpid ();
211 msg.header.cmd_type = UID_CNTRL;
212 msg.body.cntrl.cmd = UID_PORT_CONNECT;
213
214 msg.header.destination_port = indx1;
215 UiD_SocketSendto (&br1->sock, &msg, sizeof (UID_MSG_T));
216 msg.header.destination_port = indx2;
217 UiD_SocketSendto (&br2->sock, &msg, sizeof (UID_MSG_T));
218}
219
220static int link_bridges (int argc, char** argv)
221{
222 long pid1, pid2;
223 int indx1, indx2;
224 BRIDGE_T* br;
225 BRIDGE_T* br1;
226 BRIDGE_T* br2;
227 PORT_T* port1;
228 PORT_T* port2;
229
230 if (argc < 5) {
231 printf ("for this command must be 4 argumenta :(\n");
232 return 0;
233 }
234
235 pid1 = scan_br_name (argv[1]);
236 indx1 = strtoul(argv[2], 0, 10);
237 pid2 = scan_br_name (argv[3]);
238 indx2 = strtoul(argv[4], 0, 10);
239 printf ("connect B%ld port p%02d to B%ld port p%02d\n",
240 pid1, indx1, pid2, indx2);
241
242 for (br = br_lst; br; br = br->next) {
243 //printf ("check B%ld\n", br->pid);
244 if (br->pid == pid1) br1 = br;
245 if (br->pid == pid2) br2 = br;
246 }
247
248 if (! br1 || ! br2) {
249 printf ("Sorry, one of these bridges is absent :(\n");
250 return 0;
251 }
252
253 if (indx1 > br1->number_of_ports || indx1 < 0) {
254 printf ("Sorry, p%02d invalid\n", indx1);
255 return 0;
256 }
257
258 if (indx2 > br2->number_of_ports || indx2 < 0) {
259 printf ("Sorry, p%02d invalid\n", indx2);
260 return 0;
261 }
262
263 port1 = br1->ports + indx1 - 1;
264 port2 = br2->ports + indx2 - 1;
265
266 if (port1->bridge_partner)
267 printf ("port p%02d is connected\n", indx1);
268 if (port2->bridge_partner)
269 printf ("port p%02d is connected\n", indx2);
270 if (port1->bridge_partner || port2->bridge_partner)
271 return 0;
272
273 _link_two_ports (br1, port1, indx1,
274 br2, port2, indx2);
275 return 0;
276}
277
278static int unlink_port (int argc, char** argv)
279{
280 long pid1;
281 int indx1;
282 BRIDGE_T* br;
283 BRIDGE_T* br1;
284 BRIDGE_T* br2;
285 PORT_T* port1;
286 PORT_T* port2;
287
288 if (argc < 3) {
289 printf ("for this command must be 2 argumenta :(\n");
290 return 0;
291 }
292
293 pid1 = scan_br_name (argv[1]);
294 indx1 = strtoul(argv[2], 0, 10);
295
296
297 for (br = br_lst; br; br = br->next) {
298 //printf ("check B%ld\n", br->pid);
299 if (br->pid == pid1) br1 = br;
300 }
301
302 if (! br1) {
303 printf ("Sorry, the bridge B%ldis absent :(\n", pid1);
304 return 0;
305 }
306
307 if (indx1 > br1->number_of_ports || indx1 < 0) {
308 printf ("Sorry, port p%02d invalid\n", indx1);
309 return 0;
310 }
311
312 port1 = br1->ports + indx1 - 1;
313
314 if (! port1->bridge_partner) {
315 printf ("port p%02d is disconnected\n", indx1);
316 return 0;
317 }
318
319 br2 = port1->bridge_partner;
320 port2 = br2->ports + port1->port_partner - 1;
321 disconnect_port (port1, 1);
322 disconnect_port (port2, 1);
323
324 return 0;
325}
326
327static int link_ring (int argc, char** argv)
328{
329 BRIDGE_T* br1;
330 BRIDGE_T* br2;
331 PORT_T* port1;
332 PORT_T* port2;
333 register int indx;
334
335 /* unlink all */
336 for (br1 = br_lst; br1; br1 = br1->next) {
337 /* disconnect all its connceted ports */
338 for (indx = 0; indx < br1->number_of_ports; indx++) {
339 port1 = br1->ports + indx;
340 if (port1->bridge_partner) {
341 printf ("disconnect B%ld ", br1->pid);
342 printf ("port p%02d (with B%ld-p%02d)\n",
343 indx + 1,
344 port1->bridge_partner->pid,
345 port1->port_partner);
346 br2 = port1->bridge_partner;
347 port2 = br2->ports + port1->port_partner - 1;
348 disconnect_port (port1, 1);
349 disconnect_port (port2, 1);
350 }
351 }
352 }
353
354 /* buid ring */
355 for (br1 = br_lst; br1; br1 = br1->next) {
356 br2 = br1->next;
357 if (! br2) br2 = br_lst;
358 _link_two_ports (br1, br1->ports + 1, 2,
359 br2, br2->ports + 0, 1);
360 }
361
362 return 0;
363}
364
365static CMD_DSCR_T lang[] = {
366 THE_COMMAND("show", "get bridge[s] connuctivity")
367 PARAM_STRING("bridge name", "all")
368 THE_FUNC(show_bridge)
369
370 THE_COMMAND("link", "link two bridges")
371 PARAM_STRING("first bridge name", NULL)
372 PARAM_NUMBER("port number on first bridge", 1, NUMBER_OF_PORTS, NULL)
373 PARAM_STRING("second bridge name", NULL)
374 PARAM_NUMBER("port number on second bridge", 1, NUMBER_OF_PORTS, NULL)
375 THE_FUNC(link_bridges)
376
377 THE_COMMAND("unlink", "unlink the port of the bridge")
378 PARAM_STRING("bridge name", NULL)
379 PARAM_NUMBER("port number on bridge", 1, NUMBER_OF_PORTS, NULL)
380 THE_FUNC(unlink_port)
381
382 THE_COMMAND("ring", "link all bridges into a ring")
383 THE_FUNC(link_ring)
384
385 END_OF_LANG
386};
387
388void mngr_start (void)
389{
390 if (0 != UiD_SocketInit (&main_sock, UID_REPL_PATH, UID_BIND_AS_SERVER)) {
391 printf ("FATAL: can't init the connection\n");
392 exit (-3);
393 }
394
395 cli_register_language (lang);
396}
397
398void mngr_shutdown (void)
399{
400 UID_MSG_T msg;
401 BRIDGE_T* br;
402
403 msg.header.sender_pid = getpid ();
404 msg.header.cmd_type = UID_CNTRL;
405 msg.body.cntrl.cmd = UID_BRIDGE_SHUTDOWN;
406
407 for (br = br_lst; br; br = br->next) {
408 UiD_SocketSendto (&br->sock, &msg, sizeof (UID_MSG_T));
409 }
410}
411
412char *get_prompt (void)
413{
414 static char prompt[MAX_CLI_PROMT];
415 snprintf (prompt, MAX_CLI_PROMT - 1, "%s Mngr > ", UT_sprint_time_stamp());
416 return prompt;
417}
418
419int mngr_control (UID_MSG_T* msg, UID_SOCKET_T* sock_4_reply)
420{
421 switch (msg->body.cntrl.cmd) {
422 default:
423 case UID_PORT_CONNECT:
424 case UID_PORT_DISCONNECT:
425 printf ("Unexpected contol message '%d'\n", (int) msg->body.cntrl.cmd);
426 break;
427 case UID_BRIDGE_SHUTDOWN:
428 printf ("Bridge B%ld shutdown :(\n", (long) msg->header.sender_pid);
429 unregister_bridge (msg);
430 break;
431 case UID_BRIDGE_HANDSHAKE:
432 printf ("Bridge B%ld hello :)\n", (long) msg->header.sender_pid);
433 register_bridge (msg, sock_4_reply);
434 break;
435 }
436
437 return 0;
438}
439
440int mngr_rx_bpdu (UID_MSG_T* msg, size_t msgsize)
441{
442 BRIDGE_T* br;
443 PORT_T* port;
444
445 for (br = br_lst; br; br = br->next) {
446 if (br->pid == msg->header.sender_pid) {
447 break;
448 }
449 }
450
451 if (! br) {
452 printf ("RX BPDU from unknown B%ld\n", msg->header.sender_pid);
453 return 0;
454 }
455
456 port = br->ports + msg->header.source_port - 1;
457 if (! port->bridge_partner) {
458 printf ("RX BPDU from unlinked port p%02d of bridge B%ld ?\n",
459 (int) msg->header.source_port,
460 msg->header.sender_pid);
461 return 0;
462 }
463
464 br = port->bridge_partner;
465 msg->header.destination_port = port->port_partner;
466 UiD_SocketSendto (&br->sock, msg, sizeof (UID_MSG_T));
467
468 return 0;
469}
470
471char read_uid (void)
472{
473 UID_SOCKET_T sock_4_reply;
474 UID_MSG_T msg;
475 size_t msgsize;
476 int rc = 0;
477
478 msgsize = UiD_SocketRecvfrom (&main_sock, &msg, MAX_UID_MSG_SIZE, &sock_4_reply);
479 if (msgsize <= 0) {
480 printf ("Something wrong in UIF ?\n");
481 return 0;
482 }
483
484 switch (msg.header.cmd_type) {
485 case UID_CNTRL:
486 rc = mngr_control (&msg, &sock_4_reply);
487 break;
488 case UID_BPDU:
489 rc = mngr_rx_bpdu (&msg, msgsize);
490 break;
491 default:
492 printf ("Unknown message type %d\n", (int) msg.header.cmd_type);
493 rc = 0;
494 }
495
496 return rc;
497}
498
499char shutdown_flag = 0;
500
501int main_loop (void)
502{
503 fd_set readfds;
504 int rc, numfds, sock, kkk;
505
506 //rl_callback_handler_install (get_prompt (), rl_read_cli);
507
508 sock = GET_FILE_DESCRIPTOR(&main_sock);
509
510 do {
511 numfds = -1;
512 FD_ZERO(&readfds);
513
514 kkk = 0; /* stdin for commands */
515 FD_SET(kkk, &readfds);
516 if (kkk > numfds) numfds = kkk;
517
518 FD_SET(sock, &readfds);
519 if (sock > numfds) numfds = sock;
520
521 if (numfds < 0)
522 numfds = 0;
523 else
524 numfds++;
525
526 rc = select (numfds, &readfds, NULL, NULL, NULL);
527 if (rc < 0) { // Error
528 if (EINTR == errno) continue; // don't break
529 printf ("FATAL_MODE:select failed: %s\n", strerror(errno));
530 return -2;
531 }
532
533 if (FD_ISSET(0, &readfds)) {
534 rl_callback_read_char ();
535 }
536
537 if (FD_ISSET(sock, &readfds)) {
538 shutdown_flag |= read_uid ();
539 }
540
541 } while(! shutdown_flag);
542 return 0;
543}
544
545int main (int argc, char** argv)
546{
547 rl_init ();
548
549 mngr_start ();
550
551 main_loop ();
552
553 mngr_shutdown ();
554
555 rl_shutdown ();
556
557 return 0;
558}
559