X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=lib%2Frstp.c;h=f24ca0143578e36c421a2edb37ec525c70d8a54a;hb=HEAD;hp=05fa634e01ad608eda9feefac3d62721fcb89d75;hpb=2372c146f7afa2b12e7b60375c728796ff985038;p=cascardo%2Fovs.git diff --git a/lib/rstp.c b/lib/rstp.c index 05fa634e0..f24ca0143 100644 --- a/lib/rstp.c +++ b/lib/rstp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014 M3S, Srl - Italy + * Copyright (c) 2011-2015 M3S, Srl - Italy * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ * Authors: * Martino Fornasa * Daniele Venturino + * Carlo Andreotti * * References to IEEE 802.1D-2004 standard are enclosed in square brackets. * E.g. [17.3], [Table 17-1], etc. @@ -40,18 +41,19 @@ #include "connectivity.h" #include "ofpbuf.h" #include "ofproto/ofproto.h" +#include "dp-packet.h" #include "packets.h" #include "seq.h" #include "unixctl.h" #include "util.h" -#include "vlog.h" +#include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(rstp); struct ovs_mutex rstp_mutex = OVS_MUTEX_INITIALIZER; -static struct list all_rstps__ = LIST_INITIALIZER(&all_rstps__); -static struct list *const all_rstps OVS_GUARDED_BY(rstp_mutex) = &all_rstps__; +static struct ovs_list all_rstps__ = OVS_LIST_INITIALIZER(&all_rstps__); +static struct ovs_list *const all_rstps OVS_GUARDED_BY(rstp_mutex) = &all_rstps__; /* Internal use only. */ static void rstp_set_bridge_address__(struct rstp *, rstp_identifier) @@ -184,6 +186,7 @@ rstp_unref(struct rstp *rstp) list_remove(&rstp->node); ovs_mutex_unlock(&rstp_mutex); + hmap_destroy(&rstp->ports); free(rstp->name); free(rstp); } @@ -243,7 +246,7 @@ rstp_init(void) /* Creates and returns a new RSTP instance that initially has no ports. */ struct rstp * rstp_create(const char *name, rstp_identifier bridge_address, - void (*send_bpdu)(struct ofpbuf *bpdu, void *port_aux, + void (*send_bpdu)(struct dp_packet *bpdu, void *port_aux, void *rstp_aux), void *aux) OVS_EXCLUDED(rstp_mutex) @@ -279,6 +282,8 @@ rstp_create(const char *name, rstp_identifier bridge_address, rstp->aux = aux; rstp->changes = false; rstp->begin = true; + rstp->old_root_aux = NULL; + rstp->new_root_aux = NULL; ovs_refcount_init(&rstp->ref_cnt); @@ -322,10 +327,12 @@ rstp_set_bridge_address__(struct rstp *rstp, rstp_identifier bridge_address) { VLOG_DBG("%s: set bridge address to: "RSTP_ID_FMT"", rstp->name, RSTP_ID_ARGS(bridge_address)); - - rstp->address = bridge_address; - rstp->bridge_identifier = bridge_address; - set_bridge_priority__(rstp); + if (rstp->address != bridge_address) { + rstp->address = bridge_address; + rstp->bridge_identifier &= 0xffff000000000000ULL; + rstp->bridge_identifier |= bridge_address; + set_bridge_priority__(rstp); + } } /* Sets the bridge address. */ @@ -370,7 +377,8 @@ rstp_set_bridge_priority__(struct rstp *rstp, int new_priority) { new_priority = ROUND_DOWN(new_priority, RSTP_PRIORITY_STEP); - if (new_priority >= RSTP_MIN_PRIORITY + if (rstp->priority != new_priority + && new_priority >= RSTP_MIN_PRIORITY && new_priority <= RSTP_MAX_PRIORITY) { VLOG_DBG("%s: set bridge priority to %d", rstp->name, new_priority); @@ -584,7 +592,8 @@ rstp_set_bridge_transmit_hold_count__(struct rstp *rstp, int new_transmit_hold_count) OVS_REQUIRES(rstp_mutex) { - if (new_transmit_hold_count >= RSTP_MIN_TRANSMIT_HOLD_COUNT + if (rstp->transmit_hold_count != new_transmit_hold_count + && new_transmit_hold_count >= RSTP_MIN_TRANSMIT_HOLD_COUNT && new_transmit_hold_count <= RSTP_MAX_TRANSMIT_HOLD_COUNT) { struct rstp_port *p; @@ -664,7 +673,8 @@ static void rstp_port_set_priority__(struct rstp_port *port, int priority) OVS_REQUIRES(rstp_mutex) { - if (priority >= RSTP_MIN_PORT_PRIORITY + if (port->priority != priority + && priority >= RSTP_MIN_PORT_PRIORITY && priority <= RSTP_MAX_PORT_PRIORITY) { VLOG_DBG("%s, port %u: set RSTP port priority to %d", port->rstp->name, port->port_number, priority); @@ -715,27 +725,29 @@ rstp_port_set_port_number__(struct rstp_port *port, uint16_t port_number) /* If new_port_number is available, use it, otherwise use the first free * available port number. */ - port->port_number = - is_port_number_available__(port->rstp, port_number, port) - ? port_number - : rstp_first_free_number__(port->rstp, port); - - if (port->port_number != old_port_number) { - set_port_id__(port); - /* [17.13] is not clear. I suppose that a port number change - * should trigger reselection like a port priority change. */ - port->selected = false; - port->reselect = true; + if (port->port_number != port_number || port_number == 0) { + port->port_number = + is_port_number_available__(port->rstp, port_number, port) + ? port_number + : rstp_first_free_number__(port->rstp, port); + + if (port->port_number != old_port_number) { + set_port_id__(port); + /* [17.13] is not clear. I suppose that a port number change + * should trigger reselection like a port priority change. */ + port->selected = false; + port->reselect = true; + + /* Adjust the ports hmap. */ + if (!hmap_node_is_null(&port->node)) { + hmap_remove(&port->rstp->ports, &port->node); + } + hmap_insert(&port->rstp->ports, &port->node, + hash_int(port->port_number, 0)); - /* Adjust the ports hmap. */ - if (!hmap_node_is_null(&port->node)) { - hmap_remove(&port->rstp->ports, &port->node); + VLOG_DBG("%s: set new RSTP port number %d", port->rstp->name, + port->port_number); } - hmap_insert(&port->rstp->ports, &port->node, - hash_int(port->port_number, 0)); - - VLOG_DBG("%s: set new RSTP port number %d", port->rstp->name, - port->port_number); } } @@ -763,7 +775,8 @@ static void rstp_port_set_path_cost__(struct rstp_port *port, uint32_t path_cost) OVS_REQUIRES(rstp_mutex) { - if (path_cost >= RSTP_MIN_PORT_PATH_COST + if (port->port_path_cost != path_cost + && path_cost >= RSTP_MIN_PORT_PATH_COST && path_cost <= RSTP_MAX_PORT_PATH_COST) { VLOG_DBG("%s, port %u, set RSTP port path cost to %d", port->rstp->name, port->port_number, path_cost); @@ -1015,9 +1028,9 @@ rstp_port_set_administrative_bridge_port__(struct rstp_port *p, VLOG_DBG("%s, port %u: set RSTP port admin-port-state to %d", p->rstp->name, p->port_number, admin_port_state); - if (admin_port_state == RSTP_ADMIN_BRIDGE_PORT_STATE_DISABLED - || admin_port_state == RSTP_ADMIN_BRIDGE_PORT_STATE_ENABLED) { - + if (p->is_administrative_bridge_port != admin_port_state + && (admin_port_state == RSTP_ADMIN_BRIDGE_PORT_STATE_DISABLED + || admin_port_state == RSTP_ADMIN_BRIDGE_PORT_STATE_ENABLED)) { p->is_administrative_bridge_port = admin_port_state; update_port_enabled__(p); @@ -1036,8 +1049,9 @@ rstp_port_set_oper_point_to_point_mac__(struct rstp_port *p, uint8_t new_oper_p2p_mac) OVS_REQUIRES(rstp_mutex) { - if (new_oper_p2p_mac == RSTP_OPER_P2P_MAC_STATE_DISABLED - || new_oper_p2p_mac == RSTP_OPER_P2P_MAC_STATE_ENABLED) { + if (p->oper_point_to_point_mac != new_oper_p2p_mac + && (new_oper_p2p_mac == RSTP_OPER_P2P_MAC_STATE_DISABLED + || new_oper_p2p_mac == RSTP_OPER_P2P_MAC_STATE_ENABLED)) { p->oper_point_to_point_mac = new_oper_p2p_mac; update_port_enabled__(p); @@ -1228,28 +1242,29 @@ static void rstp_port_set_admin_point_to_point_mac__(struct rstp_port *port, { VLOG_DBG("%s, port %u: set RSTP port admin-point-to-point-mac to %d", port->rstp->name, port->port_number, admin_p2p_mac_state); - - if (admin_p2p_mac_state == RSTP_ADMIN_P2P_MAC_FORCE_TRUE) { - port->admin_point_to_point_mac = admin_p2p_mac_state; - rstp_port_set_oper_point_to_point_mac__(port, - RSTP_OPER_P2P_MAC_STATE_ENABLED); - } else if (admin_p2p_mac_state == RSTP_ADMIN_P2P_MAC_FORCE_FALSE) { - port->admin_point_to_point_mac = admin_p2p_mac_state; - rstp_port_set_oper_point_to_point_mac__(port, - RSTP_OPER_P2P_MAC_STATE_DISABLED); - } else if (admin_p2p_mac_state == RSTP_ADMIN_P2P_MAC_AUTO) { - /* If adminPointToPointMAC is set to Auto, then the value of - * operPointToPointMAC is determined in accordance with the - * specific procedures defined for the MAC entity concerned, as - * defined in 6.5. If these procedures determine that the MAC - * entity is connected to a point-to-point LAN, then - * operPointToPointMAC is set TRUE; otherwise it is set FALSE. - * In the absence of a specific definition of how to determine - * whether the MAC is connected to a point-to-point LAN or not, - * the value of operPointToPointMAC shall be FALSE. */ - port->admin_point_to_point_mac = admin_p2p_mac_state; - rstp_port_set_oper_point_to_point_mac__( - port, RSTP_OPER_P2P_MAC_STATE_DISABLED); + if (port->admin_point_to_point_mac != admin_p2p_mac_state) { + if (admin_p2p_mac_state == RSTP_ADMIN_P2P_MAC_FORCE_TRUE) { + port->admin_point_to_point_mac = admin_p2p_mac_state; + rstp_port_set_oper_point_to_point_mac__( + port, RSTP_OPER_P2P_MAC_STATE_ENABLED); + } else if (admin_p2p_mac_state == RSTP_ADMIN_P2P_MAC_FORCE_FALSE) { + port->admin_point_to_point_mac = admin_p2p_mac_state; + rstp_port_set_oper_point_to_point_mac__( + port, RSTP_OPER_P2P_MAC_STATE_DISABLED); + } else if (admin_p2p_mac_state == RSTP_ADMIN_P2P_MAC_AUTO) { + /* If adminPointToPointMAC is set to Auto, then the value of + * operPointToPointMAC is determined in accordance with the + * specific procedures defined for the MAC entity concerned, as + * defined in 6.5. If these procedures determine that the MAC + * entity is connected to a point-to-point LAN, then + * operPointToPointMAC is set TRUE; otherwise it is set FALSE. + * In the absence of a specific definition of how to determine + * whether the MAC is connected to a point-to-point LAN or not, + * the value of operPointToPointMAC shall be FALSE. */ + port->admin_point_to_point_mac = admin_p2p_mac_state; + rstp_port_set_oper_point_to_point_mac__( + port, RSTP_OPER_P2P_MAC_STATE_DISABLED); + } } }