+++ /dev/null
-Index: bridge_ctl.h
-===================================================================
---- bridge_ctl.h (revision 22)
-+++ bridge_ctl.h (revision 27)
-@@ -37,7 +37,7 @@
- __u8 macaddr[ETH_ALEN];
- char name[IFNAMSIZ];
-
-- bool up, stp_up;
-+ bool up;
- } sysdep_br_data_t;
-
- typedef struct
-Index: bridge-stp
-===================================================================
---- bridge-stp (revision 22)
-+++ bridge-stp (revision 27)
-@@ -44,12 +44,12 @@
- checkpid $pid_file || exit 1
- for b in $MSTP_BRIDGES; do
- if [ "$bridge" == "$b" ]; then
-- exec /sbin/mstpctl notify-daemon-that-stp-is-on $bridge
-+ exec /sbin/mstpctl addbridge $bridge
- fi
- done
- exit 1 ;;
- stop)
-- exec /sbin/mstpctl notify-daemon-that-stp-is-off $bridge
-+ exec /sbin/mstpctl delbridge $bridge
- ;;
- *)
- echo "Unknown action:" $2
-Index: ctl_functions.h
-===================================================================
---- ctl_functions.h (revision 22)
-+++ ctl_functions.h (revision 27)
-@@ -448,23 +448,16 @@
- #define set_fids2mstids_CALL (in->br_index, in->fids2mstids)
- CTL_DECLARE(set_fids2mstids);
-
--/* stp_mode_notification */
--#define CMD_CODE_stp_mode_notification (122 | RESPONSE_FIRST_HANDLE_LATER)
--#define stp_mode_notification_ARGS (int br_index, bool on)
--struct stp_mode_notification_IN
--{
-- int br_index;
-- bool on;
--};
--struct stp_mode_notification_OUT
--{
--};
--#define stp_mode_notification_COPY_IN ({ in->br_index = br_index; \
-- in->on = on; })
--#define stp_mode_notification_COPY_OUT ({ (void)0; })
--#define stp_mode_notification_CALL (in->br_index, in->on)
--CTL_DECLARE(stp_mode_notification);
-+/* add bridges */
-+#define CMD_CODE_add_bridges (122 | RESPONSE_FIRST_HANDLE_LATER)
-+#define add_bridges_ARGS (int *br_array, int* *ifaces_lists)
-+CTL_DECLARE(add_bridges);
-
-+/* delete bridges */
-+#define CMD_CODE_del_bridges (123 | RESPONSE_FIRST_HANDLE_LATER)
-+#define del_bridges_ARGS (int *br_array)
-+CTL_DECLARE(del_bridges);
-+
- /* General case part in ctl command server switch */
- #define SERVER_MESSAGE_CASE(name) \
- case CMD_CODE_ ## name : do \
-Index: bridge_track.c
-===================================================================
---- bridge_track.c (revision 22)
-+++ bridge_track.c (revision 27)
-@@ -175,27 +175,11 @@
- }
- }
-
--static bool stp_enabled(bridge_t * br)
-+static void set_br_up(bridge_t * br, bool up)
- {
-- char path[40 + IFNAMSIZ];
-- sprintf(path, "/sys/class/net/%s/bridge/stp_state", br->sysdeps.name);
-- FILE *f = fopen(path, "r");
-- int enabled = 0;
-- if(!f || (1 != fscanf(f, "%d", &enabled)))
-- ERROR("Can't read from %s", path);
-- fclose(f);
-- INFO("STP on %s state %d", br->sysdeps.name, enabled);
-+ INFO("%s was %s", br->sysdeps.name, br->sysdeps.up ? "up" : "down");
-+ INFO("Set bridge %s %s", br->sysdeps.name, up ? "up" : "down");
-
-- return enabled == 2; /* ie user mode STP */
--}
--
--static void set_br_up(bridge_t * br, bool up, bool stp_up)
--{
-- INFO("%s was %s stp was %s", br->sysdeps.name,
-- br->sysdeps.up ? "up" : "down", br->sysdeps.stp_up ? "up" : "down");
-- INFO("Set bridge %s %s stp %s" , br->sysdeps.name,
-- up ? "up" : "down", stp_up ? "up" : "down");
--
- bool changed = false;
-
- if(up != br->sysdeps.up)
-@@ -204,12 +188,6 @@
- changed = true;
- }
-
-- if(br->sysdeps.stp_up != stp_up)
-- {
-- br->sysdeps.stp_up = stp_up;
-- changed = true;
-- }
--
- if(check_mac_address(br->sysdeps.name, br->sysdeps.macaddr))
- {
- /* MAC address changed */
-@@ -218,7 +196,7 @@
- }
-
- if(changed)
-- MSTP_IN_set_bridge_enable(br, br->sysdeps.up && br->sysdeps.stp_up);
-+ MSTP_IN_set_bridge_enable(br, br->sysdeps.up);
- }
-
- static void set_if_up(port_t * ifc, bool up)
-@@ -291,15 +269,10 @@
- if((br_index >= 0) && (br_index != if_index))
- {
- if(!(br = find_br(br_index)))
-- br = create_br(br_index);
-- if(!br)
-- {
-- ERROR("Couldn't create data for bridge interface %d", br_index);
-- return -1;
-- }
-+ return -2; /* bridge not in list */
- int br_flags = get_flags(br->sysdeps.name);
- if(br_flags >= 0)
-- set_br_up(br, !!(br_flags & IFF_UP), stp_enabled(br));
-+ set_br_up(br, !!(br_flags & IFF_UP));
- }
-
- if(br)
-@@ -358,15 +331,8 @@
- if(br_index == if_index)
- {
- if(!(br = find_br(br_index)))
-- {
-- if(!(br = create_br(br_index)))
-- {
-- ERROR("Couldn't create data for bridge interface %d",
-- br_index);
-- return -1;
-- }
-- }
-- set_br_up(br, up, stp_enabled(br));
-+ return -2; /* bridge not in list */
-+ set_br_up(br, up);
- }
- }
- }
-@@ -412,8 +378,6 @@
- /* sanity checks */
- TST(br == ifc->bridge,);
- TST(ifc->sysdeps.up,);
-- if(!br->sysdeps.stp_up)
-- return;
-
- /* Validate Ethernet and LLC header,
- * maybe we can skip this check thanks to Berkeley filter in packet socket?
-@@ -840,12 +804,85 @@
- return MSTP_IN_set_all_fids2mstids(br, fids2mstids) ? 0 : -1;
- }
-
--int CTL_stp_mode_notification(int br_index, bool on)
-+int CTL_add_bridges(int *br_array, int* *ifaces_lists)
- {
-- int br_flags;
-- CTL_CHECK_BRIDGE;
-- if(0 > (br_flags = get_flags(br->sysdeps.name)))
-- return br_flags;
-- set_br_up(br, !!(br_flags & IFF_UP), on);
-+ int i, j, ifcount, brcount = br_array[0];
-+ bridge_t *br, *other_br;
-+ port_t *ifc, *nxt;
-+ int br_flags, if_flags;
-+ int *if_array;
-+ bool found;
-+
-+ for(i = 1; i <= brcount; ++i)
-+ {
-+ if(NULL == (br = find_br(br_array[i])))
-+ {
-+ if(NULL == (br = create_br(br_array[i])))
-+ {
-+ ERROR("Couldn't create data for bridge interface %d",
-+ br_array[i]);
-+ return -1;
-+ }
-+ if(0 <= (br_flags = get_flags(br->sysdeps.name)))
-+ set_br_up(br, !!(br_flags & IFF_UP));
-+ }
-+ if_array = ifaces_lists[i - 1];
-+ ifcount = if_array[0];
-+ /* delete all interfaces which are not in list */
-+ list_for_each_entry_safe(ifc, nxt, &br->ports, br_list)
-+ {
-+ found = false;
-+ for(j = 1; j <= ifcount; ++j)
-+ {
-+ if(ifc->sysdeps.if_index == if_array[j])
-+ {
-+ found = true;
-+ break;
-+ }
-+ }
-+ if(!found)
-+ delete_if(ifc);
-+ }
-+ /* add all new interfaces from the list */
-+ for(j = 1; j <= ifcount; ++j)
-+ {
-+ if(NULL != find_if(br, if_array[j]))
-+ continue;
-+ /* Check if this interface is slave of another bridge */
-+ list_for_each_entry(other_br, &bridges, list)
-+ {
-+ if(other_br != br)
-+ if(delete_if_byindex(other_br, if_array[j]))
-+ {
-+ INFO("Device %d has come to bridge %s. "
-+ "Missed notify for deletion from bridge %s",
-+ if_array[j], br->sysdeps.name,
-+ other_br->sysdeps.name);
-+ break;
-+ }
-+ }
-+ if(NULL == (ifc = create_if(br, if_array[j])))
-+ {
-+ INFO("Couldn't create data for interface %d (master %s)",
-+ if_array[j], br->sysdeps.name);
-+ continue;
-+ }
-+ if(0 <= (if_flags = get_flags(ifc->sysdeps.name)))
-+ set_if_up(ifc, (IFF_UP | IFF_RUNNING) ==
-+ (if_flags & (IFF_UP | IFF_RUNNING))
-+ );
-+ }
-+ }
-+
- return 0;
- }
-+
-+int CTL_del_bridges(int *br_array)
-+{
-+ int i, brcount = br_array[0];
-+
-+ for(i = 1; i <= brcount; ++i)
-+ delete_br_byindex(br_array[i]);
-+
-+ return 0;
-+}
-Index: ctl_socket_server.c
-===================================================================
---- ctl_socket_server.c (revision 22)
-+++ ctl_socket_server.c (revision 27)
-@@ -82,8 +82,92 @@
- SERVER_MESSAGE_CASE(set_fid2mstid);
- SERVER_MESSAGE_CASE(set_vids2fids);
- SERVER_MESSAGE_CASE(set_fids2mstids);
-- SERVER_MESSAGE_CASE(stp_mode_notification);
-
-+ case CMD_CODE_add_bridges:
-+ {
-+ if(0 != lout)
-+ {
-+ LOG("Bad sizes: lout %d != 0", lout);
-+ return -1;
-+ }
-+ if(sizeof(int) > lin)
-+ {
-+ LOG("Bad sizes: lin == 0");
-+ return -1;
-+ }
-+ int *br_array = inbuf;
-+ int i, serialized_data_count, chunk_count, brcount = br_array[0];
-+ int *ptr = br_array + (serialized_data_count = (brcount + 1));
-+ if(lin < ((serialized_data_count + 1) * sizeof(int)))
-+ {
-+bad_lin1: LOG("Bad sizes: lin %d < %d", lin,
-+ (serialized_data_count + 1) * sizeof(int));
-+ return -1;
-+ }
-+ for(i = 0; i < brcount; ++i)
-+ {
-+ serialized_data_count += (chunk_count = *ptr + 1);
-+ if(i < (brcount - 1))
-+ {
-+ if(lin < ((serialized_data_count + 1) * sizeof(int)))
-+ goto bad_lin1;
-+ ptr += chunk_count;
-+ }
-+ else
-+ {
-+ if(lin != (serialized_data_count * sizeof(int)))
-+ {
-+ LOG("Bad sizes: lin %d != %d", lin,
-+ serialized_data_count * sizeof(int));
-+ return -1;
-+ }
-+ }
-+ }
-+ int* *ifaces_lists = malloc(brcount * sizeof(int*));
-+ if(NULL == ifaces_lists)
-+ {
-+ LOG("out of memory, brcount = %d\n", brcount);
-+ return -1;
-+ }
-+ ptr = br_array + (brcount + 1);
-+ for(i = 0; i < brcount; ++i)
-+ {
-+ ifaces_lists[i] = ptr;
-+ ptr += ifaces_lists[i][0] + 1;
-+ }
-+ int r = CTL_add_bridges(br_array, ifaces_lists);
-+ free(ifaces_lists);
-+ if(r)
-+ return r;
-+ return r;
-+ }
-+
-+ case CMD_CODE_del_bridges:
-+ {
-+ if(0 != lout)
-+ {
-+ LOG("Bad sizes: lout %d != 0", lout);
-+ return -1;
-+ }
-+ if(sizeof(int) > lin)
-+ {
-+ LOG("Bad sizes: lin == 0");
-+ return -1;
-+ }
-+ int *br_array = inbuf;
-+ int brcount = br_array[0];
-+ if(((brcount + 1) * sizeof(int)) != lin)
-+ {
-+ LOG("Bad sizes: lin %d != %d", lin,
-+ (brcount + 1) * sizeof(int));
-+ return -1;
-+ }
-+ int r = CTL_del_bridges(br_array);
-+ if(r)
-+ return r;
-+ return r;
-+ }
-+
- default:
- ERROR("CTL: Unknown command %d", cmd);
- return -1;
-Index: mstp.c
-===================================================================
---- mstp.c (revision 22)
-+++ mstp.c (revision 27)
-@@ -206,7 +206,6 @@
- return false;
- list_add_tail(&cist->bridge_list, &br->trees);
-
-- br_state_machines_begin(br);
- return true;
- }
-
-Index: ctl_main.c
-===================================================================
---- ctl_main.c (revision 22)
-+++ ctl_main.c (revision 27)
-@@ -636,6 +636,18 @@
- return !('.' == n[0] && (0 == n[1] || ('.' == n[1] && 0 == n[2])));
- }
-
-+static int get_port_list(const char *br_ifname, struct dirent ***namelist)
-+{
-+ int res;
-+ char buf[SYSFS_PATH_MAX];
-+
-+ snprintf(buf, sizeof(buf), SYSFS_CLASS_NET "/%s/brif", br_ifname);
-+ if(0 > (res = scandir(buf, namelist, not_dot_dotdot, sorting_func)))
-+ fprintf(stderr, "Error getting list of all ports of bridge %s\n",
-+ br_ifname);
-+ return res;
-+}
-+
- static int cmd_showport(int argc, char *const *argv)
- {
- int r = 0;
-@@ -666,15 +678,8 @@
- }
- else
- {
-- char buf[SYSFS_PATH_MAX];
-- snprintf(buf, sizeof(buf), SYSFS_CLASS_NET "/%s/brif", argv[1]);
-- count = scandir(buf, &namelist, not_dot_dotdot, sorting_func);
-- if(0 > count)
-- {
-- fprintf(stderr, "Error getting list of all ports of bridge %s\n",
-- argv[1]);
-- return -1;
-- }
-+ if(0 > (count = get_port_list(argv[1], &namelist)))
-+ return count;
- }
-
- for(i = 0; i < count; ++i)
-@@ -740,6 +745,91 @@
- return 0;
- }
-
-+static int cmd_addbridge(int argc, char *const *argv)
-+{
-+ int i, j, res, ifcount, brcount = argc - 1;
-+ int *br_array;
-+ int* *ifaces_lists;
-+
-+ if(NULL == (br_array = malloc((brcount + 1) * sizeof(int))))
-+ {
-+out_of_memory_exit:
-+ fprintf(stderr, "out of memory, brcount = %d\n", brcount);
-+ return -1;
-+ }
-+ if(NULL == (ifaces_lists = malloc(brcount * sizeof(int*))))
-+ {
-+ free(br_array);
-+ goto out_of_memory_exit;
-+ }
-+
-+ br_array[0] = brcount;
-+ for(i = 1; i <= brcount; ++i)
-+ {
-+ struct dirent **namelist;
-+
-+ br_array[i] = get_index(argv[i], "bridge");
-+
-+ if(0 > (ifcount = get_port_list(argv[i], &namelist)))
-+ {
-+ifaces_error_exit:
-+ for(i -= 2; i >= 0; --i)
-+ free(ifaces_lists[i]);
-+ free(ifaces_lists);
-+ free(br_array);
-+ return ifcount;
-+ }
-+
-+ if(NULL == (ifaces_lists[i - 1] = malloc((ifcount + 1) * sizeof(int))))
-+ {
-+ fprintf(stderr, "out of memory, bridge %s, ifcount = %d\n",
-+ argv[i], ifcount);
-+ for(j = 0; j < ifcount; ++j)
-+ free(namelist[j]);
-+ free(namelist);
-+ ifcount = -1;
-+ goto ifaces_error_exit;
-+ }
-+
-+ ifaces_lists[i - 1][0] = ifcount;
-+ for(j = 1; j <= ifcount; ++j)
-+ {
-+ ifaces_lists[i - 1][j] = get_index(namelist[j - 1]->d_name, "port");
-+ free(namelist[j - 1]);
-+ }
-+ free(namelist);
-+ }
-+
-+ res = CTL_add_bridges(br_array, ifaces_lists);
-+
-+ for(i = 0; i < brcount; ++i)
-+ free(ifaces_lists[i]);
-+ free(ifaces_lists);
-+ free(br_array);
-+ return res;
-+}
-+
-+static int cmd_delbridge(int argc, char *const *argv)
-+{
-+ int i, res, brcount = argc - 1;
-+ int *br_array;
-+
-+ if(NULL == (br_array = malloc((brcount + 1) * sizeof(int))))
-+ {
-+ fprintf(stderr, "out of memory, brcount = %d\n", brcount);
-+ return -1;
-+ }
-+
-+ br_array[0] = brcount;
-+ for(i = 1; i <= brcount; ++i)
-+ br_array[i] = get_index(argv[i], "bridge");
-+
-+ res = CTL_del_bridges(br_array);
-+
-+ free(br_array);
-+ return res;
-+}
-+
- static unsigned int getuint(const char *s)
- {
- char *end;
-@@ -1191,23 +1281,6 @@
- return CTL_set_fid2mstid(br_index, fid, mstid);
- }
-
--static int cmd_stp_mode_notification(int argc, char *const *argv, bool on)
--{
-- int br_index;
-- /* Because this command has special handling,
-- * argc was not checked earlier
-- */
-- if(2 > argc)
-- {
-- fprintf(stderr,
-- "Incorrect number of arguments for notification command\n");
-- exit(1);
-- }
-- if(0 > (br_index = get_index(argv[1], "bridge")))
-- return br_index;
-- return CTL_stp_mode_notification(br_index, on);
--}
--
- struct command
- {
- int nargs;
-@@ -1220,6 +1293,12 @@
-
- static const struct command commands[] =
- {
-+ /* Add/delete bridges */
-+ {1, 32, "addbridge", cmd_addbridge,
-+ "<bridge> [<bridge> ...]", "Add bridges to the mstpd's list"},
-+ {1, 32, "delbridge", cmd_delbridge,
-+ "<bridge> [<bridge> ...]", "Remove bridges from the mstpd's list"},
-+
- /* Show global bridge */
- {0, 32, "showbridge", cmd_showbridge,
- "[<bridge> ... [param]]", "Show bridge state for the CIST"},
-@@ -1370,12 +1449,6 @@
- argv += optind;
- if(NULL == (cmd = command_lookup(argv[0])))
- {
-- /* Two special commands not intended for interactive use */
-- if(!strcmp(argv[0], "notify-daemon-that-stp-is-on"))
-- return cmd_stp_mode_notification(argc, argv, true);
-- if(!strcmp(argv[0], "notify-daemon-that-stp-is-off"))
-- return cmd_stp_mode_notification(argc, argv, false);
--
- fprintf(stderr, "never heard of command [%s]\n", argv[0]);
- goto help;
- }
-@@ -1417,8 +1490,61 @@
- CLIENT_SIDE_FUNCTION(set_fid2mstid)
- CLIENT_SIDE_FUNCTION(set_vids2fids)
- CLIENT_SIDE_FUNCTION(set_fids2mstids)
--CLIENT_SIDE_FUNCTION(stp_mode_notification)
-
-+CTL_DECLARE(add_bridges)
-+{
-+ int res = 0;
-+ LogString log = { .buf = "" };
-+ int i, chunk_count, brcount, serialized_data_count;
-+ int *serialized_data, *ptr;
-+
-+ chunk_count = serialized_data_count = (brcount = br_array[0]) + 1;
-+ for(i = 0; i < brcount; ++i)
-+ serialized_data_count += ifaces_lists[i][0] + 1;
-+ if(NULL == (serialized_data = malloc(serialized_data_count * sizeof(int))))
-+ {
-+ LOG("out of memory, serialized_data_count = %d",
-+ serialized_data_count);
-+ return -1;
-+ }
-+ memcpy(serialized_data, br_array, chunk_count * sizeof(int));
-+ ptr = serialized_data + chunk_count;
-+ for(i = 0; i < brcount; ++i)
-+ {
-+ chunk_count = ifaces_lists[i][0] + 1;
-+ memcpy(ptr, ifaces_lists[i], chunk_count * sizeof(int));
-+ ptr += chunk_count;
-+ }
-+
-+ int r = send_ctl_message(CMD_CODE_add_bridges, serialized_data,
-+ serialized_data_count * sizeof(int),
-+ NULL, 0, &log, &res);
-+ free(serialized_data);
-+ if(r || res)
-+ LOG("Got return code %d, %d\n%s", r, res, log.buf);
-+ if(r)
-+ return r;
-+ if(res)
-+ return res;
-+ return 0;
-+}
-+
-+CTL_DECLARE(del_bridges)
-+{
-+ int res = 0;
-+ LogString log = { .buf = "" };
-+ int r = send_ctl_message(CMD_CODE_del_bridges,
-+ br_array, (br_array[0] + 1) * sizeof(int),
-+ NULL, 0, &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;
-+ return 0;
-+}
-+
- /*********************** Logging *********************/
-
- void Dprintf(int level, const char *fmt, ...)