4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * CDDL HEADER START
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * The contents of this file are subject to the terms of the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Common Development and Distribution License (the "License").
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * You may not use this file except in compliance with the License.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * or http://www.opensolaris.org/os/licensing.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * See the License for the specific language governing permissions
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * and limitations under the License.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * When distributing Covered Code, include this CDDL HEADER in each
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If applicable, add the following below this CDDL HEADER, with the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * fields enclosed by brackets "[]" replaced with your own identifying
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * information: Portions Copyright [yyyy] [name of copyright owner]
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * CDDL HEADER END
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Use is subject to license terms.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridged - bridging control daemon. This module provides functions related
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * to the librstp (Rapid Spanning Tree Protocol) library.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <stdio.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <stdlib.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <unistd.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <stdarg.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <string.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/types.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <syslog.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <kstat.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <libdlpi.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <libdladm.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <libdllink.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <libdlstat.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <stp_in.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <stp_vectors.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <net/if_types.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <net/bridge.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/ethernet.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include "global.h"
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* current engine configuration; access protected by engine_lock */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic UID_STP_CFG_T uid_cfg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Our implementation doesn't have per-VLAN forwarding entries, so we just
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * flush by the port. If port number is zero, then flush entries.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*ARGSUSED1*/
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiflush_lt(int port_index, int vlan_id, LT_FLASH_TYPE_T type, char *reason)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata *pd;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai const char *portname;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_flushfwd_t bff;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port_index > nextport || port_index < 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port_index == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai type = LT_FLASH_ONLY_THE_PORT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai portname = "all";
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bff.bff_linkid = DATALINK_INVALID_LINKID;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pd = allports[port_index - 1];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai portname = pd->name;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bff.bff_linkid = pd->linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (debugging) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG, "flush forwarding %s %s: %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai type == LT_FLASH_ONLY_THE_PORT ? "to" : "except for",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai portname, reason);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bff.bff_exclude = (type == LT_FLASH_ALL_PORTS_EXCLUDE_THIS);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If flushing fails, we can't return. The only safe thing to do is to
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * tear down the bridge so that we're not harming the network.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_FLUSHFWD, &bff, sizeof (bff)) == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "cannot flush forwarding entries on %s %s: %m",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai instance_name, portname);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unlock_engine();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai exit(EXIT_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiget_port_mac(int port_index, unsigned char *mac)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata *pd;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port_index > nextport || port_index <= 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pd = allports[port_index - 1];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memcpy(mac, pd->mac_addr, ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* Returns speed in megabits per second */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic unsigned long
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiget_port_oper_speed(unsigned int port_index)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port_index > nextport || port_index == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (1000UL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (allports[port_index - 1]->speed);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiget_port_link_status(int port_index)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata *pd;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port_index > nextport || port_index <= 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pd = allports[port_index - 1];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (pd->phys_status && pd->admin_status &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai protect == DLADM_BRIDGE_PROT_STP && !pd->sdu_failed ?
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai 1 : 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiget_duplex(int port_index)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata *pd;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_duplex_t link_duplex;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_status_t status;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port_index > nextport || port_index <= 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (False);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pd = allports[port_index - 1];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_get_single_mac_stat(dlhandle, pd->linkid, "link_duplex",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSTAT_DATA_UINT32, &link_duplex);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status == DLADM_STATUS_OK && link_duplex == LINK_DUPLEX_FULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (True);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (False);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic const char *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibls_state(bridge_state_t bstate)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (bstate) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case BLS_LEARNING:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return ("learning");
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case BLS_FORWARDING:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return ("forwarding");
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai default:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return ("block/listen");
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*ARGSUSED1*/
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiset_port_state(int port_index, int vlan_id, RSTP_PORT_STATE state)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata *pd;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_setstate_t bss;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port_index > nextport || port_index <= 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (1);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pd = allports[port_index - 1];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (debugging)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG, "setting port state on port %d (%s) to %d",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port_index, pd->name, state);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (state) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case UID_PORT_LEARNING:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_state = BLS_LEARNING;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case UID_PORT_FORWARDING:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_state = BLS_FORWARDING;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai default:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_state = BLS_BLOCKLISTEN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_linkid = pd->linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_SETSTATE, &bss, sizeof (bss)) == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "cannot set STP state on %s from %s to %s: %m",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pd->name, bls_state(pd->state), bls_state(bss.bss_state));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If we've been unsuccessful in disabling forwarding, then the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * only safe thing to do is to make the daemon exit, so that
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the kernel will be forced to destroy the bridge state and
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * terminate all forwarding.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (pd->state == BLS_FORWARDING &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_state != BLS_FORWARDING) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unlock_engine();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai exit(EXIT_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pd->state = bss.bss_state;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Our hardware doesn't actually do anything different when STP is enabled or
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * disabled, so this function does nothing. It would be possible to open and
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * close the DLPI stream here, if such a thing were necessary.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiset_hardware_mode(int vlan_id, UID_STP_MODE_T mode)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (debugging)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG, "setting hardware mode on vlan %d to %d",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vlan_id, mode);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*ARGSUSED1*/
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitx_bpdu(int port_index, int vlan_id, unsigned char *bpdu, size_t bpdu_len)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata *pdp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int rc;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port_index > nextport || port_index <= 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (1);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pdp = allports[port_index - 1];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = dlpi_send(pdp->dlpi, NULL, 0, bpdu, bpdu_len, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rc == DLPI_SUCCESS) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (debugging)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG, "transmitted %d byte BPDU on %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bpdu_len, pdp->name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_WARNING, "failed to send to %s: %s", pdp->name,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dlpi_strerror(rc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (1);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic const char *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiget_port_name(int port_index)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port_index > nextport || port_index <= 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return ("unknown");
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (allports[port_index - 1]->name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*ARGSUSED*/
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiget_init_stpm_cfg(int vlan_id, UID_STP_CFG_T *cfg)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* under engine_lock because it's a callback from the engine */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *cfg = uid_cfg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*ARGSUSED*/
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiget_init_port_cfg(int vlan_id, int port_index, UID_STP_PORT_CFG_T *cfg)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata *pdp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint_t propval, valcnt;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai datalink_id_t linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_status_t status;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port_index > nextport || port_index <= 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (1);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pdp = allports[port_index - 1];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->field_mask = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->port_priority = DEF_PORT_PRIO;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->admin_non_stp = DEF_ADMIN_NON_STP;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->admin_edge = DEF_ADMIN_EDGE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->admin_port_path_cost = ADMIN_PORT_PATH_COST_AUTO;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->admin_point2point = DEF_P2P;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai valcnt = 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai linkid = pdp->linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_get_linkprop_values(dlhandle, linkid,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DLADM_PROP_VAL_PERSISTENT, "stp_priority", &propval, &valcnt);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status == DLADM_STATUS_OK) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->port_priority = propval;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->field_mask |= PT_CFG_PRIO;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_get_linkprop_values(dlhandle, linkid,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DLADM_PROP_VAL_PERSISTENT, "stp", &propval, &valcnt);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status == DLADM_STATUS_OK) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->admin_non_stp = !propval;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->field_mask |= PT_CFG_NON_STP;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_get_linkprop_values(dlhandle, linkid,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DLADM_PROP_VAL_PERSISTENT, "stp_edge", &propval, &valcnt);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status == DLADM_STATUS_OK) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->admin_edge = propval;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->field_mask |= PT_CFG_EDGE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_get_linkprop_values(dlhandle, linkid,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DLADM_PROP_VAL_PERSISTENT, "stp_cost", &propval, &valcnt);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status == DLADM_STATUS_OK) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->admin_port_path_cost = propval;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->field_mask |= PT_CFG_COST;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_get_linkprop_values(dlhandle, linkid,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DLADM_PROP_VAL_PERSISTENT, "stp_p2p", &propval, &valcnt);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status == DLADM_STATUS_OK) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->admin_point2point = propval;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->field_mask |= PT_CFG_P2P;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * mcheck is special. It is actually a command, but the 802 documents
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * define it as a variable that spontaneously resets itself. We need
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * to handle that behavior here.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_get_linkprop_values(dlhandle, linkid,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DLADM_PROP_VAL_PERSISTENT, "stp_mcheck", &propval, &valcnt);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status == DLADM_STATUS_OK && propval != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char *pval = "0";
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cfg->field_mask |= PT_CFG_MCHECK;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) dladm_set_linkprop(dlhandle, linkid, "stp_mcheck", &pval,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai 1, DLADM_OPT_ACTIVE|DLADM_OPT_PERSIST|DLADM_OPT_NOREFRESH);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pdp->admin_non_stp = cfg->admin_non_stp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!pdp->admin_non_stp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pdp->bpdu_protect = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrace(const char *fmt, ...)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai va_list ap;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai va_start(ap, fmt);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vsyslog(LOG_DEBUG, fmt, ap);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai va_end(ap);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic STP_VECTORS_T stp_vectors = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai flush_lt,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai get_port_mac,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai get_port_oper_speed,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai get_port_link_status,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai get_duplex,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai set_port_state,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai set_hardware_mode,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tx_bpdu,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai get_port_name,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai get_init_stpm_cfg,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai get_init_port_cfg,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trace
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavairstp_init(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_status_t status;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char buf[DLADM_STRSIZE];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai STP_IN_init(&stp_vectors);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_bridge_get_properties(instance_name, &uid_cfg, &protect);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status != DLADM_STATUS_OK) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "%s: unable to read properties: %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai instance_name, dladm_status2str(status, buf));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai exit(EXIT_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This is called by a normal refresh operation. It gets the engine properties
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * and resets.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavairstp_refresh(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_status_t status;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int rc;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char buf[DLADM_STRSIZE];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai UID_STP_CFG_T new_cfg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_bridge_prot_t new_prot;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_bridge_get_properties(instance_name, &new_cfg,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &new_prot);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status != DLADM_STATUS_OK) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "%s: unable to refresh bridge properties: %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai instance_name, dladm_status2str(status, buf));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (debugging && (protect != new_prot ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uid_cfg.stp_enabled != new_cfg.stp_enabled)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG, "loop protection %s->%s, STP %d->%d",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_bridge_prot2str(protect),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_bridge_prot2str(new_prot),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uid_cfg.stp_enabled, new_cfg.stp_enabled);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * The engine doesn't take kindly to parameter changes while
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * running. Disable first if we must do this.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (uid_cfg.stp_enabled &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai memcmp(&uid_cfg, &new_cfg, sizeof (uid_cfg)) != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG, "resetting state machine");
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uid_cfg.stp_enabled = STP_DISABLED;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = STP_IN_stpm_set_cfg(0, &uid_cfg);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rc != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "STP machine reset config: %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai STP_IN_get_error_explanation(rc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uid_cfg = new_cfg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai protect = new_prot;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = STP_IN_stpm_set_cfg(0, &uid_cfg);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rc != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "STP machine set config: %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai STP_IN_get_error_explanation(rc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This is called when a port changes its MAC address. If it's the main port,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the one that supplies us our bridge ID, then we must choose a new ID, and to
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * do that we shut the bridge down and bring it back up.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavairstp_change_mac(struct portdata *port, const unsigned char *newaddr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unsigned short prio;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unsigned char mac[ETHERADDRL];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int rc;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char curid[ETHERADDRL * 3];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char newmac[ETHERADDRL * 3];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) _link_ntoa(port->mac_addr, curid, ETHERADDRL, IFT_OTHER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) _link_ntoa(newaddr, newmac, ETHERADDRL, IFT_OTHER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai STP_IN_get_bridge_id(port->vlan_id, &prio, mac);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (memcmp(port->mac_addr, mac, ETHERADDRL) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_NOTICE, "bridge ID must change: ID %s on %s changed "
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai "to %s", curid, port->name, newmac);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uid_cfg.stp_enabled = STP_DISABLED;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((rc = STP_IN_stpm_set_cfg(0, &uid_cfg)) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "STP machine set config: %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai STP_IN_get_error_explanation(rc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memcpy(port->mac_addr, newaddr, ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uid_cfg.stp_enabled = STP_ENABLED;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((rc = STP_IN_stpm_set_cfg(0, &uid_cfg)) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "STP machine set config: %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai STP_IN_get_error_explanation(rc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai "MAC address on %s changed from %s to %s", port->name,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai curid, newmac);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memcpy(port->mac_addr, newaddr, ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiboolean_t
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavairstp_add_port(struct portdata *port)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int rc;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai UID_STP_PORT_CFG_T portcfg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_vlanenab_t bve;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_setstate_t bss;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!port->stp_added &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (rc = STP_IN_port_add(port->vlan_id, port->port_index)) != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "STP add %s %d: %s", port->name,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->port_index, STP_IN_get_error_explanation(rc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->stp_added = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* guaranteed to succeed at this point */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) get_init_port_cfg(port->vlan_id, port->port_index, &portcfg);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Restore state when reenabling STP engine, set fixed state when
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * disabling. For TRILL, we don't control forwarding at all, but we
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * need to turn off our controls for TRILL to do its thing.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_linkid = port->linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (protect != DLADM_BRIDGE_PROT_STP) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_state = port->state = BLS_BLOCKLISTEN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else if (portcfg.admin_non_stp) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_state = port->admin_status && !port->sdu_failed &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai !port->bpdu_protect ? BLS_FORWARDING : BLS_BLOCKLISTEN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_state = port->state;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_SETSTATE, &bss, sizeof (bss)) == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "cannot set STP state on %s: %m", port->name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto failure;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = STP_IN_enable_port(port->port_index,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->admin_status && port->phys_status && !port->sdu_failed &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai protect == DLADM_BRIDGE_PROT_STP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rc != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "STP enable %s %d: %s", port->name,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->port_index, STP_IN_get_error_explanation(rc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto failure;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (debugging) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = STP_IN_dbg_set_port_trace("all", True, 0,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->port_index);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* return to default debug state */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = STP_IN_dbg_set_port_trace("all", False, 0,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->port_index);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rc == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = STP_IN_dbg_set_port_trace("sttrans", True, 0,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->port_index);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rc != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "STP trace %s %d: %s", port->name,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->port_index, STP_IN_get_error_explanation(rc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto failure;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Clear out the kernel's allowed VLAN set; second walk will set */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bve.bve_linkid = port->linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bve.bve_vlan = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bve.bve_onoff = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_VLANENAB, &bve, sizeof (bve)) == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "unable to disable VLANs on %s: %m",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto failure;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((rc = STP_IN_port_set_cfg(0, port->port_index, &portcfg)) != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "STP port configure %s %d: %s", port->name,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->port_index, STP_IN_get_error_explanation(rc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto failure;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (B_TRUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifailure:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) STP_IN_port_remove(port->vlan_id, port->port_index);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->stp_added = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}