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, + " [ ...]", "Add bridges to the mstpd's list"}, + {1, 32, "delbridge", cmd_delbridge, + " [ ...]", "Remove bridges from the mstpd's list"}, + /* Show global bridge */ {0, 32, "showbridge", cmd_showbridge, "[ ... [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, ...)