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