1da14cebeSEric Cheng /* 2da14cebeSEric Cheng * CDDL HEADER START 3da14cebeSEric Cheng * 4da14cebeSEric Cheng * The contents of this file are subject to the terms of the 5da14cebeSEric Cheng * Common Development and Distribution License (the "License"). 6da14cebeSEric Cheng * You may not use this file except in compliance with the License. 7da14cebeSEric Cheng * 8da14cebeSEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da14cebeSEric Cheng * or http://www.opensolaris.org/os/licensing. 10da14cebeSEric Cheng * See the License for the specific language governing permissions 11da14cebeSEric Cheng * and limitations under the License. 12da14cebeSEric Cheng * 13da14cebeSEric Cheng * When distributing Covered Code, include this CDDL HEADER in each 14da14cebeSEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da14cebeSEric Cheng * If applicable, add the following below this CDDL HEADER, with the 16da14cebeSEric Cheng * fields enclosed by brackets "[]" replaced with your own identifying 17da14cebeSEric Cheng * information: Portions Copyright [yyyy] [name of copyright owner] 18da14cebeSEric Cheng * 19da14cebeSEric Cheng * CDDL HEADER END 20da14cebeSEric Cheng */ 21da14cebeSEric Cheng /* 22*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23da14cebeSEric Cheng * Use is subject to license terms. 24da14cebeSEric Cheng */ 25da14cebeSEric Cheng 26da14cebeSEric Cheng /* 27da14cebeSEric Cheng * Flows ioctls implementation. 28da14cebeSEric Cheng */ 29da14cebeSEric Cheng 302b24ab6bSSebastien Roy #include <sys/cred.h> 31da14cebeSEric Cheng #include <sys/dld.h> 32da14cebeSEric Cheng #include <sys/mac_provider.h> 33da14cebeSEric Cheng #include <sys/mac_client.h> 34da14cebeSEric Cheng #include <sys/mac_client_priv.h> 35da14cebeSEric Cheng 36da14cebeSEric Cheng /* 37da14cebeSEric Cheng * Implements flow add, remove, modify ioctls. 38da14cebeSEric Cheng */ 39da14cebeSEric Cheng int 40da14cebeSEric Cheng dld_add_flow(datalink_id_t linkid, char *flow_name, flow_desc_t *flow_desc, 41da14cebeSEric Cheng mac_resource_props_t *mrp) 42da14cebeSEric Cheng { 43da14cebeSEric Cheng return (mac_link_flow_add(linkid, flow_name, flow_desc, mrp)); 44da14cebeSEric Cheng } 45da14cebeSEric Cheng 46da14cebeSEric Cheng int 47da14cebeSEric Cheng dld_remove_flow(char *flow_name) 48da14cebeSEric Cheng { 49da14cebeSEric Cheng return (mac_link_flow_remove(flow_name)); 50da14cebeSEric Cheng } 51da14cebeSEric Cheng 52da14cebeSEric Cheng int 53da14cebeSEric Cheng dld_modify_flow(char *flow_name, mac_resource_props_t *mrp) 54da14cebeSEric Cheng { 55da14cebeSEric Cheng return (mac_link_flow_modify(flow_name, mrp)); 56da14cebeSEric Cheng } 57da14cebeSEric Cheng 58da14cebeSEric Cheng 59da14cebeSEric Cheng /* 60da14cebeSEric Cheng * Callback function and structure used by dld_walk_flow(). 61da14cebeSEric Cheng */ 62da14cebeSEric Cheng typedef struct flowinfo_state_s { 63da14cebeSEric Cheng int fi_bufsize; 64da14cebeSEric Cheng int fi_nflows; 65da14cebeSEric Cheng uchar_t *fi_fl; 66da14cebeSEric Cheng } flowinfo_state_t; 67da14cebeSEric Cheng 68da14cebeSEric Cheng static int 69da14cebeSEric Cheng dld_walk_flow_cb(mac_flowinfo_t *finfo, void *arg) 70da14cebeSEric Cheng { 71da14cebeSEric Cheng flowinfo_state_t *statep = arg; 72*0dc2366fSVenugopal Iyer dld_flowinfo_t *fi; 73da14cebeSEric Cheng 74da14cebeSEric Cheng if (statep->fi_bufsize < sizeof (dld_flowinfo_t)) 75da14cebeSEric Cheng return (ENOSPC); 76da14cebeSEric Cheng 77*0dc2366fSVenugopal Iyer fi = kmem_zalloc(sizeof (*fi), KM_SLEEP); 78*0dc2366fSVenugopal Iyer (void) strlcpy(fi->fi_flowname, finfo->fi_flow_name, 79*0dc2366fSVenugopal Iyer sizeof (fi->fi_flowname)); 80*0dc2366fSVenugopal Iyer fi->fi_linkid = finfo->fi_link_id; 81*0dc2366fSVenugopal Iyer fi->fi_flow_desc = finfo->fi_flow_desc; 82*0dc2366fSVenugopal Iyer fi->fi_resource_props = finfo->fi_resource_props; 83da14cebeSEric Cheng 84*0dc2366fSVenugopal Iyer if (copyout(fi, statep->fi_fl, sizeof (*fi)) != 0) { 85*0dc2366fSVenugopal Iyer kmem_free(fi, sizeof (*fi)); 86da14cebeSEric Cheng return (EFAULT); 87da14cebeSEric Cheng } 88*0dc2366fSVenugopal Iyer kmem_free(fi, sizeof (*fi)); 89da14cebeSEric Cheng statep->fi_nflows++; 90da14cebeSEric Cheng statep->fi_bufsize -= sizeof (dld_flowinfo_t); 91da14cebeSEric Cheng statep->fi_fl += sizeof (dld_flowinfo_t); 92da14cebeSEric Cheng return (0); 93da14cebeSEric Cheng } 94da14cebeSEric Cheng 95da14cebeSEric Cheng /* 96da14cebeSEric Cheng * Implements flow walk ioctl. 97da14cebeSEric Cheng * Retrieves a specific flow or a list of flows from the specified link. 98da14cebeSEric Cheng * ENOSPC is returned a bigger buffer is needed. 99da14cebeSEric Cheng */ 100da14cebeSEric Cheng int 1012b24ab6bSSebastien Roy dld_walk_flow(dld_ioc_walkflow_t *wf, intptr_t uaddr, cred_t *credp) 102da14cebeSEric Cheng { 103da14cebeSEric Cheng flowinfo_state_t state; 104*0dc2366fSVenugopal Iyer mac_flowinfo_t *finfo; 105da14cebeSEric Cheng int err = 0; 106da14cebeSEric Cheng 1072b24ab6bSSebastien Roy /* For now, one can only view flows from the global zone. */ 1082b24ab6bSSebastien Roy if (crgetzoneid(credp) != GLOBAL_ZONEID) 1092b24ab6bSSebastien Roy return (EPERM); 1102b24ab6bSSebastien Roy 111*0dc2366fSVenugopal Iyer finfo = kmem_zalloc(sizeof (*finfo), KM_SLEEP); 112da14cebeSEric Cheng state.fi_bufsize = wf->wf_len; 113da14cebeSEric Cheng state.fi_fl = (uchar_t *)uaddr + sizeof (*wf); 114da14cebeSEric Cheng state.fi_nflows = 0; 115da14cebeSEric Cheng 116da14cebeSEric Cheng if (wf->wf_name[0] == '\0') { 117da14cebeSEric Cheng err = mac_link_flow_walk(wf->wf_linkid, dld_walk_flow_cb, 118da14cebeSEric Cheng &state); 119da14cebeSEric Cheng } else { 120*0dc2366fSVenugopal Iyer err = mac_link_flow_info(wf->wf_name, finfo); 121*0dc2366fSVenugopal Iyer if (err != 0) { 122*0dc2366fSVenugopal Iyer kmem_free(finfo, sizeof (*finfo)); 123da14cebeSEric Cheng return (err); 124da14cebeSEric Cheng } 125*0dc2366fSVenugopal Iyer err = dld_walk_flow_cb(finfo, &state); 126*0dc2366fSVenugopal Iyer } 127*0dc2366fSVenugopal Iyer kmem_free(finfo, sizeof (*finfo)); 128da14cebeSEric Cheng wf->wf_nflows = state.fi_nflows; 129da14cebeSEric Cheng return (err); 130da14cebeSEric Cheng } 131