xref: /illumos-gate/usr/src/man/man9e/mc_multicst.9e (revision 8119dad84d6416f13557b0ba8e2aaf9064cbcfd3)
1.\"
2.\" This file and its contents are supplied under the terms of the
3.\" Common Development and Distribution License ("CDDL"), version 1.0.
4.\" You may only use this file in accordance with the terms of version
5.\" 1.0 of the CDDL.
6.\"
7.\" A full copy of the text of the CDDL should have accompanied this
8.\" source.  A copy of the CDDL is also available via the Internet at
9.\" http://www.illumos.org/license/CDDL.
10.\"
11.\"
12.\" Copyright 2016 Joyent, Inc.
13.\"
14.Dd May 31, 2016
15.Dt MC_MULTICST 9E
16.Os
17.Sh NAME
18.Nm mc_multicst
19.Nd add or remove multicast address from device filter
20.Sh SYNOPSIS
21.In sys/mac_provider.h
22.Ft int
23.Fo prefix_m_multicst
24.Fa "void *driver"
25.Fa "boolean_t add"
26.Fa "const uint8_t *mac"
27.Fc
28.Sh INTERFACE LEVEL
29illumos DDI Specific
30.Sh PARAMETERS
31.Bl -tag -width Fa
32.It Fa driver
33A pointer to the driver's private data that was passed in via the
34.Sy m_pdata
35member of the
36.Xr mac_register 9S
37structure to the
38.Xr mac_register 9F
39function.
40.It Fa add
41A boolean value that indicates whether the device driver should add the
42specified address to its filter list or remove it.
43.It Fa mac
44A pointer to an array of bytes that contains the new multicast address being
45added or removed.
46It is guaranteed to be at least a number of bytes long equal to the length of
47the MAC plugin's address length.
48For Ethernet devices that length is six bytes,
49.Sy ETHERADDRL .
50.El
51.Sh DESCRIPTION
52The
53.Fn mc_multicst
54entry point is used to program a device driver's multicast filters.
55For more background on filter management, see the
56.Sx MAC Address Filter Management
57section in
58.Xr mac 9E .
59.Pp
60The device driver can optionally sanity check
61.Fa mac
62by making sure that it's both a valid multicast address and by checking
63whether or not it's already programmed the address.
64Based on the value of
65.Fa add ,
66the driver should either add the specified address,
67.Fa mac ,
68or remove it from its filter tables.
69The device driver is not responsible for any form of reference counting on these
70requests: that is maintained by the broader framework.
71.Pp
72The device driver can access its own device soft state by casting the
73.Fa device
74pointer.
75The device driver should employ the appropriate locking while updating and
76manipulating its filter tables and its own records.
77It is recommended that device drivers always maintain a copy of the addresses
78programmed into the device's filter tables so that they can more easily
79recover from various device resets and errors, or handle requests to
80suspend and resume the device that may result in the device registers
81being cleared.
82.Sh RETURN VALUES
83Upon successful completion, the device driver should return
84.Sy 0 .
85Otherwise, the driver should return a positive error number to indicate
86why the request failed.
87.Sh EXAMPLES
88The following example shows how a device driver might structure its
89.Fn mc_multicst
90entry point.
91.Bd -literal
92#include <sys/mac_provider.h>
93
94/*
95 * Note, this example merely shows the structure of this function.
96 * Different devices will have different ways to manage the set of
97 * multicast MAC addresses that they can program into their filters and
98 * they have different ways of keeping track of them. Like other
99 * examples, this assumes that there is a lock which protects this data.
100 * In this case we assume we have an array of structures that is used to
101 * track each multicast entry and a count of valid entries.
102 */
103
104#define	EXAMPLE_NMULTICAST_ADDRS	100
105
106static int
107example_multicast_add(example_t *ep, const uint8_t *mac_addr)
108{
109	int i, ret;
110
111	mutex_enter(&ep->ep_lock);
112	for (i = 0; i < ep->ep_nmcast_addrs; i++) {
113		if (bcmp(ep->ep_nmcast_addrs[i].ema_addr, mac_addr,
114		    ETHERADDRL) == 0) {
115			/*
116			 * The address is alread in our list, so we can
117			 * return and say we're done.
118			 */
119			mutex_exit(&ep->ep_lock);
120			return (0);
121		}
122	}
123
124	/*
125	 * We need to add this multicast address to a filter, make sure
126	 * we have enough space to do so.
127	 */
128	if (ep->ep_nmcast_addrs >= EXAMPLE_NMULTICAST_ADDRS) {
129		mutex_exit(&ep->ep_lock);
130		return (ENOSPC);
131	}
132
133	/*
134	 * Program the device before we add it to our list. Assume zero
135	 * means success.
136	 */
137	ret = example_program_add_mcast_filter(ep, mac_addr);
138	if (ret == 0) {
139		bcopy(mac_addr,
140		    ep->ep_nmcast_addrs[ep->ep_nmcast_addrs].ema_addr,
141		    ETHERADDRL);
142		ep->ep_nmcast_addrs++;
143	}
144
145	mutex_exit(&ep->ep_lock);
146
147	return (ret);
148}
149
150static int
151example_multicast_remove(example_t *ep, const uint8_t *mac_addr)
152{
153	int i, ret;
154	boolean_t found = B_FALSE;
155
156	mutex_enter(&ep->ep_lock);
157	for (i = 0; i < ep->ep_nmcast_addrs; i++) {
158		if (bcmp(ep->ep_mcast_addrs[i].ema_addr, mac_addr,
159		    ETHERADDRL) == 0) {
160			found = B_TRUE;
161			break;
162		}
163	}
164
165	if (found == B_FALSE) {
166		mutex_exit(&ep->ep_lock);
167		return (ENOENT);
168	}
169
170	/*
171	 * Assume that a return value of zero indicates that the removal
172	 * was successful. Note that i still has the index of this
173	 * entry.
174	 */
175	ret = example_program_rem_mcast_filter(ep, mac_addr);
176	if (ret == 0) {
177		int last = ep->ep_nmcast_addrs - 1;
178		if (i != last) {
179			bcopy(ep->ep_mcast_addrs[last].ema_addr,
180			    ep->ep_mcast_addrs[i].ema_addr,
181			    ETHERADDRL);
182		}
183		bzero(ep->ep_mcast_addrs[last].ema_addr,
184		    ETHERADDRL);
185		VERIFY(ep->ep_nmcast_addrs > 0);
186		ep->ep_nmcast_addrs--;
187	}
188
189	mutex_exit(&ep->ep_lock);
190	return (ret);
191}
192
193static int
194example_m_multicst(void *arg, boolean_t add, const uint8_t *mac_addr)
195{
196	example_t *ep = arg;
197
198	/*
199	 * We sanity check that we've been given a multicast address.
200	 */
201	if ((mac_addr[0] & 0x01) == 0)
202		return (EINVAL);
203
204	if (add)
205		return (example_multicast_add(ep, mac_addr);
206	else
207		return (example_multicast_remove(ep, mac_addr));
208}
209.Ed
210.Sh ERRORS
211The device driver may return one of the following errors.
212While this list is not intended to be exhaustive, it is recommended to use one
213of these if possible.
214.Bl -tag -width Er
215.It Er EINVAL
216The address
217.Fa mac
218is not a valid unicast address.
219.It Er EIO
220The driver encountered a device or transport error while trying to
221update the device's state.
222.It Er ENOENT
223The device driver was asked to remove a multicast address that it does
224not have.
225.It Er ENOSPC
226The driver was asked to add a multicast address; however, it has no more
227filter slots available to program the entry.
228.El
229.Sh SEE ALSO
230.Xr mac 9E ,
231.Xr mac_register 9F ,
232.Xr mac_register 9S
233