1 /*****************************************************************************
2 Copyright (c) 2011 Factor-SPE
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2 of the License, or (at your option)
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc., 59
16 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 The full GNU General Public License is included in this distribution in the
21 Authors: Vitalii Demianets <vitas@nppfactor.kiev.ua>
23 ******************************************************************************/
32 #include "ctl_socket_client.h"
35 static int get_index_die(const char *ifname
, const char *doc
, bool die
)
37 int r
= if_nametoindex(ifname
);
41 "Can't find index for %s %s. Not a valid interface.\n",
50 static inline int get_index(const char *ifname
, const char *doc
)
52 return get_index_die(ifname
, doc
, true);
55 static inline int get_id(const char *str
, const char *doc
, unsigned int max_id
)
57 int id
= strtol(str
, NULL
, 10);
58 if((0 > id
) || (max_id
< id
)
59 || ((0 == id
) && ('0' != str
[0]))
62 fprintf(stderr
, "Bad %s %s\n", doc
, str
);
68 #define GET_NUM_FROM_PRIO(p) (__be16_to_cpu(p) & 0x0FFF)
70 #define BR_ID_FMT "%01hhX.%03hX.%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX"
71 #define BR_ID_ARGS(x) ((GET_PRIORITY_FROM_IDENTIFIER(x) >> 4) & 0x0F), \
72 GET_NUM_FROM_PRIO((x).s.priority), \
73 x.s.mac_address[0], x.s.mac_address[1], x.s.mac_address[2], \
74 x.s.mac_address[3], x.s.mac_address[4], x.s.mac_address[5]
76 #define PRT_ID_FMT "%01hhX.%03hX"
77 #define PRT_ID_ARGS(x) ((GET_PRIORITY_FROM_IDENTIFIER(x) >> 4) & 0x0F), \
80 #define BOOL_STR(x) ((x) ? "yes" : "no")
82 static int do_showbridge(const char *br_name
)
85 char root_port_name
[IFNAMSIZ
];
86 unsigned int root_portno
;
87 int br_index
= get_index_die(br_name
, "bridge", false);
91 if(CTL_get_cist_bridge_status(br_index
, &s
, root_port_name
))
93 printf("%s CIST info\n", br_name
);
94 printf(" enabled %s\n", BOOL_STR(s
.enabled
));
95 printf(" bridge id "BR_ID_FMT
"\n", BR_ID_ARGS(s
.bridge_id
));
96 printf(" designated root "BR_ID_FMT
"\n", BR_ID_ARGS(s
.designated_root
));
97 printf(" regional root "BR_ID_FMT
"\n", BR_ID_ARGS(s
.regional_root
));
98 printf(" root port ");
99 if(0 != (root_portno
= GET_NUM_FROM_PRIO(s
.root_port_id
)))
100 printf("%s (#%u)\n", root_port_name
, root_portno
);
103 printf(" path cost %-10u ", s
.root_path_cost
);
104 printf("internal path cost %u\n", s
.internal_path_cost
);
105 printf(" max age %-10hhu ", s
.root_max_age
);
106 printf("bridge max age %hhu\n", s
.bridge_max_age
);
107 printf(" forward delay %-10hhu ", s
.root_forward_delay
);
108 printf("bridge forward delay %hhu\n", s
.bridge_forward_delay
);
109 printf(" tx hold count %-10u ", s
.tx_hold_count
);
110 printf("max hops %hhu\n", s
.max_hops
);
111 printf(" force protocol version %u\n", s
.protocol_version
);
112 printf(" time since topology change %u\n", s
.time_since_topology_change
);
113 printf(" toplogy change count %u\n", s
.topology_change_count
);
114 printf(" topology change %s\n", BOOL_STR(s
.topology_change
));
119 #define SYSFS_PATH_MAX 256
120 #define SYSFS_CLASS_NET "/sys/class/net"
122 static int isbridge(const struct dirent
*entry
)
124 char path
[SYSFS_PATH_MAX
];
129 snprintf(path
, SYSFS_PATH_MAX
, SYSFS_CLASS_NET
"/%s/bridge",
132 result
= (0 == stat(path
, &st
)) && S_ISDIR(st
.st_mode
);
137 static int cmd_showbridge(int argc
, char *const *argv
)
141 struct dirent
**namelist
;
149 /* TODO: use versionsort, if available */
150 count
= scandir(SYSFS_CLASS_NET
, &namelist
, isbridge
, alphasort
);
153 fprintf(stderr
, "Error getting list of all bridges\n");
158 for(i
= 0; i
< count
; ++i
)
164 name
= namelist
[i
]->d_name
;
166 int err
= do_showbridge(name
);
173 for(i
= 0; i
< count
; ++i
)
181 static int cmd_showtree(int argc
, char *const *argv
)
184 char root_port_name
[IFNAMSIZ
];
185 unsigned int root_portno
;
186 int br_index
= get_index(argv
[1], "bridge");
189 int mstid
= get_id(argv
[2], "mstid", MAX_MSTID
);
193 if(CTL_get_msti_bridge_status(br_index
, mstid
, &s
, root_port_name
))
196 printf("%s MSTI %hu info\n", argv
[1], mstid
);
197 printf(" bridge id "BR_ID_FMT
"\n", BR_ID_ARGS(s
.bridge_id
));
198 printf(" regional root "BR_ID_FMT
"\n", BR_ID_ARGS(s
.regional_root
));
199 printf(" root port ");
200 if(0 != (root_portno
= GET_NUM_FROM_PRIO(s
.root_port_id
)))
201 printf("%s (#%u)\n", root_port_name
, root_portno
);
204 printf(" internal path cost %u\n", s
.internal_path_cost
);
205 printf(" time since topology change %u\n", s
.time_since_topology_change
);
206 printf(" toplogy change count %u\n", s
.topology_change_count
);
207 printf(" topology change %s\n", BOOL_STR(s
.topology_change
));
212 #define STATE_STR(_state) \
215 char *_str = "unknown"; \
218 case BR_STATE_DISABLED: \
219 case BR_STATE_BLOCKING: \
220 case BR_STATE_LISTENING: _str = "discarding"; break; \
221 case BR_STATE_LEARNING: _str = "learning"; break; \
222 case BR_STATE_FORWARDING:_str = "forwarding"; break; \
227 #define SHORT_STATE_STR(_state) \
230 char *_str = "unkn"; \
233 case BR_STATE_DISABLED: \
234 case BR_STATE_BLOCKING: \
235 case BR_STATE_LISTENING: _str = "disc"; break; \
236 case BR_STATE_LEARNING: _str = "lear"; break; \
237 case BR_STATE_FORWARDING:_str = "forw"; break; \
242 #define ADMIN_P2P_STR(_state) \
244 admin_p2p_t _s = _state; \
245 char *_str = "unkn"; \
248 case p2pForceFalse:_str = "no"; break; \
249 case p2pForceTrue: _str = "yes"; break; \
250 case p2pAuto: _str = "auto"; break; \
255 #define ROLE_STR(_role) \
257 port_role_t _r = _role; \
258 char *_str = "Unknown"; \
261 case roleRoot: _str = "Root"; break; \
262 case roleDesignated:_str = "Designated"; break; \
263 case roleAlternate: _str = "Alternate"; break; \
264 case roleBackup: _str = "Backup"; break; \
265 case roleMaster: _str = "Master"; break; \
266 case roleDisabled: _str = "Disabled"; break; \
271 #define SHORT_ROLE_STR(_role) \
273 port_role_t _r = _role; \
274 char *_str = "Unkn"; \
277 case roleRoot: _str = "Root"; break; \
278 case roleDesignated:_str = "Desg"; break; \
279 case roleAlternate: _str = "Altn"; break; \
280 case roleBackup: _str = "Back"; break; \
281 case roleMaster: _str = "Mstr"; break; \
282 case roleDisabled: _str = "Disa"; break; \
288 static int detail
= 0;
290 static int do_showport(int br_index
, const char *bridge_name
,
291 const char *port_name
)
295 int port_index
= get_index_die(port_name
, "port", false);
299 if((r
= CTL_get_cist_port_status(br_index
, port_index
, &s
)))
301 fprintf(stderr
, "%s:%s Failed to get port state\n",
302 bridge_name
, port_name
);
308 printf("%s:%s CIST info\n", bridge_name
, port_name
);
309 printf(" enabled %-23s ", BOOL_STR(s
.enabled
));
310 printf("role %s\n", ROLE_STR(s
.role
));
311 printf(" port id "PRT_ID_FMT
" ",
312 PRT_ID_ARGS(s
.port_id
));
313 printf("state %s\n", STATE_STR(s
.state
));
314 printf(" external port cost %-23u ", s
.external_port_path_cost
);
315 printf("admin external cost %u\n", s
.admin_external_port_path_cost
);
316 printf(" internal port cost %-23u ", s
.internal_port_path_cost
);
317 printf("admin internal cost %u\n", s
.admin_internal_port_path_cost
);
318 printf(" designated root "BR_ID_FMT
" ",
319 BR_ID_ARGS(s
.designated_root
));
320 printf("dsgn external cost %u\n", s
.designated_external_cost
);
321 printf(" dsgn regional root "BR_ID_FMT
" ",
322 BR_ID_ARGS(s
.designated_regional_root
));
323 printf("dsgn internal cost %u\n", s
.designated_internal_cost
);
324 printf(" designated bridge "BR_ID_FMT
" ",
325 BR_ID_ARGS(s
.designated_bridge
));
326 printf("designated port "PRT_ID_FMT
"\n",
327 PRT_ID_ARGS(s
.designated_port
));
328 printf(" admin edge port %-23s ", BOOL_STR(s
.admin_edge_port
));
329 printf("auto edge port %s\n", BOOL_STR(s
.auto_edge_port
));
330 printf(" oper edge port %-23s ", BOOL_STR(s
.oper_edge_port
));
331 printf("toplogy change ack %s\n", BOOL_STR(s
.tc_ack
));
332 printf(" point-to-point %-23s ", BOOL_STR(s
.oper_p2p
));
333 printf("admin point-to-point %s\n", ADMIN_P2P_STR(s
.admin_p2p
));
334 printf(" restricted role %-23s ", BOOL_STR(s
.restricted_role
));
335 printf("restricted TCN %s\n", BOOL_STR(s
.restricted_tcn
));
336 printf(" port hello time %-23hhu ", s
.port_hello_time
);
337 printf("disputed %s\n", BOOL_STR(s
.disputed
));
341 printf("%c%c %-5s "PRT_ID_FMT
" %4s "BR_ID_FMT
" "BR_ID_FMT
" "PRT_ID_FMT
" %s\n",
342 (s
.oper_p2p
) ? ' ' : '*',
343 (s
.oper_edge_port
) ? 'E' : ' ',
345 PRT_ID_ARGS(s
.port_id
),
346 s
.enabled
? SHORT_STATE_STR(s
.state
) : "down",
347 BR_ID_ARGS(s
.designated_root
),
348 BR_ID_ARGS(s
.designated_bridge
),
349 PRT_ID_ARGS(s
.designated_port
),
350 SHORT_ROLE_STR(s
.role
));
355 static int not_dot_dotdot(const struct dirent
*entry
)
357 const char *n
= entry
->d_name
;
359 return !('.' == n
[0] && (0 == n
[1] || ('.' == n
[1] && 0 == n
[2])));
362 static int cmd_showport(int argc
, char *const *argv
)
366 int br_index
= get_index(argv
[1], "bridge");
371 struct dirent
**namelist
;
379 char buf
[SYSFS_PATH_MAX
];
380 snprintf(buf
, sizeof(buf
), SYSFS_CLASS_NET
"/%s/brif", argv
[1]);
381 /* TODO: use versionsort, if available */
382 count
= scandir(buf
, &namelist
, not_dot_dotdot
, alphasort
);
385 fprintf(stderr
, "Error getting list of all ports of bridge %s\n",
391 for(i
= 0; i
< count
; ++i
)
397 name
= namelist
[i
]->d_name
;
399 int err
= do_showport(br_index
, argv
[1], name
);
406 for(i
= 0; i
< count
; ++i
)
414 static int cmd_showportdetail(int argc
, char *const *argv
)
417 return cmd_showport(argc
, argv
);
420 static int cmd_showtreeport(int argc
, char *const *argv
)
423 int br_index
= get_index(argv
[1], "bridge");
426 int port_index
= get_index(argv
[2], "port");
429 int mstid
= get_id(argv
[3], "mstid", MAX_MSTID
);
433 if(CTL_get_msti_port_status(br_index
, port_index
, mstid
, &s
))
436 printf("%s:%s MSTI %hu info\n", argv
[1], argv
[2], mstid
);
437 printf(" role %-23s ", ROLE_STR(s
.role
));
438 printf("port id "PRT_ID_FMT
"\n", PRT_ID_ARGS(s
.port_id
));
439 printf(" state %-23s ", STATE_STR(s
.state
));
440 printf("disputed %s\n", BOOL_STR(s
.disputed
));
441 printf(" internal port cost %-23u ", s
.internal_port_path_cost
);
442 printf("admin internal cost %u\n", s
.admin_internal_port_path_cost
);
443 printf(" dsgn regional root "BR_ID_FMT
" ",
444 BR_ID_ARGS(s
.designated_regional_root
));
445 printf("dsgn internal cost %u\n", s
.designated_internal_cost
);
446 printf(" designated bridge "BR_ID_FMT
" ",
447 BR_ID_ARGS(s
.designated_bridge
));
448 printf("designated port "PRT_ID_FMT
"\n",
449 PRT_ID_ARGS(s
.designated_port
));
454 static unsigned int getuint(const char *s
)
458 l
= strtoul(s
, &end
, 0);
459 if(0 == *s
|| 0 != *end
|| INT_MAX
< l
)
461 fprintf(stderr
, "Invalid unsigned int arg %s\n", s
);
467 static int getenum(const char *s
, const char *opt
[])
470 for(i
= 0; opt
[i
] != NULL
; ++i
)
471 if(0 == strcmp(s
, opt
[i
]))
474 fprintf(stderr
, "Invalid argument %s: expecting one of ", s
);
475 for(i
= 0; opt
[i
] != NULL
; ++i
)
476 fprintf(stderr
, "%s%s", opt
[i
], (opt
[i
+ 1] ? ", " : "\n"));
481 static int getyesno(const char *s
, const char *yes
, const char *no
)
483 /* Reverse yes and no so error message looks more normal */
484 const char *opt
[] = { yes
, no
, NULL
};
485 return 1 - getenum(s
, opt
);
488 static int cmd_setmstconfid(int argc
, char *const *argv
)
490 int br_index
= get_index(argv
[1], "bridge");
493 unsigned int revision
= getuint(argv
[2]);
494 if(revision
> 0xFFFF)
496 fprintf(stderr
, "Bad revision %s\n", argv
[2]);
499 return CTL_set_mstconfid(br_index
, revision
, argv
[3]);
502 #define set_bridge_cfg(field, value) \
504 CIST_BridgeConfig c; \
505 memset(&c, 0, sizeof(c)); \
507 c.set_ ## field = true; \
508 int r = CTL_set_cist_bridge_config(br_index, &c); \
510 printf("Couldn't change bridge " #field "\n"); \
514 #define set_port_cfg(field, value) \
517 memset(&c, 0, sizeof(c)); \
519 c.set_ ## field = true; \
520 int r = CTL_set_cist_port_config(br_index, port_index, &c); \
522 printf("Couldn't change port " #field "\n"); \
526 #define set_tree_port_cfg(field, value) \
529 memset(&c, 0, sizeof(c)); \
531 c.set_ ## field = true; \
532 int r = CTL_set_msti_port_config(br_index, port_index, mstid, &c); \
534 printf("Couldn't change per-tree port " #field "\n"); \
538 static int cmd_setbridgemaxage(int argc
, char *const *argv
)
540 int br_index
= get_index(argv
[1], "bridge");
543 unsigned int max_age
= getuint(argv
[2]);
546 return set_bridge_cfg(bridge_max_age
, max_age
);
549 static int cmd_setbridgefdelay(int argc
, char *const *argv
)
551 int br_index
= get_index(argv
[1], "bridge");
554 unsigned int forward_delay
= getuint(argv
[2]);
555 if(forward_delay
> 255)
557 return set_bridge_cfg(bridge_forward_delay
, forward_delay
);
560 static int cmd_setbridgemaxhops(int argc
, char *const *argv
)
562 int br_index
= get_index(argv
[1], "bridge");
565 unsigned int max_hops
= getuint(argv
[2]);
568 return set_bridge_cfg(max_hops
, max_hops
);
571 static int cmd_setbridgeforcevers(int argc
, char *const *argv
)
573 int br_index
= get_index(argv
[1], "bridge");
576 const char *opts
[] = { "stp", "rstp", "mstp", NULL
};
577 int vals
[] = { protoSTP
, protoRSTP
, protoMSTP
};
578 return set_bridge_cfg(protocol_version
, vals
[getenum(argv
[2], opts
)]);
581 static int cmd_setbridgetxholdcount(int argc
, char *const *argv
)
583 int br_index
= get_index(argv
[1], "bridge");
586 return set_bridge_cfg(tx_hold_count
, getuint(argv
[2]));
589 static int cmd_settreeprio(int argc
, char *const *argv
)
591 int br_index
= get_index(argv
[1], "bridge");
594 int mstid
= get_id(argv
[2], "mstid", MAX_MSTID
);
597 unsigned int prio
= getuint(argv
[3]);
600 return CTL_set_msti_bridge_config(br_index
, mstid
, prio
);
603 static int cmd_setportpathcost(int argc
, char *const *argv
)
605 int br_index
= get_index(argv
[1], "bridge");
608 int port_index
= get_index(argv
[2], "port");
611 return set_port_cfg(admin_external_port_path_cost
, getuint(argv
[3]));
614 static int cmd_setportadminedge(int argc
, char *const *argv
)
616 int br_index
= get_index(argv
[1], "bridge");
619 int port_index
= get_index(argv
[2], "port");
622 return set_port_cfg(admin_edge_port
, getyesno(argv
[3], "yes", "no"));
625 static int cmd_setportautoedge(int argc
, char *const *argv
)
627 int br_index
= get_index(argv
[1], "bridge");
630 int port_index
= get_index(argv
[2], "port");
633 return set_port_cfg(auto_edge_port
, getyesno(argv
[3], "yes", "no"));
636 static int cmd_setportp2p(int argc
, char *const *argv
)
638 int br_index
= get_index(argv
[1], "bridge");
641 int port_index
= get_index(argv
[2], "port");
644 const char *opts
[] = { "no", "yes", "auto", NULL
};
645 int vals
[] = { p2pForceFalse
, p2pForceTrue
, p2pAuto
};
646 return set_port_cfg(admin_p2p
, vals
[getenum(argv
[3], opts
)]);
649 static int cmd_setportrestrrole(int argc
, char *const *argv
)
651 int br_index
= get_index(argv
[1], "bridge");
654 int port_index
= get_index(argv
[2], "port");
657 return set_port_cfg(restricted_role
, getyesno(argv
[3], "yes", "no"));
660 static int cmd_setportrestrtcn(int argc
, char *const *argv
)
662 int br_index
= get_index(argv
[1], "bridge");
665 int port_index
= get_index(argv
[2], "port");
668 return set_port_cfg(restricted_tcn
, getyesno(argv
[3], "yes", "no"));
671 static int cmd_settreeportprio(int argc
, char *const *argv
)
673 int br_index
= get_index(argv
[1], "bridge");
676 int port_index
= get_index(argv
[2], "port");
679 int mstid
= get_id(argv
[3], "mstid", MAX_MSTID
);
682 unsigned int prio
= getuint(argv
[4]);
685 return set_tree_port_cfg(port_priority
, prio
);
688 static int cmd_settreeportcost(int argc
, char *const *argv
)
690 int br_index
= get_index(argv
[1], "bridge");
693 int port_index
= get_index(argv
[2], "port");
696 int mstid
= get_id(argv
[3], "mstid", MAX_MSTID
);
699 return set_tree_port_cfg(admin_internal_port_path_cost
, getuint(argv
[4]));
702 static int cmd_portmcheck(int argc
, char *const *argv
)
704 int br_index
= get_index(argv
[1], "bridge");
707 int port_index
= get_index(argv
[2], "port");
710 return CTL_port_mcheck(br_index
, port_index
);
713 static int cmd_debuglevel(int argc
, char *const *argv
)
715 return CTL_set_debug_level(getuint(argv
[1]));
718 static int cmd_showmstilist(int argc
, char *const *argv
)
720 int br_index
= get_index(argv
[1], "bridge");
723 int num_mstis
= 0, i
;
724 __u16 mstids
[MAX_IMPLEMENTATION_MSTIS
+ 1]; /* +1 - for the CIST */
726 if(CTL_get_mstilist(br_index
, &num_mstis
, mstids
))
729 printf("%s list of known MSTIs:\n", argv
[1]);
730 for(i
= 0; i
< num_mstis
; ++i
)
731 printf(" %hu", mstids
[i
]);
737 static int cmd_showmstconfid(int argc
, char *const *argv
)
739 mst_configuration_identifier_t cfgid
;
740 int br_index
= get_index(argv
[1], "bridge");
745 if(CTL_get_mstconfid(br_index
, &cfgid
))
748 printf("%s MST Configuration Identifier:\n", argv
[1]);
749 printf(" Format Selector: %hhu\n", cfgid
.s
.selector
);
750 printf(" Configuration Name: %.*s\n", CONFIGURATION_NAME_LEN
,
751 cfgid
.s
.configuration_name
);
752 printf(" Revision Level: %hu\n",
753 __be16_to_cpu(cfgid
.s
.revision_level
));
754 printf(" Configuration Digest: ");
755 for(i
= 0; i
< CONFIGURATION_DIGEST_LEN
; ++i
)
756 printf("%02hhX", cfgid
.s
.configuration_digest
[i
]);
762 static int cmd_createtree(int argc
, char *const *argv
)
764 int br_index
= get_index(argv
[1], "bridge");
767 int mstid
= get_id(argv
[2], "mstid", MAX_MSTID
);
770 return CTL_create_msti(br_index
, mstid
);
773 static int cmd_deletetree(int argc
, char *const *argv
)
775 int br_index
= get_index(argv
[1], "bridge");
778 int mstid
= get_id(argv
[2], "mstid", MAX_MSTID
);
781 return CTL_delete_msti(br_index
, mstid
);
784 static int cmd_showvid2fid(int argc
, char *const *argv
)
786 __u16 vid2fid
[MAX_VID
+ 2];
787 int br_index
= get_index(argv
[1], "bridge");
791 if(CTL_get_vids2fids(br_index
, vid2fid
))
794 printf("%s VID-to-FID allocation table:\n", argv
[1]);
797 vid2fid
[MAX_VID
+ 1] = 0xFFFF; /* helps to finalize last interval */
799 cur_fid
= vid2fid
[0];
800 for(i
= 1; i
<= MAX_VID
; ++i
)
801 if(cur_fid
> vid2fid
[i
])
802 cur_fid
= vid2fid
[i
];
803 if(cur_fid
> MAX_FID
)
805 printf(" FID %u:", cur_fid
);
806 for(i
= 0, interval_count
= 0; i
<= (MAX_VID
+ 1); ++i
)
808 if(cur_fid
!= vid2fid
[i
])
812 printf(" %u", i
- interval_count
);
813 if(1 < interval_count
)
814 printf("-%u", i
- 1);
828 static int cmd_showfid2mstid(int argc
, char *const *argv
)
830 __u16 fid2mstid
[MAX_FID
+ 2];
831 int br_index
= get_index(argv
[1], "bridge");
835 if(CTL_get_fids2mstids(br_index
, fid2mstid
))
838 printf("%s FID-to-MSTID allocation table:\n", argv
[1]);
841 fid2mstid
[MAX_FID
+ 1] = 0xFFFF; /* helps to finalize last interval */
843 cur_mstid
= fid2mstid
[0];
844 for(i
= 1; i
<= MAX_FID
; ++i
)
845 if(cur_mstid
> fid2mstid
[i
])
846 cur_mstid
= fid2mstid
[i
];
847 if(cur_mstid
> MAX_MSTID
)
849 printf(" MSTID %u:", cur_mstid
);
850 for(i
= 0, interval_count
= 0; i
<= (MAX_FID
+ 1); ++i
)
852 if(cur_mstid
!= fid2mstid
[i
])
856 printf(" %u", i
- interval_count
);
857 if(1 < interval_count
)
858 printf("-%u", i
- 1);
863 fid2mstid
[i
] = 0xFFFF;
872 static int cmd_setvid2fid(int argc
, char *const *argv
)
874 int br_index
= get_index(argv
[1], "bridge");
877 int vid
= get_id(argv
[2], "VID", MAX_VID
);
882 fprintf(stderr
, "Bad VID %s\n", argv
[2]);
885 int fid
= get_id(argv
[3], "FID", MAX_FID
);
888 return CTL_set_vid2fid(br_index
, vid
, fid
);
891 static int cmd_setfid2mstid(int argc
, char *const *argv
)
893 int br_index
= get_index(argv
[1], "bridge");
896 int fid
= get_id(argv
[2], "FID", MAX_FID
);
899 int mstid
= get_id(argv
[3], "mstid", MAX_MSTID
);
902 return CTL_set_fid2mstid(br_index
, fid
, mstid
);
910 int (*func
) (int argc
, char *const *argv
);
915 static const struct command commands
[] =
917 /* Show global bridge */
918 {0, 32, "showbridge", cmd_showbridge
,
919 "[<bridge> ... ]", "Show bridge state for the CIST"},
920 {1, 0, "showmstilist", cmd_showmstilist
,
921 "<bridge>", "Show list of registered MSTIs"},
922 {1, 0, "showmstconfid", cmd_showmstconfid
,
923 "<bridge>", "Show MST ConfigId"},
924 {1, 0, "showvid2fid", cmd_showvid2fid
,
925 "<bridge>", "Show VID-to-FID allocation table"},
926 {1, 0, "showfid2mstid", cmd_showfid2mstid
,
927 "<bridge>", "Show FID-to-MSTID allocation table"},
928 /* Show global port */
929 {1, 32, "showport", cmd_showport
,
930 "<bridge> [<port> ... ]", "Show port state for the CIST"},
931 {1, 32, "showportdetail", cmd_showportdetail
,
932 "<bridge> [<port> ... ]", "Show port detailed state for the CIST"},
933 /* Show tree bridge */
934 {2, 0, "showtree", cmd_showtree
,
935 "<bridge> <mstid>", "Show bridge state for the given MSTI"},
937 {3, 0, "showtreeport", cmd_showtreeport
,
938 "<bridge> <port> <mstid>", "Show port detailed state for the given MSTI"},
940 /* Set global bridge */
941 {3, 0, "setmstconfid", cmd_setmstconfid
,
942 "<bridge> <revision> <name>",
943 "Set MST ConfigId elements: Revision Level (0-65535) and Name"},
944 {3, 0, "setvid2fid", cmd_setvid2fid
,
945 "<bridge> <VID> <FID>", "Set VID-to-FID allocation"},
946 {3, 0, "setfid2mstid", cmd_setfid2mstid
,
947 "<bridge> <FID> <mstid>", "Set FID-to-MSTID allocation"},
948 {2, 0, "setmaxage", cmd_setbridgemaxage
,
949 "<bridge> <max_age>", "Set bridge max age (6-40)"},
950 {2, 0, "setfdelay", cmd_setbridgefdelay
,
951 "<bridge> <fwd_delay>", "Set bridge forward delay (4-30)"},
952 {2, 0, "setmaxhops", cmd_setbridgemaxhops
,
953 "<bridge> <max_hops>", "Set bridge max hops (6-40)"},
954 {2, 0, "setforcevers", cmd_setbridgeforcevers
,
955 "<bridge> {mstp|rstp|stp}", "Force Spanning Tree protocol version"},
956 {2, 0, "settxholdcount", cmd_setbridgetxholdcount
,
957 "<bridge> <tx_hold_count>", "Set bridge transmit hold count (1-10)"},
958 /* Set tree bridge */
959 {2, 0, "createtree", cmd_createtree
,
960 "<bridge> <mstid>", "Create new MSTI"},
961 {2, 0, "deletetree", cmd_deletetree
,
962 "<bridge> <mstid>", "Delete existing MSTI"},
963 {3, 0, "settreeprio", cmd_settreeprio
,
964 "<bridge> <mstid> <priority>",
965 "Set bridge priority (0-15) for the given MSTI"},
966 /* Set global port */
967 {3, 0, "setportpathcost", cmd_setportpathcost
,
968 "<bridge> <port> <cost>",
969 "Set port external path cost for the CIST (0 = auto)"},
970 {3, 0, "setportadminedge", cmd_setportadminedge
,
971 "<bridge> <port> {yes|no}", "Set initial edge state"},
972 {3, 0, "setportautoedge", cmd_setportautoedge
,
973 "<bridge> <port> {yes|no}", "Enable auto transition to/from edge state"},
974 {3, 0, "setportp2p", cmd_setportp2p
,
975 "<bridge> <port> {yes|no|auto}", "Set p2p detection mode"},
976 {3, 0, "setportrestrrole", cmd_setportrestrrole
,
977 "<bridge> <port> {yes|no}", "Restrict port ability to take Root role"},
978 {3, 0, "setportrestrtcn", cmd_setportrestrtcn
,
979 "<bridge> <port> {yes|no}",
980 "Restrict port ability to propagate received TCNs"},
981 {2, 0, "portmcheck", cmd_portmcheck
,
982 "<bridge> <port>", "Try to get back from STP to rapid (RSTP/MSTP) mode"},
984 {4, 0, "settreeportprio", cmd_settreeportprio
,
985 "<bridge> <port> <mstid> <priority>",
986 "Set port priority (0-15) for the given MSTI"},
987 {4, 0, "settreeportcost", cmd_settreeportcost
,
988 "<bridge> <port> <mstid> <cost>",
989 "Set port internal path cost for the given MSTI (0 = auto)"},
992 {1, 0, "debuglevel", cmd_debuglevel
, "<level>", "Level of verbosity"},
995 static const struct command
*command_lookup(const char *cmd
)
999 for(i
= 0; i
< COUNT_OF(commands
); ++i
)
1001 if(!strcmp(cmd
, commands
[i
].name
))
1002 return &commands
[i
];
1008 static void command_helpall(void)
1012 for(i
= 0; i
< COUNT_OF(commands
); ++i
)
1014 printf("-%s:\n %-16s %s\n", commands
[i
].help
, commands
[i
].name
,
1015 commands
[i
].format
);
1019 static void help(void)
1021 printf("Usage: mstpctl [commands]\n");
1022 printf("commands:\n");
1026 #define PACKAGE_VERSION2(v, b) "mstp, " #v "-" #b
1027 #define PACKAGE_VERSION(v, b) PACKAGE_VERSION2(v, b)
1029 int main(int argc
, char *const *argv
)
1031 const struct command
*cmd
;
1033 static const struct option options
[] =
1035 {.name
= "help", .val
= 'h'},
1036 {.name
= "version", .val
= 'V'},
1040 while(EOF
!= (f
= getopt_long(argc
, argv
, "Vh", options
, NULL
)))
1047 printf("%s\n", PACKAGE_VERSION(VERSION
, BUILD
));
1050 fprintf(stderr
, "Unknown option '%c'\n", f
);
1057 if(ctl_client_init())
1059 fprintf(stderr
, "can't setup control connection\n");
1065 if(NULL
== (cmd
= command_lookup(argv
[0])))
1067 fprintf(stderr
, "never heard of command [%s]\n", argv
[0]);
1071 if(argc
< cmd
->nargs
+ 1 || argc
> cmd
->nargs
+ cmd
->optargs
+ 1)
1073 printf("Incorrect number of arguments for command\n");
1074 printf("Usage: mstpctl %s %s\n %s\n",
1075 cmd
->name
, cmd
->format
, cmd
->help
);
1079 return cmd
->func(argc
, argv
);
1086 /* Implementation of client-side functions */
1087 CLIENT_SIDE_FUNCTION(get_cist_bridge_status
)
1088 CLIENT_SIDE_FUNCTION(get_msti_bridge_status
)
1089 CLIENT_SIDE_FUNCTION(set_cist_bridge_config
)
1090 CLIENT_SIDE_FUNCTION(set_msti_bridge_config
)
1091 CLIENT_SIDE_FUNCTION(get_cist_port_status
)
1092 CLIENT_SIDE_FUNCTION(get_msti_port_status
)
1093 CLIENT_SIDE_FUNCTION(set_cist_port_config
)
1094 CLIENT_SIDE_FUNCTION(set_msti_port_config
)
1095 CLIENT_SIDE_FUNCTION(port_mcheck
)
1096 CLIENT_SIDE_FUNCTION(set_debug_level
)
1097 CLIENT_SIDE_FUNCTION(get_mstilist
)
1098 CLIENT_SIDE_FUNCTION(create_msti
)
1099 CLIENT_SIDE_FUNCTION(delete_msti
)
1100 CLIENT_SIDE_FUNCTION(get_mstconfid
)
1101 CLIENT_SIDE_FUNCTION(set_mstconfid
)
1102 CLIENT_SIDE_FUNCTION(get_vids2fids
)
1103 CLIENT_SIDE_FUNCTION(get_fids2mstids
)
1104 CLIENT_SIDE_FUNCTION(set_vid2fid
)
1105 CLIENT_SIDE_FUNCTION(set_fid2mstid
)
1106 CLIENT_SIDE_FUNCTION(set_vids2fids
)
1107 CLIENT_SIDE_FUNCTION(set_fids2mstids
)
1109 /*********************** Logging *********************/
1111 void Dprintf(int level
, const char *fmt
, ...)
1113 char logbuf
[LOG_STRING_LEN
];
1114 logbuf
[sizeof(logbuf
) - 1] = 0;
1117 vsnprintf(logbuf
, sizeof(logbuf
) - 1, fmt
, ap
);
1119 printf("%s\n", logbuf
);