由于公司的需求发现需要写一个简化的PTP4L,支持OC模式就可以,目前此软件测试可用,采用的是L2组播的方法
软件框架逻辑想法来自PTP4L,为了以后方便查阅和方便有同样问题同学使用:
注意几点:
1.由于是和特定MASTER通信,所以结构体中的SYNC,FOLLOWUP,REQ,RESP字节数是固定的,如果改动需要特别注意
2.现在每两秒是一个周期
3. 这里面不夹杂任何驱动程序,只有软件通信流程,驱动只会获取t2和t3的时间戳,和读回来的t1和t4进行运算
以下是软件的PTPv2 OC模式源代码:
MAKEFILE部分:

.PHONY:all clean
common_src= ptp_raw.c
client_src= $(common_src) ptp_client.c
client_obj=$(client_src:.c=.o)serv_src= $(common_src) ptp_serv.c
serv_obj=$(serv_src:.c=.o)ptp_client=ptp_client
ptp_serv=ptp_servCC=gcc
# CC=arm-linux-gccall:$(ptp_client) $(ptp_serv)$(ptp_client):$(client_obj)$(CC) -Wall -Werror $(filter %.o,$^) -o $@
$(clinet_obj):$(client_src) $(CC) -Wall -Werror $(filter %.c,$^) -c$(ptp_serv):$(serv_obj)$(CC) -Wall -Werror $(filter %.o,$^) -o $@
$(serv_obj):$(serv_src) $(CC) -Wall -Werror $(filter %.c,$^) -c
tags:ctags -Rcscope -Rbqclean:@rm -rf $(ptp_serv) $(ptp_client) *.o tags cscope*

程序部分:
ptp_raw.c

#include <netpacket/packet.h>
#include <stdbool.h>
#include "ptp_raw.h"
#include <unistd.h>
#include <netinet/ether.h>void send_socket_init(ptp_timer_t *ptp_buf);void ptp_hex_log(unsigned char *buf,int len)
{int i,j=0;if( len > 0){for(i = 0; i < len;j++,i++){printf(" %#02X ",buf[i]);if( j == 11){printf("\n");j = 0;}}}
}bool ptp_local_mac(char *ethname, char *src)
{int i,skfd;struct ifreq ifr;skfd = socket(AF_INET, SOCK_STREAM, 0);strcpy(ifr.ifr_name, ethname);if (skfd == -1) return false;if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0){close(skfd);return false;}close(skfd);for (i=0; i<6; i++){src[i] = (char)ifr.ifr_hwaddr.sa_data[i];}return true;
}bool chioce_eth(ptp_timer_t *ptp_buf)
{if (!ptp_buf->eth_chioce) return false;int status;struct ifreq ifreq;memset(&ifreq,0,sizeof(ifreq));strncpy(ifreq.ifr_name,ptp_buf->eth_name,sizeof(ifreq.ifr_name)-1); //选择网卡发送status = ioctl(ptp_buf->raw_send_fd, SIOCGIFINDEX, &ifreq); //控制I/O设备if(status < 0){printf("error: find interface_index failed \n");return false;}ptp_buf->interface_index = ifreq.ifr_ifindex;printf("interface %d ethname:%s\n",ptp_buf->interface_index,ptp_buf->eth_name);return true;
}void init_raw_socket(ptp_timer_t *ptp_buf) //FIX_ME
{memset(&ptp_buf->ska_ll_ddr, 0, sizeof(ptp_buf->ska_ll_ddr));ptp_buf->ska_ll_ddr.sll_family = AF_PACKET;ptp_buf->ska_ll_ddr.sll_ifindex = ptp_buf->interface_index;ptp_buf->ska_ll_ddr.sll_protocol = htons(PTP); if(bind(ptp_buf->raw_fd,(struct sockaddr*)&ptp_buf->ska_ll_ddr,sizeof(ptp_buf->ska_ll_ddr))){printf("bind error for AF_PACKET\n");   }
}bool configure_raw_muli(ptp_timer_t *ptp_buf) //设置混杂模式和网卡的组播
{int option,status;struct packet_mreq mreq;option = ptp_buf->muli_ctr ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP;memset(&mreq, 0, sizeof(mreq));switch(ptp_buf->muli_type){case MULI_CTL:printf("[< select multi >] \n");mreq.mr_ifindex = ptp_buf->interface_index;mreq.mr_type = PACKET_MR_MULTICAST;mreq.mr_alen = 6; //组播Mac地址的大小memcpy(mreq.mr_address,ptp_buf->muli_mac,6);case ALLMULTI_CTL:mreq.mr_ifindex = ptp_buf->interface_index;mreq.mr_type = PACKET_MR_ALLMULTI;mreq.mr_alen = 0;break;case PROMISC_CTL:mreq.mr_ifindex = ptp_buf->interface_index;mreq.mr_type = PACKET_MR_PROMISC;mreq.mr_alen = 0;break;}status = setsockopt(ptp_buf->raw_fd, SOL_PACKET, option, &mreq, sizeof(mreq));if(status){printf("recv:_________setsockopt %d failed________\n",ptp_buf->muli_type);return false;}status = setsockopt(ptp_buf->raw_send_fd, SOL_PACKET, option, &mreq, sizeof(mreq));if(status){printf("send:_________setsockopt %d failed________\n",ptp_buf->muli_type);return false;}return true;
}bool configure_raw_ptp(ptp_timer_t *ptp_buf) //ptp 配置操作方法
{int option,status;struct packet_mreq mreq;option = ptp_buf->muli_ctr ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP;memset(&mreq, 0, sizeof(mreq));mreq.mr_ifindex = ptp_buf->interface_index;mreq.mr_type = PACKET_MR_MULTICAST;mreq.mr_alen = 8; //组播Mac地址的大小memcpy(mreq.mr_address,ptp_buf->muli_mac, 8);status = setsockopt(ptp_buf->raw_fd, SOL_PACKET, option, &mreq, sizeof(mreq));if(status){printf("setsockopt MULTICAST  failed\n");}if(!status) return true;mreq.mr_ifindex = ptp_buf->interface_index;mreq.mr_type = PACKET_MR_ALLMULTI;mreq.mr_alen = 0;status = setsockopt(ptp_buf->raw_fd, SOL_PACKET, option, &mreq, sizeof(mreq));if(status){printf("setsockopt ALLMULTI failed\n");}if(!status) return true;mreq.mr_ifindex = ptp_buf->interface_index;mreq.mr_type = PACKET_MR_PROMISC;mreq.mr_alen = 0;status = setsockopt(ptp_buf->raw_fd, SOL_PACKET, option, &mreq, sizeof(mreq));if(status){printf("setsockopt PROMISC failed\n");}if(!status) return true;return false;
}bool create_ptp_socket_raw(ptp_timer_t  *ptp_buf) //FIXME:只创建了以太网协议的头部,选择不同的设备
{if(ptp_buf->raw_fd > 0 || ptp_buf->raw_send_fd > 0){ //避免重复使用一个套接字close(ptp_buf->raw_fd);close(ptp_buf->raw_send_fd);ptp_buf->raw_fd = -1;}ptp_buf->raw_fd = socket(PF_PACKET, SOCK_RAW,htons(ptp_buf->mac_framer_type)); //所有协议监听套接字ptp_buf->raw_send_fd = socket(PF_PACKET, SOCK_RAW,htons(ptp_buf->mac_framer_send_type)); //发送套接字if(ptp_buf->raw_fd<0 || ptp_buf->raw_send_fd < 0){printf("--- create ptp raw socket error --- \n");return false;}switch(ptp_buf->ptp_mode){case PTP_SALVE:ptp_buf->clock_master_status = CHECK_MASTER_STATUS;printf("[< create slave ptp socket ok>]\n");break;case PTP_MASTER:ptp_buf->clock_salve_status = SEND_SYNC_FOLLOWUP_MSG;printf("[< create master ptp socket ok>]");break;}chioce_eth(ptp_buf);init_raw_socket(ptp_buf);configure_raw_muli(ptp_buf);return true;
}bool ptp_send_packets(ptp_timer_t *ptp_buf)
{chioce_eth(ptp_buf);send_socket_init(ptp_buf);if(sendto(ptp_buf->raw_send_fd, ptp_buf->buf, ptp_buf->msg_lenth,   \MSG_NOSIGNAL, (struct sockaddr*)&ptp_buf->ska_ll_ddr, sizeof(ptp_buf->ska_ll_ddr)) == -1){printf("[< send ptp buf error >]\n");return false;}return true;
}void ptp_delay_req_send(ptp_timer_t *ptp_buf) //test_send delay_req data_pool
{static short  send_seqence_id = 0;send_seqence_id += 1;char mac[6];ptp_local_mac(ptp_buf->eth_name,mac);char dst_mac[6] = {0x01,0x1B,0x19,0x00,0x00,0x00};ptp_delayreq_msg_t delay_req;memcpy(delay_req.ether_ptp_head.dst_mac,dst_mac,6); //数据类型一致的情况memcpy(delay_req.ether_ptp_head.src_mac,mac,6);delay_req.ether_ptp_head.ptp_type= htons(PTP);delay_req.transport_and_sync_id = 0x01;delay_req.reserved_and_ptpversion = 0x02;delay_req.msg_lenth = htons(44);delay_req.subdomain = 0;delay_req.reserved_v1 = 0;delay_req.flags = htons(0x0200);delay_req.correction = 0;delay_req.reserved_v2 = 0;delay_req.clock_id = 0x0;delay_req.source_port_id = 1;delay_req.seqence_id = htons(send_seqence_id);delay_req.ctrl_msg = 0x1;delay_req.log_period = 127;memset(delay_req.origintimestamp_seconds,0,6);memset(delay_req.origintimestamp_nanoseconds,0,6);memset(delay_req.padding,0,6);unsigned char log_pool[64];memcpy(log_pool,&delay_req,64);printf("_______send ptp packets_________\n");ptp_hex_log(log_pool,64);ptp_buf->delay_req_msg = delay_req;ptp_buf->buf =log_pool ;ptp_buf->msg_lenth = 64;ptp_send_packets(ptp_buf);ptp_buf->send_seqence_id = send_seqence_id;ptp_buf->clock_master_status = CHECK_MASTER_STATUS;
}bool ptp_recv_packets_pool(ether_head_t ether_head_type,ptp_timer_t *ptp_buf,unsigned char *pool)
{if(ntohs(ether_head_type.ptp_type) != ptp_buf->protocol) return false;ptp_buf->buf = (unsigned char*)malloc(sizeof(unsigned char)*ptp_buf->msg_lenth);if(ptp_buf->buf == NULL) return false;memcpy(ptp_buf->buf,pool,ptp_buf->msg_lenth); //接收到的数据包在做判断return true;
}bool ptp_recv_packets(ptp_timer_t *dst_ptp_buf) //首先先接收到来自BBU的数据包进行判断
{int status;fd_set check_fd;unsigned char tmp_pool[MTU] = {0};struct timeval time_record;time_record.tv_sec = 2;time_record.tv_usec = 0;FD_ZERO(&check_fd);FD_SET(dst_ptp_buf->raw_fd,&check_fd);status = select(dst_ptp_buf->raw_fd+1,&check_fd,NULL,NULL,&time_record); //超时设置时间printf("recv ether mac packets status : %d \n",status);if(!status) {dst_ptp_buf->check_recv_fd = status;printf("Can't recv ether mac packets status : %d \n",status);return false;}dst_ptp_buf->msg_lenth = recvfrom(dst_ptp_buf->raw_fd,tmp_pool,MTU,0,NULL,NULL);ether_head_t ether_ptp_head_check;memcpy(&ether_ptp_head_check,tmp_pool,14);printf("ptp type: %#x\n",ntohs(ether_ptp_head_check.ptp_type));long mac;memcpy(&mac,ether_ptp_head_check.src_mac,6);printf("src mac:%#lX\n",mac);status = ptp_recv_packets_pool(ether_ptp_head_check,dst_ptp_buf,tmp_pool); if(!status){printf("_________Is not in ctl protocol_____________ \n");dst_ptp_buf->buf = (unsigned char*)malloc(dst_ptp_buf->msg_lenth*sizeof(unsigned char));if(dst_ptp_buf->buf == NULL) return false;memcpy(dst_ptp_buf->buf,tmp_pool,dst_ptp_buf->msg_lenth); //接收到的数据包在做判断    }return true;
}void clear_ptp_buf(ptp_timer_t *ptp_buf){memset(ptp_buf->buf,0,ptp_buf->msg_lenth); //清空来源的ptp数据缓存ptp_buf->msg_lenth = 0;free(ptp_buf->buf); //释放动态数据缓冲区
}bool time_out(time_t stime,unsigned int out) //代码超时设置
{return time(NULL)-stime >= out?true:false;
}bool deal_salve_ptp_data_pool(ptp_timer_t *ptp_buf)
{unsigned char *pool;pool = ptp_buf->buf;char msg_id;ether_head_t ether_ptp_head_check;memcpy(&ether_ptp_head_check,pool,14);if(ntohs(ether_ptp_head_check.ptp_type) != PTP){printf("[< It's not ptp type >]");ptp_buf->clock_master_status = MASTER_CLOCK_NOT_OK;return false;}switch(ptp_buf->msg_lenth){case SYNC_AND_FOLLOW_UP_LEN:break;case DELAY_REQ_LEN:break;case DELAY_RESP_LEN:break;case ANNOUNCE_LEN:break;default:printf("error with ptp recv data lenth \n");return false;    }msg_id = pool[14];printf("msg id is %#x\n",msg_id);ptp_sync_msg_t *sync_msg;ptp_followup_msg_t *followup_msg;ptp_delsyresp_t *resp_msg;unsigned int sec,nsec;switch(msg_id){ //寻找同一序列的时间戳case SYNC_ID:sync_msg = (ptp_sync_msg_t*)pool;ptp_buf->sync_msg = *sync_msg;ptp_buf->recv_seqence_id = ptp_buf->sync_msg.seqence_id;printf("recv sync seqence_id : %#x \n",ntohs(ptp_buf->recv_seqence_id));break;case FOLLOW_UP_ID:followup_msg = (ptp_followup_msg_t*)pool;ptp_buf->followup_msg = *followup_msg;ptp_buf->recv_seqence_id = ptp_buf->followup_msg.seqence_id;ptp_buf->clock_master_status = (ptp_buf->followup_msg.seqence_id == ptp_buf->sync_msg.seqence_id)?MASTER_CLOCK_OK:MASTER_CLOCK_NOT_OK;printf("recv follow up seqence_id : %#x \n",ntohs(ptp_buf->recv_seqence_id));break;case DELAY_RESP_ID:resp_msg = (ptp_delsyresp_t*)pool;ptp_buf->delay_resp_msg = *resp_msg;ptp_buf->recv_seqence_id = ptp_buf->delay_resp_msg.seqence_id;ptp_buf->clock_master_status = (ptp_buf->delay_resp_msg.seqence_id == ptp_buf->delay_req_msg.seqence_id)?MASTER_CLOCK_OK:MASTER_CLOCK_NOT_OK;printf("\n__________________PTP SEQENCE ID___________________\n");printf("SYNC SEQENC ID: %#x \n",ntohs(ptp_buf->sync_msg.seqence_id));printf("FOLL SEQENC ID: %#x \n",ntohs(ptp_buf->followup_msg.seqence_id));printf("_REQ SEQENC ID: %#x \n",ntohs(ptp_buf->delay_req_msg.seqence_id));printf("RESP SEQENC ID: %#x \n",ntohs(ptp_buf->delay_resp_msg.seqence_id));printf("\n__________________END SEQENCE ID___________________\n");if(ptp_buf->clock_master_status == MASTER_CLOCK_NOT_OK) break;   memcpy(&sec,ptp_buf->followup_msg.t1_timestamp_seconds+2,4);memcpy(&nsec,ptp_buf->followup_msg.t1_timestamp_nanoseconds,4);ptp_buf->timestamp_hardware.time_stamp[0].tv_sec = ntohl(sec);ptp_buf->timestamp_hardware.time_stamp[0].tv_nsec = ntohl(nsec);sec = 0;nsec = 0;memcpy(&sec,ptp_buf->delay_resp_msg.t4_timestamp_seconds+2,4);memcpy(&nsec,ptp_buf->delay_resp_msg.t4_timestamp_nanoseconds,4);ptp_buf->timestamp_hardware.time_stamp[3].tv_sec = ntohl(sec);ptp_buf->timestamp_hardware.time_stamp[3].tv_nsec = ntohl(nsec);printf("\n__________________PTP RX TIMEST ID___________________\n");printf("FOLL SEQENC ID: %#x TIMESTAMP:%#lx.%#lx \n",ntohs(ptp_buf->followup_msg.seqence_id),ptp_buf->timestamp_hardware.time_stamp[0].tv_sec,ptp_buf->timestamp_hardware.time_stamp[0].tv_nsec);printf("RESP SEQENC ID: %#x TIMESTAMP:%#lx.%#lx \n",ntohs(ptp_buf->delay_resp_msg.seqence_id),ptp_buf->timestamp_hardware.time_stamp[3].tv_sec,ptp_buf->timestamp_hardware.time_stamp[3].tv_nsec);printf("\n__________________END RX TIMEST ID___________________\n");ptp_buf->clock_master_status = PTP_ADJ_OFFSET;break;default:printf("ptp msg id is error\n");return false;}return true;
}void init_ptp_timer_t(ptp_timer_t *ptp_buf)
{ unsigned char ptp_dst_mac[6] = {0x01,0x1B,0x19,0x00,0x00,0x00};ptp_buf->starttime = time(NULL); sprintf(ptp_buf->eth_name,"enp0s3");ptp_buf->eth_chioce = true;ptp_buf->msg_lenth = 0;ptp_buf->mac_framer_type = PTP;
/*    ptp_buf->muli_type = PROMISC_CTL;*/ptp_buf->muli_type = MULI_CTL;ptp_buf->muli_ctr = true;ptp_buf->protocol = PTP;ptp_buf->ptp_mode = PTP_SALVE;ptp_buf->mac_framer_send_type = PTP;switch(ptp_buf->muli_type){case MULI_CTL:memcpy(ptp_buf->muli_mac,ptp_dst_mac,6);break;case ALLMULTI_CTL:break;case PROMISC_CTL:break;}
}void clear_ptp_msg_t(ptp_timer_t *ptp_buf)
{memset(&ptp_buf->sync_msg,0,sizeof(60));memset(&ptp_buf->followup_msg,0,sizeof(60));memset(&ptp_buf->delay_req_msg,0,sizeof(64));memset(&ptp_buf->delay_resp_msg,0,sizeof(68));ptp_buf->recv_seqence_id = 0;ptp_buf->send_seqence_id = 0;
}void  ptp_client_main(void)
{bool status = false;ptp_timer_t ptp_buf;ptp_buf.clock_master_status = MASTER_CLOCK_NOT_OK;while(1){usleep(100*1000);init_ptp_timer_t(&ptp_buf);switch(ptp_buf.clock_master_status){case MASTER_CLOCK_NOT_OK:printf("create ptp raw socket\n");create_ptp_socket_raw(&ptp_buf); //每次都会重新回去一个新的套戒字,关闭旧的套接字break; case CHECK_MASTER_STATUS:printf("check master clock status\n");status = ptp_recv_packets(&ptp_buf);if(status){printf("____recv: ptp lenth %#x____ \n",ptp_buf.msg_lenth);ptp_hex_log(ptp_buf.buf,ptp_buf.msg_lenth);printf("\n___________________________ \n");}else{printf("wait for master clock\n");break;}status = deal_salve_ptp_data_pool(&ptp_buf);clear_ptp_buf(&ptp_buf); //第一缓存区清空if(!status){printf("[<error deal ptp data pool>]\n");}break;case MASTER_CLOCK_OK: //发送delay_reqprintf("\ncheck master clock is ok\n");ptp_delay_req_send(&ptp_buf);break;case PTP_ADJ_OFFSET: //写入offset 最后一步写入组播值printf("[< ptp adjtime >]\n");ptp_buf.clock_master_status = MASTER_CLOCK_NOT_OK;clear_ptp_msg_t(&ptp_buf); //清空第二个数据池缓冲区break;}}
}void init_master_ptp_timer_t(ptp_timer_t *ptp_buf)
{unsigned char ptp_dst_mac[6] = {0x01,0x1B,0x19,0x00,0x00,0x00};ptp_buf->starttime = time(NULL); sprintf(ptp_buf->eth_name,"enp3s0");ptp_buf->eth_chioce = true;ptp_buf->msg_lenth = 0;ptp_buf->mac_framer_type = ETH_P_ALL; //监听套接字 ,FIXMEptp_buf->muli_type = MULI_CTL;ptp_buf->muli_ctr = true;ptp_buf->protocol = PTP;  //FIXMEptp_buf->ptp_mode = PTP_MASTER;ptp_buf->mac_framer_send_type = PTP;switch(ptp_buf->muli_type){case MULI_CTL:memcpy(ptp_buf->muli_mac,ptp_dst_mac,6);break;case ALLMULTI_CTL:break;case PROMISC_CTL:break;}
}void send_socket_init(ptp_timer_t *ptp_buf)
{char local_mac[6];memset(&ptp_buf->ska_ll_ddr, 0, sizeof(ptp_buf->ska_ll_ddr));ptp_buf->ska_ll_ddr.sll_family = AF_PACKET;ptp_buf->ska_ll_ddr.sll_ifindex = ptp_buf->interface_index;ptp_buf->ska_ll_ddr.sll_protocol = htons(PTP);ptp_buf->ska_ll_ddr.sll_halen = htons(6);ptp_local_mac(ptp_buf->eth_name,local_mac);memcpy(ptp_buf->ska_ll_ddr.sll_addr,local_mac,6);if(bind(ptp_buf->raw_send_fd,(struct sockaddr*)&ptp_buf->ska_ll_ddr,sizeof(ptp_buf->ska_ll_ddr))){printf("bind error for AF_PACKET\n");  }
}bool ptp_serv_recv_deal(ptp_timer_t *ptp_buf)
{unsigned char *pool;pool = ptp_buf->buf;char msg_id;ether_head_t ether_ptp_head_check;memcpy(&ether_ptp_head_check,pool,14);if(ntohs(ether_ptp_head_check.ptp_type) != PTP){ptp_buf->clock_salve_status = CREATE_MASTER_CLOCK; //FIXME:重新接受从时钟的数据包return false;}switch(ptp_buf->msg_lenth){case SYNC_AND_FOLLOW_UP_LEN:break;case DELAY_REQ_LEN:break;case DELAY_RESP_LEN:break;case ANNOUNCE_LEN:break;default:printf("error with ptp recv data lenth \n");return false;    }msg_id = pool[14];printf("msg id is %#x\n",msg_id);ptp_delayreq_msg_t *resp_msg;switch(msg_id){ //匹配ptp_msg_idcase SYNC_ID:break;case FOLLOW_UP_ID:break;case DELAY_REQ_ID:resp_msg = (ptp_delayreq_msg_t*)pool;ptp_buf->delay_req_msg = *resp_msg;printf("recv salve clock seqence_id :%#x\n",ptp_buf->delay_req_msg.seqence_id);ptp_buf->clock_salve_status = SEND_RESP_CLOCK;break;default:printf("ptp msg id is error\n");return false;}return true;
}bool ptp_sync_followup_send(ptp_timer_t *ptp_buf)
{chioce_eth(ptp_buf);send_socket_init(ptp_buf);unsigned char sync_buf[] = {0x01,0x1B,0x19,0x00,0x00,0x00,
/*     0x08,0x00,0x27,0x8c,0x41,0x81,*/0x08,0x00,0x27,0x39,0x8b,0x5c,0x88,0xf7,0x00,0x02,0x00,0x2c,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x25,0x8a,0xff,0xfe,0xe3,0xe1,0x92,0x00,0x02,0x9f,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};if(sendto(ptp_buf->raw_send_fd, sync_buf,sizeof(sync_buf),     \MSG_NOSIGNAL, (struct sockaddr*)&ptp_buf->ska_ll_ddr, sizeof(ptp_buf->ska_ll_ddr)) == -1){printf("--- send ptp sync error ---\n");return false;}unsigned char followup_buf[] = {0x01,0x1B,0x19,0x00,0x00,0x00,/*     0x08,0x00,0x27,0x8c,0x41,0x81,*/0x08,0x00,0x27,0x39,0x8b,0x5c,0x88,0xf7,0x08,0x02,0x00,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x25,0x8a,0xff,0xfe,0xe3,0xe1,0x9a,0x00,0x02,0x9f,0xdb,0x02,0x00,0x00,0x00,0x00,0x00,0x39,0x82,0x38,0xaf,0xdb,0x51,0x00,0x00};if(sendto(ptp_buf->raw_send_fd, followup_buf,sizeof(followup_buf),   \MSG_NOSIGNAL, (struct sockaddr*)&ptp_buf->ska_ll_ddr, sizeof(ptp_buf->ska_ll_ddr)) == -1){printf("--- send ptp sync error ---\n");return false;}ptp_buf->clock_salve_status = CHECK_SALVE_CLOCK;return true;
}bool send_resp_clock_packets(ptp_timer_t *ptp_buf) //seqence_id 一致
{chioce_eth(ptp_buf);send_socket_init(ptp_buf);unsigned char resp_buf[] = {0x01,0x1B,0x19,0x00,0x00,0x00,/*     0x08,0x00,0x27,0x8c,0x41,0x81,*/0x08,0x00,0x27,0x39,0x8b,0x5c,0x88,0xf7,0x09,0x02,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x25,0x8a,0xff,0xfe,0xe3,0xe1,0x9a,0x00,0x02,0x9f,0xdb,0x03,0x00,0x00,0x00,0x00,0x00,0x39,0xff,0x08,0xf6,0x3a,0x7b,0x00,0x0a,0x35,0xff,0xfe,0x00,0x00,0x70,0x00,0x01};if(sendto(ptp_buf->raw_send_fd, resp_buf,sizeof(resp_buf),   \MSG_NOSIGNAL, (struct sockaddr*)&ptp_buf->ska_ll_ddr, sizeof(ptp_buf->ska_ll_ddr)) == -1){printf("--- send ptp sync error ---\n");return false;}ptp_buf->clock_salve_status = CREATE_MASTER_CLOCK;return true;
}void ptp_serv_main(void)
{bool status = false;ptp_timer_t ptp_buf;ptp_buf.clock_salve_status = CREATE_MASTER_CLOCK;while(1){init_master_ptp_timer_t(&ptp_buf);switch(ptp_buf.clock_salve_status){case CREATE_MASTER_CLOCK:printf("create ptp raw socket\n");create_ptp_socket_raw(&ptp_buf); //每次都会重新回去一个新的套戒字,关闭旧的套接字break; case CHECK_SALVE_CLOCK:printf("check salve clock status\n");status = ptp_recv_packets(&ptp_buf);if(status){printf("____recv: ptp lenth %#x____ \n",ptp_buf.msg_lenth);ptp_hex_log(ptp_buf.buf,ptp_buf.msg_lenth);printf("___________________________ \n");}else{printf("wait for salve clock,restart send followpup sycn\n");ptp_buf.clock_salve_status = SEND_SYNC_FOLLOWUP_MSG;break;}status = ptp_serv_recv_deal(&ptp_buf);clear_ptp_buf(&ptp_buf); //第一缓存区清空if(!status) printf("[<error deal ptp data pool>]\n");break;case SEND_SYNC_FOLLOWUP_MSG: //发送delay_reqprintf("___send_ptp_sync_followup__\n");ptp_sync_followup_send(&ptp_buf);break;case SEND_RESP_CLOCK: //写入offset 最后一步写入组播值printf("[<send resp msg>]\n");send_resp_clock_packets(&ptp_buf);clear_ptp_msg_t(&ptp_buf); //清空第二个数据池缓冲区break;}}
}

ptp_client.c

#include "ptp_raw.h"extern void ptp_client_main(void);int main(void)
{ptp_client_main();
}

ptp_serv.c

#include "ptp_raw.h"extern void ptp_serv_main(void);int main(void)
{ptp_serv_main();return 0;
}

ptp_raw.h

#ifndef __PTP_PROCOL__
#define __PTP_PROCOL__#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <math.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <poll.h>
#include <sys/epoll.h>
#include <linux/sched.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdbool.h>
#include <netpacket/packet.h>#define ENABLE_FIFO_IRQ 0x08000000
#define ISR_REG_DATA_RESET 0xFFFFFFFF //清楚中断状态
#define PTP 0x88F7
#define RX_COMPLETE_IRQ_STATUS 0x04000000
#define IRQ_CLEAR_OK 0x00000000
#define NSEC_PER_SEC    1000000000L
#define ETH_P_PARP 0x8035
#define MTU 1500typedef enum{DELAY_REQ_ID = 0x1,ANNOUNCE_ID  = 0xb,SYNC_ID = 0x0,FOLLOW_UP_ID = 0x8,DELAY_RESP_ID = 0x9
}ptp_message_id_e;typedef enum{ANNOUNCE_CTRL = 0x5,SYNC_CTRL = 0x0,FOLLOW_UP_CTRL = 0x2,DELAY_REQ_CTRL = 0x1,DELAY_RESP_CTRL = 0x3
}ptp_ctr_message_e;/* ptp sync packets 60 bytes *//*以太网协议头部*/
typedef struct{char dst_mac[6]; // 6char src_mac[6]; // 6short ptp_type;  // 2
}__attribute__ ((__packed__)) ether_head_t;/*ptp sync 44bytes*/
typedef struct{ether_head_t ether_ptp_head;    //14char transport_and_sync_id;     //1char reserved_and_ptpversion;    //1short msg_lenth;                 //2char subdomain;                  //1char reserved_v1;               //1short flags;                     //2long long correction;              //8int reserved_v2;                  //4long long clock_id;                   //8short source_port_id;            //2short seqence_id;                 //2char ctrl_msg;                    //1char log_period;                  //1char timestamp_seconds[6];         //6char timestamp_nanoseconds[4];      //4short padding;  //字段填充数
}__attribute__ ((__packed__)) ptp_sync_msg_t;/*ptp follow up 60 bytes*/
/*ptp follow up*/
typedef struct{ether_head_t ether_ptp_head;      //14char transport_and_sync_id;       //1    char reserved_and_ptpversion;     //1short msg_lenth;                  //2char subdomain;                   //1char reserved_v1;                 //1short flags;                       //2long long correction;              //8int reserved_v2;                   //4long long clock_id;                //8short source_port_id;              //2short seqence_id;                  //2char ctrl_msg;                     //1char log_period;                   //1char t1_timestamp_seconds[6];       //6char t1_timestamp_nanoseconds[4];   //4short padding;                      //2
}__attribute__ ((__packed__)) ptp_followup_msg_t;/* ptp delay req 64bytes*/
typedef struct{ether_head_t ether_ptp_head;   //14char transport_and_sync_id;    //1char reserved_and_ptpversion;  //1short msg_lenth;                 //2char subdomain;                  //1char reserved_v1;                  //1short flags;                        //2long long correction;                //8int reserved_v2;                      //4long long clock_id;                //8short source_port_id;              //2short seqence_id;                  //2char ctrl_msg;                    //1char log_period;                  //1char origintimestamp_seconds[6];         //6char origintimestamp_nanoseconds[4];   //4char padding[6];                     //6
}__attribute__ ((__packed__)) ptp_delayreq_msg_t;/*ptp delay resp 68bytes*/
typedef struct{ether_head_t ether_ptp_head;     //14char transport_and_sync_id;      //1char reserved_and_ptpversion;     //1             16short msg_lenth;                     //2char subdomain;                   //1char reserved_v1;              //1short flags;        //2                          6long long correction;    //8int reserved_v2;          //4long long clock_id;           //8short source_port_id;         //2                    22short seqence_id;              //2 char ctrl_msg;                     //1char log_period;                 //1                  4char t4_timestamp_seconds[6];         //6char t4_timestamp_nanoseconds[4];       //4long long request_clock_id;       //8short request_source_port_id;         //2            20
}__attribute__ ((__packed__)) ptp_delsyresp_t;typedef enum{MASTER_CLOCK_OK,MASTER_CLOCK_NOT_OK,CHECK_MASTER_STATUS,PTP_ADJ_OFFSET
}master_clock_status_e;typedef enum{CREATE_MASTER_CLOCK,SEND_SYNC_FOLLOWUP_MSG,CHECK_SALVE_CLOCK,SEND_RESP_CLOCK
}salve_clock_status_e;typedef enum{SYNC_AND_FOLLOW_UP_LEN = 60,DELAY_REQ_LEN = 64,DELAY_RESP_LEN = 68,ANNOUNCE_LEN = 90
}ptp_packets_lenth_e;enum{SYNC=0,FOLLOWUP=1,REQ=2,RESP=3
};/*ptp 协议*/typedef struct timespec ptp_timestamp;typedef struct{ptp_timestamp time_stamp[4];
}ptp_timestamp_t;typedef enum{MULI_CTL,PROMISC_CTL,ALLMULTI_CTL
}muli_ctr_e;typedef enum{PTP_MASTER,PTP_SALVE
}ptp_mode_e;typedef struct{int interface_index;master_clock_status_e clock_master_status;ptp_packets_lenth_e ptp_check_type_len;char eth_name[64];int mac_framer_type; //监听接受int mac_framer_send_type;bool eth_chioce;unsigned char *buf;int raw_fd;int raw_send_fd;int msg_lenth;ptp_message_id_e ptp_msg_type;ptp_ctr_message_e ptp_ctrl_msg_type;short recv_seqence_id;short send_seqence_id;time_t starttime;int waittime;int check_recv_fd;ptp_sync_msg_t sync_msg;ptp_delayreq_msg_t delay_req_msg;ptp_followup_msg_t followup_msg;ptp_delsyresp_t delay_resp_msg;ptp_timestamp_t timestamp_hardware;struct sockaddr_ll ska_ll_ddr;unsigned char muli_mac[6];muli_ctr_e muli_type;bool muli_ctr;int protocol;salve_clock_status_e clock_salve_status;ptp_mode_e ptp_mode;int salve_req_seqence_id;
}ptp_timer_t;#endif

软件测试截图:
可以从图片中看出时间戳的截图:相差一秒说明,获取的ID值和时间戳完全符合


还有一个,现在数据结构中的规划,预留兼容bc模式的数据结构,方便配置不同的模式,当然现在只适用于 SALVE模式,根据可配置,方便测试原则做了预留接口,只需要程序初始化的时候配置一次就可以

为了代码自由而开源分享

PTP4L 简化版本OC模式相关推荐

  1. Python使用openCV把原始彩色图像转化为灰度图、使用OpenCV把图像二值化(仅仅包含黑色和白色的简化版本)、基于自适应阈值预处理(adaptive thresholding)方法

    Python使用openCV把原始彩色图像转化为灰度图.使用OpenCV把图像二值化(仅仅包含黑色和白色的简化版本).基于自适应阈值预处理(adaptive thresholding)方法 目录

  2. Ajax jquery的库的简化版本

    Ajax jquery的库的简化版本 (function(){     //面向外界的唯一变量接口!     var myajax = window.myajax = {};     //作者.版本号 ...

  3. VINS简化版本 梳理

    VINS-Course是深蓝学院VIO课程中开源的一个vins-mono的简化版本,但vins系统本身较为复杂,因此对该套代码进行简单梳理,用作记录.本文章主要解释其euroc数据示例,也就是run_ ...

  4. android 工程模式mtk,Android L版本上user版本工程模式中gsensor校准失败

    [DESCRIPTION] 工程模式中gsensor的校准需要用到em_svr这个service,但是因为build选项的原因,在user编译时,这段code没有被build,导致user版本工程模式 ...

  5. 自我实现tcmalloc的项目简化版本

    项目介绍 该项目是基于现代多核多线程的开发环境和谷歌项目原型tcmalloc的自我实现的简化版本,相比于本身就比较优秀的malloc来说,能够略胜一筹,因为其考虑了 性能,多线程环境,锁竞争和内存碎片 ...

  6. S8003DXIG2版本工程模式代码

    S8003DXIG2版本工程模式代码为: 1.拨号键盘输入*#5239870*#     2 .选择 Internals     3.提示输入口令时在输入框内输入密码 *#7092463*#     ...

  7. php cli 错误日志,ThinkPHP5.0.*版本 cli模式下php每隔段时间就出错

    关于ThinkPHP5.0.*版本 cli模式下php每隔段时间就出错 cli模式下php每隔段时间就出错 官方论坛 日志如下: 控制台 Uncaught thinkexceptionErrorExc ...

  8. html5和极速模式,浅谈360浏览器6.0版本极速模式与兼容模式_蓝戒的博客

    360浏览器升级到6.0版本后对html5实现了全面兼容,于此同时360 6.0版本浏览器提供了两种模式:1.极速模式 2.兼容模式,也就是说360浏览器为双核浏览器.浏览器最核心的部分是渲染引擎(R ...

  9. 大V科技谈 | VMware利用先进的自动化技术,简化混合办公模式

    虚拟桌面基础架构.数字员工体验.统一端点管理和工作空间安全产品创新帮助IT团队事半功倍 大多数公司已经实施或计划在未来实施混合办公模式.(1)然而,支持混合办公模式给IT团队带来了新的挑战.近日,VM ...

最新文章

  1. 用函数的思想进行四则运算
  2. boost::hana::zero用法的测试程序
  3. 用shell打印下面这句话中字母数小于6的单词
  4. 关于控件postback 后viewstate加载失败的问题
  5. mysql_real_escape_string 报错_addslashes与mysql_real_escape_string的区别
  6. 算法-两最长回文子串
  7. Impala系列:Impala查询优化
  8. oracle新建用户,授权,建表空间语句
  9. 汽车倒车雷达系统的设计与实现(二)
  10. windows10未安装任何音频输出设备(1903、1909)
  11. 【测试管理】版本定义
  12. cgcs2000大地坐标系地图_CGCS2000坐标系和WGS84坐标系的区别联系
  13. 了解算法交易,此篇足矣
  14. flask的一个小项目
  15. Codeforces Round #687 (Div. 2) C. Bouncing Ball(枚举 思维)
  16. 开源代码学习之persepolis【一】
  17. SpringBoot 入门
  18. NOIP2018游记
  19. 解决Win10锁屏超1分钟,显示器关闭问题
  20. File类详解(获取文件名称、大小、路径、创建等)

热门文章

  1. python全栈学习笔记(一)网络基础之网络协议篇
  2. Android多线程断点下载
  3. 6.3 Spring Boot集成mongodb开发
  4. C#语法之匿名函数和Lambda表达式
  5. POJ 3784.Running Median
  6. QThread中的互斥、读写锁、信号量、条件变量
  7. VS2008中的“解决方案配置”和“解决方案平台”不见了(Release和Debug)的解决方法...
  8. iOS开发笔记 8、真机调试和发布软件
  9. android教程 - android ui 介绍,多图详解 “Android UI”设计官方教程
  10. ylinux系统找到软件_电脑用了段时间发现多处一些软件该怎么办?