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/*
327151705b7439cb7ab35c370f682cac7ef9523aCathy Zhou * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridged - bridging control daemon. This module handles events and general
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * port-related operations.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <stdio.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <stdlib.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <unistd.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <fcntl.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <string.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/types.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <syslog.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <libdlpi.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <libdladm.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <libdllink.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <libdlbridge.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <libdlvlan.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 Srivatsavaiint refresh_count = 1; /* never zero */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaidladm_bridge_prot_t protect = DLADM_BRIDGE_PROT_STP;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * The 'allports' array is an array of pointers to the struct portdata
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * structures. We reallocate 'allports' as needed, but the portdata must
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * remain where it's initially allocated, because libdlpi's notification
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * mechanism has a copy of a pointer to this structure.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiuint_t nextport;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistruct portdata **allports;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* Port allocation increment (arbitrary) */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define ALLOCINCR 10
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic uint_t numports;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic datalink_id_t main_linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiint control_fd;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavailinkdown(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) dladm_destroy_datalink_id(dlhandle, main_linkid,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DLADM_OPT_ACTIVE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiopen_bridge_control(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_newbridge_t bnb;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_status_t status;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char buf[DLADM_STRSIZE];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((control_fd = open(BRIDGE_CTLPATH, O_RDWR | O_NONBLOCK)) == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai perror(BRIDGE_CTLPATH);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai exit(EXIT_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) snprintf(bnb.bnb_name, sizeof (bnb.bnb_name), "%s0",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai instance_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_name2info(dlhandle, bnb.bnb_name, &bnb.bnb_linkid, NULL,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status != DLADM_STATUS_OK) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) fprintf(stderr, "bridged: %s: %s\n", bnb.bnb_name,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_status2str(status, buf));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai exit(EXIT_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_NEWBRIDGE, &bnb, sizeof (bnb)) == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai perror("NEWBRIDGE");
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai exit(EXIT_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai main_linkid = bnb.bnb_linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_TABLEMAX, &tablemax,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (tablemax)) == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "cannot set table max %lu on bridge %s: %m",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tablemax, instance_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai exit(EXIT_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This covers for any previous incarnation where we might have crashed
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * or been SIGKILL'd and failed to take down the datalink.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai linkdown();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) atexit(linkdown);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_up_datalink_id(dlhandle, bnb.bnb_linkid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status != DLADM_STATUS_OK) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) fprintf(stderr, "bridged: %s link up: %s\n",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bnb.bnb_name, dladm_status2str(status, buf));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai exit(EXIT_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistruct portdata *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifind_by_linkid(datalink_id_t linkid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata *port;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < nextport; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port = allports[i];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->linkid == linkid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (port);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*ARGSUSED2*/
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiset_vlan(dladm_handle_t handle, datalink_id_t linkid, void *arg)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata *port;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_status_t status;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_vlan_attr_t vinfo;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char pointless[DLADM_STRSIZE];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_vlanenab_t bve;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_vlan_info(handle, linkid, &vinfo, DLADM_OPT_ACTIVE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status != DLADM_STATUS_OK) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG, "can't get VLAN info on link ID %u: %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai linkid, dladm_status2str(status, pointless));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (DLADM_WALK_CONTINUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port = find_by_linkid(vinfo.dv_linkid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port == NULL || !port->kern_added)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (DLADM_WALK_CONTINUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bve.bve_linkid = port->linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bve.bve_vlan = vinfo.dv_vid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bve.bve_onoff = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_VLANENAB, &bve, sizeof (bve)) == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "unable to enable VLAN %d on linkid %u: %m",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vinfo.dv_vid, port->linkid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (DLADM_WALK_TERMINATE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (DLADM_WALK_CONTINUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If the named port already exists, then update its configuration. If it
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * doesn't, then create and enable it.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiupdate_port(int vlan_id, const char *portname, datalink_id_t linkid,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai datalink_class_t class)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int posn;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata *port;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct pollfd *fds;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int port_index;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai datalink_id_t linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char linkname[MAXLINKNAMELEN];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } adddata;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_setpvid_t bsv;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint_t propval, valcnt;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_status_t status;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (posn = 0; posn < nextport; posn++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (allports[posn]->linkid == linkid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* If we need to allocate more array space, then do so in chunks. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (posn >= numports) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata **newarr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai newarr = realloc(allports,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (*newarr) * (nextport + ALLOCINCR));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (newarr != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai allports = newarr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fds = realloc(fdarray,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (*fds) * (nextport + ALLOCINCR + FDOFFSET));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (fds != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fdarray = fds;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (newarr == NULL || fds == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "unable to add %s; no memory",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai portname);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai numports = nextport + ALLOCINCR;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port_index = posn + 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fds = fdarray + posn + FDOFFSET;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* If our linkid search ran to the end, then this is a new port. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (posn == nextport) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((port = calloc(1, sizeof (*port))) == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "unable to add %s; no memory",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai portname);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai allports[posn] = port;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->vlan_id = vlan_id;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->linkid = linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->port_index = port_index;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->phys_status = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->admin_status = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->state = BLS_BLOCKLISTEN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai nextport++;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Located port by linkid; we're just updating existing data */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port = allports[posn];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If it changed name, then close and reopen so we log under
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the most current name for this port.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->name != NULL && strcmp(portname, port->name) != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->dlpi != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dlpi_close(port->dlpi);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->dlpi = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->name = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fds->fd = -1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fds->events = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If the port is not yet attached to the bridge in the kernel, then do
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * that now.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!port->kern_added) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai adddata.linkid = linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) strlcpy(adddata.linkname, portname,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (adddata.linkname));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_ADDLINK, &adddata,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (adddata.linkid) + strlen(adddata.linkname)) == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "cannot bridge %s: %m", portname);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto failure;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->kern_added = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->referenced = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai valcnt = 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_get_linkprop_values(dlhandle, linkid,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DLADM_PROP_VAL_PERSISTENT, "forward", &propval, &valcnt);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status == DLADM_STATUS_OK)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->admin_status = propval;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bsv.bsv_vlan = 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_get_linkprop_values(dlhandle, linkid,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DLADM_PROP_VAL_PERSISTENT, "default_tag", &propval, &valcnt);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status == DLADM_STATUS_OK)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bsv.bsv_vlan = propval;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bsv.bsv_linkid = linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_SETPVID, &bsv, sizeof (bsv)) == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "can't set PVID on %s: %m", portname);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto failure;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->dlpi == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!port_dlpi_open(portname, port, class))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto failure;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fds->fd = dlpi_fd(port->dlpi);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fds->events = POLLIN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rstp_add_port(port))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifailure:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->dlpi != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dlpi_close(port->dlpi);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->dlpi = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->name = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fds->fd = -1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fds->events = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->kern_added) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_REMLINK, &port->linkid,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (port->linkid)) == -1)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "cannot remove from bridge %s: %m",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai portname);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->kern_added = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (posn + 1 == nextport) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai free(port);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai nextport--;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*ARGSUSED2*/
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiupdate_link(dladm_handle_t handle, datalink_id_t linkid, void *arg)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_status_t status;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char bridge[MAXLINKNAMELEN], linkname[MAXLINKNAMELEN];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char pointless[DLADM_STRSIZE];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai datalink_class_t class;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_bridge_getlink(handle, linkid, bridge, sizeof (bridge));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status == DLADM_STATUS_OK && strcmp(bridge, instance_name) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_datalink_id2info(handle, linkid, NULL, &class,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, linkname, sizeof (linkname));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status == DLADM_STATUS_OK) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai update_port(0, linkname, linkid, class);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "unable to get link info for ID %u: %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai linkid, dladm_status2str(status, pointless));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else if (debugging) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status != DLADM_STATUS_OK)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai "unable to get bridge data for ID %u: %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai linkid, dladm_status2str(status, pointless));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG, "link ID %u is on bridge %s, not %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai linkid, bridge, instance_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (DLADM_WALK_CONTINUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Refresh action - reread configuration properties.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaihandle_refresh(int sigfd)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata *pdp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct pollfd *fdp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char buf[16];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_status_t status;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t new_debug;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint32_t new_tablemax;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Drain signal events from pipe */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (sigfd != -1)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) read(sigfd, buf, sizeof (buf));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_bridge_get_privprop(instance_name, &new_debug,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &new_tablemax);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status == DLADM_STATUS_OK) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (debugging && !new_debug)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG, "disabling debugging");
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai debugging = new_debug;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (new_tablemax != tablemax) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG, "changed tablemax from %lu to %lu",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tablemax, new_tablemax);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_TABLEMAX, &new_tablemax,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (tablemax)) == -1)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "cannot set table max "
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai "%lu on bridge %s: %m", tablemax,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai instance_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tablemax = new_tablemax;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "%s: unable to refresh bridge properties: %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai instance_name, dladm_status2str(status, buf));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rstp_refresh();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < nextport; i++)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai allports[i]->referenced = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * libdladm doesn't guarantee anything about link ordering in a walk,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * so we do this walk twice: once to pick up the ports, and a second
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * time to get the enabled VLANs on all ports.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) dladm_walk_datalink_id(update_link, dlhandle, NULL,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) dladm_walk_datalink_id(set_vlan, dlhandle, NULL,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If any ports now show up as unreferenced, then they've been removed
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * from the configuration.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < nextport; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pdp = allports[i];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fdp = fdarray + i + FDOFFSET;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!pdp->referenced) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (pdp->stp_added) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) STP_IN_port_remove(pdp->vlan_id,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pdp->port_index);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pdp->stp_added = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (pdp->dlpi != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dlpi_close(pdp->dlpi);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pdp->dlpi = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pdp->name = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fdp->fd = -1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fdp->events = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (pdp->kern_added) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_REMLINK,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &pdp->linkid, sizeof (pdp->linkid)) == -1)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "cannot remove linkid "
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai "%u from bridge %s: %m",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pdp->linkid, instance_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pdp->kern_added = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (++refresh_count == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai refresh_count = 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Handle messages on the common control stream. This currently just deals
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * with port SDU mismatches.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaihandle_control(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_ctl_t bc;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ssize_t retv;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata *port;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int rc;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai retv = read(control_fd, &bc, sizeof (bc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (retv != sizeof (bc))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((port = find_by_linkid(bc.bc_linkid)) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->sdu_failed == bc.bc_failed)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->sdu_failed = bc.bc_failed;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!port->phys_status || !port->admin_status ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai protect != DLADM_BRIDGE_PROT_STP)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->admin_non_stp) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_setstate_t bss;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_linkid = port->linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_state = !port->sdu_failed && !port->bpdu_protect ?
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BLS_FORWARDING : BLS_BLOCKLISTEN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_SETSTATE, &bss,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (bss)) == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "cannot set STP state on %s: %m",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((rc = STP_IN_enable_port(port->port_index, !bc.bc_failed)) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "STP can't %s port %s for SDU failure: %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->name, bc.bc_failed ? "disable" : "enable",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai STP_IN_get_error_explanation(rc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaireceive_packet(struct portdata *port)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int rc;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai size_t buflen;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t buffer[ETHERMAX / sizeof (uint16_t)];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct ether_header *eh;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char sender[ETHERADDRL * 3];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai buflen = sizeof (buffer);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = dlpi_recv(port->dlpi, NULL, NULL, buffer, &buflen, 1, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rc != DLPI_SUCCESS) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rc != DLPI_ETIMEDOUT)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "receive failure on %s: %s", port->name,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dlpi_strerror(rc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If we're administratively disabled, then don't deliver packets to
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the STP state machine. It will re-enable the port because it uses
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the same variable for both link status and administrative state.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!port->admin_status || protect != DLADM_BRIDGE_PROT_STP) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (debugging)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai "discard BPDU on non-forwarding interface %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * There's a mismatch between the librstp and libdlpi expectations on
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * receive. librstp wants the packet to start with the 802 length
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * field, not the destination address.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai eh = (struct ether_header *)buffer;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = STP_IN_check_bpdu_header((BPDU_T *)&eh->ether_type, buflen);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Note that we attempt to avoid calling the relatively expensive
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * _link_ntoa function unless we're going to use the result. In normal
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * usage, we don't need this string.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rc == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->admin_non_stp && !port->bpdu_protect) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_setstate_t bss;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) _link_ntoa(eh->ether_shost.ether_addr_octet,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sender, ETHERADDRL, IFT_OTHER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_WARNING, "unexpected BPDU on %s from %s; "
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai "forwarding disabled", port->name, sender);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->bpdu_protect = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_linkid = port->linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_state = BLS_BLOCKLISTEN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strioctl(control_fd, BRIOC_SETSTATE, &bss,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (bss)) == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "cannot set STP state on "
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai "%s: %m", port->name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (debugging) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) _link_ntoa(eh->ether_shost.ether_addr_octet,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sender, ETHERADDRL, IFT_OTHER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG, "got BPDU from %s on %s; %d bytes",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sender, port->name, buflen);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = STP_IN_rx_bpdu(port->vlan_id, port->port_index,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (BPDU_T *)&eh->ether_type, buflen);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rc != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) _link_ntoa(eh->ether_shost.ether_addr_octet, sender,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ETHERADDRL, IFT_OTHER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_DEBUG,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai "discarded malformed packet on %s from %s: %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->name, sender, STP_IN_get_error_explanation(rc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiget_dladm_speed(struct portdata *port)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dladm_status_t status;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint64_t ifspeed;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai status = dladm_get_single_mac_stat(dlhandle, port->linkid, "ifspeed",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSTAT_DATA_UINT64, &ifspeed);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (status == DLADM_STATUS_OK && ifspeed != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->speed = ifspeed / 1000000;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->speed = 10UL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaienable_forwarding(struct portdata *port)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_setstate_t bss;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_linkid = port->linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss.bss_state = BLS_FORWARDING;
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}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaievent_loop(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hrtime_t last_time, now;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int tout;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (lock_engine() != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "mutex lock");
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai exit(EXIT_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Bootstrap configuration */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai handle_refresh(-1);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai last_time = gethrtime();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while (!shutting_down) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai now = gethrtime();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (now - last_time >= 1000000000ll) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) STP_IN_one_second();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tout = 1000;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai last_time = now;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tout = 1000 - (now - last_time) / 1000000ll;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unlock_engine();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) poll(fdarray, nextport + FDOFFSET, tout);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (lock_engine() != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "mutex lock");
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai exit(EXIT_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (fdarray[0].revents & POLLIN)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai handle_refresh(fdarray[0].fd);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (fdarray[1].revents & POLLIN)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai handle_control();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < nextport; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (fdarray[i + FDOFFSET].revents & POLLIN)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai receive_packet(allports[i]);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unlock_engine();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}