]> git.ipfire.org Git - people/ms/rstp.git/blobdiff - ctl_main.c
Use new RSTP library.
[people/ms/rstp.git] / ctl_main.c
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,