📄 en_util.c
字号:
/*
** If we are a bridge, trigger the data send it now.
*/
if( pTranRec->fBridged )
{
/*
** First get the sequence count out of the packet and store
** it in the transport record.
** The ComBuf is shrunk so that only raw data is passes along.
*/
pTranRec->iLeSeqCount = *( ( UINT16 * ) ( CB_GetDataPtrComBuf( upsTrrbl.Packet->pComBuf ) ) );
CB_ShrinkComBuf( upsTrrbl.Packet->pComBuf, 2 );
en_cd_TxClass3Packet( upsTrrbl.Packet, pTranRec );
}
else
{
/*
** Bump the sequence count and mark this data as unverified
** if we're a client.
*/
if( !pTranRec->fServerConsumer )
{
pTranRec->iLeSeqCount++;
pTranRec->fVerified = FALSE;
upsTrrbl.Packet->iMsgSeq = pTranRec->iLeSeqCount; /* return seq count to application */
}
}
}
break;
default:
/*
** Unsupported request. Pull the plug.
*/
GS_LogEvent( CD_BAD_TX_TRIBBLE_REQUEST, upsTrrbl.Generic->eRequest, upsTrrbl.Generic, FATAL );
break;
} /* end switch */
/*
** Determine the final disposition of the tribble.
*/
if( ( upsTrrbl.Generic->xReturnQueue == CD_s[CD_ETHERNET_PORT].xTxUnschedHiQid ) ||
( upsTrrbl.Generic->xReturnQueue == CD_s[CD_ETHERNET_PORT].xTxUnschedLoQid ) )
{
/*
** This was a cleverly routed tribble ( generated by someone else
** and "returned" to this task. Toss the tribble now or we get
** locked into an infinite loop processing the same tribble.
*/
GS_DeleteTrrbl( upsTrrbl.Generic );
}
else
{
/*
** Normally routed tribble.
** Set completion status in the tribble to whatever is set in
** eStatus and then return the tribble to the requestor.
** If the tribble is to be deleted, this will happen in the
** GS_ReturnTrrbl( ) service when it finds an INVALID message
** queue-id in the tribble return Q-Id field.
*/
upsTrrbl.Generic->eStatus = eStatus;
GS_ReturnTrrbl( upsTrrbl.Generic );
}
} /* end while */
} /* end of EN_CD_TxUnscheduledTask( ) */
/****************************************************************************
**
** Private Services
**
*****************************************************************************
*/
/*---------------------------------------------------------------------------
** en_cd_Class1TxPacket( )
**---------------------------------------------------------------------------
*/
void en_cd_Class1TxPacket( UINT8 *pBuf, cd_TransportRecordType * pTranRec )
{
CPFHDR *msg;
struct sockaddr_in sto;
int ret;
/*
** Allocate a buffer to be used for all the transmitt headers including
** the UDP, Ethernet and IP headers. It will be freed in the stoptransport
** call
*/
msg = (CPFHDR *) pTranRec->pBufB;
/*
** Check to see if the data in the buffer last sent is different
** from the new buffer by checking the transport sequence. IT
** IS IMPORTANT to note that unless the sequence count changed
** from the last update, data in the send buffer will NOT be
** sent per the following if statement. If you want new data
** to be sent regardless of sequence count remove the if statement
** below. THe penalty will be the increased time for the copy operation.
** Also see en_cd_PutTransportBuffer.
** 02/07/01 jjw Check to see if this is the first buffer to be sent.
** if it is then copy the data regaurdless of the serial numbers.
*/
if ( (*( (UINT16 *) (&msg->iDs_length + 1)) != *((UINT16 *)pBuf) ) ||
( pTranRec->iBufState != A_CURRENT_B_FREE ) )
{
UC_CopyMem((char *) (&msg->iDs_length + 1), pBuf,
pTranRec->iDataSize + 2); /* throw in the Transport Seq num*/
}
/*
** We are done using the buffer locked with the GetTransport call. Unlock
** access to it by doing a set semaphore
*/
GS_SetSemaphore(pTranRec->xSBufAccess);
/*
** pTranRec->iDataSize is the length of the data only. It does not include the 2 bytes
** of transport sequence number. Do not confuse transport sequence number with
** with Common Packet Encapsulation sequence number. The Common Packet Encapsulation sequence
** number is incremented every packet. The transport sequence number is only incremented
** when new data is produced
**/
*( ( UINT32 * ) msg->aiAs_seq ) = ENCAP_TO_PL( pTranRec->iSeqCount );
/*
** Increment the transmission (Common Packet Encapsulation) count. This should not be confused with the
** transport packet sequence count. Send this message on to
** the xmit task. The connection is already open so we can send it
** immediately
*/
pTranRec->iSeqCount += 1;
pTranRec->iMsecLastSent = gs_sTimers.sSysTime.iMSecTime;
sto = pTranRec->sEce.sSa.sTransmit;
ret = sendto(sClass1Ece.lSockFd,
(char *) msg,
sizeof(CPFHDR) + pTranRec->iDataSize + 2,
0,
(struct sockaddr *) & sto,
sizeof(struct sockaddr_in));
}
/*---------------------------------------------------------------------------
** en_cd_TxClass3Packet( )
**---------------------------------------------------------------------------
*/
void en_cd_TxClass3Packet( CD_PacketTrrblType * pTrrbl, cd_TransportRecordType * pTranRec )
{
typedef packet_struct CI_LeGenTagTranHeaderType2
{
UINT8 bSize;
UINT8 bControl;
UINT8 bTagPad;
UINT8 bTag0;
UINT8 bTag1;
UINT8 bTag2;
UINT8 bTag3;
LeUINT16 iLeSeqCount;
}
GNU_PACKED CI_LeGenTagTranHeaderType2;
CI_LeGenTagTranHeaderType2 sHeader;
UINT16 iSize;
if( pTranRec == NULL )
{
return;
}
/*
** Collect the header information for the packet from the tribble.
** This gets loaded into the buffer ahead of the packet.
** Include the latest sequence number in the header.
**
** Determine direction based on Transaction record
*/
if( pTranRec->sEce.sEid.u.type == ECE_TYPE_INBOUND )
pTrrbl->bRequest = TRUE;
else
pTrrbl->bRequest = 0;
iSize = CB_GetDataSizeComBuf( pTrrbl->pComBuf ) +
sizeof( CI_LeGenTagTranHeaderType );
sHeader.bSize = ( ( iSize + 1 ) >> 1 );
sHeader.bControl = CI_CTRL_TAG_PAD |
CI_CTRL_ACCEPT_ALWAYS |
( ( iSize & 1 ) ? CI_CTRL_DATA_PAD : 0 );
*( UINT32 * ) & ( sHeader.bTag0 ) = *( UINT32 * ) & pTranRec->abTxTag[0];
sHeader.iLeSeqCount = pTranRec->iLeSeqCount;
/*
** Call the generic Tx ring buffer load routine with both the packet
** and the header we just built.
*/
en_cd_LoadUnschedTxPacket( ( CD_PacketTrrblType * ) pTrrbl,
( UINT8 * ) ( &sHeader ),
pTranRec,
sizeof( CI_LeGenTagTranHeaderType2 ),
iSize,
FALSE );
} /* end of en_cd_TxClass3Packet */
/*---------------------------------------------------------------------------
** en_cd_ParseClass1Packet( )
**---------------------------------------------------------------------------
*/
UINT32 en_cd_ParseClass1Packet( PKTBUF * psPacketBuf )
{
UINT32 iCId;
UINT16 iTagIndex;
UINT32 iSeqCount;
UINT16 iTPUSeqCount;
cd_TransportRecordType *pTagEntry;
CPFHDR *msg = ( CPFHDR * ) psPacketBuf->pData;
UINT32 iTransport;
GS_UseCritical( );
if( ( msg->iAs_type == CPF_TAG_ADR_SEQUENCED ) && /* connected class 1 */
( msg->iAs_length == 8 ) )
{
iCId = ENCAP_VALUE_LONG( *(UINT32 *) &msg->aiAs_cid[0] );
/*
** The transport ID might have been assigned by the other node. It does not necessarily
** match our convention. Therefore, we need to loop through all our transport records to
** find the correct transport
*/
/*
** jjw 3/16/01, changed the upper bound to EN_CD_FIRST_C1P_TRANSPORT
*/
for(iTransport = EN_CD_FIRST_C1C_TRANSPORT; iTransport < EN_CD_FIRST_C1P_TRANSPORT; iTransport++)
{
iTagIndex = iTransport - 1;
pTagEntry = ( CD_s[CD_ETHERNET_PORT].papTransportRecords )[ iTagIndex ];
/*
** Sanity check 1, Make sure we have a valid transport pointer.
*/
if (pTagEntry == NULL)
{
continue;
}
/*
** Sanity check 2, Make sure transport ID's match
*/
if( *(UINT32 *)pTagEntry->abRxTag != iCId )
{
continue;
}
/*
** Sanity check 3, Is this being sent by the same IP as opened the connection in the first place ?
** Note that this checks Class 1 point to point as well as multicast connections.
*/
if( pTagEntry->sEce.sAddr.sin_addr.s_addr != psPacketBuf->sEce.sAddr.sin_addr.s_addr )
{
continue;
}
/*
** If we got to here after all the above checks, we have the correct transport.
*/
break;
} /* End search through all transports */
/*
** If transport == first class 1 producer, we did not find a match.
*/
if (iTransport == EN_CD_FIRST_C1P_TRANSPORT)
{
return OK;
}
/*
** Check the Common Packet Encapsulation sequence count. This count is incremented each time a message is sent out
**/
iSeqCount = ENCAP_VALUE_LONG( *( ( UINT32 * ) & msg->aiAs_seq[0] ) );
/*
** First, check to make sure that the Common Packet Encapsulation sequence number is greater than the last received. This
** makes sure that if the packet was routed, etc we do not reuse an old packet. Also, no assumptions can
** be made wrt the first packet serial number, so just check and allow any SN to pass through.
**
*/
if( ( IS_GT( iSeqCount, pTagEntry->iSeqCount ) ) ||
( pTagEntry->fFirstMessageRcvd == 0) )
{
/*
** Now that the Common Packet Encapsulation sequence count has been verified lets move on to check the sequence count of the TP
** itself.
**/
iTPUSeqCount = ENCAP_VALUE_SHORT(*((UINT16 *) ((char *) psPacketBuf->pData + CPFHDR_SIZE ))); /* First word of data is seq count */
/*
** Call the appropriate Rx copy function to copy the I/O data if
** the sequence numbers are not the same, OR if this is a bridged transport.
*/
if( ( iTPUSeqCount != pTagEntry->iLeSeqCount )
|| ( pTagEntry->fFirstMessageRcvd == 0 )
|| ( pTagEntry->fDupNotify )
|| ( pTagEntry->fBridged ) )
{
/*
** Now get the data information that is appended to this packet
*/
msg->iDs_type = ENCAP_TO_HS( msg->iDs_type );
msg->iDs_length = ENCAP_TO_HS( msg->iDs_length );
/*
** Several sanity checks here before the copy call. First, make sure there
** is a copy function specified. Then make sure we have a connected
** packet type. Finally make sure that the length of the received
** message is less than the length specified in the connection, do not trust
** that the other end of this connection is going to send what they
** promised when they originated. The length includes the transport
** sequence count so subtract 2 off whenever we are figuring out
** how much actual data is included. Also make sure that the length
** of the complete message agrees with the length of the components.
*/
if( ( ( UINT32 ) psPacketBuf->lLength != CPFHDR_SIZE + 2 + pTagEntry->iDataSize ) ||
( msg->iDs_type != CPF_TAG_PKT_CONNECTED ) ||
( msg->iDs_length - 2 > pTagEntry->iDataSize ) )
{
pTagEntry->fFirstMessageRcvd = 0;
return OK;
}
if( pTagEntry->pRxCopyFunction != NULL )
{
if( ( pTagEntry->pRxCopyFunction )( pTagEntry->xRxAppHandle,
&iTPUSeqCount,
(char *) psPacketBuf->pData + CPFHDR_SIZE + 2, /* pointer to actual data */
(UINT16) (msg->iDs_length - 2) ) /* actual recvd data length */
!= 0xffff )
{
/*
** Copy the packet sequence number
*/
pTagEntry->iLeSeqCount = iTPUSeqCount;
pTagEntry->fFirstMessageRcvd = ~0; /* No longer first message received */
}
else
{
pTagEntry->fFirstMessageRcvd = 0;
}
}
else
{
/*
** Copy the packet sequence number
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -