gldutil.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* gld - Generic LAN Driver
* media dependent routines
*/
#include <sys/byteorder.h>
#include <sys/ethernet.h>
#include <sys/multidata.h>
#include <sys/sysmacros.h>
#define DLSAPLENGTH(macinfo) \
#ifdef GLD_DEBUG
extern int gld_debug;
#endif
extern char *gld_macaddr_sprintf(char *, unsigned char *, int);
extern uint32_t gld_global_options;
static struct llc_snap_hdr llc_snap_def = {
LSAP_SNAP, /* DLSAP 0xaa */
LSAP_SNAP, /* SLSAP 0xaa */
CNTL_LLC_UI, /* Control 0x03 */
0x00, 0x00, 0x00, /* Org[3] */
0x00 /* Type */
};
#define ISETHERTYPE(snaphdr) \
/* ======== */
/* Ethernet */
/* ======== */
void
{
/* Assumptions we make for this medium */
#ifndef lint
#endif
/*
* only initialize the new statistics if the driver
* knows about them.
*/
return;
"first_collisions", KSTAT_DATA_UINT32);
"multi_collisions", KSTAT_DATA_UINT32);
"sqe_errors", KSTAT_DATA_UINT32);
"macxmt_errors", KSTAT_DATA_UINT32);
"macrcv_errors", KSTAT_DATA_UINT32);
"toolong_errors", KSTAT_DATA_UINT32);
}
/*ARGSUSED*/
void
{
}
int
{
struct ether_mac_frm *mh;
struct llc_snap_hdr *snaphdr;
unsigned short typelen;
/*
* Quickly handle receive fastpath for IPQ hack.
*/
if (flags == GLD_RXQUICK) {
/*
* Check whether the header is contiguous, which
* also implicitly makes sure the packet is big enough.
*/
return (-1);
return (0);
}
/* make sure packet has at least a whole mac header */
return (-1);
/* make sure the mac header falls into contiguous memory */
#ifdef GLD_DEBUG
"GLD: interpret_ether cannot msgpullup");
#endif
return (-1);
}
}
/* Check to see if the mac is a broadcast or multicast address. */
/*
* If the hardware is capable of VLAN tag insertion
* strip out the VLAN tag info. Knowing hardware is
* capable of VLAN can be established by the presance
* of non null 'macinfo->gldm_send_tagged'.
*/
2 * ETHERADDRL);
}
goto out; /* Got all info we need for xmit case */
}
/*
* Deal with the mac header
*/
goto out;
}
/*
* specifies the number of bytes that should be present
* in the data field. Additional bytes are padding, and
* should be removed
*/
{
(sizeof (struct ether_mac_frm) + typelen);
}
/*
* Before trying to look beyond the MAC header, make sure the LLC
* header exists, and that both it and any SNAP header are contiguous.
*/
goto out; /* LLC hdr should have been there! */
if (gld_global_options & GLD_OPT_NO_ETHRXSNAP ||
goto out;
/*
* we don't have the entire packet within the first mblk (and
* therefore we didn't do the msgpullup above), AND the first
* mblk may not contain all the data we need to look at.
*/
#ifdef GLD_DEBUG
"GLD: interpret_ether cannot msgpullup2");
#endif
goto out; /* can't interpret this pkt further */
}
}
/*
*/
if (ISETHERTYPE(snaphdr)) {
}
out:
return (0);
}
mblk_t *
{
unsigned short typelen;
struct ether_mac_frm *mh;
int hdrlen;
/* extract needed info from the mblk before we maybe reuse it */
/* look in the unitdata request for a sap, else use bound one */
else
/*
* We take values less than or equal to ETHERMTU to mean that the
* packet should not have an encoded EtherType and so we use the
*/
hdrlen = sizeof (struct ether_mac_frm);
/*
* Check to see if VLAN is enabled on this stream
* if so then make the header bigger to hold a clone
* vlan tag.
*/
}
/* need a buffer big enough for the headers */
/* it fits at the beginning of the first M_DATA block */
/* we can reuse the dl_unitdata_req M_PROTO mblk */
} else {
/* we need to allocate one */
return (NULL);
}
/* Got the space, now copy in the header components */
if (hdrlen > sizeof (struct ether_mac_frm)) {
vptag >>= 16;
}
/*
* We access the mac address without the mutex to prevent
* mutex contention (BUG 4211361)
*/
return (nmp);
}
mblk_t *
{
unsigned short typelen;
struct ether_mac_frm *mh;
int hdrlen;
/* look in the unitdata request for a sap, else use bound one */
else
/*
* We only do fast-path for EtherType encoding because this is the only
* case where the media header will be consistent from packet to packet.
*/
return (NULL);
/*
* Initialize the fast path header to include the
* basic source address information and type field.
*/
hdrlen = sizeof (struct ether_mac_frm);
/*
* Check to see if VLAN is enabled on this stream
* if so then make the header bigger to hold a clone
* vlan tag.
*/
}
return (NULL);
/* Got the space, now copy in the header components */
/*
* If the header is for a VLAN stream, then add
* in the VLAN tag to the clone header.
*/
if (hdrlen > sizeof (struct ether_mac_frm)) {
vptag >>= 16;
}
return (nmp);
}
/* == */
/* IB */
/* == */
void
{
/*
* Currently, the generic stats maintained by GLD is
* sufficient for IPoIB.
*/
/* Assumptions we make for this medium */
}
/* ARGSUSED */
void
{
}
/*
* The packet format sent to the driver is:
* IPOIB_ADDRL bytes dest addr :: 2b sap :: 2b 0s :: data
* The packet format received from the driver is:
* IPOIB_GRH_SIZE bytes pseudo GRH :: 2b sap :: 2b 0s :: data.
*/
int
{
/*
* Quickly handle receive fastpath for IPQ hack.
*/
if (flags == GLD_RXQUICK) {
/*
* Check whether the header is contiguous, which
* also implicitly makes sure the packet is big enough.
*/
return (-1);
/*
* Almost all times, unicast will not have
* a valid pgrh; quickly identify and ask for
* IPQ hack optimization only in that case.
*/
if (grh->ipoib_vertcflow == 0) {
return (0);
} else {
return (-1);
}
}
/*
* Handle the GLD_TX, GLD_RX, GLD_RXLOOP cases now.
*/
/*
* GLD_TX and GLD_RXLOOP cases.
*/
/* make sure packet has at least a pseudo header */
return (-1);
/* make sure the mac header falls into contiguous memory */
#ifdef GLD_DEBUG
"GLD: interpret_ib "
"cannot msgpullup");
#endif
return (-1);
}
/* this mblk contains the whole mac header */
}
/*
* Check if mac is broadcast or multicast address; all these
* types of address have the top 4 bytes as 0x00FFFFFF.
*/
sizeof (uint32_t))) {
else
}
/*
* Only count bytes we will be sending over the wire
* or looping back.
*/
goto out; /* Got all info we need for xmit case */
/*
* Loopback case: this is a dup'ed message.
*/
} else {
/*
* GLD_RX case; process packet sent from driver.
*/
/* make sure packet has at least pgrh and mac header */
return (-1);
/* make sure the header falls into contiguous memory */
#ifdef GLD_DEBUG
"GLD: interpret_ib "
"cannot msgpullup2");
#endif
return (-1);
}
/* this mblk contains the whole mac header */
}
if (grh->ipoib_vertcflow) {
/*
* First, copy source address from grh.
*/
/*
* Then copy destination address from grh;
* first, the 16 bytes of GID.
*/
/* Is this a multicast address */
/*
* Only check for hardware looping in
* multicast case. It is assumed higher
* layer code (IP) will stop unicast loops;
* ie will prevent a transmit to self.
*/
IPOIB_ADDRL) == 0)
else
/*
* Now copy the 4 bytes QPN part of the
* destination address.
*/
} else {
/*
* Now copy the 4 bytes QPN part of the
* destination address.
*/
/*
* Any unicast packets received on IBA are
* for the node.
*/
}
} else {
/*
* It can not be a IBA multicast packet.
* Must have been unicast to us. We do not
* have shost information, which is used in
*/
/*
* Any unicast packets received on IBA are
* for the node.
*/
}
}
out:
return (0);
}
/*
* The packet format sent to the driver is: 2b sap :: 2b 0s :: data
*/
void
{
/*
* Per packet formatting.
*/
if (flags == GLD_MDT_TXPKT) {
if (PDESC_HDRL(pinfo) == 0)
return;
/*
* Update packet's link header.
*/
/*
* Total #bytes that will be put on wire.
*/
return;
}
/*
* The following two cases of GLD_MDT_TX and GLD_MDT_RXLOOP are per
* MDT message processing.
*/
if (flags == GLD_MDT_TX) {
return;
/*
* Check if mac is broadcast or multicast address; all these
* types of address have the top 4 bytes as 0x00FFFFFF.
*/
sizeof (uint32_t))) {
else
}
} else {
return;
}
}
mblk_t *
{
unsigned short type;
int hdrlen;
/* extract needed info from the mblk before we maybe reuse it */
/* look in the unitdata request for a sap, else use bound one */
else
hdrlen = sizeof (ipoib_ptxhdr_t);
/* need a buffer big enough for the headers */
/* it fits at the beginning of the first M_DATA block */
/* we can reuse the dl_unitdata_req M_PROTO mblk */
} else {
/* we need to allocate one */
return (NULL);
}
/* Got the space, now copy in the header components */
return (nmp);
}
mblk_t *
{
unsigned short type;
int hdrlen;
/* look in the unitdata request for a sap, else use bound one */
else
hdrlen = sizeof (ipoib_ptxhdr_t);
return (NULL);
/* Got the space, now copy in the header components */
return (nmp);
}
/* ==== */
/* FDDI */
/* ==== */
void
{
/* Assumptions we make for this medium */
#ifndef lint
#endif
/* Wire address format is bit reversed from canonical format */
"mac_errors", KSTAT_DATA_UINT32);
"mac_lost_errors", KSTAT_DATA_UINT32);
"mac_tokens", KSTAT_DATA_UINT32);
"mac_tvx_expired", KSTAT_DATA_UINT32);
"mac_late", KSTAT_DATA_UINT32);
"mac_ring_ops", KSTAT_DATA_UINT32);
}
/*ARGSUSED*/
void
{
}
int
{
struct fddi_mac_frm *mh;
struct llc_snap_hdr *snaphdr;
/*
* Quickly handle receive fastpath; FDDI does not support IPQ hack.
*/
if (flags == GLD_RXQUICK) {
return (-1);
}
/* make sure packet has at least a whole mac header */
return (-1);
/* make sure the mac header falls into contiguous memory */
#ifdef GLD_DEBUG
"GLD: interpret_fddi cannot msgpullup");
#endif
return (-1);
}
}
/* Check to see if the mac is a broadcast or multicast address. */
/* NB we are still in wire format (non canonical) */
/* mac_eq works because ether_broadcast is the same either way */
goto out; /* Got all info we need for xmit case */
/*
* Deal with the mac header
*/
/*
* Before trying to look beyond the MAC header, make sure the LLC
* header exists, and that both it and any SNAP header are contiguous.
*/
/*
* we don't have the entire packet within the first mblk (and
* therefore we didn't do the msgpullup above), AND the first
* mblk may not contain all the data we need to look at.
*/
#ifdef GLD_DEBUG
"GLD: interpret_fddi cannot msgpullup2");
#endif
goto out; /* can't interpret this pkt further */
}
}
/*
*/
goto out;
goto out;
if (ISETHERTYPE(snaphdr)) {
}
}
out:
return (0);
}
mblk_t *
{
unsigned short type;
struct fddi_mac_frm *mh;
int hdrlen;
/* extract needed info from the mblk before we maybe reuse it */
/* look in the unitdata request for a sap, else use bound one */
else
hdrlen = sizeof (struct fddi_mac_frm);
/*
* Check whether we need to do EtherType encoding or whether the packet
* is LLC.
*/
if (type > GLD_MAX_802_SAP)
hdrlen += sizeof (struct llc_snap_hdr);
/* need a buffer big enough for the headers */
/* it fits at the beginning of the first M_DATA block */
/* we can reuse the dl_unitdata_req M_PROTO mblk */
} else {
/* we need to allocate one */
return (NULL);
}
/* Got the space, now copy in the header components */
if (type > GLD_MAX_802_SAP) {
/* create the snap header */
struct llc_snap_hdr *snap;
*snap = llc_snap_def;
}
/*
* We access the mac address without the mutex to prevent
* mutex contention (BUG 4211361)
*/
return (nmp);
}
mblk_t *
{
unsigned short type;
struct fddi_mac_frm *mh;
int hdrlen;
/* look in the unitdata request for a sap, else use bound one */
else
hdrlen = sizeof (struct fddi_mac_frm);
/*
* Check whether we need to do EtherType encoding or whether the packet
* will be LLC.
*/
if (type > GLD_MAX_802_SAP)
hdrlen += sizeof (struct llc_snap_hdr);
return (NULL);
/* Got the space, now copy in the header components */
if (type > GLD_MAX_802_SAP) {
/* create the snap header */
struct llc_snap_hdr *snap;
*snap = llc_snap_def;
}
return (nmp);
}
/* ========== */
/* Token Ring */
/* ========== */
#define GLD_SR_VAR(macinfo) \
#define GLD_SR_MUTEX(macinfo) \
static void gld_sr_clear(gld_mac_info_t *);
uchar_t *, int);
static struct gld_ri ri_ste_def;
void
{
/* avoid endian-dependent code by initializing here instead of static */
ri_ste_def.dir = 0;
ri_ste_def.res = 0;
/* Assumptions we make for this medium */
#ifndef lint
#endif
KM_SLEEP);
/* Default is RDE enabled for this medium */
"gld_rde_enable", 1);
/*
* Default is to use STE for unknown paths if RDE is enabled.
* If RDE is disabled, default is to use NULL RIF fields.
*
* It's possible to force use of STE for ALL packets:
* disable RDE but enable STE. This may be useful for
* non-transparent bridges, when it is not desired to run
* the RDE algorithms.
*/
"gld_rde_str_indicator_ste",
/* Default 10 second route timeout on lack of activity */
{
"gld_rde_timeout", 10);
if (t < 1)
t = 1; /* Let's be reasonable */
if (t > 600)
t = 600; /* Let's be reasonable */
/* We're using ticks (lbolts) for our timeout -- convert from seconds */
t = drv_usectohz(1000000 * t);
}
"line_errors", KSTAT_DATA_UINT32);
"burst_errors", KSTAT_DATA_UINT32);
"signal_losses", KSTAT_DATA_UINT32);
/*
* only initialize the new statistics if the driver
* knows about them.
*/
return;
"ace_errors", KSTAT_DATA_UINT32);
"internal_errors", KSTAT_DATA_UINT32);
"lost_frame_errors", KSTAT_DATA_UINT32);
"frame_copied_errors", KSTAT_DATA_UINT32);
"token_errors", KSTAT_DATA_UINT32);
"freq_errors", KSTAT_DATA_UINT32);
}
void
{
}
int
{
struct tr_mac_frm *mh;
struct llc_snap_hdr *snaphdr;
/*
* Quickly handle receive fastpath; TR does not support IPQ hack.
*/
if (flags == GLD_RXQUICK) {
return (-1);
}
/* make sure packet has at least a whole mac header */
return (-1);
/* make sure the mac header falls into contiguous memory */
#ifdef GLD_DEBUG
"GLD: interpret_tr cannot msgpullup");
#endif
return (-1);
}
}
/* Check to see if the mac is a broadcast or multicast address. */
goto out; /* Got all info we need for xmit case */
/*
* Deal with the mac header
*/
/*
* Before trying to look beyond the MAC header, make sure the data
* structures are all contiguously where we can conveniently look at
* them. We'll use a worst-case estimate of how many bytes into the
* packet data we'll be needing to look. Things will be more efficient
* if the driver puts at least this much into the first mblk.
*
* Even after this, we still will have to do checks against the total
* length of the packet. A bad incoming packet may not hold all the
* data structures it says it does.
*/
LLC_HDR1_LEN + sizeof (struct rde_pdu) &&
/*
* we don't have the entire packet within the first mblk (and
* therefore we didn't do the msgpullup above), AND the first
* mblk may not contain all the data we need to look at.
*/
#ifdef GLD_DEBUG
"GLD: interpret_tr cannot msgpullup2");
#endif
goto out; /* can't interpret this pkt further */
}
}
/* Routing Information Field (RIF) is present */
goto out; /* RIF should have been there! */
/* Bogus RIF, don't handle this packet */
#ifdef GLD_DEBUG
"GLD: received TR packet with "
"bogus RIF length %d",
#endif
goto out;
}
goto out; /* RIF should have been there! */
}
goto out;
goto out;
if (ISETHERTYPE(snaphdr)) {
}
/* Inform the Route Control Component of received LLC frame */
}
out:
return (0);
}
mblk_t *
{
unsigned short type;
struct tr_mac_frm_nori *mh;
int hdrlen;
/* extract needed info from the mblk before we maybe reuse it */
/* look in the unitdata request for a sap, else use bound one */
else
/* includes maximum possible Routing Information Field (RIF) size */
hdrlen = sizeof (struct tr_mac_frm);
/*
* Check whether we need to do EtherType encoding or whether the packet
* is LLC.
*/
if (type > GLD_MAX_802_SAP)
hdrlen += sizeof (struct llc_snap_hdr);
/* need a buffer big enough for the headers */
/*
* We are going to need to look at the LLC header, so make sure it
* is contiguously in a single mblk. If we're the ones who create
* the LLC header (below, in the case where sap > 0xff) then we don't
* have to worry about it here.
*/
if (type <= GLD_MAX_802_SAP) {
#ifdef GLD_DEBUG
"GLD: unitdata_tr "
"cannot msgpullup");
#endif
return (NULL);
}
}
}
/* it fits at the beginning of the first M_DATA block */
/* we can reuse the dl_unitdata_req M_PROTO mblk */
} else {
/* we need to allocate one */
return (NULL);
}
}
/* Got the space, now copy in the header components */
if (type > GLD_MAX_802_SAP) {
/* create the snap header */
struct llc_snap_hdr *snap;
*snap = llc_snap_def;
}
/* Hold SR tables still while we maybe point at an entry */
/* copy in the RIF */
}
/* no longer need the pulled-up mblk */
/*
* fill in token ring header
*/
/*
* We access the mac address without the mutex to prevent
* mutex contention (BUG 4211361)
*/
else
return (nmp);
}
/*
* We cannot have our client sending us "fastpath" M_DATA messages,
* because to do that we must provide to him a fixed MAC header to
* be prepended to each outgoing packet. But with Source Routing
* media, the length and content of the MAC header changes as the
* routes change, so there is no fixed header we can provide. So
* we decline to accept M_DATA messages if Source Routing is enabled.
*/
mblk_t *
{
unsigned short type;
struct tr_mac_frm_nori *mh;
int hdrlen;
/*
* If we are doing Source Routing, then we cannot provide a fixed
* MAC header, so fail.
*/
return (NULL);
/* look in the unitdata request for a sap, else use bound one */
else
hdrlen = sizeof (struct tr_mac_frm_nori);
/*
* Check whether we need to do EtherType encoding or whether the packet
* will be LLC.
*/
if (type > GLD_MAX_802_SAP)
hdrlen += sizeof (struct llc_snap_hdr);
return (NULL);
/* Got the space, now copy in the header components */
if (type > GLD_MAX_802_SAP) {
/* create the snap header */
struct llc_snap_hdr *snap;
*snap = llc_snap_def;
}
/* RDE is disabled, use NULL RIF, or STE RIF */
}
/*
* fill in token ring header
*/
else
return (nmp);
}
/*
* Route Determination Entity (ISO 8802-2 / IEEE 802.2 : 1994, Section 9)
*
* RDE is an LLC layer entity. GLD is a MAC layer entity. The proper
* solution to this architectural anomaly is to move RDE support out of GLD
* and into LLC where it belongs. In particular, only LLC has the knowledge
* necessary to reply to XID and TEST packets. If and when it comes time to
* move RDE out of GLD to LLC, the LLC-to-GLD interface should be modified
* to use MA_UNITDATA structures rather than DL_UNITDATA structures. Of
* course, GLD will still have to continue to also support the DL_ structures
* as long as IP is not layered over LLC. Another, perhaps better, idea
* would be to make RDE an autopush module on top of the token ring drivers:
* RDE would sit between LLC and GLD. It would then also sit between IP and
* GLD would still have to continue to support the DL_ interface for non-
* Token Ring interfaces, using the MA_ interface only for media supporting
* Source Routing media.
*
* At present, Token Ring is the only source routing medium we support.
* Since Token Ring is not at this time a strategic network medium for Sun,
* rather than devote a large amount of resources to creating a proper
* architecture and implementation of RDE, we do the minimum necessary to
* get it to work. The interface between the above token ring code and the
* below RDE code is designed to make it relatively easy to change to an
* MA_UNITDATA model later should this ever become a priority.
*/
struct rde_pdu *, int);
int);
/*
* This routine implements a modified subset of the 802.2 RDE RCC receive
* actions:
* we implement RCC receive events 3 to 12 (ISO 8802-2:1994 9.6.3.4);
* we omit special handling for the NULL SAP;
* we pass all packets (including RDE) upstream to LLC.
*/
static void
{
return;
/*
* First, ensure this packet wasn't something we received just
* because we were in promiscuous mode. Since none of the below
* code wants to see group addressed packets anyway, we can do
* this check up front. Since we're doing that, we can omit the
* checks for group addressed packets below.
*/
return; /* Event 6 */
/* Process a subset of Route Determination Entity (RDE) packets */
/* sanity check the PDU */
return;
return;
case RDE_RQC: /* Route Query Command; Events 8 - 11 */
/* FALLTHROUGH */
case RDE_RQR: /* Route Query Response; Event 12 */
case RDE_RS: /* Route Selected; Event 7 */
break;
default: /* ignore if unrecognized ptype */
return;
}
return;
}
/* Consider routes seen in other IA SRF packets */
return; /* no RIF; Event 3 */
return; /* not SRF; Event 5 */
}
/*
* Send RQR: 802.2 9.6.3.4.2(9) RCC Receive Events 8-11
*
* The routing processing really doesn't belong here; it should be handled in
* the LLC layer above. If that were the case then RDE could just send down
* an extra MA_UNITDATA_REQ with the info needed to construct the packet. But
* at the time we get control here, it's not a particularly good time to be
* constructing packets and trying to send them. Specifically, at this layer
* we need to construct the full media packet, which means the below routine
* knows that it is dealing with Token Ring media. If this were instead done
* via a proper MA_UNITDATA interface, the RDE stuff could all be completely
* media independent. But since TR is the only source routing medium we
* support, this works even though it is not clean.
*
* We "know" that the only time we can get here is from the "interpret"
* routine, and only when it was called at receive time.
*/
static void
{
int nlen;
struct tr_mac_frm_nori *nmh;
struct llc_snap_hdr *nsnaphdr;
/* We know and assume we're on the receive path */
return; /* Bad incoming PDU */
sizeof (struct rde_pdu);
return;
/* no RIF (Event 8), or RIF type STE (Event 9): send ARE RQR */
} else {
/*
* RIF must be ARE (Event 10) or SRF (Event 11):
* send SRF (reverse) RQR
*/
}
/*
* Packet assembled; send it.
*
* As noted before, this is not really a good time to be trying to
* send out packets. We have no obvious queue to use if the packet
* can't be sent right away. We pick one arbitrarily.
*/
{
queue_t *q;
/* oops, no vlan on the list for this macinfo! */
/* this should not happen */
return;
}
/*
* Queue the packet and let gld_wsrv
* handle it, thus preventing a panic
* caused by v2 TR in promiscuous mode
* where it attempts to get the mutex
* in this thread while already holding
* it.
*/
}
}
/*
* This routine implements a modified subset of the 802.2 RDE RCC send actions:
* we implement RCC send events 5 to 10 (ISO 8802-2:1994 9.6.3.5);
* we omit special handling for the NULL SAP;
* events 11 to 12 are handled by gld_rde_pdu_req below;
* we require an immediate response to our GET_ROUTE_REQUEST.
*/
static void
{
/*
* Our caller has to take the mutex because: to avoid an extra bcopy
* of the RIF on every transmit, we pass back a pointer to our sr
* table entry via rhp. He has to keep the mutex until he has a
* chance to copy the RIF out into the outgoing packet, so that we
* don't modify the entry while he's trying to copy it. This is a
* little ugly, but saves the extra bcopy.
*/
/* RDE is disabled -- use NULL or STE always */
return;
}
if (!(dhost[0] & 0x80)) {
/* individual address; Events 7 - 10 */
/* TEST command, reset the route */
}
gld_get_route(macinfo, q,
}
/*
* group address (Events 5 - 6),
* or no route available (Events 8 - 9):
* Need to send NSR or STE, as configured.
*/
}
}
/*
* RCC send events 11 - 12
*
* At present we only handle the RQC ptype.
*
* We "know" that the only time we can get here is from the "unitdata"
* routine, called at wsrv time.
*
* If we ever implement the RS ptype (Event 13), this may no longer be true!
*/
static void
{
int nlen;
struct tr_mac_frm_nori *nmh;
struct llc_snap_hdr *nsnaphdr;
int srpresent = 0;
/* if you change this to process other types, review all code below */
sizeof (struct rde_pdu);
return;
/*
* access the mac address without a mutex - take a risk -
* to prevent mutex contention (BUG 4211361)
*/
#if 0 /* we don't need this for now */
/* send an SRF frame with specified RIF */
srpresent = 1;
} else
#endif
/* Need to send NSR or STE, as configured. */
/* send an STE frame */
srpresent = 1;
} /* else send an NSR frame */
/*
* access the mac address without a mutex - take a risk -
* to prevent mutex contention - BUG 4211361
*/
if (srpresent)
else
/*
* Packet assembled; send it.
*
* Since we own the SR_MUTEX, we don't want to take the maclock
* mutex (since they are acquired in the opposite order on the
* receive path, so deadlock could occur). We could rearrange
* the code in gld_get_route() and drop the SR_MUTEX around the
* call to gld_rde_pdu_req(), but that's kind of ugly. Rather,
* we just refrain from calling gld_start() from here, and
* instead just queue the packet for wsrv to send next. Besides,
* it's more important to get the packet we're working on out
* quickly than this RQC.
*/
}
/*
* Route Determination Component (RDC)
*
* We do not implement separate routes for each SAP, as specified by
* ISO 8802-2; instead we implement only one route per remote mac address.
*/
static void
{
clock_t t = ddi_get_lbolt();
/*
* we have no entry -- never heard of this address:
* create an empty entry and initiate RQC
*/
if (sr)
return;
}
/* we have an entry; see if we know a route yet */
/* Have asked RQC, but no reply (yet) */
/* RQR overdue, resend RQC */
}
return;
}
/* we know a route, or it's local */
/* if it might be stale, reset and get a new one */
return;
}
/* the remote site is on our local ring -- no route needed */
return;
}
}
/*
* zap the specified entry and reinitiate RQC
*/
static void
{
return;
}
/*
* This routine is called when an RDE PDU is received from our peer.
* If it is an RS (Route Selected) PDU, we adopt the specified route.
* If it is an RQR (reply to our previous RQC), we evaluate the
* specified route in comparison with our current known route, if any,
* and we keep the "better" of the two routes.
*/
static void
int pdulen)
{
return; /* Bad incoming PDU */
return; /* ignore RQC */
#ifdef GLD_DEBUG
#endif
return;
}
#ifdef GLD_DEBUG
"gld: bogus NULL RIF, ptype 0x%x received",
#endif
return;
}
/* A reply to our RQC has his address as target mac */
} else {
/* An RS has his address as orig mac */
}
return; /* oh well, out of memory */
}
/* see if new route is better than what we may already have */
return; /* we have one, and new one is no shorter */
}
}
/* adopt the new route */
}
/*
* This routine is called when a packet with a RIF is received. Our
* policy is to adopt the route.
*/
/* ARGSUSED3 */
static void
{
return; /* oh well, out of memory */
}
/* we have an entry; fill it in */
}
static struct srtab **
{
while (--addr_length >= 0)
}
static struct srtab *
{
return (sr);
return ((struct srtab *)0);
}
static struct srtab *
{
return (sr);
#ifdef GLD_DEBUG
"gld: gld_sr_create_entry kmem_alloc failed");
#endif
return ((struct srtab *)0);
}
return (sr);
}
static void
{
int i;
/*
* Walk through the table, deleting all entries.
*
* Only called from uninit, so don't need the mutex.
*/
for (i = 0; i < SR_HASH_SIZE; i++) {
}
}
}
#ifdef DEBUG
void
{
int i, j;
struct srtab **sr_hash_tbl;
if (sr_hash_tbl == NULL)
return;
/*
* Walk through the table, printing all entries
*/
for (i = 0; i < SR_HASH_SIZE; i++) {
"%x:%x:%x:%x:%x:%x %d,%x,%x,%x,%x ",
REF_NET_USHORT(*(unsigned short *)
}
}
}
#endif