X-Git-Url: http://git.ipfire.org/?p=people%2Fms%2Frstp.git;a=blobdiff_plain;f=bridge_track.c;fp=bridge_track.c;h=e93c014f5e7c1b6cb5dcaf4bc500bcb234e3b6fe;hp=cd84cd9f79e18a4e7fb8e1d292fdab605e3a1b7f;hb=b600a2c3f85c73aafcabe690b3dc542ac637fa46;hpb=325941057766e20bfde2052d99b4b54b32856249 diff --git a/bridge_track.c b/bridge_track.c index cd84cd9..e93c014 100644 --- a/bridge_track.c +++ b/bridge_track.c @@ -34,17 +34,12 @@ #include #include -#include -#include -#include -#include -#include - #include #include #include "log.h" +#include "rstp.h" /*------------------------------------------------------------*/ struct ifdata { @@ -60,16 +55,8 @@ struct ifdata { struct ifdata *port_list; int do_stp; int stp_up; - struct stp_instance *stp; - UID_BRIDGE_ID_T bridge_id; - /* Bridge config */ - UID_STP_MODE_T stp_enabled; - int bridge_priority; - int max_age; - int hello_time; - int forward_delay; - int force_version; - int hold_time; + STP_Bridge *stp_bridge; + /* If port */ int speed; @@ -78,12 +65,7 @@ struct ifdata { struct ifdata *port_next; /* STP port index */ int port_index; - /* STP port config */ - int port_priority; - int admin_port_path_cost; - ADMIN_P2P_T admin_point2point; - unsigned char admin_edge; - unsigned char admin_non_stp; /* 1- doesn't participate in STP, 1 - regular */ + STP_Port *stp_port; struct epoll_event_handler event; }; @@ -91,22 +73,6 @@ struct ifdata { /* Instances */ struct ifdata *current_br = NULL; -void instance_begin(struct ifdata *br) -{ - if (current_br) { - ERROR("BUG: Trying to set instance over existing instance."); - ERROR("%d", *(int *)0); /* ABORT */ - } - current_br = br; - STP_IN_instance_begin(br->stp); -} - -void instance_end(void) -{ - STP_IN_instance_end(current_br->stp); - current_br = NULL; -} - struct ifdata *find_port(int port_index) { struct ifdata *ifc = current_br->port_list; @@ -115,170 +81,6 @@ struct ifdata *find_port(int port_index) return ifc; } -/*************************************************************/ -/* Bridge and port defaults */ - -UID_STP_CFG_T default_bridge_stp_cfg = { - .field_mask = BR_CFG_ALL, - .bridge_priority = DEF_BR_PRIO, - .max_age = DEF_BR_MAXAGE, - .hello_time = DEF_BR_HELLOT, - .forward_delay = DEF_BR_FWDELAY, - .force_version = DEF_FORCE_VERS, /*NORMAL_RSTP */ -}; - -void update_bridge_stp_config(struct ifdata *br, UID_STP_CFG_T * cfg) -{ - if (cfg->field_mask & BR_CFG_PRIO) - br->bridge_priority = cfg->bridge_priority; - if (cfg->field_mask & BR_CFG_AGE) - br->max_age = cfg->max_age; - if (cfg->field_mask & BR_CFG_HELLO) - br->hello_time = cfg->hello_time; - if (cfg->field_mask & BR_CFG_DELAY) - br->forward_delay = cfg->forward_delay; - if (cfg->field_mask & BR_CFG_FORCE_VER) - br->force_version = cfg->force_version; -} - -UID_STP_PORT_CFG_T default_port_stp_cfg = { - .field_mask = PT_CFG_ALL, - .port_priority = DEF_PORT_PRIO, - .admin_non_stp = DEF_ADMIN_NON_STP, - .admin_edge = False, // DEF_ADMIN_EDGE, - .admin_port_path_cost = ADMIN_PORT_PATH_COST_AUTO, - .admin_point2point = DEF_P2P, -}; - -void update_port_stp_config(struct ifdata *ifc, UID_STP_PORT_CFG_T * cfg) -{ - if (cfg->field_mask & PT_CFG_PRIO) - ifc->port_priority = cfg->port_priority; - if (cfg->field_mask & PT_CFG_NON_STP) - ifc->admin_non_stp = cfg->admin_non_stp; - if (cfg->field_mask & PT_CFG_EDGE) - ifc->admin_edge = cfg->admin_edge; - if (cfg->field_mask & PT_CFG_COST) - ifc->admin_port_path_cost = cfg->admin_port_path_cost; - if (cfg->field_mask & PT_CFG_P2P) - ifc->admin_point2point = cfg->admin_point2point; -} - -/**************************************************************/ - -int add_port_stp(struct ifdata *ifc) -{ /* Bridge is ifc->master */ - TST((ifc->port_index = get_bridge_portno(ifc->name)) >= 0, -1); - - /* Add port to STP */ - instance_begin(ifc->master); - int r = STP_IN_port_create(0, ifc->port_index); - if (r == 0) { /* Update bridge ID */ - UID_STP_STATE_T state; - STP_IN_stpm_get_state(0, &state); - ifc->master->bridge_id = state.bridge_id; - } - instance_end(); - if (r /* check for failure */ ) { - ERROR("Couldn't add port for ifindex %d to STP", ifc->if_index); - return -1; - } - return 0; -} - -void remove_port_stp(struct ifdata *ifc) -{ - /* Remove port from STP */ - instance_begin(ifc->master); - int r = STP_IN_port_delete(0, ifc->port_index); - instance_end(); - ifc->port_index = -1; - if (r != 0) { - ERROR("removing port %s failed for bridge %s: %s", - ifc->name, ifc->master->name, - STP_IN_get_error_explanation(r)); - } -} - -int init_rstplib_instance(struct ifdata *br) -{ - br->stp = STP_IN_instance_create(); - if (br->stp == NULL) { - ERROR("Couldn't create STP instance for bridge %s", br->name); - return -1; - } - - BITMAP_T ports; - BitmapClear(&ports); - instance_begin(br); - int r = STP_IN_stpm_create(0, br->name, &ports); - instance_end(); - if (r != 0) { - ERROR("stpm create failed for bridge %s: %s", - br->name, STP_IN_get_error_explanation(r)); - return -1; - } - - return 0; -} - -void clear_rstplib_instance(struct ifdata *br) -{ - instance_begin(br); - int r = STP_IN_delete_all(); - instance_end(); - if (r != 0) { - ERROR("stpm delete failed for bridge %s: %s", - br->name, STP_IN_get_error_explanation(r)); - } - - STP_IN_instance_delete(br->stp); - br->stp = NULL; -} - -int init_bridge_stp(struct ifdata *br) -{ - if (br->stp_up) { - ERROR("STP already started"); - return 0; - } - - /* Init STP state */ - TST(init_rstplib_instance(br) == 0, -1); - - struct ifdata *p = br->port_list; - while (p) { - if (add_port_stp(p) != 0) - break; - p = p->port_next; - } - if (p) { - struct ifdata *q = br->port_list; - while (q != p) { - remove_port_stp(q); - q = q->port_next; - } - /* Clear bridge STP state */ - clear_rstplib_instance(br); - return -1; - } - br->stp_up = 1; - return 0; -} - -void clear_bridge_stp(struct ifdata *br) -{ - if (!br->stp_up) - return; - br->stp_up = 0; - struct ifdata *p = br->port_list; - while (p) { - remove_port_stp(p); - p = p->port_next; - } - /* Clear bridge STP state */ - clear_rstplib_instance(br); -} struct ifdata *if_head = NULL; struct ifdata *br_head = NULL; @@ -327,15 +129,26 @@ struct ifdata *create_if(int if_index, struct ifdata *br) if (p->is_bridge) { INFO("Add bridge %s", p->name); + p->stp_bridge = STP_IN_bridge_create(p); + if (!p->stp_bridge) { + ERROR("Couldn't create STP Bridge"); + free(p); + return NULL; + } + STP_IN_set_bridge_address(p->stp_bridge, + (STP_MacAddress *)p->macaddr); + INFO("Set bridge address %s to %02x:%02x:%02x:%02x:%02x:%02x", + p->name, + p->macaddr[0], p->macaddr[1], p->macaddr[2], + p->macaddr[1], p->macaddr[4], p->macaddr[5] + ); /* Init slave list */ p->port_list = NULL; p->do_stp = 0; p->up = 0; p->stp_up = 0; - p->stp = NULL; - update_bridge_stp_config(p, &default_bridge_stp_cfg); - ADD_TO_LIST(br_head, bridge_next, p); /* Add to bridge list */ + ADD_TO_LIST(br_head, bridge_next, p); /* Add to bridge list */ } else { INFO("Add iface %s to bridge %s", p->name, br->name); p->up = 0; @@ -343,12 +156,22 @@ struct ifdata *create_if(int if_index, struct ifdata *br) p->duplex = 0; p->master = br; - update_port_stp_config(p, &default_port_stp_cfg); + p->port_index = get_bridge_portno(p->name); + if (p->port_index < 0) { + ERROR("Couldn't get port number for %s", p->name); + free(p); + return NULL; + } + p->stp_port = STP_IN_port_create(p->master->stp_bridge, + p->port_index, p); + if (!p->stp_port) { + ERROR("Couldn't create STP Port"); + free(p); + return NULL; + } + ADD_TO_LIST(br->port_list, port_next, p); /* Add to bridge port list */ - if (br->stp_up) { - add_port_stp(p); - } } /* Add to interface list */ @@ -361,8 +184,7 @@ void delete_if(struct ifdata *ifc) { INFO("Delete iface %s", ifc->name); if (ifc->is_bridge) { /* Bridge: */ - /* Stop STP */ - clear_bridge_stp(ifc); + STP_IN_set_bridge_enable(ifc->stp_bridge, 0); /* Delete ports */ while (ifc->port_list) delete_if(ifc->port_list); @@ -370,13 +192,13 @@ void delete_if(struct ifdata *ifc) REMOVE_FROM_LIST(br_head, bridge_next, ifc, "Can't find interface ifindex %d bridge list", ifc->if_index); + STP_IN_bridge_delete(ifc->stp_bridge); } else { /* Port */ - if (ifc->master->stp_up) - remove_port_stp(ifc); /* Remove from bridge port list */ REMOVE_FROM_LIST(ifc->master->port_list, port_next, ifc, "Can't find interface ifindex %d on br %d's port list", ifc->if_index, ifc->master->if_index); + STP_IN_port_delete(ifc->stp_port); } /* Remove from bridge interface list */ @@ -392,6 +214,7 @@ static int check_mac_address(char *name, unsigned char *addr) { unsigned char temp_addr[6]; if (get_hwaddr(name, temp_addr)) { + LOG("Error getting hw address: %s", name); /* Error. Ignore the new value */ return 0; } @@ -424,26 +247,32 @@ static int stp_enabled(struct ifdata *br) void set_br_up(struct ifdata *br, int up) { int stp_up = stp_enabled(br); - INFO("%s was %s stp was %s", br->name,up ? "up" : "down", br->stp_up ? "up" : "down"); + INFO("%s was %s stp was %s", br->name, br->up ? "up" : "down", br->stp_up ? "up" : "down"); INFO("Set bridge %s %s stp %s" , br->name, up ? "up" : "down", stp_up ? "up" : "down"); - if (up != br->up) + int changed = 0; + + if (up != br->up) { br->up = up; + changed = 1; + } + if (br->stp_up != stp_up) { + br->stp_up = stp_up; + changed = 1; + } + if (check_mac_address(br->name, br->macaddr)) { /* MAC address changed */ - if (br->stp_up && stp_up) { - /* Notify bridge address change */ - } + /* Notify bridge address change */ + STP_IN_set_bridge_address( + br->stp_bridge, (STP_MacAddress *)br->macaddr); } - if (br->stp_up != stp_up) { - if (stp_up) - init_bridge_stp(br); - else - clear_bridge_stp(br); - } + if (changed) + STP_IN_set_bridge_enable(br->stp_bridge, + (br->up && br->stp_up)?1:0); } void set_if_up(struct ifdata *ifc, int up) @@ -451,21 +280,23 @@ void set_if_up(struct ifdata *ifc, int up) INFO("Port %s : %s", ifc->name, (up ? "up" : "down")); int speed = -1; int duplex = -1; - int notify_flags = 0; - const int NOTIFY_UP = 1, NOTIFY_SPEED = 2, NOTIFY_DUPLEX = 4; + int changed = 0; if (check_mac_address(ifc->name, ifc->macaddr)) { /* MAC address changed */ if (check_mac_address(ifc->master->name, ifc->master->macaddr) - && ifc->master->stp_up) { + ) { /* Notify bridge address change */ + STP_IN_set_bridge_address( + ifc->master->stp_bridge, + (STP_MacAddress *)ifc->master->macaddr); } } if (!up) { /* Down */ if (ifc->up) { ifc->up = up; - notify_flags |= NOTIFY_UP; + changed = 1; } } else { /* Up */ int r = ethtool_get_speed_duplex(ifc->name, &speed, &duplex); @@ -478,29 +309,20 @@ void set_if_up(struct ifdata *ifc, int up) if (speed != ifc->speed) { ifc->speed = speed; - notify_flags |= NOTIFY_SPEED; + changed = 1; } if (duplex != ifc->duplex) { ifc->duplex = duplex; - notify_flags |= NOTIFY_DUPLEX; + changed = 1; } if (!ifc->up) { ifc->up = 1; - notify_flags |= NOTIFY_UP; + changed = 1; } } - if (notify_flags && ifc->master->stp_up) { - instance_begin(ifc->master); - - if (notify_flags & NOTIFY_SPEED) - STP_IN_changed_port_speed(ifc->port_index, speed); - if (notify_flags & NOTIFY_DUPLEX) - STP_IN_changed_port_duplex(ifc->port_index); - if (notify_flags & NOTIFY_UP) - STP_IN_enable_port(ifc->port_index, ifc->up); - - instance_end(); - } + if (changed) + STP_IN_set_port_enable(ifc->stp_port, + ifc->up, ifc->speed, ifc->duplex); } /*------------------------------------------------------------*/ @@ -509,7 +331,8 @@ int bridge_notify(int br_index, int if_index, int newlink, int up) { if (up) up = 1; - LOG("br_index %d, if_index %d, up %d", br_index, if_index, up); + LOG("br_index %d, if_index %d, newlink %d, up %d", + br_index, if_index, newlink, up); struct ifdata *br = NULL; if (br_index >= 0) { @@ -528,7 +351,7 @@ int bridge_notify(int br_index, int if_index, int newlink, int up) return -1; } /* Bridge must be up if we get such notifications */ - set_br_up(br, 1); + // Not true anymore - set_br_up(br, 1); } struct ifdata *ifc = find_if(if_index); @@ -619,14 +442,14 @@ const unsigned char STP_SAP = 0x42; void bridge_bpdu_rcv(int if_index, const unsigned char *data, int len) { struct ifdata *ifc = find_if(if_index); - BPDU_T *bpdu; LOG("ifindex %d, len %d", if_index, len); if (!ifc) return; TST(ifc->up,); - TST(ifc->master->stp_up,); + if (!ifc->master->stp_up) + return; /* Validate Ethernet and LLC header */ { @@ -635,48 +458,19 @@ void bridge_bpdu_rcv(int if_index, const unsigned char *data, int len) TST(len > sizeof(struct llc_header),); h = (struct llc_header *)data; TST(memcmp(h->dest_addr, bridge_group_address, ETH_ALEN) == 0, - ); + INFO("ifindex %d, len %d, %02x:%02x:%02x:%02x:%02x:%02x", + if_index, len, + h->dest_addr[0],h->dest_addr[1],h->dest_addr[2], + h->dest_addr[3],h->dest_addr[4],h->dest_addr[5])); l = ntohs(h->len8023); TST(l <= ETH_DATA_LEN && l <= len - ETH_HLEN && l >= 3,); TST(h->d_sap == STP_SAP && h->s_sap == STP_SAP && (h->llc_ui & 0x3) == 0x3 /* LLC UI */,); - /* BPDU_T includes ETH_HEADER_T, i.e. {d_sap, s_sap, llc_ui} */ - bpdu = (BPDU_T *)(data + sizeof(*h) - sizeof(ETH_HEADER_T)); - len = l + 2; /* ETH_HEADER_T includes the 2 bytes of len8023 */ - } - - TST(len > sizeof(ETH_HEADER_T) + sizeof(BPDU_HEADER_T),); - /* Do some BPDU validation as per 9.3.4 of standard */ - if (bpdu->hdr.protocol[0] || bpdu->hdr.protocol[1]) - return; - - switch (bpdu->hdr.bpdu_type) { - case BPDU_RSTP: - TST(len >= sizeof(ETH_HEADER_T) + 36,); - case BPDU_CONFIG_TYPE: - TST(len >= sizeof(ETH_HEADER_T) + 35,); - /* 802.1w doesn't ask for this */ - // TST(ntohs(*(uint16_t*)bpdu.body.message_age) - // < ntohs(*(uint16_t*)bpdu.body.max_age), ); - TST(memcmp(bpdu->body.bridge_id, &ifc->master->bridge_id, 8) != 0 - || (ntohs(*(uint16_t *) bpdu->body.port_id) & 0xfff) != - ifc->port_index,); - break; - case BPDU_TOPO_CHANGE_TYPE: - break; - default: - LOG("Receive unknown bpdu type %x", bpdu->hdr.bpdu_type); - return; + STP_IN_rx_bpdu(ifc->stp_port, + /* Don't include LLC header */ + data + sizeof(*h), l - 3); } - - // dump_hex(data, len); - instance_begin(ifc->master); - int r = STP_IN_rx_bpdu(0, ifc->port_index, bpdu, len); - if (r) - ERROR("STP_IN_rx_bpdu on port %s returned %s", ifc->name, - STP_IN_get_error_explanation(r)); - instance_end(); } void bridge_one_second(void) @@ -684,20 +478,8 @@ void bridge_one_second(void) // LOG(""); struct ifdata *br; for (br = br_head; br; br = br->bridge_next) { - if (br->stp_up) { - instance_begin(br); - STP_IN_one_second(); - instance_end(); - } + STP_IN_one_second(br->stp_bridge); } - - /* To get information about port changes when bridge is down */ - /* But won't work so well since we will not sense deletions */ - static int count = 0; - count++; - if (count % 60 == 0) - bridge_get_configuration(); - } /* Implementing STP_OUT functions */ @@ -712,203 +494,121 @@ int flush_port(char *sys_name) return 0; } -int -STP_OUT_flush_lt(IN int port_index, IN int vlan_id, - IN LT_FLASH_TYPE_T type, IN char *reason) +void STP_OUT_port_fdb_flush(void *user_ref) { - LOG("port index %d, flash type %d, reason %s", port_index, type, - reason); - TST(vlan_id == 0, 0); - + struct ifdata *port = user_ref; char fname[128]; - if (port_index == 0) { /* i.e. passed port_index was 0 */ - sprintf(fname, "/sys/class/net/%s/bridge/flush", - current_br->name); - flush_port(fname); - } else if (type == LT_FLASH_ONLY_THE_PORT) { - struct ifdata *port = find_port(port_index); - TST(port != NULL, 0); - sprintf(fname, "/sys/class/net/%s/brif/%s/flush", - current_br->name, port->name); - flush_port(fname); - } else if (type == LT_FLASH_ALL_PORTS_EXCLUDE_THIS) { - struct ifdata *port; - for (port = current_br->port_list; port; port = port->port_next) { - if (port->port_index != port_index) { - sprintf(fname, - "/sys/class/net/%s/brif/%s/flush", - current_br->name, port->name); - flush_port(fname); - } - } - } else - TST(0, 0); - - return 0; -} - -void /* for bridge id calculation */ STP_OUT_get_port_mac(IN int port_index, - OUT unsigned char - *mac) -{ - LOG("port index %d", port_index); - struct ifdata *port = find_port(port_index); - TST(port != NULL,); - memcpy(mac, port->macaddr, sizeof(port->macaddr)); -} - -unsigned long STP_OUT_get_port_oper_speed(IN unsigned int port_index) -{ - LOG("port index %d", port_index); - struct ifdata *port = find_port(port_index); - TST(port != NULL, 0); - LOG("Speed: %d", port->speed); - return port->speed; + snprintf(fname, sizeof(fname), + "/sys/class/net/%s/brport/flush", port->name); + fname[sizeof(fname) - 1] = 0; + TST(flush_port(fname) == 0,); } -int /* 1- Up, 0- Down */ STP_OUT_get_port_link_status(IN int port_index) +void STP_OUT_port_set_state(void *user_ref, unsigned int flags) { - LOG("port index %d", port_index); - struct ifdata *port = find_port(port_index); - TST(port != NULL, 0); - LOG("Link status: %d", port->up); - return port->up; -} - -int /* 1- Full, 0- Half */ STP_OUT_get_duplex(IN int port_index) -{ - LOG("port index %d", port_index); - struct ifdata *port = find_port(port_index); - TST(port != NULL, 0); - LOG("Duplex: %d", port->duplex); - return port->duplex; -} - -int -STP_OUT_set_port_state(IN int port_index, IN int vlan_id, - IN RSTP_PORT_STATE state) -{ - LOG("port index %d, state %d", port_index, state); - struct ifdata *port = find_port(port_index); - TST(port != NULL, 0); - TST(vlan_id == 0, 0); - + struct ifdata *port = user_ref; int br_state; - switch (state) { - case UID_PORT_DISCARDING: - br_state = BR_STATE_BLOCKING; - break; - case UID_PORT_LEARNING: - br_state = BR_STATE_LEARNING; - break; - case UID_PORT_FORWARDING: + + LOG("port index %d, flags %d", port->if_index, flags); + + if (flags & STP_PORT_STATE_FLAG_FORWARDING) br_state = BR_STATE_FORWARDING; - break; - default: - fprintf(stderr, "set_port_state: Unexpected state %d\n", state); - return -1; - } + else if (flags & STP_PORT_STATE_FLAG_LEARNING) + br_state = BR_STATE_LEARNING; + else + br_state = BR_STATE_BLOCKING; + if (port->up) bridge_set_state(port->if_index, br_state); - return 0; } -int STP_OUT_set_hardware_mode(int vlan_id, UID_STP_MODE_T mode) -{ - LOG("vlan id %d, mode %d", vlan_id, mode); - return 0; -} -int -STP_OUT_tx_bpdu(IN int port_index, IN int vlan_id, - IN unsigned char *bpdu, IN size_t bpdu_len) +void STP_OUT_tx_bpdu(void *port_user_ref, void *base, unsigned int len) { - LOG("port index %d, len %zd", port_index, bpdu_len); - struct ifdata *port = find_port(port_index); - TST(port != NULL, 0); - TST(vlan_id == 0, 0); + struct ifdata *port = port_user_ref; + + LOG("port index %d, len %d", port->if_index, len); struct llc_header h; memcpy(h.dest_addr, bridge_group_address, ETH_ALEN); memcpy(h.src_addr, port->macaddr, ETH_ALEN); /* bpdu_len excludes MAC and LLC headers */ - h.len8023 = htons(bpdu_len + 3); + h.len8023 = htons(len + 3); h.d_sap = h.s_sap = STP_SAP; - h.llc_ui = 0x03; /* LLC UI packet */ + h.llc_ui = 0x03; /* LLC UI packet */ struct iovec iov[2] = { { .iov_base = &h, .iov_len = sizeof(h) }, - { .iov_base = bpdu + sizeof(h), .iov_len = bpdu_len } + { .iov_base = base, .iov_len = len } }; - packet_send(port->if_index, iov, 2, sizeof(h) + bpdu_len); - return 0; + packet_send(port->if_index, iov, 2, sizeof(h) + len); } -const char *STP_OUT_get_port_name(IN int port_index) -{ - LOG("port index %d", port_index); - struct ifdata *port = find_port(port_index); - TST(port != NULL, 0); - return port->name; -} -int STP_OUT_get_init_stpm_cfg(IN int vlan_id, INOUT UID_STP_CFG_T * cfg) +void STP_OUT_logmsg(void *br_user_ref, void *port_user_ref, + int level, char *fmt, ...) { - LOG(""); - TST(vlan_id == 0, 0); - - cfg->bridge_priority = current_br->bridge_priority; - cfg->max_age = current_br->max_age; - cfg->hello_time = current_br->hello_time; - cfg->forward_delay = current_br->forward_delay; - cfg->force_version = current_br->force_version; + struct ifdata *bridge = br_user_ref; + struct ifdata *port = port_user_ref; + char buf[256]; + int r; + int ll = (level < STP_LOG_LEVEL_DEBUG) ? + LOG_LEVEL_INFO : LOG_LEVEL_DEBUG; + struct timeval tv; + gettimeofday(&tv, NULL); + r = snprintf(buf, sizeof(buf), "LOG Level %d:%s:%s: %02d.%03d: ", + level, + (bridge?bridge->name:""), (port?port->name:""), + (int)tv.tv_sec % 60, (int)tv.tv_usec / 1000); + if (r >= sizeof(buf)) { + buf[sizeof(buf) - 1] = 0; + Dprintf(ll, "%s", buf); + r = 0; + } - return 0; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf + r, sizeof(buf) - r, fmt, ap); + buf[sizeof(buf) - 1] = 0; + Dprintf(ll, "%s", buf); + va_end(ap); + if (level == STP_LOG_LEVEL_ERROR) + ctl_err_log("%s", buf + r); } -int -STP_OUT_get_init_port_cfg(IN int vlan_id, - IN int port_index, INOUT UID_STP_PORT_CFG_T * cfg) +void *STP_OUT_mem_zalloc(unsigned int size) { - LOG("port index %d", port_index); - struct ifdata *port = find_port(port_index); - TST(port != NULL, 0); - TST(vlan_id == 0, 0); - - cfg->port_priority = port->port_priority; - cfg->admin_non_stp = port->admin_non_stp; - cfg->admin_edge = port->admin_edge; - cfg->admin_port_path_cost = port->admin_port_path_cost; - cfg->admin_point2point = port->admin_point2point; - - return 0; + return calloc(1, size); } -extern void stp_trace(const char *fmt, ...) + +void STP_OUT_mem_free(void *p) { - va_list ap; - va_start(ap, fmt); - vDprintf(LOG_LEVEL_RSTPLIB, fmt, ap); - va_end(ap); + free(p); } + /* Commands and status */ #include "ctl_functions.h" #define CTL_CHECK_BRIDGE \ - struct ifdata *br = find_if(br_index); \ - if (br == NULL || !br->is_bridge) return Err_Interface_not_a_bridge; \ - if (!br->do_stp) return Err_Bridge_RSTP_not_enabled; \ - if (!br->stp_up) return Err_Bridge_is_down; \ - do { } while (0) + struct ifdata *br = find_if(br_index); \ + if (br == NULL || !br->is_bridge) { \ + ERROR("Couldn't find bridge with index %d", br_index); \ + return -1; \ + } \ + do { } while (0) #define CTL_CHECK_BRIDGE_PORT \ - CTL_CHECK_BRIDGE; \ - struct ifdata *port = find_if(port_index); \ - if (port == NULL || port->is_bridge || port->master != br) \ - return Err_Port_does_not_belong_to_bridge; \ - do { } while (0) + CTL_CHECK_BRIDGE; \ + struct ifdata *port = find_if(port_index); \ + if (port == NULL || port->is_bridge || port->master != br) { \ + ERROR("Interface with index %d not a port of bridge " \ + "with index %d", port_index, br_index); \ + return -1; \ + } \ + do { } while (0) int CTL_enable_bridge_rstp(int br_index, int enable) { @@ -922,110 +622,77 @@ int CTL_enable_bridge_rstp(int br_index, int enable) if (if_indextoname(br_index, ifname) && is_bridge(ifname)) br = create_if(br_index, NULL); } - if (br == NULL || !br->is_bridge) - return Err_Interface_not_a_bridge; - if (br->do_stp != enable) { - br->do_stp = enable; - if (br->up) - r = enable ? init_bridge_stp(br) - : (clear_bridge_stp(br), 0); + if (br == NULL || !br->is_bridge) { + ERROR("Couldn't find bridge with index %d", br_index); + return -1; } + if (br->up) + set_br_up(br, 1); return r; } -int CTL_get_bridge_state(int br_index, - UID_STP_CFG_T * cfg, UID_STP_STATE_T * state) +int CTL_get_bridge_status(int br_index, STP_BridgeStatus *status) { LOG("bridge %d", br_index); CTL_CHECK_BRIDGE; - int r; - instance_begin(br); - r = STP_IN_stpm_get_state(0, state); - if (r) { - ERROR("Error getting bridge state for %d: %s", br_index, - STP_IN_get_error_explanation(r)); - instance_end(); - return r; - } - r = STP_IN_stpm_get_cfg(0, cfg); - if (r) { - ERROR("Error getting bridge config for %d: %s", br_index, - STP_IN_get_error_explanation(r)); - instance_end(); - return r; - } - instance_end(); + + STP_IN_get_bridge_status(br->stp_bridge, status); return 0; } -int CTL_set_bridge_config(int br_index, UID_STP_CFG_T * cfg) +int CTL_set_bridge_config(int br_index, STP_BridgeConfig *cfg) { - INFO("bridge %d, flags %#lx", br_index, cfg->field_mask); + INFO("bridge %d", br_index); CTL_CHECK_BRIDGE; - int r; - instance_begin(br); - r = STP_IN_stpm_set_cfg(0, NULL, cfg); + + if (cfg->set_bridge_address) { + ERROR("Setting bridge address not permitted: %s", br->name); + return -1; + } + + int r = STP_IN_set_bridge_config(br->stp_bridge, cfg); + if (r) { - ERROR("Error setting bridge config for %d: %s", br_index, - STP_IN_get_error_explanation(r)); - instance_end(); + ERROR("Error setting bridge config for %s", br->name); return r; } - instance_end(); - /* Change init config in ifdata so it will be applied if we - disable and enable rstp */ - update_bridge_stp_config(br, cfg); return 0; } -int CTL_get_port_state(int br_index, int port_index, - UID_STP_PORT_CFG_T * cfg, UID_STP_PORT_STATE_T * state) +int CTL_get_port_status(int br_index, int port_index, STP_PortStatus *status) { LOG("bridge %d port %d", br_index, port_index); CTL_CHECK_BRIDGE_PORT; - int r; - instance_begin(br); - state->port_no = port->port_index; - r = STP_IN_port_get_state(0, state); - if (r) { - ERROR("Error getting port state for port %d, bridge %d: %s", - port->port_index, br_index, - STP_IN_get_error_explanation(r)); - instance_end(); - return r; - } - r = STP_IN_port_get_cfg(0, port->port_index, cfg); + + STP_IN_get_port_status(port->stp_port, status); + return 0; +} + +int CTL_set_port_config(int br_index, int port_index, STP_PortConfig *cfg) +{ + INFO("bridge %d, port %d", br_index, port_index); + CTL_CHECK_BRIDGE_PORT; + + int r = STP_IN_set_port_config(port->stp_port, cfg); if (r) { - ERROR("Error getting port config for port %d, bridge %d: %s", - port->port_index, br_index, - STP_IN_get_error_explanation(r)); - instance_end(); + ERROR("Error setting port config for %s", port->name); return r; } - instance_end(); + return 0; - } -int CTL_set_port_config(int br_index, int port_index, UID_STP_PORT_CFG_T * cfg) +int CTL_port_mcheck(int br_index, int port_index) { - INFO("bridge %d, port %d, flags %#lx", br_index, port_index, - cfg->field_mask); + INFO("bridge %d, port %d", br_index, port_index); CTL_CHECK_BRIDGE_PORT; - int r; - instance_begin(br); - r = STP_IN_set_port_cfg(0, port->port_index, cfg); + + int r = STP_IN_port_mcheck(port->stp_port); if (r) { - ERROR("Error setting port config for port %d, bridge %d: %s", - port->port_index, br_index, - STP_IN_get_error_explanation(r)); - instance_end(); + ERROR("Error doing port mcheck for %s", port->name); return r; } - instance_end(); - /* Change init config in ifdata so it will be applied if we - disable and enable rstp */ - update_port_stp_config(port, cfg); + return 0; }