⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zl5011xpackettx.c

📁 Zalink50114----TDMoIP芯片驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
                  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 + -