MC_MULTICST(9E) Driver Entry Points MC_MULTICST(9E)
NAME
mc_multicst - add or remove multicast address from device filter
SYNOPSIS
#include <sys/mac_provider.h> int prefix_m_multicst(
void *driver,
boolean_t add,
const uint8_t *mac);
INTERFACE LEVEL
illumos DDI Specific
PARAMETERS
driver A pointer to the driver's private data that was passed in
via the
m_pdata member of the
mac_register(9S) structure
to the
mac_register(9F) function.
add A boolean value that indicates whether the device driver
should add the specified address to its filter list or
remove it.
mac A pointer to an array of bytes that contains the new
multicast address being added or removed. It is
guaranteed to be at least a number of bytes long equal to
the length of the MAC plugin's address length. For
Ethernet devices that length is six bytes,
ETHERADDRL.
DESCRIPTION
The
mc_multicst() entry point is used to program a device driver's
multicast filters. For more background on filter management, see the
MAC Address Filter Management section in
mac(9E).
The device driver can optionally sanity check
mac by making sure that
it's both a valid multicast address and by checking whether or not it's
already programmed the address. Based on the value of
add, the driver
should either add the specified address,
mac, or remove it from its
filter tables. The device driver is not responsible for any form of
reference counting on these requests: that is maintained by the broader
framework.
The device driver can access its own device soft state by casting the
device pointer. The device driver should employ the appropriate
locking while updating and manipulating its filter tables and its own
records. It is recommended that device drivers always maintain a copy
of the addresses programmed into the device's filter tables so that
they can more easily recover from various device resets and errors, or
handle requests to suspend and resume the device that may result in the
device registers being cleared.
RETURN VALUES
Upon successful completion, the device driver should return
0.
Otherwise, the driver should return a positive error number to indicate
why the request failed.
EXAMPLES
The following example shows how a device driver might structure its
mc_multicst() entry point.
#include <sys/mac_provider.h>
/*
* Note, this example merely shows the structure of this function.
* Different devices will have different ways to manage the set of
* multicast MAC addresses that they can program into their filters and
* they have different ways of keeping track of them. Like other
* examples, this assumes that there is a lock which protects this data.
* In this case we assume we have an array of structures that is used to
* track each multicast entry and a count of valid entries.
*/
#define EXAMPLE_NMULTICAST_ADDRS 100
static int
example_multicast_add(example_t *ep, const uint8_t *mac_addr)
{
int i, ret;
mutex_enter(&ep->ep_lock);
for (i = 0; i < ep->ep_nmcast_addrs; i++) {
if (bcmp(ep->ep_nmcast_addrs[i].ema_addr, mac_addr,
ETHERADDRL) == 0) {
/*
* The address is alread in our list, so we can
* return and say we're done.
*/
mutex_exit(&ep->ep_lock);
return (0);
}
}
/*
* We need to add this multicast address to a filter, make sure
* we have enough space to do so.
*/
if (ep->ep_nmcast_addrs >= EXAMPLE_NMULTICAST_ADDRS) {
mutex_exit(&ep->ep_lock);
return (ENOSPC);
}
/*
* Program the device before we add it to our list. Assume zero
* means success.
*/
ret = example_program_add_mcast_filter(ep, mac_addr);
if (ret == 0) {
bcopy(mac_addr,
ep->ep_nmcast_addrs[ep->ep_nmcast_addrs].ema_addr,
ETHERADDRL);
ep->ep_nmcast_addrs++;
}
mutex_exit(&ep->ep_lock);
return (ret);
}
static int
example_multicast_remove(example_t *ep, const uint8_t *mac_addr)
{
int i, ret;
boolean_t found = B_FALSE;
mutex_enter(&ep->ep_lock);
for (i = 0; i < ep->ep_nmcast_addrs; i++) {
if (bcmp(ep->ep_mcast_addrs[i].ema_addr, mac_addr,
ETHERADDRL) == 0) {
found = B_TRUE;
break;
}
}
if (found == B_FALSE) {
mutex_exit(&ep->ep_lock);
return (ENOENT);
}
/*
* Assume that a return value of zero indicates that the removal
* was successful. Note that i still has the index of this
* entry.
*/
ret = example_program_rem_mcast_filter(ep, mac_addr);
if (ret == 0) {
int last = ep->ep_nmcast_addrs - 1;
if (i != last) {
bcopy(ep->ep_mcast_addrs[last].ema_addr,
ep->ep_mcast_addrs[i].ema_addr,
ETHERADDRL);
}
bzero(ep->ep_mcast_addrs[last].ema_addr,
ETHERADDRL);
VERIFY(ep->ep_nmcast_addrs > 0);
ep->ep_nmcast_addrs--;
}
mutex_exit(&ep->ep_lock);
return (ret);
}
static int
example_m_multicst(void *arg, boolean_t add, const uint8_t *mac_addr)
{
example_t *ep = arg;
/*
* We sanity check that we've been given a multicast address.
*/
if ((mac_addr[0] & 0x01) == 0)
return (EINVAL);
if (add)
return (example_multicast_add(ep, mac_addr);
else
return (example_multicast_remove(ep, mac_addr));
}
ERRORS
The device driver may return one of the following errors. While this
list is not intended to be exhaustive, it is recommended to use one of
these if possible.
EINVAL The address
mac is not a valid unicast address.
EIO The driver encountered a device or transport error
while trying to update the device's state.
ENOENT The device driver was asked to remove a multicast
address that it does not have.
ENOSPC The driver was asked to add a multicast address;
however, it has no more filter slots available to
program the entry.
SEE ALSO
mac(9E),
mac_register(9F),
mac_register(9S)illumos May 31, 2016 illumos