/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* IEEE 802.3ad Link Aggregation - Send code.
*
* Implements the Distributor function.
*/
#include <sys/aggr_impl.h>
/*
* Update the TX load balancing policy of the specified group.
*/
void
{
if ((policy & AGGR_POLICY_L2) != 0)
if ((policy & AGGR_POLICY_L3) != 0)
if ((policy & AGGR_POLICY_L4) != 0)
}
/*
* Function invoked by mac layer to find a specific TX ring on a port
* to send data.
*/
mblk_t *
{
if (grp->lg_ntx_ports == 0) {
/*
* We could have returned from aggr_m_start() before
* the ports were actually attached. Drop the chain.
*/
return (NULL);
}
/*
* Use hash as the hint so to direct traffic to
* different TX rings. Note below bit operation
* is needed in case hint is 0 to get the most
* benefit from HASH_HINT() algorithm.
*/
if (hint == 0) {
} else {
}
} else {
}
return (mp);
}
/*
* aggr_tx_notify_thread:
*
* aggr_tx_ring_update() callback function wakes up this thread when
* it gets called. This thread will call mac_tx_ring_update() to
* notify upper mac of flow control getting relieved. Note that
* aggr_tx_ring_update() cannot call mac_tx_ring_update() directly
* because aggr_tx_ring_update() is called from lower mac with
* mi_rw_lock held.
*/
void
{
"aggr_tx_notify_thread");
while (!grp->lg_tx_notify_done) {
if ((grp->lg_tx_blocked_cnt) == 0) {
continue;
}
while (grp->lg_tx_blocked_cnt != 0) {
grp->lg_tx_blocked_cnt--;
}
}
/*
* The grp is being destroyed, exit the thread.
*/
thread_exit();
}
/*
* Callback function registered with lower mac to receive wakeups from
* drivers when flow control is relieved (i.e. Tx descriptors are
* available).
*/
void
{
int i = 0;
/*
* If the underlying NIC does not expose TX rings,
* still as pseudo TX ring is presented to the
* aggr mac.
*/
} else {
for (i = 0; i < port->lp_tx_ring_cnt; i++) {
break;
}
}
/*
* It could be possible that some (broken?) device driver
* could send more than one wakeup on the same ring. In
* such a case, multiple instances of the same pseudo TX
* ring should not be saved in lg_tx_blocked_rings[]
* array. So first check if woken up ring (pseudo_mrh) is
* already in the lg_tx_blocked_rings[] array.
*/
for (i = 0; i < grp->lg_tx_blocked_cnt; i++) {
return;
}
}
/* A distinct mac_ring_handle. Save and increment count */
grp->lg_tx_blocked_cnt++;
}
/*
* Send function invoked by the MAC service module.
*/
mblk_t *
{
}
/*
* Enable sending on the specified port.
*/
void
{
/* already enabled or port not yet attached */
return;
}
/*
* Add to group's array of tx ports.
*/
/* current array too small */
KM_SLEEP);
if (grp->lg_tx_ports_size > 0) {
}
}
}
/*
* Disable sending from the specified port.
*/
void
{
if (!port->lp_tx_enabled) {
/* not yet enabled */
return;
}
/* remove from array of attached ports */
} else {
/* not the last entry, replace with last one */
}
grp->lg_ntx_ports--;
}