aggr_ctl.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * CDDL HEADER START
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * The contents of this file are subject to the terms of the
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Common Development and Distribution License, Version 1.0 only
269473047d747f7815af570197e4ef7322d3632cEvan Yan * (the "License"). You may not use this file except in compliance
269473047d747f7815af570197e4ef7322d3632cEvan Yan * with the License.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
269473047d747f7815af570197e4ef7322d3632cEvan Yan * or http://www.opensolaris.org/os/licensing.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * See the License for the specific language governing permissions
269473047d747f7815af570197e4ef7322d3632cEvan Yan * and limitations under the License.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * When distributing Covered Code, include this CDDL HEADER in each
269473047d747f7815af570197e4ef7322d3632cEvan Yan * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * If applicable, add the following below this CDDL HEADER, with the
269473047d747f7815af570197e4ef7322d3632cEvan Yan * fields enclosed by brackets "[]" replaced with your own identifying
269473047d747f7815af570197e4ef7322d3632cEvan Yan * information: Portions Copyright [yyyy] [name of copyright owner]
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * CDDL HEADER END
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Use is subject to license terms.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan#pragma ident "%Z%%M% %I% %E% SMI"
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * IEEE 802.3ad Link Aggregation -- IOCTL processing.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/ddi.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/aggr.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/aggr_impl.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int aggr_ioc_create(int, void *, int);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int aggr_ioc_delete(int, void *, int);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int aggr_ioc_info(int, void *, int);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int aggr_ioc_add_remove(int, void *, int);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int aggr_ioc_status(int, void *, int);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int aggr_ioc_modify(int, void *, int);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yantypedef struct ioc_cmd_s {
269473047d747f7815af570197e4ef7322d3632cEvan Yan int ic_cmd;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int (*ic_func)(int, void *, int);
269473047d747f7815af570197e4ef7322d3632cEvan Yan} ioc_cmd_t;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic ioc_cmd_t ioc_cmd[] = {
269473047d747f7815af570197e4ef7322d3632cEvan Yan {LAIOC_CREATE, aggr_ioc_create},
269473047d747f7815af570197e4ef7322d3632cEvan Yan {LAIOC_DELETE, aggr_ioc_delete},
269473047d747f7815af570197e4ef7322d3632cEvan Yan {LAIOC_INFO, aggr_ioc_info},
269473047d747f7815af570197e4ef7322d3632cEvan Yan {LAIOC_ADD, aggr_ioc_add_remove},
269473047d747f7815af570197e4ef7322d3632cEvan Yan {LAIOC_REMOVE, aggr_ioc_add_remove},
269473047d747f7815af570197e4ef7322d3632cEvan Yan {LAIOC_MODIFY, aggr_ioc_modify}};
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*ARGSUSED*/
269473047d747f7815af570197e4ef7322d3632cEvan Yanint
269473047d747f7815af570197e4ef7322d3632cEvan Yanaggr_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* only the control interface can be opened */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (getminor(*devp) != AGGR_MINOR_CTL)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ENOSYS);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*ARGSUSED*/
269473047d747f7815af570197e4ef7322d3632cEvan Yanint
269473047d747f7815af570197e4ef7322d3632cEvan Yanaggr_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Process a LAIOC_MODIFY request.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan/* ARGSUSED */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanaggr_ioc_modify(int cmd, void *arg, int mode)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan STRUCT_DECL(laioc_modify, modify_arg);
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint32_t policy;
269473047d747f7815af570197e4ef7322d3632cEvan Yan boolean_t mac_fixed;
269473047d747f7815af570197e4ef7322d3632cEvan Yan uchar_t mac_addr[ETHERADDRL];
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint8_t modify_mask_arg, modify_mask = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint32_t key;
269473047d747f7815af570197e4ef7322d3632cEvan Yan aggr_lacp_mode_t lacp_mode;
269473047d747f7815af570197e4ef7322d3632cEvan Yan aggr_lacp_timer_t lacp_timer;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan STRUCT_INIT(modify_arg, mode);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (copyin(arg, STRUCT_BUF(modify_arg), STRUCT_SIZE(modify_arg)) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EFAULT);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan key = STRUCT_FGET(modify_arg, lu_key);
269473047d747f7815af570197e4ef7322d3632cEvan Yan modify_mask_arg = STRUCT_FGET(modify_arg, lu_modify_mask);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (modify_mask_arg & LAIOC_MODIFY_POLICY) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan modify_mask |= AGGR_MODIFY_POLICY;
269473047d747f7815af570197e4ef7322d3632cEvan Yan policy = STRUCT_FGET(modify_arg, lu_policy);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (modify_mask_arg & LAIOC_MODIFY_MAC) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan modify_mask |= AGGR_MODIFY_MAC;
269473047d747f7815af570197e4ef7322d3632cEvan Yan bcopy(STRUCT_FGET(modify_arg, lu_mac), mac_addr, ETHERADDRL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan mac_fixed = STRUCT_FGET(modify_arg, lu_mac_fixed);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (modify_mask_arg & LAIOC_MODIFY_LACP_MODE) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan modify_mask |= AGGR_MODIFY_LACP_MODE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan lacp_mode = STRUCT_FGET(modify_arg, lu_lacp_mode);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (modify_mask_arg & LAIOC_MODIFY_LACP_TIMER) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan modify_mask |= AGGR_MODIFY_LACP_TIMER;
269473047d747f7815af570197e4ef7322d3632cEvan Yan lacp_timer = STRUCT_FGET(modify_arg, lu_lacp_timer);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (aggr_grp_modify(key, NULL, modify_mask, policy, mac_fixed,
269473047d747f7815af570197e4ef7322d3632cEvan Yan mac_addr, lacp_mode, lacp_timer));
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Process a LAIOC_CREATE request.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan/* ARGSUSED */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanaggr_ioc_create(int cmd, void *arg, int mode)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan STRUCT_DECL(laioc_create, create_arg);
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint16_t nports;
269473047d747f7815af570197e4ef7322d3632cEvan Yan laioc_port_t *ports = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint32_t policy;
269473047d747f7815af570197e4ef7322d3632cEvan Yan boolean_t mac_fixed;
269473047d747f7815af570197e4ef7322d3632cEvan Yan uchar_t mac_addr[ETHERADDRL];
269473047d747f7815af570197e4ef7322d3632cEvan Yan aggr_lacp_mode_t lacp_mode;
269473047d747f7815af570197e4ef7322d3632cEvan Yan aggr_lacp_timer_t lacp_timer;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rc;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan STRUCT_INIT(create_arg, mode);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (copyin(arg, STRUCT_BUF(create_arg), STRUCT_SIZE(create_arg)) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EFAULT);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan nports = STRUCT_FGET(create_arg, lc_nports);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nports > AGGR_MAX_PORTS)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EINVAL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan policy = STRUCT_FGET(create_arg, lc_policy);
269473047d747f7815af570197e4ef7322d3632cEvan Yan lacp_mode = STRUCT_FGET(create_arg, lc_lacp_mode);
269473047d747f7815af570197e4ef7322d3632cEvan Yan lacp_timer = STRUCT_FGET(create_arg, lc_lacp_timer);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ports = kmem_alloc(nports * sizeof (laioc_port_t), KM_SLEEP);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (copyin(STRUCT_FGETP(create_arg, lc_ports), ports,
269473047d747f7815af570197e4ef7322d3632cEvan Yan nports * sizeof (laioc_port_t)) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan rc = EFAULT;
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto bail;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan bcopy(STRUCT_FGET(create_arg, lc_mac), mac_addr, ETHERADDRL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan mac_fixed = STRUCT_FGET(create_arg, lc_mac_fixed);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan rc = aggr_grp_create(STRUCT_FGET(create_arg, lc_key),
269473047d747f7815af570197e4ef7322d3632cEvan Yan nports, ports, policy, mac_fixed, mac_addr, lacp_mode, lacp_timer);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yanbail:
269473047d747f7815af570197e4ef7322d3632cEvan Yan kmem_free(ports, nports * sizeof (laioc_port_t));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rc);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/* ARGSUSED */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanaggr_ioc_delete(int cmd, void *arg, int mode)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan STRUCT_DECL(laioc_delete, delete_arg);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan STRUCT_INIT(delete_arg, mode);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (copyin(arg, STRUCT_BUF(delete_arg), STRUCT_SIZE(delete_arg)) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EFAULT);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (aggr_grp_delete(STRUCT_FGET(delete_arg, ld_key)));
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yantypedef struct aggr_ioc_info_state {
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint32_t bytes_left;
269473047d747f7815af570197e4ef7322d3632cEvan Yan uchar_t *where; /* in user buffer */
269473047d747f7815af570197e4ef7322d3632cEvan Yan} aggr_ioc_info_state_t;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanaggr_ioc_info_new_grp(void *arg, uint32_t key, uchar_t *mac,
269473047d747f7815af570197e4ef7322d3632cEvan Yan boolean_t mac_fixed, uint32_t policy, uint32_t nports,
269473047d747f7815af570197e4ef7322d3632cEvan Yan aggr_lacp_mode_t lacp_mode, aggr_lacp_timer_t lacp_timer)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan aggr_ioc_info_state_t *state = arg;
269473047d747f7815af570197e4ef7322d3632cEvan Yan laioc_info_group_t grp;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (state->bytes_left < sizeof (grp))
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ENOSPC);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan grp.lg_key = key;
269473047d747f7815af570197e4ef7322d3632cEvan Yan bcopy(mac, grp.lg_mac, ETHERADDRL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan grp.lg_mac_fixed = mac_fixed;
269473047d747f7815af570197e4ef7322d3632cEvan Yan grp.lg_policy = policy;
269473047d747f7815af570197e4ef7322d3632cEvan Yan grp.lg_nports = nports;
269473047d747f7815af570197e4ef7322d3632cEvan Yan grp.lg_lacp_mode = lacp_mode;
269473047d747f7815af570197e4ef7322d3632cEvan Yan grp.lg_lacp_timer = lacp_timer;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (copyout(&grp, state->where, sizeof (grp)) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EFAULT);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan state->where += sizeof (grp);
269473047d747f7815af570197e4ef7322d3632cEvan Yan state->bytes_left -= sizeof (grp);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanaggr_ioc_info_new_port(void *arg, char *devname, uint32_t portnum,
269473047d747f7815af570197e4ef7322d3632cEvan Yan uchar_t *mac, aggr_port_state_t portstate, aggr_lacp_state_t *lacp_state)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan aggr_ioc_info_state_t *state = arg;
269473047d747f7815af570197e4ef7322d3632cEvan Yan laioc_info_port_t port;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (state->bytes_left < sizeof (port))
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ENOSPC);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan bcopy(devname, port.lp_devname, MAXNAMELEN + 1);
269473047d747f7815af570197e4ef7322d3632cEvan Yan port.lp_port = portnum;
269473047d747f7815af570197e4ef7322d3632cEvan Yan bcopy(mac, port.lp_mac, ETHERADDRL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan port.lp_state = portstate;
269473047d747f7815af570197e4ef7322d3632cEvan Yan port.lp_lacp_state = *lacp_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (copyout(&port, state->where, sizeof (port)) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EFAULT);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan state->where += sizeof (port);
269473047d747f7815af570197e4ef7322d3632cEvan Yan state->bytes_left -= sizeof (port);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*ARGSUSED*/
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanaggr_ioc_info(int cmd, void *arg, int mode)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan laioc_info_t info_arg;
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint32_t ngroups, group_key;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rc;
269473047d747f7815af570197e4ef7322d3632cEvan Yan aggr_ioc_info_state_t state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (copyin(arg, &info_arg, sizeof (info_arg)) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EFAULT);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Key of the group to return. If zero, the call returns information
269473047d747f7815af570197e4ef7322d3632cEvan Yan * regarding all groups currently defined.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan group_key = info_arg.li_group_key;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan state.bytes_left = info_arg.li_bufsize - sizeof (laioc_info_t);
269473047d747f7815af570197e4ef7322d3632cEvan Yan state.where = (uchar_t *)arg + sizeof (laioc_info_t);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan rc = aggr_grp_info(&ngroups, group_key, &state, aggr_ioc_info_new_grp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan aggr_ioc_info_new_port);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rc == 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan info_arg.li_ngroups = ngroups;
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (copyout(&info_arg, arg, sizeof (info_arg)) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EFAULT);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rc);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*ARGSUSED*/
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanaggr_ioc_add_remove(int cmd, void *arg, int mode)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan STRUCT_DECL(laioc_add_rem, add_rem_arg);
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint16_t nports;
269473047d747f7815af570197e4ef7322d3632cEvan Yan laioc_port_t *ports = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rc;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan STRUCT_INIT(add_rem_arg, mode);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (copyin(arg, STRUCT_BUF(add_rem_arg), STRUCT_SIZE(add_rem_arg)) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EFAULT);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan nports = STRUCT_FGET(add_rem_arg, la_nports);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nports > AGGR_MAX_PORTS)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EINVAL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ports = kmem_alloc(nports * sizeof (laioc_port_t), KM_SLEEP);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (copyin(STRUCT_FGETP(add_rem_arg, la_ports), ports,
269473047d747f7815af570197e4ef7322d3632cEvan Yan nports * sizeof (laioc_port_t)) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan rc = EFAULT;
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto bail;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (cmd) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan case LAIOC_ADD:
269473047d747f7815af570197e4ef7322d3632cEvan Yan rc = aggr_grp_add_ports(STRUCT_FGET(add_rem_arg, la_key),
269473047d747f7815af570197e4ef7322d3632cEvan Yan nports, ports);
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case LAIOC_REMOVE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan rc = aggr_grp_rem_ports(STRUCT_FGET(add_rem_arg, la_key),
269473047d747f7815af570197e4ef7322d3632cEvan Yan nports, ports);
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan default:
269473047d747f7815af570197e4ef7322d3632cEvan Yan rc = EINVAL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yanbail:
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (ports != NULL)
269473047d747f7815af570197e4ef7322d3632cEvan Yan kmem_free(ports, nports * sizeof (laioc_port_t));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rc);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*ARGSUSED*/
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanaggr_ioc_remove(void *arg, int mode)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan STRUCT_DECL(laioc_add_rem, rem_arg);
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint16_t nports;
269473047d747f7815af570197e4ef7322d3632cEvan Yan laioc_port_t *ports = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rc;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan STRUCT_INIT(rem_arg, mode);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (copyin(arg, STRUCT_BUF(rem_arg), STRUCT_SIZE(rem_arg)) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EFAULT);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan nports = STRUCT_FGET(rem_arg, la_nports);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (nports > AGGR_MAX_PORTS)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EINVAL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ports = kmem_alloc(nports * sizeof (laioc_port_t), KM_SLEEP);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (copyin(STRUCT_FGETP(rem_arg, la_ports), ports,
269473047d747f7815af570197e4ef7322d3632cEvan Yan nports * sizeof (laioc_port_t)) != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan rc = EFAULT;
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto bail;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan rc = aggr_grp_rem_ports(STRUCT_FGET(rem_arg, la_key),
269473047d747f7815af570197e4ef7322d3632cEvan Yan nports, ports);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yanbail:
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (ports != NULL)
269473047d747f7815af570197e4ef7322d3632cEvan Yan kmem_free(ports, nports * sizeof (laioc_port_t));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rc);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*ARGSUSED*/
269473047d747f7815af570197e4ef7322d3632cEvan Yanint
269473047d747f7815af570197e4ef7322d3632cEvan Yanaggr_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rv)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan int i;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan for (i = 0; i < sizeof (ioc_cmd) / sizeof (ioc_cmd_t); i++) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (cmd == ioc_cmd[i].ic_cmd)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ioc_cmd[i].ic_func(cmd, (void *)arg, mode));
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (EINVAL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan