]> git.ipfire.org Git - people/ms/rstp.git/commitdiff
Use new RSTP library.
authorSrinivas Aji <Aji_Srinivas@emc.com>
Thu, 29 Nov 2007 20:34:32 +0000 (02:04 +0530)
committerSrinivas Aji <Aji_Srinivas@emc.com>
Wed, 27 Feb 2008 18:03:50 +0000 (23:33 +0530)
   This is a somewhat big commit which replaces the use of RSTPLIB in the
   RSTP daemon by the new RSTP library. This makes the daemon much more
   compliant with the 802.1D-2004 standard. The control program, rstpctl,
   has been modified so its output closer to the output of brctl showstp.

Signed-off-by: Srinivas Aji <Aji_Srinivas@emc.com>
12 files changed:
Makefile
bridge_track.c
ctl_cli_wrap.c
ctl_functions.h
ctl_main.c
ctl_socket.c
ctl_socket.h
ctl_socket_client.c
ctl_socket_client.h
ctl_socket_server.h
log.h
rstpctl.8

index 4840a00cfbc6162d96949de426b09a0a8f04f3b5..c65dd39c2ffbba73c540d76931bda99536926c1f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 
-DSOURCES =  brstate.c libnetlink.c epoll_loop.c bridge_track.c \
+DSOURCES =  brstate.c libnetlink.c epoll_loop.c bridge_track.c rstp.c \
           packet.c ctl_socket.c netif_utils.c main.c brmon.c
 
 DOBJECTS = $(DSOURCES:.c=.o)
@@ -9,24 +9,18 @@ CTLSOURCES = ctl_main.c ctl_cli_wrap.c ctl_socket_client.c
 CTLOBJECTS = $(CTLSOURCES:.c=.o)
 
 CC=gcc
-CFLAGS = -Wall -Werror -O2 -g -D_REENTRANT -D__LINUX__ -DVERSION=$(version) -DBUILD=$(build) -I. -I./include -I./rstplib
+CFLAGS = -Wall -Werror -O2 -g -D_REENTRANT -D__LINUX__ -DVERSION=$(version) -DBUILD=$(build) -I. -I./include
 
 all: rstpd rstpctl
 
-rstplib:
-       make -C rstplib librstp.a
-
-.PHONY: rstplib
-
-rstpd: $(DOBJECTS) rstplib
-       $(CC) -o $@ $(DOBJECTS) -L ./rstplib -lrstp
+rstpd: $(DOBJECTS)
+       $(CC) -o $@ $(DOBJECTS)
 
 rstpctl: $(CTLOBJECTS)
        $(CC) -o $@ $(CTLOBJECTS)
 
 clean:
        rm -f *.o rstpd rstpctl
-       make -C rstplib clean
        rm -fr $(TOPDIR) $(BUILDDIR)
 
 install: all
@@ -38,7 +32,7 @@ install: all
        install -m 644 rstpctl.8 $(INSTALLPREFIX)/usr/share/man/man8
 
 # RPM Building, as non root
-version := 0.16
+version := 0.21
 build := 1
 
 BUILDROOT := $(CURDIR)/rpm_buildroot
index cd84cd9f79e18a4e7fb8e1d292fdab605e3a1b7f..e93c014f5e7c1b6cb5dcaf4bc500bcb234e3b6fe 100644 (file)
 #include <arpa/inet.h>
 #include <sys/types.h>
 
-#include <bitmap.h>
-#include <uid_stp.h>
-#include <stp_bpdu.h>
-#include <stp_in.h>
-#include <stp_to.h>
-
 #include <stdio.h>
 #include <string.h>
 
 #include "log.h"
 
+#include "rstp.h"
 /*------------------------------------------------------------*/
 
 struct ifdata {
@@ -60,16 +55,8 @@ struct ifdata {
        struct ifdata *port_list;
        int do_stp;
        int stp_up;
-       struct stp_instance *stp;
-       UID_BRIDGE_ID_T bridge_id;
-       /* Bridge config */
-       UID_STP_MODE_T stp_enabled;
-       int bridge_priority;
-       int max_age;
-       int hello_time;
-       int forward_delay;
-       int force_version;
-       int hold_time;
+       STP_Bridge *stp_bridge;
+
 
        /* If port */
        int speed;
@@ -78,12 +65,7 @@ struct ifdata {
        struct ifdata *port_next;
        /* STP port index */
        int port_index;
-       /* STP port config */
-       int port_priority;
-       int admin_port_path_cost;
-       ADMIN_P2P_T admin_point2point;
-       unsigned char admin_edge;
-       unsigned char admin_non_stp;    /* 1- doesn't participate in STP, 1 - regular */
+       STP_Port *stp_port;
 
        struct epoll_event_handler event;
 };
@@ -91,22 +73,6 @@ struct ifdata {
 /* Instances */
 struct ifdata *current_br = NULL;
 
-void instance_begin(struct ifdata *br)
-{
-       if (current_br) {
-               ERROR("BUG: Trying to set instance over existing instance.");
-               ERROR("%d", *(int *)0); /* ABORT */
-       }
-       current_br = br;
-       STP_IN_instance_begin(br->stp);
-}
-
-void instance_end(void)
-{
-       STP_IN_instance_end(current_br->stp);
-       current_br = NULL;
-}
-
 struct ifdata *find_port(int port_index)
 {
        struct ifdata *ifc = current_br->port_list;
@@ -115,170 +81,6 @@ struct ifdata *find_port(int port_index)
        return ifc;
 }
 
-/*************************************************************/
-/* Bridge and port defaults */
-
-UID_STP_CFG_T default_bridge_stp_cfg = {
-       .field_mask = BR_CFG_ALL,
-       .bridge_priority = DEF_BR_PRIO,
-       .max_age = DEF_BR_MAXAGE,
-       .hello_time = DEF_BR_HELLOT,
-       .forward_delay = DEF_BR_FWDELAY,
-       .force_version = DEF_FORCE_VERS,        /*NORMAL_RSTP */
-};
-
-void update_bridge_stp_config(struct ifdata *br, UID_STP_CFG_T * cfg)
-{
-       if (cfg->field_mask & BR_CFG_PRIO)
-               br->bridge_priority = cfg->bridge_priority;
-       if (cfg->field_mask & BR_CFG_AGE)
-               br->max_age = cfg->max_age;
-       if (cfg->field_mask & BR_CFG_HELLO)
-               br->hello_time = cfg->hello_time;
-       if (cfg->field_mask & BR_CFG_DELAY)
-               br->forward_delay = cfg->forward_delay;
-       if (cfg->field_mask & BR_CFG_FORCE_VER)
-               br->force_version = cfg->force_version;
-}
-
-UID_STP_PORT_CFG_T default_port_stp_cfg = {
-       .field_mask = PT_CFG_ALL,
-       .port_priority = DEF_PORT_PRIO,
-       .admin_non_stp = DEF_ADMIN_NON_STP,
-       .admin_edge = False,    // DEF_ADMIN_EDGE,
-       .admin_port_path_cost = ADMIN_PORT_PATH_COST_AUTO,
-       .admin_point2point = DEF_P2P,
-};
-
-void update_port_stp_config(struct ifdata *ifc, UID_STP_PORT_CFG_T * cfg)
-{
-       if (cfg->field_mask & PT_CFG_PRIO)
-               ifc->port_priority = cfg->port_priority;
-       if (cfg->field_mask & PT_CFG_NON_STP)
-               ifc->admin_non_stp = cfg->admin_non_stp;
-       if (cfg->field_mask & PT_CFG_EDGE)
-               ifc->admin_edge = cfg->admin_edge;
-       if (cfg->field_mask & PT_CFG_COST)
-               ifc->admin_port_path_cost = cfg->admin_port_path_cost;
-       if (cfg->field_mask & PT_CFG_P2P)
-               ifc->admin_point2point = cfg->admin_point2point;
-}
-
-/**************************************************************/
-
-int add_port_stp(struct ifdata *ifc)
-{                              /* Bridge is ifc->master */
-       TST((ifc->port_index = get_bridge_portno(ifc->name)) >= 0, -1);
-
-       /* Add port to STP */
-       instance_begin(ifc->master);
-       int r = STP_IN_port_create(0, ifc->port_index);
-       if (r == 0) {           /* Update bridge ID */
-               UID_STP_STATE_T state;
-               STP_IN_stpm_get_state(0, &state);
-               ifc->master->bridge_id = state.bridge_id;
-       }
-       instance_end();
-       if (r /* check for failure */ ) {
-               ERROR("Couldn't add port for ifindex %d to STP", ifc->if_index);
-               return -1;
-       }
-       return 0;
-}
-
-void remove_port_stp(struct ifdata *ifc)
-{
-       /* Remove port from STP */
-       instance_begin(ifc->master);
-       int r = STP_IN_port_delete(0, ifc->port_index);
-       instance_end();
-       ifc->port_index = -1;
-       if (r != 0) {
-               ERROR("removing port %s failed for bridge %s: %s",
-                     ifc->name, ifc->master->name,
-                     STP_IN_get_error_explanation(r));
-       }
-}
-
-int init_rstplib_instance(struct ifdata *br)
-{
-       br->stp = STP_IN_instance_create();
-       if (br->stp == NULL) {
-               ERROR("Couldn't create STP instance for bridge %s", br->name);
-               return -1;
-       }
-
-       BITMAP_T ports;
-       BitmapClear(&ports);
-       instance_begin(br);
-       int r = STP_IN_stpm_create(0, br->name, &ports);
-       instance_end();
-       if (r != 0) {
-               ERROR("stpm create failed for bridge %s: %s",
-                     br->name, STP_IN_get_error_explanation(r));
-               return -1;
-       }
-
-       return 0;
-}
-
-void clear_rstplib_instance(struct ifdata *br)
-{
-       instance_begin(br);
-       int r = STP_IN_delete_all();
-       instance_end();
-       if (r != 0) {
-               ERROR("stpm delete failed for bridge %s: %s",
-                     br->name, STP_IN_get_error_explanation(r));
-       }
-
-       STP_IN_instance_delete(br->stp);
-       br->stp = NULL;
-}
-
-int init_bridge_stp(struct ifdata *br)
-{
-       if (br->stp_up) {
-               ERROR("STP already started");
-               return 0;
-       }
-
-       /* Init STP state */
-       TST(init_rstplib_instance(br) == 0, -1);
-
-       struct ifdata *p = br->port_list;
-       while (p) {
-               if (add_port_stp(p) != 0)
-                       break;
-               p = p->port_next;
-       }
-       if (p) {
-               struct ifdata *q = br->port_list;
-               while (q != p) {
-                       remove_port_stp(q);
-                       q = q->port_next;
-               }
-               /* Clear bridge STP state */
-               clear_rstplib_instance(br);
-               return -1;
-       }
-       br->stp_up = 1;
-       return 0;
-}
-
-void clear_bridge_stp(struct ifdata *br)
-{
-       if (!br->stp_up)
-               return;
-       br->stp_up = 0;
-       struct ifdata *p = br->port_list;
-       while (p) {
-               remove_port_stp(p);
-               p = p->port_next;
-       }
-       /* Clear bridge STP state */
-       clear_rstplib_instance(br);
-}
 
 struct ifdata *if_head = NULL;
 struct ifdata *br_head = NULL;
@@ -327,15 +129,26 @@ struct ifdata *create_if(int if_index, struct ifdata *br)
 
        if (p->is_bridge) {
                INFO("Add bridge %s", p->name);
+               p->stp_bridge = STP_IN_bridge_create(p);
+               if (!p->stp_bridge) {
+                       ERROR("Couldn't create STP Bridge");
+                       free(p);
+                       return NULL;
+               }
+               STP_IN_set_bridge_address(p->stp_bridge,
+                                         (STP_MacAddress *)p->macaddr);
+               INFO("Set bridge address %s to %02x:%02x:%02x:%02x:%02x:%02x",
+                     p->name,
+                     p->macaddr[0], p->macaddr[1], p->macaddr[2],
+                     p->macaddr[1], p->macaddr[4], p->macaddr[5]
+                     );
                /* Init slave list */
                p->port_list = NULL;
 
                p->do_stp = 0;
                p->up = 0;
                p->stp_up = 0;
-               p->stp = NULL;
-               update_bridge_stp_config(p, &default_bridge_stp_cfg);
-               ADD_TO_LIST(br_head, bridge_next, p);   /* Add to bridge list */
+               ADD_TO_LIST(br_head, bridge_next, p);  /* Add to bridge list */
        } else {
                INFO("Add iface %s to bridge %s", p->name, br->name);
                p->up = 0;
@@ -343,12 +156,22 @@ struct ifdata *create_if(int if_index, struct ifdata *br)
                p->duplex = 0;
                p->master = br;
 
-               update_port_stp_config(p, &default_port_stp_cfg);
+               p->port_index = get_bridge_portno(p->name);
+               if (p->port_index < 0) {
+                       ERROR("Couldn't get port number for %s", p->name);
+                       free(p);
+                       return NULL;
+               }
+               p->stp_port = STP_IN_port_create(p->master->stp_bridge,
+                                                p->port_index, p);
+               if (!p->stp_port) {
+                       ERROR("Couldn't create STP Port");
+                       free(p);
+                       return NULL;
+               }
+
                ADD_TO_LIST(br->port_list, port_next, p);       /* Add to bridge port list */
 
-               if (br->stp_up) {
-                       add_port_stp(p);
-               }
        }
 
        /* Add to interface list */
@@ -361,8 +184,7 @@ void delete_if(struct ifdata *ifc)
 {
        INFO("Delete iface %s", ifc->name);
        if (ifc->is_bridge) {   /* Bridge: */
-               /* Stop STP */
-               clear_bridge_stp(ifc);
+               STP_IN_set_bridge_enable(ifc->stp_bridge, 0);
                /* Delete ports */
                while (ifc->port_list)
                        delete_if(ifc->port_list);
@@ -370,13 +192,13 @@ void delete_if(struct ifdata *ifc)
                REMOVE_FROM_LIST(br_head, bridge_next, ifc,
                                 "Can't find interface ifindex %d bridge list",
                                 ifc->if_index);
+               STP_IN_bridge_delete(ifc->stp_bridge);
        } else {                /* Port */
-               if (ifc->master->stp_up)
-                       remove_port_stp(ifc);
                /* Remove from bridge port list */
                REMOVE_FROM_LIST(ifc->master->port_list, port_next, ifc,
                                 "Can't find interface ifindex %d on br %d's port list",
                                 ifc->if_index, ifc->master->if_index);
+               STP_IN_port_delete(ifc->stp_port);
        }
 
        /* Remove from bridge interface list */
@@ -392,6 +214,7 @@ static int check_mac_address(char *name, unsigned char *addr)
 {
        unsigned char temp_addr[6];
        if (get_hwaddr(name, temp_addr)) {
+               LOG("Error getting hw address: %s", name);
                /* Error. Ignore the new value */
                return 0;
        }
@@ -424,26 +247,32 @@ static int stp_enabled(struct ifdata *br)
 void set_br_up(struct ifdata *br, int up)
 {
        int stp_up = stp_enabled(br);
-       INFO("%s was %s stp was %s", br->name,up ? "up" : "down", br->stp_up ? "up" : "down");
+       INFO("%s was %s stp was %s", br->name, br->up ? "up" : "down", br->stp_up ? "up" : "down");
        INFO("Set bridge %s %s stp %s" , br->name,
             up ? "up" : "down", stp_up ? "up" : "down");
 
-       if (up != br->up)
+       int changed = 0;
+
+       if (up != br->up) {
                br->up = up;
+               changed = 1;
+       }
        
+       if (br->stp_up != stp_up) {
+               br->stp_up = stp_up;
+               changed = 1;
+       }
+
        if (check_mac_address(br->name, br->macaddr)) {
                /* MAC address changed */
-               if (br->stp_up && stp_up) {
-                       /* Notify bridge address change */
-               }
+               /* Notify bridge address change */
+               STP_IN_set_bridge_address(
+                       br->stp_bridge, (STP_MacAddress *)br->macaddr);
        }
 
-       if (br->stp_up != stp_up) {
-               if (stp_up)
-                       init_bridge_stp(br);
-               else 
-                       clear_bridge_stp(br);
-       }
+       if (changed)
+               STP_IN_set_bridge_enable(br->stp_bridge,
+                                        (br->up && br->stp_up)?1:0);
 }
 
 void set_if_up(struct ifdata *ifc, int up)
@@ -451,21 +280,23 @@ void set_if_up(struct ifdata *ifc, int up)
        INFO("Port %s : %s", ifc->name, (up ? "up" : "down"));
        int speed = -1;
        int duplex = -1;
-       int notify_flags = 0;
-       const int NOTIFY_UP = 1, NOTIFY_SPEED = 2, NOTIFY_DUPLEX = 4;
+       int changed = 0;
 
        if (check_mac_address(ifc->name, ifc->macaddr)) {
                /* MAC address changed */
                if (check_mac_address(ifc->master->name, ifc->master->macaddr)
-                       && ifc->master->stp_up) {
+                       ) {
                        /* Notify bridge address change */
+                       STP_IN_set_bridge_address(
+                               ifc->master->stp_bridge,
+                               (STP_MacAddress *)ifc->master->macaddr);
                }
        }
 
        if (!up) {              /* Down */
                if (ifc->up) {
                        ifc->up = up;
-                       notify_flags |= NOTIFY_UP;
+                       changed = 1;
                }
        } else {                /* Up */
                int r = ethtool_get_speed_duplex(ifc->name, &speed, &duplex);
@@ -478,29 +309,20 @@ void set_if_up(struct ifdata *ifc, int up)
 
                if (speed != ifc->speed) {
                        ifc->speed = speed;
-                       notify_flags |= NOTIFY_SPEED;
+                       changed = 1;
                }
                if (duplex != ifc->duplex) {
                        ifc->duplex = duplex;
-                       notify_flags |= NOTIFY_DUPLEX;
+                       changed = 1;
                }
                if (!ifc->up) {
                        ifc->up = 1;
-                       notify_flags |= NOTIFY_UP;
+                       changed = 1;
                }
        }
-       if (notify_flags && ifc->master->stp_up) {
-               instance_begin(ifc->master);
-
-               if (notify_flags & NOTIFY_SPEED)
-                       STP_IN_changed_port_speed(ifc->port_index, speed);
-               if (notify_flags & NOTIFY_DUPLEX)
-                       STP_IN_changed_port_duplex(ifc->port_index);
-               if (notify_flags & NOTIFY_UP)
-                       STP_IN_enable_port(ifc->port_index, ifc->up);
-
-               instance_end();
-       }
+       if (changed)
+               STP_IN_set_port_enable(ifc->stp_port,
+                                      ifc->up, ifc->speed, ifc->duplex);
 }
 
 /*------------------------------------------------------------*/
@@ -509,7 +331,8 @@ int bridge_notify(int br_index, int if_index, int newlink, int up)
 {
        if (up)
                up = 1;
-       LOG("br_index %d, if_index %d, up %d", br_index, if_index, up);
+       LOG("br_index %d, if_index %d, newlink %d, up %d",
+               br_index, if_index, newlink, up);
 
        struct ifdata *br = NULL;
        if (br_index >= 0) {
@@ -528,7 +351,7 @@ int bridge_notify(int br_index, int if_index, int newlink, int up)
                        return -1;
                }
                /* Bridge must be up if we get such notifications */
-               set_br_up(br, 1);
+               // Not true anymore - set_br_up(br, 1);
        }
 
        struct ifdata *ifc = find_if(if_index);
@@ -619,14 +442,14 @@ const unsigned char STP_SAP = 0x42;
 void bridge_bpdu_rcv(int if_index, const unsigned char *data, int len)
 {
        struct ifdata *ifc = find_if(if_index);
-       BPDU_T *bpdu;
 
        LOG("ifindex %d, len %d", if_index, len);
        if (!ifc)
                return;
 
        TST(ifc->up,);
-       TST(ifc->master->stp_up,);
+       if (!ifc->master->stp_up)
+               return;
 
        /* Validate Ethernet and LLC header */
        {
@@ -635,48 +458,19 @@ void bridge_bpdu_rcv(int if_index, const unsigned char *data, int len)
                TST(len > sizeof(struct llc_header),);
                h = (struct llc_header *)data;
                TST(memcmp(h->dest_addr, bridge_group_address, ETH_ALEN) == 0,
-                       );
+                    INFO("ifindex %d, len %d, %02x:%02x:%02x:%02x:%02x:%02x",
+                         if_index, len,
+                         h->dest_addr[0],h->dest_addr[1],h->dest_addr[2],
+                         h->dest_addr[3],h->dest_addr[4],h->dest_addr[5]));
                l = ntohs(h->len8023);
                TST(l <= ETH_DATA_LEN && l <= len - ETH_HLEN && l >= 3,);
                TST(h->d_sap == STP_SAP && h->s_sap == STP_SAP
                    && (h->llc_ui & 0x3) == 0x3 /* LLC UI */,);
-               /* BPDU_T includes ETH_HEADER_T, i.e. {d_sap, s_sap, llc_ui} */
-               bpdu = (BPDU_T *)(data + sizeof(*h) - sizeof(ETH_HEADER_T));
-               len = l + 2; /* ETH_HEADER_T includes the 2 bytes of len8023 */
-       }
-
-       TST(len > sizeof(ETH_HEADER_T) + sizeof(BPDU_HEADER_T),);
 
-       /* Do some BPDU validation as per 9.3.4 of standard */
-       if (bpdu->hdr.protocol[0] || bpdu->hdr.protocol[1])
-               return;
-
-       switch (bpdu->hdr.bpdu_type) {
-       case BPDU_RSTP:
-               TST(len >= sizeof(ETH_HEADER_T) + 36,);
-       case BPDU_CONFIG_TYPE:
-               TST(len >= sizeof(ETH_HEADER_T) + 35,);
-               /* 802.1w doesn't ask for this */
-               //    TST(ntohs(*(uint16_t*)bpdu.body.message_age)
-               //        < ntohs(*(uint16_t*)bpdu.body.max_age), );
-               TST(memcmp(bpdu->body.bridge_id, &ifc->master->bridge_id, 8) != 0
-                   || (ntohs(*(uint16_t *) bpdu->body.port_id) & 0xfff) !=
-                   ifc->port_index,);
-               break;
-       case BPDU_TOPO_CHANGE_TYPE:
-               break;
-       default:
-               LOG("Receive unknown bpdu type %x", bpdu->hdr.bpdu_type);
-               return;
+               STP_IN_rx_bpdu(ifc->stp_port,
+                              /* Don't include LLC header */
+                              data + sizeof(*h), l - 3);
        }
-
-       // dump_hex(data, len);
-       instance_begin(ifc->master);
-       int r = STP_IN_rx_bpdu(0, ifc->port_index, bpdu, len);
-       if (r)
-               ERROR("STP_IN_rx_bpdu on port %s returned %s", ifc->name,
-                     STP_IN_get_error_explanation(r));
-       instance_end();
 }
 
 void bridge_one_second(void)
@@ -684,20 +478,8 @@ void bridge_one_second(void)
        //  LOG("");
        struct ifdata *br;
        for (br = br_head; br; br = br->bridge_next) {
-               if (br->stp_up) {
-                       instance_begin(br);
-                       STP_IN_one_second();
-                       instance_end();
-               }
+               STP_IN_one_second(br->stp_bridge);
        }
-
-       /* To get information about port changes when bridge is down */
-       /* But won't work so well since we will not sense deletions */
-       static int count = 0;
-       count++;
-       if (count % 60 == 0)
-               bridge_get_configuration();
-
 }
 
 /* Implementing STP_OUT functions */
@@ -712,203 +494,121 @@ int flush_port(char *sys_name)
        return 0;
 }
 
-int
-STP_OUT_flush_lt(IN int port_index, IN int vlan_id,
-                IN LT_FLASH_TYPE_T type, IN char *reason)
+void STP_OUT_port_fdb_flush(void *user_ref)
 {
-       LOG("port index %d, flash type %d, reason %s", port_index, type,
-           reason);
-       TST(vlan_id == 0, 0);
-
+       struct ifdata *port = user_ref;
        char fname[128];
-       if (port_index == 0) {  /* i.e. passed port_index was 0 */
-               sprintf(fname, "/sys/class/net/%s/bridge/flush",
-                       current_br->name);
-               flush_port(fname);
-       } else if (type == LT_FLASH_ONLY_THE_PORT) {
-               struct ifdata *port = find_port(port_index);
-               TST(port != NULL, 0);
-               sprintf(fname, "/sys/class/net/%s/brif/%s/flush",
-                       current_br->name, port->name);
-               flush_port(fname);
-       } else if (type == LT_FLASH_ALL_PORTS_EXCLUDE_THIS) {
-               struct ifdata *port;
-               for (port = current_br->port_list; port; port = port->port_next) {
-                       if (port->port_index != port_index) {
-                               sprintf(fname,
-                                       "/sys/class/net/%s/brif/%s/flush",
-                                       current_br->name, port->name);
-                               flush_port(fname);
-                       }
-               }
-       } else
-               TST(0, 0);
-
-       return 0;
-}
-
-void /* for bridge id calculation */ STP_OUT_get_port_mac(IN int port_index,
-                                                         OUT unsigned char
-                                                         *mac)
-{
-       LOG("port index %d", port_index);
-       struct ifdata *port = find_port(port_index);
-       TST(port != NULL,);
-       memcpy(mac, port->macaddr, sizeof(port->macaddr));
-}
-
-unsigned long STP_OUT_get_port_oper_speed(IN unsigned int port_index)
-{
-       LOG("port index %d", port_index);
-       struct ifdata *port = find_port(port_index);
-       TST(port != NULL, 0);
-       LOG("Speed: %d", port->speed);
-       return port->speed;
+       snprintf(fname, sizeof(fname),
+                "/sys/class/net/%s/brport/flush", port->name);
+       fname[sizeof(fname) - 1] = 0;
+       TST(flush_port(fname) == 0,);
 }
 
-int /* 1- Up, 0- Down */ STP_OUT_get_port_link_status(IN int port_index)
+void STP_OUT_port_set_state(void *user_ref, unsigned int flags)
 {
-       LOG("port index %d", port_index);
-       struct ifdata *port = find_port(port_index);
-       TST(port != NULL, 0);
-       LOG("Link status: %d", port->up);
-       return port->up;
-}
-
-int /* 1- Full, 0- Half */ STP_OUT_get_duplex(IN int port_index)
-{
-       LOG("port index %d", port_index);
-       struct ifdata *port = find_port(port_index);
-       TST(port != NULL, 0);
-       LOG("Duplex: %d", port->duplex);
-       return port->duplex;
-}
-
-int
-STP_OUT_set_port_state(IN int port_index, IN int vlan_id,
-                      IN RSTP_PORT_STATE state)
-{
-       LOG("port index %d, state %d", port_index, state);
-       struct ifdata *port = find_port(port_index);
-       TST(port != NULL, 0);
-       TST(vlan_id == 0, 0);
-
+       struct ifdata *port = user_ref;
        int br_state;
-       switch (state) {
-       case UID_PORT_DISCARDING:
-               br_state = BR_STATE_BLOCKING;
-               break;
-       case UID_PORT_LEARNING:
-               br_state = BR_STATE_LEARNING;
-               break;
-       case UID_PORT_FORWARDING:
+       
+       LOG("port index %d, flags %d", port->if_index, flags);
+       
+       if (flags & STP_PORT_STATE_FLAG_FORWARDING)
                br_state = BR_STATE_FORWARDING;
-               break;
-       default:
-               fprintf(stderr, "set_port_state: Unexpected state %d\n", state);
-               return -1;
-       }
+       else if (flags & STP_PORT_STATE_FLAG_LEARNING)
+               br_state = BR_STATE_LEARNING;
+       else
+               br_state = BR_STATE_BLOCKING;
+       
        if (port->up)
                bridge_set_state(port->if_index, br_state);
-       return 0;
 }
 
-int STP_OUT_set_hardware_mode(int vlan_id, UID_STP_MODE_T mode)
-{
-       LOG("vlan id %d, mode %d", vlan_id, mode);
-       return 0;
-}
 
-int
-STP_OUT_tx_bpdu(IN int port_index, IN int vlan_id,
-               IN unsigned char *bpdu, IN size_t bpdu_len)
+void STP_OUT_tx_bpdu(void *port_user_ref, void *base, unsigned int len)
 {
-       LOG("port index %d, len %zd", port_index, bpdu_len);
-       struct ifdata *port = find_port(port_index);
-       TST(port != NULL, 0);
-       TST(vlan_id == 0, 0);
+       struct ifdata *port = port_user_ref;
+
+       LOG("port index %d, len %d", port->if_index, len);
 
        struct llc_header h;
        memcpy(h.dest_addr, bridge_group_address, ETH_ALEN);
        memcpy(h.src_addr, port->macaddr, ETH_ALEN);
        /* bpdu_len excludes MAC and LLC headers */
-       h.len8023 = htons(bpdu_len + 3);
+       h.len8023 = htons(len + 3);
        h.d_sap = h.s_sap = STP_SAP;
-       h.llc_ui = 0x03;          /* LLC UI packet */
+       h.llc_ui = 0x03; /* LLC UI packet */
 
        struct iovec iov[2] = {
                { .iov_base = &h, .iov_len = sizeof(h) },
-               { .iov_base = bpdu + sizeof(h), .iov_len = bpdu_len }
+               { .iov_base = base, .iov_len = len }
        };
 
-       packet_send(port->if_index, iov, 2, sizeof(h) + bpdu_len);
-       return 0;
+       packet_send(port->if_index, iov, 2, sizeof(h) + len);
 }
 
-const char *STP_OUT_get_port_name(IN int port_index)
-{
-       LOG("port index %d", port_index);
-       struct ifdata *port = find_port(port_index);
-       TST(port != NULL, 0);
-       return port->name;
-}
 
-int STP_OUT_get_init_stpm_cfg(IN int vlan_id, INOUT UID_STP_CFG_T * cfg)
+void STP_OUT_logmsg(void *br_user_ref, void *port_user_ref,
+                   int level, char *fmt, ...)
 {
-       LOG("");
-       TST(vlan_id == 0, 0);
-
-       cfg->bridge_priority = current_br->bridge_priority;
-       cfg->max_age = current_br->max_age;
-       cfg->hello_time = current_br->hello_time;
-       cfg->forward_delay = current_br->forward_delay;
-       cfg->force_version = current_br->force_version;
+       struct ifdata *bridge = br_user_ref;
+       struct ifdata *port = port_user_ref;
+       char buf[256];
+       int r;
+       int ll = (level < STP_LOG_LEVEL_DEBUG) ?
+               LOG_LEVEL_INFO : LOG_LEVEL_DEBUG;
+        struct timeval tv;
+        gettimeofday(&tv, NULL);
+       r = snprintf(buf, sizeof(buf), "LOG Level %d:%s:%s: %02d.%03d: ",
+                     level,
+                    (bridge?bridge->name:""), (port?port->name:""),
+                     (int)tv.tv_sec % 60, (int)tv.tv_usec / 1000);
+       if (r >= sizeof(buf)) {
+               buf[sizeof(buf) - 1] = 0;
+               Dprintf(ll, "%s", buf);
+               r = 0;
+       }
 
-       return 0;
+       va_list ap;
+       va_start(ap, fmt);
+       vsnprintf(buf + r, sizeof(buf) - r, fmt, ap);
+       buf[sizeof(buf) - 1] = 0;
+       Dprintf(ll, "%s", buf);
+       va_end(ap);
+       if (level == STP_LOG_LEVEL_ERROR)
+               ctl_err_log("%s", buf + r);
 }
 
-int
-STP_OUT_get_init_port_cfg(IN int vlan_id,
-                         IN int port_index, INOUT UID_STP_PORT_CFG_T * cfg)
+void *STP_OUT_mem_zalloc(unsigned int size)
 {
-       LOG("port index %d", port_index);
-       struct ifdata *port = find_port(port_index);
-       TST(port != NULL, 0);
-       TST(vlan_id == 0, 0);
-
-       cfg->port_priority = port->port_priority;
-       cfg->admin_non_stp = port->admin_non_stp;
-       cfg->admin_edge = port->admin_edge;
-       cfg->admin_port_path_cost = port->admin_port_path_cost;
-       cfg->admin_point2point = port->admin_point2point;
-
-       return 0;
+       return calloc(1, size);
 }
 
-extern void stp_trace(const char *fmt, ...)
+
+void STP_OUT_mem_free(void *p)
 {
-       va_list ap;
-       va_start(ap, fmt);
-       vDprintf(LOG_LEVEL_RSTPLIB, fmt, ap);
-       va_end(ap);
+       free(p);
 }
 
+
 /* Commands and status */
 #include "ctl_functions.h"
 
 #define CTL_CHECK_BRIDGE \
-  struct ifdata *br = find_if(br_index); \
-  if (br == NULL || !br->is_bridge) return Err_Interface_not_a_bridge; \
-  if (!br->do_stp) return Err_Bridge_RSTP_not_enabled; \
-  if (!br->stp_up) return Err_Bridge_is_down; \
-  do { } while (0)
+       struct ifdata *br = find_if(br_index);                          \
+       if (br == NULL || !br->is_bridge) {                             \
+               ERROR("Couldn't find bridge with index %d", br_index);  \
+               return -1;                                              \
+       }                                                               \
+       do { } while (0)
 
 #define CTL_CHECK_BRIDGE_PORT \
-  CTL_CHECK_BRIDGE; \
-  struct ifdata *port = find_if(port_index); \
-  if (port == NULL || port->is_bridge || port->master != br) \
-    return Err_Port_does_not_belong_to_bridge; \
-  do { } while (0)
+       CTL_CHECK_BRIDGE;                    \
+       struct ifdata *port = find_if(port_index);                      \
+       if (port == NULL || port->is_bridge || port->master != br) {    \
+               ERROR("Interface with index %d not a port of bridge "   \
+                     "with index %d", port_index, br_index);           \
+               return -1;                                              \
+       }                                                               \
+       do { } while (0)
 
 int CTL_enable_bridge_rstp(int br_index, int enable)
 {
@@ -922,110 +622,77 @@ int CTL_enable_bridge_rstp(int br_index, int enable)
                if (if_indextoname(br_index, ifname) && is_bridge(ifname))
                        br = create_if(br_index, NULL);
        }
-       if (br == NULL || !br->is_bridge)
-               return Err_Interface_not_a_bridge;
-       if (br->do_stp != enable) {
-               br->do_stp = enable;
-               if (br->up)
-                       r = enable ? init_bridge_stp(br)
-                           : (clear_bridge_stp(br), 0);
+       if (br == NULL || !br->is_bridge) {
+               ERROR("Couldn't find bridge with index %d", br_index);
+               return -1;
        }
+       if (br->up)
+               set_br_up(br, 1);
        return r;
 }
 
-int CTL_get_bridge_state(int br_index,
-                        UID_STP_CFG_T * cfg, UID_STP_STATE_T * state)
+int CTL_get_bridge_status(int br_index, STP_BridgeStatus *status)
 {
        LOG("bridge %d", br_index);
        CTL_CHECK_BRIDGE;
-       int r;
-       instance_begin(br);
-       r = STP_IN_stpm_get_state(0, state);
-       if (r) {
-               ERROR("Error getting bridge state for %d: %s", br_index,
-                     STP_IN_get_error_explanation(r));
-               instance_end();
-               return r;
-       }
-       r = STP_IN_stpm_get_cfg(0, cfg);
-       if (r) {
-               ERROR("Error getting bridge config for %d: %s", br_index,
-                     STP_IN_get_error_explanation(r));
-               instance_end();
-               return r;
-       }
-       instance_end();
+
+       STP_IN_get_bridge_status(br->stp_bridge, status);
        return 0;
 }
 
-int CTL_set_bridge_config(int br_index, UID_STP_CFG_T * cfg)
+int CTL_set_bridge_config(int br_index,  STP_BridgeConfig *cfg)
 {
-       INFO("bridge %d, flags %#lx", br_index, cfg->field_mask);
+       INFO("bridge %d", br_index);
        CTL_CHECK_BRIDGE;
-       int r;
-       instance_begin(br);
-       r = STP_IN_stpm_set_cfg(0, NULL, cfg);
+
+       if (cfg->set_bridge_address) {
+               ERROR("Setting bridge address not permitted: %s", br->name);
+               return -1;
+       }
+       
+       int r = STP_IN_set_bridge_config(br->stp_bridge, cfg);
+
        if (r) {
-               ERROR("Error setting bridge config for %d: %s", br_index,
-                     STP_IN_get_error_explanation(r));
-               instance_end();
+               ERROR("Error setting bridge config for %s", br->name);
                return r;
        }
-       instance_end();
-       /* Change init config in ifdata so it will be applied if we 
-          disable and enable rstp */
-       update_bridge_stp_config(br, cfg);
        return 0;
 }
 
-int CTL_get_port_state(int br_index, int port_index,
-                      UID_STP_PORT_CFG_T * cfg, UID_STP_PORT_STATE_T * state)
+int CTL_get_port_status(int br_index, int port_index, STP_PortStatus *status)
 {
        LOG("bridge %d port %d", br_index, port_index);
        CTL_CHECK_BRIDGE_PORT;
-       int r;
-       instance_begin(br);
-       state->port_no = port->port_index;
-       r = STP_IN_port_get_state(0, state);
-       if (r) {
-               ERROR("Error getting port state for port %d, bridge %d: %s",
-                     port->port_index, br_index,
-                     STP_IN_get_error_explanation(r));
-               instance_end();
-               return r;
-       }
-       r = STP_IN_port_get_cfg(0, port->port_index, cfg);
+
+       STP_IN_get_port_status(port->stp_port, status);
+       return 0;
+}
+
+int CTL_set_port_config(int br_index, int port_index, STP_PortConfig *cfg)
+{
+       INFO("bridge %d, port %d", br_index, port_index);
+       CTL_CHECK_BRIDGE_PORT;
+
+       int r = STP_IN_set_port_config(port->stp_port, cfg);
        if (r) {
-               ERROR("Error getting port config for port %d, bridge %d: %s",
-                     port->port_index, br_index,
-                     STP_IN_get_error_explanation(r));
-               instance_end();
+               ERROR("Error setting port config for %s", port->name);
                return r;
        }
-       instance_end();
+       
        return 0;
-
 }
 
-int CTL_set_port_config(int br_index, int port_index, UID_STP_PORT_CFG_T * cfg)
+int CTL_port_mcheck(int br_index, int port_index)
 {
-       INFO("bridge %d, port %d, flags %#lx", br_index, port_index,
-            cfg->field_mask);
+       INFO("bridge %d, port %d", br_index, port_index);
        CTL_CHECK_BRIDGE_PORT;
-       int r;
-       instance_begin(br);
-       r = STP_IN_set_port_cfg(0, port->port_index, cfg);
+
+       int r = STP_IN_port_mcheck(port->stp_port);
        if (r) {
-               ERROR("Error setting port config for port %d, bridge %d: %s",
-                     port->port_index, br_index,
-                     STP_IN_get_error_explanation(r));
-               instance_end();
+               ERROR("Error doing port mcheck for %s", port->name);
                return r;
        }
-       instance_end();
-       /* Change init config in ifdata so it will be applied if we 
-          disable and enable rstp */
-       update_port_stp_config(port, cfg);
+       
        return 0;
 }
 
index 72665a8d5428422a6e852cc7ff91a269720a5efc..6edde4ad4269e621350e6e7bdc27c24b63dfad9f 100644 (file)
 #include "log.h"
 
 CLIENT_SIDE_FUNCTION(enable_bridge_rstp)
-    CLIENT_SIDE_FUNCTION(get_bridge_state)
-    CLIENT_SIDE_FUNCTION(set_bridge_config)
-    CLIENT_SIDE_FUNCTION(get_port_state)
-    CLIENT_SIDE_FUNCTION(set_port_config)
-    CLIENT_SIDE_FUNCTION(set_debug_level)
-#include <base.h>
-const char *CTL_error_explanation(int err_no)
-{
-#define CHOOSE(a) #a
-       static const char *rstp_error_names[] = RSTP_ERRORS;
-       static const char *ctl_error_names[] = { CTL_ERRORS };
-
-#undef CHOOSE
-       if (err_no < 0)
-               return "Error doing ctl command";
-       else if (err_no >= STP_OK && err_no < STP_LAST_DUMMY)
-               return rstp_error_names[err_no];
-       else if (err_no > Err_Dummy_Start && err_no < Err_Dummy_End)
-               return ctl_error_names[err_no - Err_Dummy_Start - 1];
-
-       static char buf[32];
-       sprintf(buf, "Unknown error code %d", err_no);
-       return buf;
-}
+CLIENT_SIDE_FUNCTION(get_bridge_status)
+CLIENT_SIDE_FUNCTION(set_bridge_config)
+CLIENT_SIDE_FUNCTION(get_port_status)
+CLIENT_SIDE_FUNCTION(set_port_config)
+CLIENT_SIDE_FUNCTION(port_mcheck)
+CLIENT_SIDE_FUNCTION(set_debug_level)
 
 void Dprintf(int level, const char *fmt, ...)
 {
index 9d630f652157d06a77b3c75420904e45053cb52c..74ac158b40470408589239b2aa0fa2440f69704d 100644 (file)
 #ifndef CTL_FUNCTIONS_H
 #define CTL_FUNCTIONS_H
 
-#include <bitmap.h>
-#include <uid_stp.h>
+#include "rstp.h"
 
 int CTL_enable_bridge_rstp(int br_index, int enable);
 
-int CTL_get_bridge_state(int br_index,
-                        UID_STP_CFG_T * cfg, UID_STP_STATE_T * state);
+int CTL_get_bridge_status(int br_index, STP_BridgeStatus *status);
 
-int CTL_set_bridge_config(int br_index, UID_STP_CFG_T * cfg);
+int CTL_set_bridge_config(int br_index,  STP_BridgeConfig *cfg);
 
-int CTL_get_port_state(int br_index, int port_index,
-                      UID_STP_PORT_CFG_T * cfg, UID_STP_PORT_STATE_T * state);
+int CTL_get_port_status(int br_index, int port_index, STP_PortStatus *status);
 
-int CTL_set_port_config(int br_index, int port_index, UID_STP_PORT_CFG_T * cfg);
+int CTL_set_port_config(int br_index, int port_index, STP_PortConfig *cfg);
 
-int CTL_set_debug_level(int level);
-
-#define CTL_ERRORS \
- CHOOSE(Err_Interface_not_a_bridge), \
- CHOOSE(Err_Bridge_RSTP_not_enabled), \
- CHOOSE(Err_Bridge_is_down), \
- CHOOSE(Err_Port_does_not_belong_to_bridge), \
-
-#define CHOOSE(a) a
+int CTL_port_mcheck(int br_index, int port_index);
 
-enum Errors {
-       Err_Dummy_Start = 1000,
-       CTL_ERRORS Err_Dummy_End
-};
-
-#undef CHOOSE
-
-const char *CTL_error_explanation(int err);
+int CTL_set_debug_level(int level);
 
 #endif
index 8eaa76d13912183163be25385dcc6ae1ba2dae6f..82bf02c2f540442fbd479c56abae74eba561474d 100644 (file)
 #include "ctl_socket_client.h"
 #include "ctl_functions.h"
 
-#ifndef False
-# define False 0
-# define True 1
-#endif
-
-#define STP_IN_get_error_explanation CTL_error_explanation
-
-static void print_bridge_id(UID_BRIDGE_ID_T * bridge_id, unsigned char cr)
-{
-       printf("%04lX-%02x%02x%02x%02x%02x%02x",
-              (unsigned long)bridge_id->prio,
-              (unsigned char)bridge_id->addr[0],
-              (unsigned char)bridge_id->addr[1],
-              (unsigned char)bridge_id->addr[2],
-              (unsigned char)bridge_id->addr[3],
-              (unsigned char)bridge_id->addr[4],
-              (unsigned char)bridge_id->addr[5]);
-       if (cr)
-               printf("\n");
-}
-
-static char *stp_state2str(RSTP_PORT_STATE stp_port_state, int detail)
-{
-       if (detail) {
-               switch (stp_port_state) {
-               case UID_PORT_DISABLED:
-                       return "Disabled";
-               case UID_PORT_DISCARDING:
-                       return "Discarding";
-               case UID_PORT_LEARNING:
-                       return "Learning";
-               case UID_PORT_FORWARDING:
-                       return "Forwarding";
-               case UID_PORT_NON_STP:
-                       return "NoStp";
-               default:
-                       return "Unknown";
-               }
-       }
-
-       switch (stp_port_state) {
-       case UID_PORT_DISABLED:
-               return "Dis";
-       case UID_PORT_DISCARDING:
-               return "Blk";
-       case UID_PORT_LEARNING:
-               return "Lrn";
-       case UID_PORT_FORWARDING:
-               return "Fwd";
-       case UID_PORT_NON_STP:
-               return "Non";
-       default:
-               return "Unk";
-       }
-}
-
-static void CLI_out_port_id(int port, unsigned char cr)
-{
-       static char ifname[IFNAMSIZ];
-       if (if_indextoname(port, ifname))
-               printf("%s", ifname);
-       else
-               printf("Ifindex %02d", port);
-       if (cr)
-               printf("\n");
-}
-
 int get_index_die(const char *ifname, const char *doc, int die)
 {
        int r = if_nametoindex(ifname);
@@ -106,99 +39,44 @@ int get_index(const char *ifname, const char *doc)
        return get_index_die(ifname, doc, 1);
 }
 
-static int cmd_rstp(int argc, char *const *argv)
-{
-       int stp, r;
-       int br_index = get_index(argv[1], "bridge");
+#define BR_ID_FMT "%02x%02x.%02x%02x%02x%02x%02x%02x"
+#define BR_ID_ARGS(x) x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]
 
-       if (!strcmp(argv[2], "on") || !strcmp(argv[2], "yes")
-           || !strcmp(argv[2], "1"))
-               stp = 1;
-       else if (!strcmp(argv[2], "off") || !strcmp(argv[2], "no")
-                || !strcmp(argv[2], "0"))
-               stp = 0;
-       else {
-               fprintf(stderr, "expect on/off for argument\n");
-               return 1;
-       }
-       r = CTL_enable_bridge_rstp(br_index, stp);
-       if (r) {
-               fprintf(stderr, "Failed to enable/disable RSTP: %s\n",
-                       CTL_error_explanation(r));
-               return -1;
-       }
-       return 0;
-}
+#define BOOL_STR(x) ((x) ? "yes" : "no")
 
 static int do_showbridge(const char *br_name)
 {
-       UID_STP_STATE_T uid_state;
-       UID_STP_CFG_T uid_cfg;
+       STP_BridgeStatus s;
 
        int br_index = get_index_die(br_name, "bridge", 0);
        if (br_index < 0)
                return -1;
 
-       int r = CTL_get_bridge_state(br_index, &uid_cfg, &uid_state);
+       int r = CTL_get_bridge_status(br_index, &s);
        if (r) {
-               fprintf(stderr, "Failed to get bridge state: %s\n",
-                       CTL_error_explanation(r));
                return -1;
        }
-#if 0
-       printf("Interface:       %-7s (tag:%d)    State: ",
-              uid_state.vlan_name, (int)uid_state.vlan_id);
-#else
-       printf("Bridge:          %-7s               State:",
-              uid_state.vlan_name);
-#endif
-       switch (uid_state.stp_enabled) {
-       case STP_ENABLED:
-               printf("enabled\n");
-               break;
-       case STP_DISABLED:
-               printf("disabled\n");
-               break;
-       default:
-               printf("unknown\n");
-               return 0;
-       }
-
-       printf("BridgeId:        ");
-       print_bridge_id(&uid_state.bridge_id, 0);
-       printf("     Bridge Proirity: %lu (0x%lX)\n",
-              (unsigned long)uid_state.bridge_id.prio,
-              (unsigned long)uid_state.bridge_id.prio);
-       if (uid_cfg.force_version < 2)
-               printf("Force Version:   stp\n");
-
-       printf("Designated Root: ");
-       print_bridge_id(&uid_state.designated_root, 1);
-       if (uid_state.root_port) {
-               printf("Root Port:       %04lx",
-                      (unsigned long)uid_state.root_port);
-               //        CLI_out_port_id (uid_state.root_port & 0xfff, False);
-               //    printf("not implemented"); // XXX
-               printf(", Root Cost:     %-lu\n",
-                      (unsigned long)uid_state.root_path_cost);
-       } else {
-               printf("Root Port:       none\n");
-       }
-
-       if (uid_state.Topo_Change)
-               printf("Topology Change Count: %lu\n",
-                      uid_state.Topo_Change_Count);
-       else
-               printf("Time Since Topology Change: %lu\n",
-                      uid_state.timeSince_Topo_Change);
-
-       printf("Max Age:         %2d   Bridge Max Age:       %-2d\n",
-              (int)uid_state.max_age, (int)uid_cfg.max_age);
-       printf("Hello Time:      %2d   Bridge Hello Time:    %-2d\n",
-              (int)uid_state.hello_time, (int)uid_cfg.hello_time);
-       printf("Forward Delay:   %2d   Bridge Forward Delay: %-2d\n",
-              (int)uid_state.forward_delay, (int)uid_cfg.forward_delay);
-       printf("Hold Time:       %2d\n", (int)uid_cfg.hold_time);
+       printf("%s\n", br_name);
+       printf(" enabled\t\t%4s\n", BOOL_STR(s.enabled));
+       printf(" bridge id\t\t" BR_ID_FMT "\n", BR_ID_ARGS(s.bridge_id));
+       printf(" designated root\t" BR_ID_FMT "\n",
+              BR_ID_ARGS(s.designated_root));
+       //printf(" designated bridge\t\t", BR_ID_FMT "\n",
+       //       BR_ID_ARGS(s.designated_bridge));
+       printf(" root port\t\t%4u", s.root_port);
+       printf("\t\t\tpath cost\t\t%4u\n", s.root_path_cost);
+       printf(" max age\t\t%4u", s.max_age);
+       printf("\t\t\tbridge max age\t\t%4u\n", s.bridge_max_age);
+       printf(" hello time\t\t%4u", s.hello_time);
+       printf("\t\t\tbridge hello time\t%4u\n", s.bridge_hello_time);
+       printf(" forward delay\t\t%4u", s.forward_delay);
+       printf("\t\t\tbridge forward delay\t%4u\n", s.bridge_forward_delay);
+       printf(" tx hold count\t\t%4u\n", s.tx_hold_count);
+       printf(" protocol version\t%4u\n", s.protocol_version);
+       printf(" time since topology change\t%4u\n",
+              s.time_since_topology_change);
+       printf(" toplogy change count\t\t%4u\n", s.topology_change_count);
+       printf(" topology change\t\t%4s\n", BOOL_STR(s.topology_change));
 
        return 0;
 }
@@ -254,157 +132,95 @@ static int cmd_showbridge(int argc, char *const *argv)
        return r;
 }
 
+
+#define STATE_STR(_state)                      \
+       ({                                      \
+               int _s = _state;                \
+               char *_str = "unknown";         \
+               switch (_s)                     \
+               {                                            \
+               case STP_PORT_STATE_DISCARDING: _str = "discarding"; break; \
+               case STP_PORT_STATE_LEARNING:   _str = "learning"; break; \
+               case STP_PORT_STATE_FORWARDING: _str = "forwarding"; break; \
+               }                                                       \
+               _str;                                                   \
+       })
+
+#define SHORT_STATE_STR(_state)                        \
+       ({                                      \
+               int _s = _state;                \
+               char *_str = "unkn";            \
+               switch (_s)                     \
+               {                                      \
+               case STP_PORT_STATE_DISCARDING: _str = "disc"; break;   \
+               case STP_PORT_STATE_LEARNING:   _str = "lear"; break;   \
+               case STP_PORT_STATE_FORWARDING: _str = "forw"; break;   \
+               }                                                       \
+               _str;                                                   \
+       })
+
+#define ADMIN_P2P_STR(_state)                  \
+       ({                                      \
+               int _s = _state;                \
+               char *_str = "unkn";            \
+               switch (_s)                     \
+               {                                    \
+               case STP_ADMIN_P2P_FORCE_FALSE: _str = "no"; break;     \
+               case STP_ADMIN_P2P_FORCE_TRUE:   _str = "yes"; break;   \
+               case STP_ADMIN_P2P_AUTO: _str = "auto"; break;          \
+               }                                                       \
+               _str;                                                   \
+       })
+
+
 int detail = 0;
 
-static int do_showport(int br_index, const char *port_name,
-                      UID_STP_STATE_T * uid_state)
+static int do_showport(int br_index, const char *port_name)
 {
-       UID_STP_PORT_STATE_T uid_port;
-       UID_STP_PORT_CFG_T uid_cfg;
+       STP_PortStatus s;
        int r = 0;
        int port_index = get_index_die(port_name, "port", 0);
        if (port_index < 0)
                return -1;
 
-       memset(&uid_cfg, 0, sizeof(UID_STP_PORT_CFG_T));
-       r = CTL_get_port_state(br_index, port_index, &uid_cfg, &uid_port);
+       r = CTL_get_port_status(br_index, port_index, &s);
        if (r) {
-               fprintf(stderr, "Failed to get port state for port %d: %s\n",
-                       port_index, CTL_error_explanation(r));
+               fprintf(stderr, "Failed to get port state for port %d\n",
+                       port_index);
                return -1;
        }
 
        if (detail) {
-               printf("Stp Port ");
-               CLI_out_port_id(port_index, False);
-#if 0
-               printf(": PortId: %04lx in vlan '%s' with tag %d:\n",
-                      (unsigned long)uid_port.port_id, uid_state->vlan_name,
-                      (int)uid_state->vlan_id);
-#else
-               printf(": PortId: %04lx in Bridge '%s':\n",
-                      (unsigned long)uid_port.port_id, uid_state->vlan_name);
-#endif
-               printf("Priority:          %-d\n",
-                      (int)(uid_port.port_id >> 8));
-               printf("State:             %-16s",
-                      stp_state2str(uid_port.state, 1));
-               printf("       Uptime: %-9lu\n", uid_port.uptime);
-               printf("PortPathCost:      admin: ");
-               if (ADMIN_PORT_PATH_COST_AUTO == uid_cfg.admin_port_path_cost)
-                       printf("%-9s", "Auto");
-               else
-                       printf("%-9lu", uid_cfg.admin_port_path_cost);
-               printf("       oper: %-9lu\n", uid_port.oper_port_path_cost);
-
-               printf("Point2Point:       admin: ");
-               switch (uid_cfg.admin_point2point) {
-               case P2P_FORCE_TRUE:
-                       printf("%-9s", "ForceYes");
-                       break;
-               case P2P_FORCE_FALSE:
-                       printf("%-9s", "ForceNo");
-                       break;
-               case P2P_AUTO:
-                       printf("%-9s", "Auto");
-                       break;
-               }
-               printf("       oper: %-9s\n",
-                      uid_port.oper_point2point ? "Yes" : "No");
-               printf("Edge:              admin: %-9s       oper: %-9s\n",
-                      uid_cfg.admin_edge ? "Y" : "N",
-                      uid_port.oper_edge ? "Y" : "N");
-               printf("Partner:                                  oper: %-9s\n",
-                      uid_port.oper_stp_neigb ? "Slow" : "Rapid");
-
-               if (' ' != uid_port.role) {
-                       if ('-' != uid_port.role) {
-                               printf("PathCost:          %-lu\n",
-                                      (unsigned long)(uid_port.path_cost));
-                               printf("Designated Root:   ");
-                               print_bridge_id(&uid_port.designated_root, 1);
-                               printf("Designated Cost:   %-ld\n",
-                                      (unsigned long)uid_port.designated_cost);
-                               printf("Designated Bridge: ");
-                               print_bridge_id(&uid_port.designated_bridge, 1);
-                               printf("Designated Port:   %-4lx\n\r",
-                                      (unsigned long)uid_port.designated_port);
-                       }
-                       printf("Role:              ");
-                       switch (uid_port.role) {
-                       case 'A':
-                               printf("Alternate\n");
-                               break;
-                       case 'B':
-                               printf("Backup\n");
-                               break;
-                       case 'R':
-                               printf("Root\n");
-                               break;
-                       case 'D':
-                               printf("Designated\n");
-                               break;
-                       case '-':
-                               printf("NonStp\n");
-                               break;
-                       default:
-                               printf("Unknown(%c)\n", uid_port.role);
-                               break;
-                       }
-
-                       if ('R' == uid_port.role || 'D' == uid_port.role) {
-                               /* printf("Tc:                %c  ", uid_port.tc ? 'Y' : 'n'); */
-                               printf("TcAck:             %c  ",
-                                      uid_port.top_change_ack ? 'Y' : 'N');
-                               printf("TcWhile:       %3d\n",
-                                      (int)uid_port.tcWhile);
-                       }
-               }
-
-               if (UID_PORT_DISABLED == uid_port.state || '-' == uid_port.role) {
-#if 0
-                       printf("helloWhen:       %3d  ",
-                              (int)uid_port.helloWhen);
-                       printf("lnkWhile:      %3d\n", (int)uid_port.lnkWhile);
-                       printf("fdWhile:         %3d\n", (int)uid_port.fdWhile);
-#endif
-               } else if ('-' != uid_port.role) {
-                       printf("fdWhile:         %3d  ", (int)uid_port.fdWhile);
-                       printf("rcvdInfoWhile: %3d\n",
-                              (int)uid_port.rcvdInfoWhile);
-                       printf("rbWhile:         %3d  ", (int)uid_port.rbWhile);
-                       printf("rrWhile:       %3d\n", (int)uid_port.rrWhile);
-#if 0
-                       printf("mdelayWhile:     %3d  ",
-                              (int)uid_port.mdelayWhile);
-                       printf("lnkWhile:      %3d\n", (int)uid_port.lnkWhile);
-                       printf("helloWhen:       %3d  ",
-                              (int)uid_port.helloWhen);
-                       printf("txCount:       %3d\n", (int)uid_port.txCount);
-#endif
-               }
-
-               printf("RSTP BPDU rx:      %lu\n",
-                      (unsigned long)uid_port.rx_rstp_bpdu_cnt);
-               printf("CONFIG BPDU rx:    %lu\n",
-                      (unsigned long)uid_port.rx_cfg_bpdu_cnt);
-               printf("TCN BPDU rx:       %lu\n",
-                      (unsigned long)uid_port.rx_tcn_bpdu_cnt);
+               printf("%s (%u)\n", port_name, (s.id & 0xfff));
+               printf(" enabled\t\t%4s\n", BOOL_STR(s.enabled));
+               printf(" port id\t\t%04x\t\t\tstate\t\t%15s\n",
+                      s.id, STATE_STR(s.state));
+               printf(" path cost\t%12d\t\t\tadmin path cost\t%12d\n", 
+                      s.path_cost, s.admin_path_cost);
+               printf(" designated root\t" BR_ID_FMT,
+                      BR_ID_ARGS(s.designated_root));
+               printf("\tdesignated cost\t%12u\n", s.designated_cost);
+               printf(" designated bridge\t" BR_ID_FMT,
+                      BR_ID_ARGS(s.designated_bridge));
+               printf("\tdesignated port\t\t%04x\n", s.designated_port);
+               printf(" admin edge port\t%4s", BOOL_STR(s.admin_edge_port));
+               printf("\t\t\tauto edge port\t\t%4s\n",
+                      BOOL_STR(s.auto_edge_port));
+               printf(" oper edge port\t\t%4s", BOOL_STR(s.oper_edge_port));
+               printf("\t\t\ttoplogy change ack\t%4s\n", BOOL_STR(s.tc_ack));
+               printf(" point to point\t\t%4s", BOOL_STR(s.oper_p2p));
+               printf("\t\t\tadmin point to point\t%4s\n",
+                      ADMIN_P2P_STR(s.admin_p2p));
        } else {
-               printf("%c%c%c  ",
-                      (uid_port.oper_point2point) ? ' ' : '*',
-                      (uid_port.oper_edge) ? 'E' : ' ',
-                      (uid_port.oper_stp_neigb) ? 's' : ' ');
-               CLI_out_port_id(port_index, False);
-               printf(" %04lx %3s ", (unsigned long)uid_port.port_id,
-                      stp_state2str(uid_port.state, 0));
-               printf(" ");
-               print_bridge_id(&uid_port.designated_root, 0);
-               printf(" ");
-               print_bridge_id(&uid_port.designated_bridge, 0);
-               printf(" %4lx %c", (unsigned long)uid_port.designated_port,
-                      uid_port.role);
-               printf("\n");
+               printf("%c%c %4s %04x %4s " BR_ID_FMT " " BR_ID_FMT " %04x\n",
+                      (s.oper_p2p) ? ' ' : '*',
+                      (s.oper_edge_port) ? 'E' : ' ',
+                      port_name,
+                      s.id,
+                      s.enabled?SHORT_STATE_STR(s.state):"down",
+                      BR_ID_ARGS(s.designated_root),
+                      BR_ID_ARGS(s.designated_bridge),
+                      s.designated_port);
        }
        return 0;
 }
@@ -418,19 +234,10 @@ static int not_dot_dotdot(const struct dirent *entry)
 
 static int cmd_showport(int argc, char *const *argv)
 {
-       UID_STP_STATE_T uid_state;
-       UID_STP_CFG_T uid_br_cfg;
        int r = 0;
 
        int br_index = get_index(argv[1], "bridge");
 
-       r = CTL_get_bridge_state(br_index, &uid_br_cfg, &uid_state);
-       if (r) {
-               fprintf(stderr, "Failed to get bridge state: %s\n",
-                       CTL_error_explanation(r));
-               return -1;
-       }
-
        int i, count = 0;
        struct dirent **namelist;
 
@@ -455,7 +262,7 @@ static int cmd_showport(int argc, char *const *argv)
                else
                        name = namelist[i]->d_name;
 
-               int err = do_showport(br_index, name, &uid_state);
+               int err = do_showport(br_index, name);
                if (err)
                        r = err;
        }
@@ -508,170 +315,82 @@ int getyesno(const char *s, const char *yes, const char *no)
        return 1 - getenum(s, opt);
 }
 
-static int set_bridge_cfg_value(int br_index, unsigned long value,
-                               unsigned long val_mask)
-{
-       UID_STP_CFG_T uid_cfg;
-       char *val_name;
-       int rc;
-
-       uid_cfg.field_mask = val_mask;
-       switch (val_mask) {
-       case BR_CFG_STATE:
-               uid_cfg.stp_enabled = value;
-               val_name = "state";
-               break;
-       case BR_CFG_PRIO:
-               uid_cfg.bridge_priority = value;
-               val_name = "priority";
-               break;
-       case BR_CFG_AGE:
-               uid_cfg.max_age = value;
-               val_name = "max_age";
-               break;
-       case BR_CFG_HELLO:
-               uid_cfg.hello_time = value;
-               val_name = "hello_time";
-               break;
-       case BR_CFG_DELAY:
-               uid_cfg.forward_delay = value;
-               val_name = "forward_delay";
-               break;
-       case BR_CFG_FORCE_VER:
-               uid_cfg.force_version = value;
-               val_name = "force_version";
-               break;
-       case BR_CFG_AGE_MODE:
-       case BR_CFG_AGE_TIME:
-       default:
-               printf("Invalid value mask 0X%lx\n", val_mask);
-               return -1;
-               break;
-       }
-
-       rc = CTL_set_bridge_config(br_index, &uid_cfg);
-
-       if (0 != rc) {
-               printf("Can't change rstp bridge %s:%s\n", val_name,
-                      STP_IN_get_error_explanation(rc));
-               return -1;
-       }
-       return 0;
-}
-
-static int cmd_setbridgestate(int argc, char *const *argv)
-{
+#define set_bridge_cfg(field, value) \
+({ \
+       STP_BridgeConfig c; \
+       memset(&c, 0, sizeof(c)); \
+       c.field = value; \
+       c.set_ ## field = 1; \
+       int r = CTL_set_bridge_config(br_index, &c); \
+       if (r) \
+               printf("Couldn't change bridge " #field "\n"); \
+       r; \
+})
+   
+#define set_port_cfg(field, value) \
+({ \
+       STP_PortConfig c; \
+       memset(&c, 0, sizeof(c)); \
+       c.field = value; \
+       c.set_ ## field = 1; \
+       int r = CTL_set_port_config(br_index, port_index, &c); \
+       if (r) \
+               printf("Couldn't change port " #field "\n"); \
+       r; \
+})
+   
 
-       int br_index = get_index(argv[1], "bridge");
-       return set_bridge_cfg_value(br_index,
-                                   getyesno(argv[2], "on", "off"),
-                                   BR_CFG_STATE);
-}
 
 static int cmd_setbridgeprio(int argc, char *const *argv)
 {
 
        int br_index = get_index(argv[1], "bridge");
-       return set_bridge_cfg_value(br_index, getuint(argv[2]), BR_CFG_PRIO);
+       return set_bridge_cfg(bridge_priority, getuint(argv[2]));
 }
 
 static int cmd_setbridgemaxage(int argc, char *const *argv)
 {
 
        int br_index = get_index(argv[1], "bridge");
-       return set_bridge_cfg_value(br_index, getuint(argv[2]), BR_CFG_AGE);
+       return set_bridge_cfg(bridge_max_age, getuint(argv[2]));
 }
 
 static int cmd_setbridgehello(int argc, char *const *argv)
 {
 
        int br_index = get_index(argv[1], "bridge");
-       return set_bridge_cfg_value(br_index, getuint(argv[2]), BR_CFG_HELLO);
+       return set_bridge_cfg(bridge_hello_time, getuint(argv[2]));
 }
 
 static int cmd_setbridgefdelay(int argc, char *const *argv)
 {
 
        int br_index = get_index(argv[1], "bridge");
-       return set_bridge_cfg_value(br_index, getuint(argv[2]), BR_CFG_DELAY);
+       return set_bridge_cfg(bridge_forward_delay, getuint(argv[2]));
 }
 
 static int cmd_setbridgeforcevers(int argc, char *const *argv)
 {
 
        int br_index = get_index(argv[1], "bridge");
-       return set_bridge_cfg_value(br_index,
-                                   2 * getyesno(argv[2], "normal", "slow"),
-                                   BR_CFG_FORCE_VER);
+       return set_bridge_cfg(bridge_protocol_version,
+                             2 * getyesno(argv[2], "normal", "slow"));
 }
 
-static int
-set_port_cfg_value(int br_index, int port_index,
-                  unsigned long value, unsigned long val_mask)
+static int cmd_setbridgetxholdcount(int argc, char *const *argv)
 {
-       UID_STP_PORT_CFG_T uid_cfg;
-       int rc;
-       char *val_name;
-
-       BitmapClear(&uid_cfg.port_bmp);
-       uid_cfg.field_mask = val_mask;
-       switch (val_mask) {
-       case PT_CFG_MCHECK:
-               val_name = "mcheck";
-               break;
-       case PT_CFG_COST:
-               uid_cfg.admin_port_path_cost = value;
-               val_name = "path cost";
-               break;
-       case PT_CFG_PRIO:
-               uid_cfg.port_priority = value;
-               val_name = "priority";
-               break;
-       case PT_CFG_P2P:
-               uid_cfg.admin_point2point = (ADMIN_P2P_T) value;
-               val_name = "p2p flag";
-               break;
-       case PT_CFG_EDGE:
-               uid_cfg.admin_edge = value;
-               val_name = "adminEdge";
-               break;
-       case PT_CFG_NON_STP:
-               uid_cfg.admin_non_stp = value;
-               val_name = "adminNonStp";
-               break;
-#ifdef STP_DBG
-       case PT_CFG_DBG_SKIP_TX:
-               uid_cfg.skip_tx = value;
-               val_name = "skip tx";
-               break;
-       case PT_CFG_DBG_SKIP_RX:
-               uid_cfg.skip_rx = value;
-               val_name = "skip rx";
-               break;
-#endif
-       case PT_CFG_STATE:
-       default:
-               printf("Invalid value mask 0X%lx\n", val_mask);
-               return -1;
-       }
 
-       rc = CTL_set_port_config(br_index, port_index, &uid_cfg);
-
-       if (0 != rc) {
-               printf("can't change rstp port[s] %s: %s\n",
-                      val_name, STP_IN_get_error_explanation(rc));
-               return -1;
-       }
-       return 0;
+       int br_index = get_index(argv[1], "bridge");
+       return set_bridge_cfg(bridge_tx_hold_count, getuint(argv[2]));
 }
 
+
 static int cmd_setportprio(int argc, char *const *argv)
 {
 
        int br_index = get_index(argv[1], "bridge");
        int port_index = get_index(argv[2], "port");
-       return set_port_cfg_value(br_index, port_index,
-                                 getuint(argv[3]), PT_CFG_PRIO);
+       return set_port_cfg(port_priority, getuint(argv[3]));
 }
 
 static int cmd_setportpathcost(int argc, char *const *argv)
@@ -679,27 +398,23 @@ static int cmd_setportpathcost(int argc, char *const *argv)
 
        int br_index = get_index(argv[1], "bridge");
        int port_index = get_index(argv[2], "port");
-       return set_port_cfg_value(br_index, port_index,
-                                 getuint(argv[3]), PT_CFG_COST);
+       return set_port_cfg(port_pathcost, getuint(argv[3]));
 }
 
-static int cmd_setportedge(int argc, char *const *argv)
+static int cmd_setportadminedge(int argc, char *const *argv)
 {
 
        int br_index = get_index(argv[1], "bridge");
        int port_index = get_index(argv[2], "port");
-       return set_port_cfg_value(br_index, port_index,
-                                 getyesno(argv[3], "yes", "no"), PT_CFG_EDGE);
+       return set_port_cfg(port_admin_edge, getyesno(argv[3], "yes", "no"));
 }
 
-static int cmd_setportnonstp(int argc, char *const *argv)
+static int cmd_setportautoedge(int argc, char *const *argv)
 {
 
        int br_index = get_index(argv[1], "bridge");
        int port_index = get_index(argv[2], "port");
-       return set_port_cfg_value(br_index, port_index,
-                                 getyesno(argv[3], "yes", "no"),
-                                 PT_CFG_NON_STP);
+       return set_port_cfg(port_auto_edge, getyesno(argv[3], "yes", "no"));
 }
 
 static int cmd_setportp2p(int argc, char *const *argv)
@@ -707,11 +422,11 @@ static int cmd_setportp2p(int argc, char *const *argv)
 
        int br_index = get_index(argv[1], "bridge");
        int port_index = get_index(argv[2], "port");
-       const char *opts[] = { "yes", "no", "auto", NULL };
-       int vals[] = { P2P_FORCE_TRUE, P2P_FORCE_FALSE, P2P_AUTO };
+       const char *opts[] = { "no", "yes", "auto", NULL };
+       int vals[] = { STP_ADMIN_P2P_FORCE_FALSE, STP_ADMIN_P2P_FORCE_TRUE,
+                      STP_ADMIN_P2P_AUTO };
 
-       return set_port_cfg_value(br_index, port_index,
-                                 vals[getenum(argv[3], opts)], PT_CFG_P2P);
+       return set_port_cfg(port_admin_p2p, vals[getenum(argv[3], opts)]);
 }
 
 static int cmd_portmcheck(int argc, char *const *argv)
@@ -719,7 +434,7 @@ static int cmd_portmcheck(int argc, char *const *argv)
 
        int br_index = get_index(argv[1], "bridge");
        int port_index = get_index(argv[2], "port");
-       return set_port_cfg_value(br_index, port_index, 0, PT_CFG_MCHECK);
+       return CTL_port_mcheck(br_index, port_index);
 }
 
 static int cmd_debuglevel(int argc, char *const *argv)
@@ -742,10 +457,6 @@ static const struct command commands[] = {
         "<bridge> [<port> ... ]\tshow port state"},
        {1, 32, "showportdetail", cmd_showportdetail,
         "<bridge> [<port> ... ]\tshow port state (detail)"},
-       {2, 0, "rstp", cmd_rstp,
-        "<bridge> {on|off}\tenable/disable rstpd control"},
-       {2, 0, "setbridgestate", cmd_setbridgestate,
-        "<bridge> {on|off}\tstart/stop rstp (when enabled)"},
        {2, 0, "setbridgeprio", cmd_setbridgeprio,
         "<bridge> <priority>\tset bridge priority (0-61440)"},
        {2, 0, "sethello", cmd_setbridgehello,
@@ -756,14 +467,16 @@ static const struct command commands[] = {
         "<bridge> <fwd_delay>\tset bridge forward delay (4-30)"},
        {2, 0, "setforcevers", cmd_setbridgeforcevers,
         "<bridge> {normal|slow}\tnormal RSTP or force to STP"},
+       {2, 0, "settxholdcount", cmd_setbridgetxholdcount,
+        "<bridge> <tx_hold_count>\tset bridge transmit hold count (1-10)"},
        {3, 0, "setportprio", cmd_setportprio,
         "<bridge> <port> <priority>\tset port priority (0-240)"},
        {3, 0, "setportpathcost", cmd_setportpathcost,
         "<bridge> <port> <cost>\tset port path cost"},
-       {3, 0, "setportedge", cmd_setportedge,
-        "<bridge> <port> {yes|no}\tconfigure if it is an edge port"},
-       {3, 0, "setportnonstp", cmd_setportnonstp,
-        "<bridge> <port> {yes|no}\tdisable STP for the port"},
+       {3, 0, "setportadminedge", cmd_setportadminedge,
+        "<bridge> <port> {yes|no}\tconfigure if it is an admin edge port"},
+       {3, 0, "setportautoedge", cmd_setportautoedge,
+        "<bridge> <port> {yes|no}\tconfigure if it is an auto edge port"},
        {3, 0, "setportp2p", cmd_setportp2p,
         "<bridge> <port> {yes|no|auto}\tset whether p2p connection"},
        {2, 0, "portmcheck", cmd_portmcheck,
index f37e8b151f7bbff0a344d958f079e86a8681c500..d918861bf8293fc01f49ed940eeafef6947d41b1 100644 (file)
@@ -31,6 +31,8 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <fcntl.h>
+#include <stdarg.h>
+#include <string.h>
 
 #include "epoll_loop.h"
 #include "log.h"
@@ -59,14 +61,15 @@ int server_socket(void)
        return s;
 }
 
-int handle_message(int cmd, void *inbuf, int lin, void *outbuf, int *lout)
+int handle_message(int cmd, void *inbuf, int lin, void *outbuf, int lout)
 {
        switch (cmd) {
                SERVER_MESSAGE_CASE(enable_bridge_rstp);
-               SERVER_MESSAGE_CASE(get_bridge_state);
+               SERVER_MESSAGE_CASE(get_bridge_status);
                SERVER_MESSAGE_CASE(set_bridge_config);
-               SERVER_MESSAGE_CASE(get_port_state);
+               SERVER_MESSAGE_CASE(get_port_status);
                SERVER_MESSAGE_CASE(set_port_config);
+               SERVER_MESSAGE_CASE(port_mcheck);
                SERVER_MESSAGE_CASE(set_debug_level);
 
        default:
@@ -75,28 +78,52 @@ int handle_message(int cmd, void *inbuf, int lin, void *outbuf, int *lout)
        }
 }
 
+int ctl_in_handler = 0;
+static unsigned char msg_logbuf[1024];
+static unsigned int msg_log_offset;
+void _ctl_err_log(char *fmt, ...)
+{
+       if (msg_log_offset >= sizeof(msg_logbuf) - 1)
+               return;
+       int r;
+       va_list ap;
+       va_start(ap, fmt);
+       r = vsnprintf((char *)msg_logbuf + msg_log_offset,
+                     sizeof(msg_logbuf) - msg_log_offset,
+                     fmt, ap);
+       va_end(ap);
+       msg_log_offset += r;
+       if (msg_log_offset == sizeof(msg_logbuf)) {
+               msg_log_offset = sizeof(msg_logbuf) - 1;
+               msg_logbuf[sizeof(msg_logbuf) - 1] = 0;
+       }
+}
+
+
 #define msg_buf_len 1024
-unsigned char msg_inbuf[1024];
-unsigned char msg_outbuf[1024];
+static unsigned char msg_inbuf[1024];
+static unsigned char msg_outbuf[1024];
 
 void ctl_rcv_handler(uint32_t events, struct epoll_event_handler *p)
 {
        struct ctl_msg_hdr mhdr;
        struct msghdr msg;
        struct sockaddr_un sa;
-       struct iovec iov[2];
+       struct iovec iov[3];
        int l;
 
        msg.msg_name = &sa;
        msg.msg_namelen = sizeof(sa);
        msg.msg_iov = iov;
-       msg.msg_iovlen = 2;
+       msg.msg_iovlen = 3;
        msg.msg_control = NULL;
        msg.msg_controllen = 0;
        iov[0].iov_base = &mhdr;
        iov[0].iov_len = sizeof(mhdr);
        iov[1].iov_base = msg_inbuf;
        iov[1].iov_len = msg_buf_len;
+       iov[2].iov_base = NULL;
+       iov[2].iov_len = 0;
        l = recvmsg(p->fd, &msg, MSG_NOSIGNAL | MSG_DONTWAIT);
        TST(l > 0,);
        if (msg.msg_flags != 0 || l < sizeof(mhdr) ||
@@ -106,17 +133,22 @@ void ctl_rcv_handler(uint32_t events, struct epoll_event_handler *p)
                return;
        }
 
-       if (mhdr.lout)
-               mhdr.res = handle_message(mhdr.cmd, msg_inbuf, mhdr.lin,
-                                         msg_outbuf, &mhdr.lout);
-       else
-               mhdr.res = handle_message(mhdr.cmd, msg_inbuf, mhdr.lin,
-                                         NULL, NULL);
+       msg_log_offset = 0;
+       ctl_in_handler = 1;
+
+       mhdr.res = handle_message(mhdr.cmd, msg_inbuf, mhdr.lin,
+                                 msg_outbuf, mhdr.lout);
 
+       ctl_in_handler = 0;
        if (mhdr.res < 0)
-               mhdr.lout = 0;
+               memset(msg_outbuf, 0, mhdr.lout);
+       if (msg_log_offset < mhdr.llog)
+               mhdr.llog = msg_log_offset;
+       
        iov[1].iov_base = msg_outbuf;
        iov[1].iov_len = mhdr.lout;
+       iov[2].iov_base = msg_logbuf;
+       iov[2].iov_len = mhdr.llog;
        l = sendmsg(p->fd, &msg, MSG_NOSIGNAL);
        if (l < 0)
                ERROR("CTL: Couldn't send response: %m");
index 089a7176e4905e4f4289505329c43c887f7269a6..a41c32218ae858771b058b1fd15e6559eeae7bb5 100644 (file)
@@ -34,9 +34,17 @@ struct ctl_msg_hdr {
        int cmd;
        int lin;
        int lout;
+       int llog;
        int res;
 };
 
+#define LOG_STRING_LEN 256
+
+typedef struct _log_string 
+{
+       char buf[LOG_STRING_LEN];
+} LogString;
+
 #define set_socket_address(sa, string) \
  do {\
   (sa)->sun_family = AF_UNIX; \
@@ -65,31 +73,29 @@ struct enable_bridge_rstp_OUT {
 #define enable_bridge_rstp_CALL (in->br_index, in->enable)
 
 #if 0
-int CTL_get_bridge_state(int br_index,
-                        UID_STP_CFG_T * cfg, UID_STP_STATE_T * state);
+int CTL_get_bridge_status(int br_index, STP_BridgeStatus *status);
 #endif
-#define CMD_CODE_get_bridge_state  102
-#define get_bridge_state_ARGS (int br_index, UID_STP_CFG_T *cfg, UID_STP_STATE_T *state)
-struct get_bridge_state_IN {
+#define CMD_CODE_get_bridge_status  102
+#define get_bridge_status_ARGS (int br_index, STP_BridgeStatus *status)
+struct get_bridge_status_IN {
        int br_index;
 };
-struct get_bridge_state_OUT {
-       UID_STP_CFG_T cfg;
-       UID_STP_STATE_T state;
+struct get_bridge_status_OUT {
+       STP_BridgeStatus status;
 };
-#define get_bridge_state_COPY_IN \
+#define get_bridge_status_COPY_IN \
   ({ in->br_index = br_index; })
-#define get_bridge_state_COPY_OUT ({ *cfg = out->cfg; *state = out->state; })
-#define get_bridge_state_CALL (in->br_index, &out->cfg, &out->state)
+#define get_bridge_status_COPY_OUT ({ *status = out->status; })
+#define get_bridge_status_CALL (in->br_index, &out->status)
 
 #if 0
-int CTL_set_bridge_config(int br_index, UID_STP_CFG_T * cfg);
+int CTL_set_bridge_config(int br_index,  STP_BridgeConfig *cfg);
 #endif
 #define CMD_CODE_set_bridge_config  103
-#define set_bridge_config_ARGS (int br_index, UID_STP_CFG_T *cfg)
+#define set_bridge_config_ARGS (int br_index, STP_BridgeConfig *cfg)
 struct set_bridge_config_IN {
        int br_index;
-       UID_STP_CFG_T cfg;
+       STP_BridgeConfig cfg;
 };
 struct set_bridge_config_OUT {
 };
@@ -99,33 +105,31 @@ struct set_bridge_config_OUT {
 #define set_bridge_config_CALL (in->br_index, &in->cfg)
 
 #if 0
-int CTL_get_port_state(int br_index, int port_index,
-                      UID_STP_PORT_CFG_T * cfg, UID_STP_PORT_STATE_T * state);
+int CTL_get_port_status(int br_index, int port_index, STP_PortStatus *status);
 #endif
-#define CMD_CODE_get_port_state  104
-#define get_port_state_ARGS (int br_index, int port_index, UID_STP_PORT_CFG_T *cfg, UID_STP_PORT_STATE_T *state)
-struct get_port_state_IN {
+#define CMD_CODE_get_port_status  104
+#define get_port_status_ARGS (int br_index, int port_index, STP_PortStatus *status)
+struct get_port_status_IN {
        int br_index;
        int port_index;
 };
-struct get_port_state_OUT {
-       UID_STP_PORT_CFG_T cfg;
-       UID_STP_PORT_STATE_T state;
+struct get_port_status_OUT {
+       STP_PortStatus status;
 };
-#define get_port_state_COPY_IN \
+#define get_port_status_COPY_IN \
   ({ in->br_index = br_index; in->port_index = port_index; })
-#define get_port_state_COPY_OUT ({ *cfg = out->cfg; *state = out->state; })
-#define get_port_state_CALL (in->br_index, in->port_index, &out->cfg, &out->state)
+#define get_port_status_COPY_OUT ({ *status = out->status; })
+#define get_port_status_CALL (in->br_index, in->port_index, &out->status)
 
 #if 0
-int CTL_set_port_config(int br_index, int port_index, UID_STP_PORT_CFG_T * cfg);
+int CTL_set_port_config(int br_index, int port_index, STP_PortConfig *cfg);
 #endif
 #define CMD_CODE_set_port_config  105
-#define set_port_config_ARGS (int br_index, int port_index, UID_STP_PORT_CFG_T *cfg)
+#define set_port_config_ARGS (int br_index, int port_index, STP_PortConfig *cfg)
 struct set_port_config_IN {
        int br_index;
        int port_index;
-       UID_STP_PORT_CFG_T cfg;
+       STP_PortConfig cfg;
 };
 struct set_port_config_OUT {
 };
@@ -134,10 +138,26 @@ struct set_port_config_OUT {
 #define set_port_config_COPY_OUT ({ (void)0; })
 #define set_port_config_CALL (in->br_index, in->port_index, &in->cfg)
 
+#if 0
+int CTL_port_mcheck(int br_index, int port_index);
+#endif
+#define CMD_CODE_port_mcheck  106
+#define port_mcheck_ARGS (int br_index, int port_index)
+struct port_mcheck_IN {
+       int br_index;
+       int port_index;
+};
+struct port_mcheck_OUT {
+};
+#define port_mcheck_COPY_IN \
+  ({ in->br_index = br_index; in->port_index = port_index; })
+#define port_mcheck_COPY_OUT ({ (void)0; })
+#define port_mcheck_CALL (in->br_index, in->port_index)
+
 #if 0
 int CTL_set_debug_level(int level);
 #endif
-#define CMD_CODE_set_debug_level 106
+#define CMD_CODE_set_debug_level 107
 #define set_debug_level_ARGS (int level)
 struct set_debug_level_IN {
        int level;
@@ -155,15 +175,15 @@ case CMD_CODE_ ## name : do { \
   if (0) LOG("CTL command " #name); \
   struct name ## _IN in0, *in = &in0; \
   struct name ## _OUT out0, *out = &out0; \
-  if (sizeof(*in) != lin || sizeof(*out) != (outbuf?*lout:0)) { \
+  if (sizeof(*in) != lin || sizeof(*out) != lout) { \
   LOG("Bad sizes lin %d != %zd or lout %d != %zd", \
-       lin, sizeof(*in), lout?*lout:0, sizeof(*out)); \
+       lin, sizeof(*in), lout, sizeof(*out)); \
     return -1; \
   } \
   memcpy(in, inbuf, lin); \
   int r = CTL_ ## name name ## _CALL; \
   if (r) return r; \
-  if (outbuf) memcpy(outbuf, out, *lout); \
+  if (outbuf) memcpy(outbuf, out, lout); \
   return r; \
 } while (0)
 
@@ -173,16 +193,16 @@ int CTL_ ## name name ## _ARGS \
 { \
   struct name ## _IN in0, *in=&in0; \
   struct name ## _OUT out0, *out = &out0; \
-  int l = sizeof(*out); \
   name ## _COPY_IN; \
   int res = 0; \
-  int r = send_ctl_message(CMD_CODE_ ## name, in, sizeof(*in), out, &l, \
-                           &res); \
-  if (r || res) LOG("Got return code %d, %d", r, res); \
+  LogString log = { .buf = "" };                                       \
+  int r = send_ctl_message(CMD_CODE_ ## name, in, sizeof(*in),         \
+                          out, sizeof(*out), &log, &res);              \
+  if (r || res) LOG("Got return code %d, %d\n%s", r, res, log.buf);    \
   if (r) return r; \
   if (res) return res; \
   name ## _COPY_OUT; \
-  return r; \
+  return 0; \
 }
 
 #endif
index 46d585193b876fa0ea93e7eec83a80e970d7c293..1a219bc441672b349dfbec64eb4fa4f5eac27c75 100644 (file)
@@ -32,6 +32,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#define NO_DAEMON
 #include "log.h"
 
 static int fd = -1;
@@ -81,28 +82,31 @@ void ctl_client_cleanup(void)
        }
 }
 
-int send_ctl_message(int cmd, void *inbuf, int lin, void *outbuf, int *lout,
-                    int *res)
+int send_ctl_message(int cmd, void *inbuf, int lin, void *outbuf, int lout,
+                    LogString *log, int *res)
 {
        struct ctl_msg_hdr mhdr;
        struct msghdr msg;
-       struct iovec iov[2];
+       struct iovec iov[3];
        int l;
 
        msg.msg_name = NULL;
        msg.msg_namelen = 0;
        msg.msg_iov = iov;
-       msg.msg_iovlen = 2;
+       msg.msg_iovlen = 3;
        msg.msg_control = NULL;
        msg.msg_controllen = 0;
 
        mhdr.cmd = cmd;
        mhdr.lin = lin;
-       mhdr.lout = lout != NULL ? *lout : 0;
+       mhdr.lout = lout;
+       mhdr.llog = sizeof(log->buf) - 1;
        iov[0].iov_base = &mhdr;
        iov[0].iov_len = sizeof(mhdr);
        iov[1].iov_base = (void *)inbuf;
        iov[1].iov_len = lin;
+        iov[2].iov_base = log->buf;
+        iov[2].iov_len = 0;
 
        l = sendmsg(fd, &msg, 0);
        if (l < 0) {
@@ -115,7 +119,10 @@ int send_ctl_message(int cmd, void *inbuf, int lin, void *outbuf, int *lout,
        }
 
        iov[1].iov_base = outbuf;
-       iov[1].iov_len = lout != NULL ? *lout : 0;
+       iov[1].iov_len = lout;
+
+        iov[2].iov_base = log->buf;
+        iov[2].iov_len = sizeof(log->buf);
 
        {
                struct pollfd pfd;
@@ -145,16 +152,24 @@ int send_ctl_message(int cmd, void *inbuf, int lin, void *outbuf, int *lout,
                        ERROR("Error getting message from server: %m");
                        return -1;
                }
-               if (l < sizeof(mhdr) || l != sizeof(mhdr) + mhdr.lout
+               if (l < sizeof(mhdr)
+                   || l != sizeof(mhdr) + mhdr.lout + mhdr.llog
                    || mhdr.cmd != cmd) {
                        ERROR("Error getting message from server: Bad format");
                        return -1;
                }
+               if (mhdr.lout != lout) {
+                       ERROR("Error, unexpected result length %d, "
+                             "expected %d\n", mhdr.lout, lout);
+                       return -1;
+               }
+               if (mhdr.llog >= sizeof(log->buf)) {
+                       ERROR("Invalid log message length %d", mhdr.llog);
+                       return -1;
+               }
        }
-       if (lout)
-               *lout = mhdr.lout;
        if (res)
                *res = mhdr.res;
-
+       log->buf[mhdr.llog] = 0;
        return 0;
 }
index 5d8a7d390118112f3cc0af70f5f0df6ccbe950ee..c3f2fac1a0065a756a0a54fc888807a43b1d40e0 100644 (file)
 #ifndef CTL_SOCKET_CLIENT_H
 #define CTL_SOCKET_CLIENT_H
 
-int send_ctl_message(int cmd, void *inbuf, int lin, void *outbuf, int *lout,
-                    int *res);
+#include "ctl_socket.h"
+
+int send_ctl_message(int cmd, void *inbuf, int lin, void *outbuf, int lout,
+                    LogString *log, int *res);
 
 int ctl_client_init(void);
 
index 88f6bf408396cc92391b8895bfae9f99275be2f6..df18ad3368e4a794dbe692f2352cac78310a4a85 100644 (file)
@@ -28,4 +28,9 @@
 int ctl_socket_init(void);
 void ctl_socket_cleanup(void);
 
+extern int ctl_in_handler;
+void _ctl_err_log(char *fmt, ...);
+
+#define ctl_err_log(_fmt...) ({ if (ctl_in_handler) _ctl_err_log(_fmt); })
+
 #endif
diff --git a/log.h b/log.h
index 145243863caadd7872dd5e152fbfcbb5c5e6f13b..ce0d94e14301753fd370673c0bd207e2460d2671 100644 (file)
--- a/log.h
+++ b/log.h
 
 #include <stdio.h>
 #include <stdarg.h>
+#include "ctl_socket_server.h"
 
 #define LOG_LEVEL_NONE 0
 #define LOG_LEVEL_ERROR 1
 #define LOG_LEVEL_INFO  2
 #define LOG_LEVEL_DEBUG 3
-#define LOG_LEVEL_RSTPLIB 4
 #define LOG_LEVEL_MAX 100
 
 #define LOG_LEVEL_DEFAULT LOG_LEVEL_INFO
@@ -60,9 +60,18 @@ extern int log_level;
 #define INFO(_fmt, _args...) \
        PRINT(LOG_LEVEL_INFO, "%s: " _fmt, __PRETTY_FUNCTION__, ##_args)
 
+#ifdef NO_DAEMON
+
 #define ERROR(_fmt, _args...) \
-       PRINT(LOG_LEVEL_ERROR, "error, %s: " _fmt, __PRETTY_FUNCTION__, ##_args)
+       PRINT(LOG_LEVEL_ERROR, "%s: " _fmt, ##_args)
 
+#else
+#define ERROR(_fmt, _args...) \
+       ({                                                              \
+               PRINT(LOG_LEVEL_ERROR, "error, %s: " _fmt, __PRETTY_FUNCTION__, ##_args); \
+               ctl_err_log(_fmt "\n", ##_args);                        \
+       })
+#endif
 static inline void dump_hex(void *b, int l)
 {
        unsigned char *buf = b;
index 456a8796f910faef27015240109aad8938f9982f..ca72eafbd9f55739a3e012ca42e71d01b05ae38a 100644 (file)
--- a/rstpctl.8
+++ b/rstpctl.8
@@ -18,11 +18,6 @@ command.
 
 .SH COMMANDS
 
-.B rstpctl rstp <bridge> {on|off}
-configures whether rstpd implements RSTP (Rapid Spanning Tree
-Protocol) for the specified bridge. The remaining commands are
-applicable only if rstpd is configured to run RSTP on that bridge.
-
 .B rstpctl showbridge [<bridge> ... ]
 displays the spanning tree configuration and status for the specified
 bridges. If no bridges are given, it displays the information for all
@@ -35,7 +30,7 @@ the information for all ports of the bridge.
 
 The format of the line is :
 .br
-.B "pes  name iiii sss  rrrr-rootbridgeid dddd-desgbridgeid dprt R"
+.B "pe  name iiii ssss  rrrr-rootbridgeid dddd-desgbridgeid dprt"
 .br
 where the following abbreviations are used.
 
@@ -43,23 +38,18 @@ where the following abbreviations are used.
 .br
 \fBe\fR: 'E' if the port is operating as an edge port, ' ' otherwise.
 .br
-\fBs\fR: 's' if the port is in STP (slow) mode, ' ' otherwise.
-.br
 \fBname\fR: The name of the port, i.e, the network interface name.
 .br
 \fBiiii\fR: The port id, containing the port priority and port number
 .br
-\fBsss\fR: The port state, one of Dis (disabled), Blk (blocking), Lrn
-(learning), Fwd (forwading), Non (non-stp), Unk (unknown).
+\fBssss\fR: The port state, one of down (disabled), disc (discarding),
+lear (learning), forw (forwading), unkn (unknown).
 .br
 \fBrrrr-rootbridgeid\fR: Root bridge id, including priority.
 .br
 \fBdddd-desgbridgeid\fR: Designated bridge id, including priority
 .br
 \fBdprt\fR: Designated port id
-.br
-\fBR\fR: Port role, one of 'A' (alternate), 'B' (backup), 'R' (root), 'D'
-(designated), '-' (non-stp)
 
 
 .B rstpctl showportdetail <bridge> [<port> ... ]
@@ -67,12 +57,6 @@ displays the spanning tree configuration and status for the specified
 ports much more verbosely. If no ports are specified, it displays the
 information for all ports of the bridge.
 
-.B rstpctl setbridgestate <bridge> {on|off}
-enables/disables the operation of RSTP. When RSTP is configured with
-the
-.BR rstp
-subcommand listed above, the default is enabled.
-
 .B rstpctl setbridgeprio <bridge> <priority>
 sets the bridge's priority to <priority>. The priority value is a
 number between 0 and 61440 in steps of 4096, and defaults to 32768.
@@ -94,6 +78,11 @@ sets the bridge's spanning tree algorithm to operate in normal
 mode. In normal mode, RSTP falls back to STP on ports where it
 sees other hosts operating in STP mode.
 
+.B rstpctl settxholdcount <bridge> <tx_hold_count>
+sets the transmit hold count, which limits the rate of transmission
+of BPDUs. No more than <tx_hold_count> + 1 BPDUs are transmitted in
+one second. This is a number from 1 to 10.
+
 .B rstpctl setportprio <bridge> <port> <priority>
 sets the ports's priority to <priority>. The priority value is a
 number from 0 to 240 in steps of 16, defaulting to 128.
@@ -104,15 +93,17 @@ automatically based on the link speed. This setting overrides the
 automatic setting. Setting this to zero puts it back in automatic
 mode.
 
-.B rstpctl setportedge <bridge> <port> {yes|no}
-sets or unsets the port's configures as an edge port. If a port is an
-edge port, then it is assumed to be a leaf link in the graph, not
+.B rstpctl setportadminedge <bridge> <port> {yes|no}
+sets or unsets the port's configuration as an edge port. If a port is
+an edge port, then it is assumed to be a leaf link in the graph, not
 connected to any other bridges. Receiving any STP BPDU's on a port
 configured as an edge port turns off edge port behaviour for the port.
 
-.B rstpctl setportnonstp <bridge> <port> {yes|no}
-: Setting this to yes disables RSTP operation on the port, which then
-is always kept in FORWARDING state.
+.B rstpctl setportautoedge <bridge> <port> {yes|no}
+sets or unsets the port's configuration as an auto edge port.
+If it is configured as auto edge, the port is brought up based on a
+shorter timer when no response in received and treated as an edge port.
+Receiving any STP BPDU's turns off edge port behaviour for the port.
 
 .B rstpctl portmcheck <bridge> <port>
 : This command is used when the port is operating in STP compatibility