?? zl5011xpackettx.c
字號:
break;
case ZL5011X_IP_CD:
/* Layer 3: IP */
if (status == ZL5011X_OK)
{
status = zl5011xAddIPHeader(layer2and3Header, par);
}
layer4and5Header->header.txHighLength = 0;
if (status == ZL5011X_OK)
{
status = zl5011xAddCDHeader(layer2and3Header, layer4and5Header, par, &cdPos);
cdEnable = ZL5011X_TRUE;
}
break;
case ZL5011X_IP_UDP_CD:
/* Layer 3: IP */
if (status == ZL5011X_OK)
{
status = zl5011xAddIPHeader(layer2and3Header, par);
}
/* add the UDP header fields */
if (status == ZL5011X_OK)
{
status = zl5011xAddUDPHeader(layer4and5Header, par);
udpEnable = ZL5011X_TRUE;
}
layer4and5Header->header.txHighLength = ZL5011X_PKT_UDP_HDR_LEN;
if (status == ZL5011X_OK)
{
status = zl5011xAddCDHeader(layer2and3Header, layer4and5Header, par, &cdPos);
cdEnable = ZL5011X_TRUE;
}
break;
case ZL5011X_ETHERNET :
/* Only Ethernet header is required so nothing more to add */
break;
case ZL5011X_CUSTOM8_PW:
/* Layer 3: 8 byte header - place in the PE block to allow context switching.
Setup the PW sequence number */
layer4and5Header->header.layer5SequenceNumEnable = ZL5011X_TRUE;
layer4and5Header->header.layer5SequenceNum16bit = ZL5011X_TRUE;
layer4and5Header->header.layer5SequenceNumPos = 8 + ZL5011X_PKT_PW_SEQ_POS;
layer4and5Header->header.txHighLength = 8 + ZL5011X_PKT_PW_HDR_LEN;
pwStatusPos = layer4and5Header->header.txHighLength - ZL5011X_PKT_PW_HDR_LEN;
break;
case ZL5011X_CUSTOM8_PW_RTP:
/* Layer 3: 8 byte header - place in the PE block to allow context switching.
Setup the PW sequence number */
layer4and5Header->header.layer5SequenceNumEnable = ZL5011X_TRUE;
layer4and5Header->header.layer5SequenceNum16bit = ZL5011X_TRUE;
if (par->rtpForceSeqNumber == ZL5011X_TRUE)
{
layer4and5Header->header.layer5SequenceNumPos = 8 + ZL5011X_PKT_PW_HDR_LEN + ZL5011X_PKT_RTP_SEQ_POS;
}
else
{
layer4and5Header->header.layer5SequenceNumPos = 8 + ZL5011X_PKT_PW_SEQ_POS;
}
/* setup the timestamp field for the RTP header */
layer4and5Header->header.layer5TimestampEnable = ZL5011X_TRUE;
layer4and5Header->header.layer5TimestampIncrement = (Uint16T)par->rtpTimestampInc;
layer4and5Header->header.layer5TimestampFromWan = par->rtpTimestampFromWan;
layer4and5Header->header.layer5Timestamp32bit = ZL5011X_TRUE;
layer4and5Header->header.layer5TimestampPos = 8 + ZL5011X_PKT_PW_HDR_LEN + ZL5011X_PKT_RTP_TS_POS;
layer4and5Header->header.txHighLength = 8 + ZL5011X_PKT_PW_HDR_LEN + ZL5011X_PKT_RTP_HDR_LEN;
pwStatusPos = layer4and5Header->header.txHighLength - ZL5011X_PKT_RTP_HDR_LEN - ZL5011X_PKT_PW_HDR_LEN;
break;
case ZL5011X_CUSTOM8_RTP_PW:
/* Layer 3: 8 byte header - place in the PE block to allow context switching.
Setup the PW sequence number */
layer4and5Header->header.layer5SequenceNumEnable = ZL5011X_TRUE;
layer4and5Header->header.layer5SequenceNum16bit = ZL5011X_TRUE;
if (par->rtpForceSeqNumber == ZL5011X_TRUE)
{
layer4and5Header->header.layer5SequenceNumPos = 8 + ZL5011X_PKT_RTP_SEQ_POS;
}
else
{
layer4and5Header->header.layer5SequenceNumPos = 8 + ZL5011X_PKT_RTP_HDR_LEN + ZL5011X_PKT_PW_SEQ_POS;
}
/* setup the timestamp field for the RTP header */
layer4and5Header->header.layer5TimestampEnable = ZL5011X_TRUE;
layer4and5Header->header.layer5TimestampIncrement = (Uint16T)par->rtpTimestampInc;
layer4and5Header->header.layer5TimestampFromWan = par->rtpTimestampFromWan;
layer4and5Header->header.layer5Timestamp32bit = ZL5011X_TRUE;
layer4and5Header->header.layer5TimestampPos = 8 + ZL5011X_PKT_RTP_TS_POS;
layer4and5Header->header.txHighLength = 8 + ZL5011X_PKT_PW_HDR_LEN + ZL5011X_PKT_RTP_HDR_LEN;
pwStatusPos = layer4and5Header->header.txHighLength - ZL5011X_PKT_PW_HDR_LEN;
break;
default:
status = ZL5011X_PARAMETER_INVALID;
ZL5011X_TRACE(ZL5011X_PACKET_FN_ID,
"zl5011xPacketTxSetHeader: protocol type error %d",
par->protocolType, 0, 0, 0, 0, 0);
}
}
if (status == ZL5011X_OK)
{
if ((pwStatusPos != (Uint8T)ZL5011X_INVALID) &&
(par->protocolType != ZL5011X_IP_UDP_RTP_PW) &&
(par->protocolType != ZL5011X_IP_UDP_RTP_PW_ALT) &&
(par->protocolType != ZL5011X_IP_L2TPV3_RTP_PW) &&
(par->protocolType != ZL5011X_MPLS_PW_RTP) &&
(par->protocolType != ZL5011X_CUSTOM8_PW_RTP) &&
(par->protocolType != ZL5011X_CUSTOM8_RTP_PW))
{
if ((par->protocolType == ZL5011X_IP_PW_TS) && (par->fixIpv4Header == ZL5011X_TRUE))
{
/* using the IP->PW->TS header and the IP checksum is fixed. This header is
small enough to fit most of the IP into the PE block, so shift up bytes
from the PTX into the PE */
pwShuffle = ZL5011X_RTP_HIGH_HEADER_MAX_LEN - layer4and5Header->header.txHighLength;
}
else
{
/* need to shuffle the PW byte so that it is not in the same 32 bit word
as the sequence number field */
pwShuffle = 2;
}
pwStatusPos += pwShuffle;
layer4and5Header->header.txHighLength += pwShuffle;
layer2and3Header->header.txLowLength -= pwShuffle;
if (layer2and3Header->header.layer3LengthEnable == ZL5011X_TRUE)
{
layer2and3Header->header.layer3LengthValue -= pwShuffle;
}
if (layer4and5Header->header.layer4ChecksumPresent == ZL5011X_TRUE)
{
layer4and5Header->header.layer4ChecksumPos += pwShuffle;
}
if (layer4and5Header->header.layer4LengthEnable == ZL5011X_TRUE)
{
/* have an issue - the UDP length is being calculated on the fly,
but have just shifted 2 bytes into the PE from the PTX.
Therefore the calculation will fail, so need to write the header
length into the packet. Check that a length has been specified. */
if (par->payloadLength == 0)
{
status = ZL5011X_PARAMETER_INVALID;
}
else
{
layer4and5Header->header.layer4LengthEnable = ZL5011X_FALSE;
layer4and5Header->header.layer4LengthPos += pwShuffle;
}
}
if (layer4and5Header->header.layer5SequenceNumEnable == ZL5011X_TRUE)
{
layer4and5Header->header.layer5SequenceNumPos += pwShuffle;
}
if (layer4and5Header->header.layer5TimestampEnable == ZL5011X_TRUE)
{
layer4and5Header->header.layer5TimestampPos += pwShuffle;
}
}
}
if (status == ZL5011X_OK)
{
/* check that neither of the headers is too long */
if (layer2and3Header->header.txLowLength > ZL5011X_PTX_LOW_HEADER_MAX_LEN)
{
ZL5011X_TRACE(ZL5011X_PACKET_FN_ID,
"zl5011xPacketTxSetHeader: ERROR - layer 2 & 3 header %2d, max %2d",
layer2and3Header->header.txLowLength, ZL5011X_PTX_LOW_HEADER_MAX_LEN, 0, 0, 0, 0);
status = ZL5011X_PKT_HEADER_SIZE_ERROR;
}
else
{
if (layer4and5Header->header.txHighLength > ZL5011X_RTP_HIGH_HEADER_MAX_LEN)
{
ZL5011X_TRACE(ZL5011X_PACKET_FN_ID,
"zl5011xPacketTxSetHeader: ERROR - layer 4 & 5 header %2d, max %2d",
layer4and5Header->header.txHighLength, ZL5011X_RTP_HIGH_HEADER_MAX_LEN, 0, 0, 0, 0);
status = ZL5011X_PKT_HEADER_SIZE_ERROR;
}
}
}
if (status == ZL5011X_OK)
{
/* if the ethernet length is being used, then update it now */
if (layer2and3Header->header.layer2LengthEnable == ZL5011X_TRUE)
{
layer2and3Header->header.layer2LengthValue = (Uint16T)(layer2and3Header->header.txLowLength -
ZL5011X_PKT_ETHERNET_HDR_LEN);
}
/* Check that there is enough data in the original buffer to populate the required headers */
if ((layer2and3Header->header.txLowLength + layer4and5Header->header.txHighLength) > par->headerLength)
{
status = ZL5011X_PKT_HEADER_SIZE_ERROR;
}
else
{
status = zl5011xCopyHeaders(layer2and3Header, layer4and5Header, par);
}
}
if (status == ZL5011X_OK)
{
/* if the layer 3 checksum is enabled (IPv4) and the length field is
enabled then need to update the checksum to take care of the fact
that the length field needs to be 0 for the partial checksum.
This will also impact on the UDP checksum if it is enabled. */
if ((layer2and3Header->header.layer3ChecksumEnable == ZL5011X_TRUE) &&
(layer2and3Header->header.layer3LengthEnable == ZL5011X_TRUE))
{
status = zl5011xUpdateIPChecksum(layer2and3Header, layer4and5Header, par);
if (status == ZL5011X_OK)
{
if ((par->protocolType == ZL5011X_IP_PW_TS) && (par->fixIpv4Header == ZL5011X_TRUE))
{
Uint32T loop;
/* the IP header has been updated so need to refresh this in the PE block,
since for IP->PW->TS the IP fields are no longer in the PTX */
for (loop = 0; loop < pwShuffle; loop++)
{
layer4and5Header->header.txHighData[loop] =
layer2and3Header->header.txLowData[layer2and3Header->header.txLowLength + loop];
}
}
}
}
}
if (cdEnable == ZL5011X_TRUE)
{
if (status == ZL5011X_OK)
{
/* fill in the CD field in the header */
status = zl5011xPacketGetWanRxCDHeader(zl5011xParams,
par, &temp, cdPos);
}
if (status == ZL5011X_OK)
{
/* adjust the CD field in the header */
status = zl5011xPacketChangeField(layer4and5Header->header.txHighData,
cdPos, temp, 0xffff, &checksumMod);
}
}
if (status == ZL5011X_OK)
{
if (udpEnable == ZL5011X_TRUE)
{
/* a UDP header is present, so update the checksum based on the dynamic
field positions etc. */
status = zl5011xUpdateUDPChecksum(layer4and5Header, layer2and3Header, par);
}
}
}
}
/* check that the flow type is consistent with the protocol selected. The
PE block must be included in the flow if the layer 4/5 header is required */
if (status == ZL5011X_OK)
{
switch (zl5011xParams->wanIf.wanRxFlow[par->context])
{
case ZL5011X_FLOW_WAN_PE_PKT:
case ZL5011X_FLOW_CPU_PE_PKT:
case ZL5011X_FLOW_PKT_PE_PKT:
/* PE block is included in flow so its header must be specified
as it does not support addition of zero length headers */
if (layer4and5Header->header.txHighLength == 0)
{
status = ZL5011X_INVALID_FLOW_TYPE;
}
break;
case ZL5011X_FLOW_WAN_PKT:
case ZL5011X_FLOW_CPU_PKT:
case ZL5011X_FLOW_PKT_PKT:
/* PE block is NOT included in flow so if header is specified this is an error */
if (layer4and5Header->header.txHighLength != 0)
{
status = ZL5011X_INVALID_FLOW_TYPE;
}
break;
default:
/* Flow type does not end in _PKT so is not correct for packet transmit */
status = ZL5011X_INVALID_FLOW_TYPE;
break;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -