经过一段时间的学习,基于以太网交换机的TRDP PD开发调试结果已经正常了,故此,记录一下。
TRDP基于生产者、消费者模型。
TRDP PD 通信模式有两种,push和pull。在这两种模式中,网络设备又可以分为三种角色:publisher、subscriber、requester.
publisher是数据的提供者,在push和pull模式中负责发送注册的comId的数据,即所谓的生产者;
subscriber是数据的接受者,这push和pull模式中负责接收注册的comid的数据,即所谓的消费者;
requester是数据的请求者,在pull模式中负责对publisher发起请求,pd-pdu的头部中会带有相应的reply IP和reply comID,如果头部中没有指定需要reply的IP和comID,则publisher会把接收到的报文的源作为reply的目的给发送回去。
在pull模式中,requester也可以是subscriber。
/**************************************************************************************************************************************************/
tlc_ 提供了trdp的通用接口,因此在验证功能时非常好用。
//trdp 协议栈初始化
//初始化打印函数和VOS的内存管理
EXT_DECL TRDP_ERR_T tlc_init (
const TRDP_PRINT_DBG_T pPrintDebugString,
void *pRefCon,
const TRDP_MEM_CONFIG_T *pMemConfig);
//打开一个trdp 协议栈session入口,这里主要是进行协议栈的配置,返回pAppHandle,这个至关重要
EXT_DECL TRDP_ERR_T tlc_openSession (
TRDP_APP_SESSION_T *pAppHandle,
TRDP_IP_ADDR_T ownIpAddr,
TRDP_IP_ADDR_T leaderIpAddr,
const TRDP_MARSHALL_CONFIG_T *pMarshall,
const TRDP_PD_CONFIG_T *pPdDefault,
const TRDP_MD_CONFIG_T *pMdDefault,
const TRDP_PROCESS_CONFIG_T *pProcessConfig);
1、PD publisher验证
数据的发布者需要先准备发送的数据,将comID、destip、timeout等信息作为一个实体添加到协议栈的发送队列中
EXT_DECL TRDP_ERR_T tlp_publish (
TRDP_APP_SESSION_T appHandle,
TRDP_PUB_T *pPubHandle,
const void *pUserRef,
TRDP_PD_CALLBACK_T pfCbFunction,
UINT32 comId,
UINT32 etbTopoCnt,
UINT32 opTrnTopoCnt,
TRDP_IP_ADDR_T srcIpAddr,
TRDP_IP_ADDR_T destIpAddr,
UINT32 interval,
UINT32 redId,
TRDP_FLAGS_T pktFlags,
const TRDP_SEND_PARAM_T *pSendParam,
const UINT8 *pData,
UINT32 dataSize);
TRDP_ERR_T tlp_put (
TRDP_APP_SESSION_T appHandle,
TRDP_PUB_T pubHandle,
const UINT8 *pData,
UINT32 dataSize);
这里的每一个实体都是不重复的。因此,在周期推送数据的过程中,trdp 会 依次遍历自己的发送队列,将信息发送给目的地址。
这里的tlp_put()的功能就是将所需要发送的信息作为pd-pdu的dataset组织好数据报,放入发送队列中相应的节点存储。利用linux的select()函数来进行非阻塞的等待,周期性推送timeout的数据,即马上要发送的数据。
2、subscriber验证
subscriber是数据的接受者,需要先注册接收的信息,包含了源IP范围、comID,然后调用tlp_subscribe来注册到协议栈session的接收队列中。
EXT_DECL TRDP_ERR_T tlp_subscribe (
TRDP_APP_SESSION_T appHandle,
TRDP_SUB_T *pSubHandle,
const void *pUserRef,
TRDP_PD_CALLBACK_T pfCbFunction,
UINT32 comId,
UINT32 etbTopoCnt,
UINT32 opTrnTopoCnt,
TRDP_IP_ADDR_T srcIpAddr1,
TRDP_IP_ADDR_T srcIpAddr2,
TRDP_IP_ADDR_T destIpAddr,
TRDP_FLAGS_T pktFlags,
UINT32 timeout,
TRDP_TO_BEHAVIOR_T toBehavior)
协议栈根据timeout时间来接收绑定的socket数据,对接收到的数据进行校验,例如CRC、TOPOCOUNT、SRCIP、COMID。根据pdu的msgType来判断是否是Pr类型的数据,pr类型也就是请求包,收到这样的包需要查看发送队列是否存在comid相同的节点,如果存在,需要马上将数据作为msgType==Pp推送给reply IP,并且通知trdp user层(打印函数)。
3、requester验证
请求数据和publisher很相似,不过这里是调用了tlp_request来进行msgType==Pr数据的准备。
EXT_DECL TRDP_ERR_T tlp_request (
TRDP_APP_SESSION_T appHandle,
TRDP_SUB_T subHandle,
UINT32 comId,
UINT32 etbTopoCnt,
UINT32 opTrnTopoCnt,
TRDP_IP_ADDR_T srcIpAddr,
TRDP_IP_ADDR_T destIpAddr,
UINT32 redId,
TRDP_FLAGS_T pktFlags,
const TRDP_SEND_PARAM_T *pSendParam,
const UINT8 *pData,
UINT32 dataSize,
UINT32 replyComId,
TRDP_IP_ADDR_T replyIpAddr)
tlp_request会生成一个新的实体,放入trdp session的发送队列中去。如果收到相应的Pp报文,则需要通知trdp user层。
/***********************************************************************************************************************************************/
PD数据的推拉模式,源码中已经写的比较独立和清晰,需要关注的点是和操作系统的对接,主要也就是socket编程。PD使用的是UDP协议,IANA 分配的port为17224,iec61375-2-3中规定的是20548。在UDP对接中,不同的系统的难度是不一样的,源码可以再Windows系统和linux系统直接生成相应的执行文件,适配网络平台则需要慢慢调试,验证相应的收发功能。