From: Michael Tremer Date: Sat, 7 Jan 2012 11:16:34 +0000 (+0100) Subject: mstpd: Add patch by Vitalii. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4023155684b9803bc95fdebfefc40fad4c2dbe2c;p=ipfire-3.x.git mstpd: Add patch by Vitalii. I have not tested this, yet. --- diff --git a/mstpd/mstpd.nm b/mstpd/mstpd.nm index 3e886d996..e4783f23a 100644 --- a/mstpd/mstpd.nm +++ b/mstpd/mstpd.nm @@ -6,7 +6,7 @@ name = mstpd version = 0.01 svn_ver = 22 -release = 0.3-svn%{svn_ver}.1 +release = 0.3-svn%{svn_ver}.2 thisapp = %{name}-%{version}-svn%{svn_ver} groups = Networking/Tools diff --git a/mstpd/patches/add-del-bridge-commands.patch0 b/mstpd/patches/add-del-bridge-commands.patch0 new file mode 100644 index 000000000..5f3e5926c --- /dev/null +++ b/mstpd/patches/add-del-bridge-commands.patch0 @@ -0,0 +1,619 @@ +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, ...)