]>
Commit | Line | Data |
---|---|---|
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 "uid.h" | |
37 | #include "stp_cli.h" | |
38 | ||
39 | #include "base.h" | |
40 | #include "bitmap.h" | |
41 | #include "uid_stp.h" | |
42 | #include "stp_in.h" | |
43 | ||
44 | long my_pid = 0; | |
45 | BITMAP_T enabled_ports; | |
46 | UID_SOCKET_T uid_socket; | |
47 | ||
48 | int bridge_tx_bpdu (int port_index, unsigned char *bpdu, size_t bpdu_len) | |
49 | { | |
50 | UID_MSG_T msg; | |
51 | ||
52 | msg.header.sender_pid = my_pid; | |
53 | msg.header.cmd_type = UID_BPDU; | |
54 | msg.header.source_port = port_index; | |
55 | msg.header.body_len = bpdu_len; | |
56 | memcpy (&msg.body, bpdu, bpdu_len); | |
57 | UiD_SocketSendto (&uid_socket, &msg, sizeof (UID_MSG_T)); | |
58 | return 0; | |
59 | } | |
60 | ||
61 | int bridge_start (void) | |
62 | { | |
63 | BITMAP_T ports; | |
64 | UID_MSG_T msg; | |
65 | UID_STP_CFG_T uid_cfg; | |
66 | register int iii; | |
67 | ||
68 | //rl_callback_handler_install (get_prompt (), rl_read_cli); | |
69 | ||
70 | if (0 != UiD_SocketInit (&uid_socket, UID_REPL_PATH, UID_BIND_AS_CLIENT)) { | |
71 | printf ("FATAL: can't init the connection\n"); | |
72 | exit (-3); | |
73 | } | |
74 | ||
75 | /* send HANDSHAKE */ | |
76 | msg.header.sender_pid = my_pid; | |
77 | msg.header.cmd_type = UID_CNTRL; | |
78 | msg.body.cntrl.cmd = UID_BRIDGE_HANDSHAKE; | |
79 | msg.body.cntrl.param1 = NUMBER_OF_PORTS; | |
80 | iii = UiD_SocketSendto (&uid_socket, &msg, sizeof (UID_MSG_T)); | |
81 | if (iii < 0) { | |
82 | printf ("can't send HANDSHAKE: %s\n", strerror(errno)); | |
83 | printf ("May be 'mngr' is not alive ? :(\n"); | |
84 | return (-4); | |
85 | } | |
86 | ||
87 | stp_cli_init (); | |
88 | ||
89 | STP_IN_init (NUMBER_OF_PORTS); | |
90 | BitmapClear(&enabled_ports); | |
91 | BitmapClear(&ports); | |
92 | for (iii = 1; iii <= NUMBER_OF_PORTS; iii++) { | |
93 | BitmapSetBit(&ports, iii - 1); | |
94 | } | |
95 | ||
96 | uid_cfg.field_mask = BR_CFG_STATE; | |
97 | uid_cfg.stp_enabled = STP_ENABLED; | |
98 | snprintf (uid_cfg.vlan_name, NAME_LEN - 1, "B%ld", (long) my_pid); | |
99 | iii = STP_IN_stpm_set_cfg (0, &ports, &uid_cfg); | |
100 | if (STP_OK != iii) { | |
101 | printf ("FATAL: can't enable:%s\n", | |
102 | STP_IN_get_error_explanation (iii)); | |
103 | return (-1); | |
104 | } | |
105 | return 0; | |
106 | } | |
107 | ||
108 | void bridge_shutdown (void) | |
109 | { | |
110 | UID_MSG_T msg; | |
111 | int rc; | |
112 | ||
113 | /* send SHUTDOWN */ | |
114 | msg.header.sender_pid = my_pid; | |
115 | msg.header.cmd_type = UID_CNTRL; | |
116 | msg.body.cntrl.cmd = UID_BRIDGE_SHUTDOWN; | |
117 | UiD_SocketSendto (&uid_socket, &msg, sizeof (UID_MSG_T)); | |
118 | ||
119 | rc = STP_IN_stpm_delete (0); | |
120 | if (STP_OK != rc) { | |
121 | printf ("FATAL: can't delete:%s\n", | |
122 | STP_IN_get_error_explanation (rc)); | |
123 | exit (1); | |
124 | } | |
125 | } | |
126 | ||
127 | char *get_prompt (void) | |
128 | { | |
129 | static char prompt[MAX_CLI_PROMT]; | |
130 | snprintf (prompt, MAX_CLI_PROMT - 1, "%s B%ld > ", UT_sprint_time_stamp(), my_pid); | |
131 | return prompt; | |
132 | } | |
133 | ||
134 | int bridge_control (int port_index, | |
135 | UID_CNTRL_BODY_T* cntrl) | |
136 | { | |
137 | switch (cntrl->cmd) { | |
138 | case UID_PORT_CONNECT: | |
139 | printf ("connected port p%02d\n", port_index); | |
140 | BitmapSetBit(&enabled_ports, port_index - 1); | |
141 | STP_IN_enable_port (port_index, True); | |
142 | break; | |
143 | case UID_PORT_DISCONNECT: | |
144 | printf ("disconnected port p%02d\n", port_index); | |
145 | BitmapClearBit(&enabled_ports, port_index - 1); | |
146 | STP_IN_enable_port (port_index, False); | |
147 | break; | |
148 | case UID_BRIDGE_SHUTDOWN: | |
149 | printf ("shutdown from manager :(\n"); | |
150 | return 1; | |
151 | default: | |
152 | printf ("Unknown control command <%d> for port %d\n", | |
153 | cntrl->cmd, port_index); | |
154 | } | |
155 | return 0; | |
156 | } | |
157 | ||
158 | int bridge_rx_bpdu (UID_MSG_T* msg, size_t msgsize) | |
159 | { | |
160 | register int port_index; | |
161 | ||
162 | if (I_am_a_stupid_hub) { // flooding | |
163 | msg->header.sender_pid = my_pid; | |
164 | for (port_index = 1; port_index <= NUMBER_OF_PORTS; port_index++) { | |
165 | if (BitmapGetBit (&enabled_ports, (port_index - 1)) && | |
166 | msg->header.destination_port != port_index) { | |
167 | msg->header.source_port = port_index; | |
168 | UiD_SocketSendto (&uid_socket, msg, msgsize); | |
169 | } | |
170 | } | |
171 | } else { | |
172 | STP_IN_rx_bpdu (0, msg->header.destination_port, | |
173 | (BPDU_T*) (msg->body.bpdu + sizeof (MAC_HEADER_T)), | |
174 | msg->header.body_len - sizeof (MAC_HEADER_T)); | |
175 | } | |
176 | return 0; | |
177 | } | |
178 | ||
179 | char read_uid (UID_SOCKET_T* uid_sock) | |
180 | { | |
181 | char buff[MAX_UID_MSG_SIZE]; | |
182 | UID_MSG_T* msg; | |
183 | size_t msgsize; | |
184 | int rc; | |
185 | ||
186 | msgsize = UiD_SocketRecvfrom (uid_sock, buff, MAX_UID_MSG_SIZE, 0); | |
187 | if (msgsize <= 0) { | |
188 | printf ("Something wrong in UIF ?\n"); | |
189 | return 0; | |
190 | } | |
191 | ||
192 | msg = (UID_MSG_T*) buff; | |
193 | switch (msg->header.cmd_type) { | |
194 | case UID_CNTRL: | |
195 | rc = bridge_control (msg->header.destination_port, | |
196 | &msg->body.cntrl); | |
197 | break; | |
198 | case UID_BPDU: | |
199 | rc = bridge_rx_bpdu (msg, msgsize); | |
200 | break; | |
201 | default: | |
202 | printf ("Unknown message type %d\n", (int) msg->header.cmd_type); | |
203 | rc = 0; | |
204 | } | |
205 | ||
206 | return rc; | |
207 | } | |
208 | ||
209 | char shutdown_flag = 0; | |
210 | ||
211 | int main_loop (void) | |
212 | { | |
213 | fd_set readfds; | |
214 | struct timeval tv; | |
215 | struct timeval now, earliest; | |
216 | int rc, numfds, sock, kkk; | |
217 | ||
218 | ||
219 | sock = GET_FILE_DESCRIPTOR(&uid_socket); | |
220 | ||
221 | gettimeofday (&earliest, NULL); | |
222 | earliest.tv_sec++; | |
223 | ||
224 | do { | |
225 | numfds = -1; | |
226 | FD_ZERO(&readfds); | |
227 | ||
228 | kkk = 0; /* stdin for commands */ | |
229 | FD_SET(kkk, &readfds); | |
230 | if (kkk > numfds) numfds = kkk; | |
231 | ||
232 | FD_SET(sock, &readfds); | |
233 | if (sock > numfds) numfds = sock; | |
234 | ||
235 | if (numfds < 0) | |
236 | numfds = 0; | |
237 | else | |
238 | numfds++; | |
239 | ||
240 | gettimeofday (&now, 0); | |
241 | tv.tv_usec = 0; | |
242 | tv.tv_sec = 0; | |
243 | ||
244 | if (now.tv_sec < earliest.tv_sec) { /* we must wait more than 1 sec. */ | |
245 | tv.tv_sec = 1; | |
246 | tv.tv_usec = 0; | |
247 | } else if (now.tv_sec == earliest.tv_sec) { | |
248 | if (now.tv_usec < earliest.tv_usec) { | |
249 | if (earliest.tv_usec < now.tv_usec) | |
250 | tv.tv_usec = 0; | |
251 | else | |
252 | tv.tv_usec = earliest.tv_usec - now.tv_usec; | |
253 | } | |
254 | } | |
255 | ||
256 | //printf ("wait %ld-%ld\n", (long) tv.tv_sec, (long) tv.tv_usec); | |
257 | rc = select (numfds, &readfds, NULL, NULL, &tv); | |
258 | if (rc < 0) { // Error | |
259 | if (EINTR == errno) continue; // don't break | |
260 | printf ("FATAL_MODE:select failed: %s\n", strerror(errno)); | |
261 | return -2; | |
262 | } | |
263 | ||
264 | if (! rc) { // Timeout expired | |
265 | STP_IN_one_second (); | |
266 | gettimeofday (&earliest, NULL); | |
267 | //printf ("tick %ld-%ld\n", (long) earliest.tv_sec - 1005042800L, (long) earliest.tv_usec); | |
268 | ||
269 | earliest.tv_sec++; | |
270 | continue; | |
271 | } | |
272 | ||
273 | if (FD_ISSET(0, &readfds)) { | |
274 | rl_callback_read_char (); | |
275 | } | |
276 | ||
277 | if (FD_ISSET(sock, &readfds)) { | |
278 | shutdown_flag |= read_uid (&uid_socket); | |
279 | } | |
280 | ||
281 | } while(! shutdown_flag); | |
282 | return 0; | |
283 | } | |
284 | ||
285 | int main (int argc, char** argv) | |
286 | { | |
287 | rl_init (); | |
288 | ||
289 | my_pid = getpid(); | |
290 | printf ("my pid: %ld\n", my_pid); | |
291 | ||
292 | if (0 == bridge_start ()) { | |
293 | main_loop (); | |
294 | } | |
295 | ||
296 | bridge_shutdown (); | |
297 | ||
298 | rl_shutdown (); | |
299 | ||
300 | return 0; | |
301 | } | |
302 | ||
303 | char* sprint_time_stump (void) | |
304 | { | |
305 | return UT_sprint_time_stamp(); | |
306 | } | |
307 |