mac_client.c revision 7507fc2c908837ebd87f3bf16a6d7d4528eccb23
* Return the lower MAC client handle from the VNIC driver for the * specified VNIC MAC instance. * Return the MAC client handle of the primary MAC client for the * specified MAC instance, or NULL otherwise. * Open a MAC specified by its MAC name. * Look up its entry in the global hash table. * Hold the dip associated to the MAC to prevent it from being * detached. For a softmac, its underlying dip is held by the * This is done to be more tolerant with some defective drivers, * which incorrectly handle mac_unregister() failure in their * xxx_detach() routine. For example, some drivers ignore the * failure of mac_unregister() and free all resources that * that are needed for data transmition. * The mac perimeter is used in both mac_open and mac_close by the * Open a MAC specified by its linkid. * Open a MAC specified by its link name. * Close the specified MAC. * The mac perimeter is used in both mac_open and mac_close by the * Misc utility functions to retrieve various information about a MAC * instance or a MAC client. * Return the VID associated with a MAC client. This function should * be called for clients which are associated with only one VID. * Return the link speed associated with the specified MAC client. * The link speed of a MAC client is equal to the smallest value of * 1) the current link speed of the underlying NIC, or * 2) the bandwidth limit set for the MAC client. * Note that the bandwidth limit can be higher than the speed * of the underlying NIC. This is allowed to avoid spurious * administration action failures or artifically lowering the * bandwidth limit of a link that may have temporarily lowered * its link speed due to hardware problem or administrator action. * Return the link state of the specified client. If here are more * than one clients of the underying mac_impl_t, the link state * will always be UP regardless of the link state of the underlying * mac_impl_t. This is needed to allow the MAC clients to continue * to communicate with each other even when the physical link of * their mac_impl_t is down. * Returns LINK_STATE_UP if there are other MAC clients defined on * mac_impl_t which share same VLAN ID as that of mcip. Note that * if 'mcip' has more than one VID's then we match ANY one of the * VID's with other MAC client's VID's and return LINK_STATE_UP. * Return the statistics of a MAC client. These statistics are different * then the statistics of the underlying MAC which are returned by * Return the statistics of the specified MAC instance. * The range of stat determines where it is maintained. Stat * values from 0 up to (but not including) MAC_STAT_MIN are * mainteined by the mac module itself. Everything else is * maintained by the driver. * If the mac_impl_t being queried corresponds to a VNIC, * the stats need to be queried from the lower MAC client * corresponding to the VNIC. (The mac_link_update() * invoked by the driver to the lower MAC causes the *lower * MAC* to update its mi_linkstate, and send a notification * to its MAC clients. Due to the VNIC passthrough, * these notifications are sent to the upper MAC clients * of the VNIC directly, and the upper mac_impl_t of the VNIC * does not have a valid mi_linkstate. /* these stats are maintained by the mac module itself */ * Call the driver to get the given statistic. * The driver doesn't support this statistic. Get the * statistic's default value. * Utility function which returns the VID associated with a flow entry. * Verify the validity of the specified unicast MAC address. Returns B_TRUE * if the address is valid, B_FALSE otherwise (multicast address, or incorrect * Verify the address. No lock is needed since mi_type and plugin * details don't change after mac_register(). * Update the MAC unicast address of the specified client's flows. Currently * only one unicast MAC unicast address is allowed per client. * A MAC client could have one MAC address but multiple * VLANs. In that case update the flow entries corresponding * to all VLANs of the MAC client. * Update all clients that share the same unicast address. * Find all clients that share the same unicast MAC address and update * Ignore clients that don't share this MAC address. * Update those clients with same old unicast MAC address. * Update the unicast MAC address of the specified VNIC MAC client. * Check whether the operation is valid. Any of following cases should fail: * 1. It's a VLAN type of VNIC. * 2. The new value is current "primary" MAC address. * 3. The current MAC address is shared with other clients. * 4. The new MAC address has been used. This case will be valid when * client migration is fully supported. * If this is a VLAN type of VNIC, it's using "primary" MAC address * of the underlying interface. Must fail here. Refer to case 1 above. * If the new address is the "primary" one, must fail. Refer to * If the address is shared by multiple clients, must fail. Refer * If the new address has been used, must fail for now. Refer to * Update the MAC address. * Update all flows of this MAC client. * Program the new primary unicast address of the specified MAC. * Function mac_update_macaddr() takes care different types of underlying * MAC. If the underlying MAC is VNIC, the VNIC driver must have registerd * mi_unicst() entry point, that indirectly calls mac_vnic_unicast_set() * which will take care of updating the MAC address of the corresponding * This is the only interface that allow the client to update the "primary" * MAC address of the underlying MAC. The new value must have not been /* verify the address validity */ * If the new value is the same as the current primary address value, * Update the MAC address. * If the mac is an aggregation, other than the unicast * addresses programming, aggr must be informed about this * primary unicst address change to change its mac address * policy to be user-specified. * Save the new primary MAC address in mac_impl_t. * Return the current primary MAC address of the specified MAC. * Return information about the use of the primary MAC address of the * specified MAC instance: * - if client_name is non-NULL, it must point to a string of at * least MAXNAMELEN bytes, and will be set to the name of the MAC * client which uses the primary MAC address. * - if in_use is non-NULL, used to return whether the primary MAC * address is currently in use. * The mi_rw_lock is used to protect threads that don't hold the * mac perimeter to get a consistent view of the mi_clients_list. * Threads that modify the list must hold both the mac perimeter and * Add the specified MAC client to the list of clients which opened /* add VNIC to the front of the list */ * Remove the specified MAC client from the list of clients which opened * Return whether the specified (MAC address, VID) tuple is already used by * one of the MAC clients associated with the specified MAC. * Ignore clients that don't have unicast address. * Generate a random MAC address. The MAC address prefix is * stored in the array pointed to by mac_addr, and its length, in bytes, * is specified by prefix_len. The least significant bits * after prefix_len bytes are generated, and stored after the prefix /* check the prefix value */ /* generate the MAC address */ * Set the priority range for this MAC client. This will be used to * determine the absolute priority for the threads created for this * MAC client using the specified "low", "medium" and "high" level. * This will also be used for any subflows on this MAC client. * MAC client open entry point. Return a new MAC client handle. Each * MAC client is associated with a name, specified through the 'name' /* can't have shares but no hardware rings */ * The underlying MAC is a VNIC. Return the MAC client * handle of the lower MAC which was obtained by * the VNIC driver when it did its mac_client_open(). * Note that multiple mac clients share the same mcip in * Use mac name if dlmgmtd is not available. /* the subflow table will be created dynamically */ /* Create an initial flow */ * Place initial creation reference on the flow. This reference * is released in the corresponding delete action viz. * mac_unicast_remove after waiting for all transient refs to * to go away. The wait happens in mac_flow_wait. * Do this ahead of the mac_bcast_add() below so that the mi_nclients * will have the right value for mac_rx_srs_setup(). * Close the specified MAC client handle. * This is an upper VNIC client initiated operation. * The lower MAC client will be closed by the VNIC driver * when the VNIC is deleted. * Remove the flent associated with the MAC client * MAC clients must remove the unicast addresses and promisc callbacks * they added before issuing a mac_client_close(). * Enable bypass for the specified MAC client. * If the mac_client is a VLAN, we should not do DLS bypass and * instead let the packets come up via mac_rx_deliver so the vlan * header can be stripped. * These are not accessed directly in the data path, and hence * don't need any protection * Set the receive callback for the specified MAC client. There can be * at most one such callback per MAC client. * Instead of adding an extra set of locks and refcnts in * the datapath at the mac client boundary, we temporarily quiesce * the SRS and related entities. We then change the receive function * without interference from any receive data thread and then reenable * the data flow subsequently. * Reset the receive callback for the specified MAC client. * Walk the MAC client subflow table and updates their priority values. * When the MAC client is being brought up (i.e. we do a unicast_add) we need * to initialize the cpu and resource control structure in the * mac_client_impl_t from the mac_impl_t (i.e if there are any cached * properties before the flow entry for the unicast address was created). * We have to set this prior to calling mac_flow_modify. * First unicast address being added, create a new flow * XXX-nicolas. For now I'm keeping the FLOW_PRIMARY_MAC * and FLOW_VNIC. Even though they're a hack inherited * from the SRS code, we'll keep them for now. They're currently * consumed by mac_datapath_setup() to create the SRS. * That code should be eventually moved out of * mac_datapath_setup() and moved to a mac_srs_create() * function of some sort to keep things clean. * Also, there's no reason why the SRS for the primary MAC * client should be different than any other MAC client. Until * this is cleaned-up, we support only one MAC unicast address * We set FLOW_PRIMARY_MAC for the primary MAC address, * FLOW_VNIC for everything else. * For the first flow we use the mac client's name - mci_name, for * subsequent ones we just create a name with the vid. This is * so that we can add these flows to the same flow table. This is * fine as the flow name (except for the one with the mac client's * name) is not visible. When the first flow is removed, we just replace * its fdesc with another from the list, so we will still retain the * flent with the MAC client's flow name. * Place initial creation reference on the flow. This reference * is released in the corresponding delete action viz. * mac_unicast_remove after waiting for all transient refs to * to go away. The wait happens in mac_flow_wait. * We have already held the reference in mac_client_open(). /* Refresh the multicast grouping for this VID. */ * We don't call mac_multicast_add()/mac_multicast_remove() as * we want to add/remove for this specific vid. * Find the one active MAC client from the list of MAC * clients. The active MAC client has at least one * mi_single_active_client is protected by the MAC impl's read/writer * lock, which allows mac_rx() to check the value of that pointer * Add a new unicast address to the MAC client. * The MAC address can be specified either by value, or the MAC client * can specify that it wants to use the primary MAC address of the * underlying MAC. See the introductory comments at the beginning * of this file for more more information on primary MAC addresses. * Note also the tuple (MAC address, VID) must be unique * for the MAC clients defined on top of the same underlying MAC * instance, unless the MAC_UNICAST_NODUPCHECK is specified. /* when VID is non-zero, the underlying MAC can not be VNIC */ * Check whether it's the primary client and flag it. * is_vnic_primary is true when we come here as a VLAN VNIC * which uses the primary mac client's address but with a non-zero * VID. In this case the MAC address is not specified by an upper * The address is being set by the upper MAC client * of a VNIC. The MAC address was already set by the * VNIC driver during VNIC creation. * Note: a VNIC has only one MAC address. We return * the MAC unicast address handle of the lower MAC client * corresponding to the VNIC. We allocate a new entry * which is flagged appropriately, so that mac_unicast_remove() * doesn't attempt to free the original entry that * was allocated by the VNIC driver. /* Check for VLAN flags, if present */ * Ensure that the primary unicast address of the VNIC * Create a handle for vid 0. /* primary MAC clients cannot be opened on top of anchor VNICs */ * If this is a VNIC/VLAN, disable softmac fast-path. * - there is an exclusively active mac client exists. * - this is an exclusive active mac client but * a. there is already active mac clients exist, or * b. fastpath streams are already plumbed on this legacy device * Apply the property cached in the mac_impl_t to the primary * mac client. If the mac client is a VNIC or an aggregation * port, its property should be set in the mcip when the * Verify the validity of the specified MAC addresses value. * Make sure that the specified MAC address is different * than the unicast MAC address of the underlying NIC. * Make sure the MAC address is not already used by * another MAC client defined on top of the same * xxx-venu mac_unicast_add doesnt' seem to be called * with MAC_UNICAST_NODUPCHECK currently, if it does * get called we need to do mac_addr_in_use() just * to check for addr_in_use till 6697876 is fixed. /* add the MAC client to the broadcast address group by default */ * If this is the first unicast address addition for this * client, reuse the pre-allocated larval flow entry associated with /* We are configuring the unicast flow now */ * The client requires a hardware MAC address slot * for that unicast address. Since we support only * one unicast MAC address per client, flag the /* Check for VLAN flags, if present */ * This will allocate the RX ring group if possible for the * flow and program the software classifier as needed. * The unicast MAC address must have been added successfully. * Push down the sub-flows that were defined on this link * hitherto. The flows are added to the active flow table * and SRS, softrings etc. are created as needed. * A unicast flow already exists for that MAC client, * this flow must be the same mac address but with * different VID. It has been checked by mac_addr_in_use(). * We will use the SRS etc. from the mci_flent. Note that * We don't need to create kstat for this as except for * the fdesc, everything will be used from in the 1st flent. * Assert that the specified flags are consistent with the * flags specified by previous calls to mac_unicast_add(). * Make sure the client is consistent about its requests * for MAC addresses. I.e. all requests from the clients * must have the MAC_UNICAST_HW flag set or clear. /* update the multicast group for this vid */ /* populate the shared MAC address */ * First add the flent to the flow list of this mcip. Then set * the mip's mi_single_active_client if needed. The Rx path assumes * that mip->mi_single_active_client will always have an associated * Trigger a renegotiation of the capabilities when the number of * active clients changes from 1 to 2, since some of the capabilities * might have to be disabled. Also send a MAC_NOTE_LINK notification * to all the MAC clients whenever physical link is DOWN. * Now that the setup is complete, clear the INCIPIENT flag. * The flag was set to avoid incoming packets seeing inconsistent * structures while the setup was in progress. Clear the mci_tx_flag * by calling mac_tx_client_block. It is possible that * mac_unicast_remove was called prior to this mac_unicast_add which * could have set the MCI_TX_QUIESCE flag. * Remove a MAC address which was previously added by mac_unicast_add(). * Called made by the upper MAC client of a VNIC. * There's nothing much to do, the unicast address will * be removed by the VNIC driver when the VNIC is deleted, * but let's ensure that all our transmit is done before * the client does a mac_client_stop lest it trigger an * Remove the VID from the list of client's VIDs. * This MAC client is shared by more than one unicast * addresses, so we will just remove the flent * corresponding to the address being removed. We don't invoke * mac_rx_classify_flow_rem() since the additional flow is * not associated with its own separate set of SRS and rings, * and these constructs are still needed for the remaining * The first one is disappearing, need to make sure * we replace it with another from the list of * The multicast groups that were added by the client so * far must be removed from the brodcast domain corresponding * to the VID being removed. * We would have initialized subflows etc. only if we brought up * the primary client and set the unicast unicast address etc. * Deactivate the flows. The flow entry will be removed from the * active flow tables, and the associated SRS, softrings etc will * be deleted. But the flow entry itself won't be destroyed, instead * it will continue to be archived off the the global flow hash * list, for a possible future activation when say IP is plumbed /* Tear down the Data path */ * Prevent any future access to the flow entry through the mci_flent * pointer by setting the mci_flent to NULL. Access to mci_flent in * mac_bcast_send is also under mi_rw_lock. * This is the last unicast address being removed and there shouldn't * be any outbound data threads at this point coming down from mac * clients. We have waited for the data threads to finish before * starting dld_str_detach. Non-data threads must access TX SRS * Don't use FLOW_MARK with FE_MC_NO_DATAPATH, as the flow might * contain other flags, such as FE_CONDEMNED, which we need to * cleared. We don't call mac_flow_cleanup() for this unicast * flow as we have a already cleaned up SRSs etc. (via the teadown * path). We just clear the stats and reset the initial callback * function, the rest will be set when we call mac_flow_create, /* Initialize the receiver function to a safe routine */ * Disable fastpath if this is a VNIC or a VLAN. * Multicast add function invoked by MAC clients. /* Verify the address is a valid multicast address */ * If we failed adding, then undo all, rather than partial * Multicast delete function invoked by MAC clients. * When a MAC client desires to capture packets on an interface, * it registers a promiscuous call back with mac_promisc_add(). * There are three types of promiscuous callbacks: * * MAC_CLIENT_PROMISC_ALL * Captures all packets sent and received by the MAC client, * the physical interface, as well as all other MAC clients * defined on top of the same MAC. * * MAC_CLIENT_PROMISC_FILTERED * Captures all packets sent and received by the MAC client, * plus all multicast traffic sent and received by the phyisical * interface and the other MAC clients. * * MAC_CLIENT_PROMISC_MULTI * Captures all broadcast and multicast packets sent and * received by the MAC clients as well as the physical interface. * In all cases, the underlying MAC is put in promiscuous mode. * The function is being invoked by the upper MAC client * of a VNIC. The VNIC should only see the traffic * Turn on promiscuous mode for the underlying NIC. * This is needed even for filtered callbacks which * expect to receive all multicast traffic on the wire. * Physical promiscuous mode should not be turned on if * MAC_PROMISC_FLAGS_NO_PHYS is set. * Remove a multicast address previously aded through mac_promisc_add(). * Even if the device can't be reset into normal mode, we still * need to clear the client promisc callbacks. The client may want * to close the mac end point and we can't have stale callbacks. * Reference count the number of active Tx threads. MCI_TX_QUIESCE indicates * that a control operation wants to quiesce the Tx data flow in which case * we return an error. Holding any of the per cpu locks ensures that the * mci_tx_flag won't change. * 'CPU' must be accessed just once and used to compute the index into the * percpu array, and that index must be used for the entire duration of the * packet send operation. Note that the thread may be preempted and run on * another cpu any time and so we can't use 'CPU' more than once for the * Release the reference. If needed, signal any control operation waiting * for Tx quiescence. The wait and signal are always done using the * Bump the count of the number of active Tx threads. This is maintained as * a per CPU counter. On (CMT kind of) machines with large number of CPUs, * a single mci_tx_lock may become contended. However a count of the total * number of Tx threads per client is needed in order to quiesce the Tx side * prior to reassigning a Tx ring dynamically to another client. The thread * that needs to quiesce the Tx traffic grabs all the percpu locks and checks * the sum of the individual percpu refcnts. Each Tx data thread only grabs * its own percpu lock and increments its own refcnt. * Send function invoked by MAC clients. * Check whether the active Tx threads count is bumped already. * The main assumption here is that if in the event * we get a chain, all the packets will be classified * to the same Flow/SRS. If this changes for any * reason, the following logic should change as well. * I suppose the fanout_hint also assumes this . * Since dls always opens the underlying MAC, nclients equals * to 1 means that the only active client is dls itself acting * as a primary client of the MAC instance. Since dls will not * send tagged packets in that case, and dls is trusted to send * packets for its allowed VLAN(s), the VLAN tag insertion and * check is required only if nclients is greater than 1. * Given a cookie, it returns if the ring identified by the cookie is * flow-controlled or not. If NULL is passed in place of a cookie, * then it finds out if any of the underlying rings belonging to the * SRS is flow controlled or not and returns that status. * Bump the reference count so that mac_srs won't be deleted. * If the client is currently quiesced and we failed to bump * the reference, return B_TRUE so that flow control stays * Flow control will then be disabled once the client is no * Check if the MAC client is the primary MAC client. * If ndd props were registered, call them. * Note that ndd ioctls are Obsolete * Call the driver to handle the ioctl. The driver may not support * any ioctls, in which case we reply with a NAK on its behalf. * Return the link state of the specified MAC instance. * Add a mac client specified notification callback. Please see the comments * above mac_callback_add() for general information about mac callback * Allocate a notify callback structure, fill in the details and * use the mac callback list manipulation functions to chain into * Remove a mac client specified notification callback * If there aren't any list walkers, the remove would succeed * inline, else we wait for the deferred remove to complete * If we failed to remove the notification callback and "wait" is set * to be B_TRUE, wait for the callback to finish after we exit the * Associate resource management callbacks with the specified MAC /* update the 'resource_add' callback */ * Sets up the client resources and enable the polling interface over all the * SRS's and the soft rings of the client * Tears down the client resources and disable the polling interface over all * the SRS's and the soft rings of the client * Associate the CPUs specified by the given property with a MAC client. * Apply the specified properties to the specified MAC client. * Return the properties currently associated with the specified MAC client. * Pass a copy of the specified packet to the promiscuous callbacks * If sender is NULL, the function is being invoked for a packet chain * received from the wire. If sender is non-NULL, it points to * the MAC client from which the packet is being sent. * The packets are distributed to the promiscuous callbacks as follows: * - all packets are sent to the MAC_CLIENT_PROMISC_ALL callbacks * - all broadcast and multicast packets are sent to the * MAC_CLIENT_PROMISC_FILTER and MAC_CLIENT_PROMISC_MULTI. * The unicast packets of MAC_CLIENT_PROMISC_FILTER callbacks are dispatched * after classification by mac_rx_deliver(). * Return the VID of a packet. Zero if the packet is not tagged. * Return whether the specified packet contains a multicast or broadcast * destination MAC address. * Send a copy of an mblk chain to the MAC clients of the specified MAC. * "sender" points to the sender MAC client for outbound packets, and * is set to NULL for inbound packets. /* send packet to interested callbacks */ * The sender doesn't want to receive * copies of the packets it sends. * For an ethernet MAC, don't displatch a multicast * packet to a non-PROMISC_ALL callbacks unless the VID * of the packet matches the VID of the client. * The unicast packets for the MAC client still * need to be delivered to the MAC_CLIENT_PROMISC_FILTERED * promiscuous callbacks. The broadcast and multicast * packets were delivered from mac_rx(). * Return the margin value currently assigned to the specified MAC instance. * mac_info_get() is used for retrieving the mac_info when a DL_INFO_REQ is * issued before a DL_ATTACH_REQ. we walk the i_mac_impl_hash table and find * the first mac_impl_t with a matching driver name; then we copy its mac_info_t * to the caller. we do all this with i_mac_impl_lock held so the mac_impl_t * cannot disappear while we are accessing it. * To get the capabilities that MAC layer cares about, such as rings, factory * mac address, vnic or not, it should directly invoke this function * Capability query function. If number of active mac clients is greater than * 1, only limited capabilities can be advertised to the caller no matter the * driver has certain capability or not. Else, we query the driver to get the * if mi_nactiveclients > 1, only MAC_CAPAB_LEGACY, MAC_CAPAB_HCKSUM, * MAC_CAPAB_NO_NATIVEVLAN and MAC_CAPAB_NO_ZCOPY can be advertised. /* else get capab from driver */ /* True if a MAC is a VNIC */ * This routine associates properties with the primary MAC client of * the specified MAC instance. * - Cache the properties in mac_impl_t * - Apply the properties to the primary MAC client if exists * Bandwidth, priority or cpu link properties configured, * Since bind_cpu may be modified by mac_client_set_resources() * we use a copy of bind_cpu and finally cache bind_cpu in mip. * This allows us to cache only user edits in mip. /* Only update the values if mac_client_set_resources succeeded */ * If bankwidth, priority or cpu link properties cleared, * Get the properties cached for the specified MAC instance. * Rename a mac client, its flow, and the kstat. * VNICs: we need to change the sys flow name and * the associated flow kstat. * This mac may itself be an aggr link, or it may have some client * which is an aggr port. For both cases, we need to change the * aggr port's mac client name, its flow name and the associated flow * The aggr's client name and kstat flow name will be * updated below, i.e. via mac_rename_flow_names. * Rename the MAC client's flow names * Use mi_rw_lock to ensure that threads not in the mac perimeter * see a self-consistent value for mci_name * We have to rename all the others too, no stats to destroy for * Add a flow to the MAC client's flow list - i.e list of MAC/VID tuples * defined for the specified MAC client. * The promisc Rx data path walks the mci_flent_list. Protect by * Keep track of the number of non-zero VIDs addresses per MAC * client to avoid figuring it out in the data-path. * Remove a flow entry from the MAC client's list. * The promisc Rx data path walks the mci_flent_list. Protect by /* Deleting the first node */ * Check if the given VID belongs to this MAC client. /* The mci_flent_list is protected by mci_rw_lock */ * Get the flow entry for the specified <MAC addr, VID> tuple. * Since mci_flent has the SRSs, when we want to remove it, we replace * the flow_desc_t in mci_flent with that of an existing flent and then * remove that flent instead of mci_flent. /* get the next flent following the primary flent */ * Remove the flent from the flow table before updating the * flow descriptor as the hash depends on the flow descriptor. * This also helps incoming packet classification avoid having * to grab fe_lock. Access to fe_flow_desc of a flent not in the * flow table is done under the fe_lock so that log or stat functions * see a self-consistent fe_flow_desc. The name and desc are specific * to a flow, the rest are shared by all the clients, including /* update the primary flow entry */ /* update the flow entry that is to be freed */ /* now reinsert the flow entries in the table */ * Return whether there is only one flow entry associated with this * Send a MAC_NOTE_LINK notification to all the MAC clients whenever the * underlying physical link is down. This is to allow MAC clients to * communicate with other clients. * For clients that have a pass-thru MAC, e.g. VNIC, we set the VNIC's * mac handle in the client. * Mark the mac as being used exclusively by the single mac client that is * doing some control operation on this mac. No further opens of this mac * will be allowed until this client calls mac_unmark_exclusive. The mac * client calling this function must already be in the mac perimeter * Look up its entry in the global hash table. * A reference to mac is held even if the link is not plumbed. * In i_dls_link_create() we open the MAC interface and hold the * reference. There is an additional reference for the mac_open * done in acquiring the mac perimeter /* 1 for the creation and another for the perimeter */ * Set the MTU for the specified device. The function returns EBUSY if * another MAC client prevents the caller to become the exclusive client. * Returns EAGAIN if the client is started. * The MAC instance is started, for example due to the * presence of a promiscuous clients. Fail the operation * since the MAC's MTU cannot be changed while the NIC /* Revisit when we implement fully dynamic group allocation */ * MAXCLIENTNAMELEN is the buffer size reserved for client * XXXX Formating the client name string needs to be moved * to user land when fixing the size of dhi_clnts in * dld_hwgrpinfo_t. We should use n_clients * client_name for * dhi_clntsin instead of MAXCLIENTNAMELEN /* Get rid of the last , */