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