?? zl5011xpackettx.c
字號:
Function:
zl5011xAddCDHeader
Description:
Modify the structure information passed in to setup header for
Context Descriptor
Inputs:
layer2and3Header Pointer to zl5011xLanTxSetLayer2and3HeaderS structure to
check CD position
layer4and5Header Pointer to zl5011xLanTxSetLayer4and5HeaderS structure to
check CD position
par Pointer to the zl5011xPacketTxSetHeaderS structure.
Outputs:
None
Returns:
zlStatusE
Remarks:
None
******************************************************************************/
zlStatusE zl5011xAddCDHeader(zl5011xLanTxSetLayer2and3HeaderS *layer2and3Header,
zl5011xLanTxSetLayer4and5HeaderS *layer4and5Header, zl5011xPacketTxSetHeaderS *par,
Uint8T *cdPos)
{
zlStatusE status = ZL5011X_OK;
zl5011xBooleanE noHighHeader = ZL5011X_FALSE;
ZL5011X_TRACE(ZL5011X_PACKET_FN_ID,
"zl5011xAddCDHeader:",
0, 0, 0, 0, 0, 0);
if (par->protocolType == ZL5011X_IP_UDP_CD)
{
/* if CD is being used on top of UDP, then it must immediately
follow the UDP header */
par->contextDescriptorOffset = layer4and5Header->header.txHighLength +
layer2and3Header->header.txLowLength;
}
else
{
if (par->contextDescriptorOffset == (Uint32T)ZL5011X_INVALID)
{
par->contextDescriptorOffset = par->headerLength - ZL5011X_PKT_CD_HDR_LEN;
}
}
if ((par->headerLength < (par->contextDescriptorOffset + ZL5011X_PKT_CD_HDR_LEN)) ||
((Uint8T)par->contextDescriptorOffset < (layer4and5Header->header.txHighLength + layer2and3Header->header.txLowLength)))
{
status = ZL5011X_PARAMETER_INVALID;
}
else
{
if (par->contextDescriptorTeardown == ZL5011X_TRUE)
{
/* setting the silence control to 0, will allow only one packet to be transmitted
by the RTP block. After this packet, the RTP will discard all further packets */
layer4and5Header->header.highSilenceCtrl = 0;
}
/* if there is no high header at the moment, then remember since that allows
more tweaking of the low and high header lengths */
if (layer4and5Header->header.txHighLength == 0)
{
noHighHeader = ZL5011X_TRUE;
/* put the CD field at the start of the header in the RTP block */
layer2and3Header->header.txLowLength = (Uint8T)par->contextDescriptorOffset;
layer4and5Header->header.txHighLength = (Uint8T)(par->headerLength - par->contextDescriptorOffset);
}
else
{
/* leave the RTP header as it is, but change the length to
account for the CD + padding */
layer4and5Header->header.txHighLength = (Uint8T)(par->headerLength - layer2and3Header->header.txLowLength);
}
}
if (status == ZL5011X_OK)
{
if (noHighHeader == ZL5011X_TRUE)
{
/* can only include an even number of bytes in the RTP block */
if ((layer4and5Header->header.txHighLength % 2) == 1)
{
layer2and3Header->header.txLowLength--;
layer4and5Header->header.txHighLength++;
}
}
/* return the position of the CD header in the RTP header */
*cdPos = (Uint8T)(par->contextDescriptorOffset - layer2and3Header->header.txLowLength);
}
return(status);
}
/******************************************************************************
Function:
zl5011xUpdateIPChecksum
Description:
In IPv4 mode, the checksum needs to be presented to the device, based on the
length and the identification fields being zero for the partial checksum.
This function re-calculates the checksum based on these fields being zero.
Inputs:
layer2and3Header Pointer to the zl5011xLanTxSetLayer2and3HeaderS structure.
par Pointer to the zl5011xPacketTxSetHeaderS structure.
Outputs:
None
Returns:
zlStatusE
Remarks:
The PTX uses the length field from a seperate register in the control
header. The value in the header itself is as set by the calling function
- and as used for calculating the checksum. So, change this field to
zero and re-calculate the checksum.
******************************************************************************/
zlStatusE zl5011xUpdateIPChecksum(zl5011xLanTxSetLayer2and3HeaderS *layer2and3Header,
zl5011xLanTxSetLayer4and5HeaderS *layer4and5Header,
zl5011xPacketTxSetHeaderS * par)
{
zlStatusE status = ZL5011X_OK;
Uint16T chkChange, tempPos, newLength = 0;
ZL5011X_TRACE(ZL5011X_PACKET_FN_ID,
"zl5011xUpdateIPChecksum:",
0, 0, 0, 0, 0, 0);
chkChange = 0;
if (par->fixIpv4Header == ZL5011X_TRUE)
{
/* check that the payload length is non-zero, to be sure that a value
has been set */
if (par->payloadLength == 0)
{
status = ZL5011X_PARAMETER_INVALID;
}
else
{
newLength = layer2and3Header->header.layer3LengthValue +
layer4and5Header->header.txHighLength + par->payloadLength;
}
}
else
{
newLength = 0;
}
if (status == ZL5011X_OK)
{
/* change the length field to 0 */
status = zl5011xPacketChangeField(layer2and3Header->header.txLowData,
layer2and3Header->header.layer3LengthPos,
newLength, 0xffff, &chkChange);
}
if (status == ZL5011X_OK)
{
if (par->fixIpv4Header != ZL5011X_TRUE)
{
/* change the identification field to 0 */
tempPos = layer2and3Header->header.layer3LengthPos + (ZL5011X_PKT_IPV4_IDENT_POS - ZL5011X_PKT_IPV4_LEN_POS);
layer2and3Header->header.txLowData[tempPos] = 0;
layer2and3Header->header.txLowData[tempPos + 1] = 0;
}
/* change the checksum field to 0 */
tempPos = layer2and3Header->header.layer3ChecksumPos;
layer2and3Header->header.txLowData[tempPos] = 0;
layer2and3Header->header.txLowData[tempPos + 1] = 0;
/* calculate the checksum */
status = zl5011xPacketCalculateChecksum(layer2and3Header->header.txLowData + tempPos - ZL5011X_PKT_IPV4_CHKSUM_POS,
ZL5011X_PKT_IPV4_HDR_LEN, &chkChange);
if (par->fixIpv4Header == ZL5011X_TRUE)
{
/* disable the IPv4 dynamic fields if the header is to be fixed */
layer2and3Header->header.layer3LengthEnable = ZL5011X_FALSE;
layer2and3Header->header.layer3ChecksumEnable = ZL5011X_FALSE;
/* insert the checksum into the header, inverting as required for the partial checksum */
layer2and3Header->header.txLowData[tempPos] = (chkChange >> 8) & 0xff;
layer2and3Header->header.txLowData[tempPos + 1] = (chkChange >> 0) & 0xff;
}
else
{
/* insert the checksum into the header, inverting as required for the partial checksum */
layer2and3Header->header.txLowData[tempPos] = (~chkChange >> 8) & 0xff;
layer2and3Header->header.txLowData[tempPos + 1] = (~chkChange >> 0) & 0xff;
}
}
return(status);
}
/******************************************************************************
Function:
zl5011xUpdateUDPChecksum
Description:
The UDP checksum needs to be presented to the device, based on the
length and any subsequent header fields being zero for the partial checksum.
This function, amends the checksum based on these fields being zero.
Inputs:
layer4and5Header Pointer to the zl5011xLanTxSetLayer4and5HeaderS structure.
layer2and3Header Pointer to the zl5011xLanTxSetLayer2and3HeaderS structure.
par Pointer to the zl5011xPacketTxSetHeaderS structure.
Outputs:
None
Returns:
zlStatusE
Remarks:
None
******************************************************************************/
zlStatusE zl5011xUpdateUDPChecksum(zl5011xLanTxSetLayer4and5HeaderS *layer4and5Header,
zl5011xLanTxSetLayer2and3HeaderS *layer2and3Header, zl5011xPacketTxSetHeaderS *par)
{
zlStatusE status = ZL5011X_OK;
Uint16T chkChange, temp, ipStart;
Uint8T tempHeader[ZL5011X_PTX_LOW_HEADER_MAX_LEN + ZL5011X_RTP_HIGH_HEADER_MAX_LEN + 16];
Uint16T newLength = layer4and5Header->header.txHighLength + par->payloadLength - 2;
ZL5011X_TRACE(ZL5011X_PACKET_FN_ID,
"zl5011xUpdateUDPChecksum:",
0, 0, 0, 0, 0, 0);
/* if the UDP checksum is required then need to take care of the dynamic fields */
if (par->enableUDPChecksum == ZL5011X_TRUE)
{
if (layer4and5Header->header.layer4LengthEnable == ZL5011X_FALSE)
{
/* have a checksum but no length - this means that the UDP header has been shuffled!!
need to set the correct value for UDP in the header since the dynamic field is
not enabled. Also need to offset the checksum calculation, since the length the
device will use is too low */
layer4and5Header->header.txHighData[layer4and5Header->header.layer4LengthPos] = (Uint8T)(newLength >> 8);
layer4and5Header->header.txHighData[layer4and5Header->header.layer4LengthPos + 1] = (Uint8T)newLength;
}
temp = layer4and5Header->header.txHighLength;
memcpy(tempHeader, layer4and5Header->header.txHighData, temp);
/* if the length is an odd number of bytes, then round up to the next 16 bit word */
if ((temp & 1) != 0)
{
tempHeader[temp++] = 0;
}
if (layer4and5Header->header.layer4LengthEnable == ZL5011X_FALSE)
{
/* the last 2 bytes from the PTX have been shifted into the PE block.
Need to remove them or they will affect the checksum calculation -
overwrite them with the length, which is needed for the pseudo header */
tempHeader[0] = (Uint8T)(newLength >> 8);
tempHeader[1] = (Uint8T)newLength;
}
else
{
/* zero out the length field for the calculation */
tempHeader[layer4and5Header->header.layer4LengthPos] = 0;
tempHeader[layer4and5Header->header.layer4LengthPos + 1] = 0;
}
/* zero out the checksum field for the calculation */
tempHeader[layer4and5Header->header.layer4ChecksumPos] = 0;
tempHeader[layer4and5Header->header.layer4ChecksumPos + 1] = 0;
/* zero out the sequence number field for the calculation */
if (layer4and5Header->header.layer5SequenceNumEnable == ZL5011X_TRUE)
{
tempHeader[layer4and5Header->header.layer5SequenceNumPos] = 0;
if (layer4and5Header->header.layer5SequenceNum16bit == ZL5011X_TRUE)
{
tempHeader[layer4and5Header->header.layer5SequenceNumPos + 1] = 0;
}
}
/* zero out the timestamp field for the calculation */
if (layer4and5Header->header.layer5TimestampEnable == ZL5011X_TRUE)
{
tempHeader[layer4and5Header->header.layer5TimestampPos] = 0;
tempHeader[layer4and5Header->header.layer5TimestampPos + 1] = 0;
if (layer4and5Header->header.layer5Timestamp32bit == ZL5011X_TRUE)
{
tempHeader[layer4and5Header->header.layer5TimestampPos + 2] = 0;
tempHeader[layer4and5Header->header.layer5TimestampPos + 3] = 0;
}
}
/* tack the pseudo header fields onto the end of the array */
if (par->ipVer4 == ZL5011X_TRUE)
{
ipStart = layer2and3Header->header.layer3LengthPos - ZL5011X_PKT_IPV4_L
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -