bridge.c
上传用户:allwinjm
上传日期:2021-08-29
资源大小:99k
文件大小:8k
源码类别:

Internet/IE编程

开发平台:

Unix_Linux

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