#include "bnxe.h"
int BnxeRouteTxRing(um_device_t * pUM,
mblk_t * pMblk)
{
u32_t numRings = pUM->devParams.numRings;
int ring = 0;
uint8_t * pHdr;
mblk_t * pTmpMblk;
size_t mblkLen;
ushort_t etype;
size_t eHdrSize;
if (!numRings)
{
return 0;
}
size_t hdrs_size;
uint8_t hdrs_buf[sizeof(struct ether_vlan_header) +
IP_MAX_HDR_LENGTH +
sizeof(uint32_t)];
switch (pUM->devParams.routeTxRingPolicy)
{
case BNXE_ROUTE_RING_TCPUDP:
pHdr = pMblk->b_rptr;
etype = ntohs(((struct ether_header *)pHdr)->ether_type);
if (etype == ETHERTYPE_VLAN)
{
etype = ntohs(((struct ether_vlan_header *)pHdr)->ether_type);
eHdrSize = sizeof(struct ether_vlan_header);
}
else
{
eHdrSize = sizeof(struct ether_header);
}
if (etype == ETHERTYPE_IP)
{
mblkLen = MBLKL(pMblk);
pHdr = NULL;
if (mblkLen > (eHdrSize + sizeof(uint8_t)))
{
pHdr = (pMblk->b_rptr + eHdrSize);
mblkLen -= eHdrSize;
pHdr = (mblkLen > (((*pHdr & 0x0f) << 2) + sizeof(uint32_t))) ?
pMblk->b_rptr : NULL;
}
if (pHdr == NULL)
{
pTmpMblk = pMblk;
hdrs_size = 0;
while (pTmpMblk && (hdrs_size < sizeof(hdrs_buf)))
{
mblkLen = MBLKL(pTmpMblk);
if (mblkLen >= (sizeof(hdrs_buf) - hdrs_size))
{
mblkLen = (sizeof(hdrs_buf) - hdrs_size);
}
bcopy(pTmpMblk->b_rptr, &hdrs_buf[hdrs_size], mblkLen);
hdrs_size += mblkLen;
pTmpMblk = pTmpMblk->b_cont;
}
pHdr = hdrs_buf;
}
pHdr += eHdrSize;
if (!(pHdr[6] & 0x3f) && !(pHdr[7] & 0xff))
{
switch (pHdr[9])
{
case IPPROTO_TCP:
case IPPROTO_UDP:
case IPPROTO_ESP:
pHdr += (((*pHdr) & 0x0f) << 2);
ring = ((u32_t)(pHdr[0] ^ pHdr[1] ^ pHdr[2] ^ pHdr[3]) %
numRings);
break;
case IPPROTO_AH:
pHdr += (((*pHdr) & 0x0f) << 2);
ring = ((pHdr[4] ^ pHdr[5] ^ pHdr[6] ^ pHdr[7]) %
numRings);
break;
default:
ring = (pHdr[19] % numRings);
break;
}
}
else
{
ring = (pHdr[19] % numRings);
}
}
else
{
ring = (pMblk->b_band % numRings);
}
break;
case BNXE_ROUTE_RING_DEST_MAC:
pHdr = pMblk->b_rptr;
ring = (pHdr[5] % numRings);
break;
case BNXE_ROUTE_RING_MSG_PRIO:
ring = (pMblk->b_band % numRings);
break;
case BNXE_ROUTE_RING_NONE:
default:
ring = 0;
break;
}
return ring;
}