X710 received SYNC without timestamp

关于使用linuxptp 最新的4.1版本,在X710 上使用 -H 硬件时钟打戳时,linuxptp的ptp4l报

received SYNC without timestamp

出现这个是因为ptp4l收到的报文没有hwts,也就是没有硬件的时间戳;

关于这部分的排查主要是找到代码中打印这句话的位置

	if (msg_sots_missing(msg) &&
	    !(p->timestamping == TS_P2P1STEP && msg_type(msg) == PDELAY_REQ)) {
		pr_err("%s: received %s without timestamp",
		       p->log_name, msg_type_string(msg_type(msg)));
		msg_put(msg);
		return EV_NONE;
	}

其中

int msg_sots_missing(struct ptp_message *m)
{
	int type = msg_type(m);
	switch (type) {
	case SYNC:
	case DELAY_REQ:
	case PDELAY_REQ:
	case PDELAY_RESP:
		break;
	case FOLLOW_UP:
	case DELAY_RESP://从这里可以看到 FOLLOW_UP和DELAY_RESP是不用验证的
	case PDELAY_RESP_FOLLOW_UP:
	case ANNOUNCE:
	case SIGNALING:
	case MANAGEMENT:
	default:
		return 0;
	}
	return msg_sots_valid(m) ? 0 : 1;
}


static inline int msg_sots_valid(struct ptp_message *m)
{
	return !tmv_is_zero(m->hwts.ts);
}


static inline int tmv_is_zero(tmv_t x)
{
	return x.ns == 0 ? 1 : 0; //这里是说ns数是不是0,如果有硬件时戳,就不是0
}

那么这个硬件时戳是哪来的呢?

msg = msg_allocate();
//申请内存

msg->hwts.type = p->timestamping;//时戳类型,如果执行时加了-H那就是硬件时戳TS_HARDWARE

cnt = transport_recv(p->trp, fd, msg);//就收UDP包

int transport_recv(struct transport *t, int fd, struct ptp_message *msg)
{
	return t->recv(t, fd, msg, sizeof(msg->data), &msg->address, &msg->hwts);
}

static int udp_recv(struct transport *t, int fd, void *buf, int buflen,
		    struct address *addr, struct hw_timestamp *hwts)
{
	return sk_receive(fd, buf, buflen, addr, hwts, MSG_DONTWAIT);
}

int sk_receive(int fd, void *buf, int buflen,
	       struct address *addr, struct hw_timestamp *hwts, int flags)
{
...
    cnt = recvmsg(fd, &msg, flags);


...
	for (cm = CMSG_FIRSTHDR(&msg); cm != NULL; cm = CMSG_NXTHDR(&msg, cm)) {
		level = cm->cmsg_level;
		type  = cm->cmsg_type;
		if (SOL_SOCKET == level && SO_TIMESTAMPING == type) {
			if (cm->cmsg_len < sizeof(*ts) * 3) {
				pr_warning("short SO_TIMESTAMPING message");
				return -EMSGSIZE;
			}
			ts = (struct timespec *) CMSG_DATA(cm);//提取时戳信息
		}
		if (SOL_SOCKET == level && SO_TIMESTAMPNS == type) {
			if (cm->cmsg_len < sizeof(*sw)) {
				pr_warning("short SO_TIMESTAMPNS message");
				return -EMSGSIZE;
			}
			sw = (struct timespec *) CMSG_DATA(cm);
			hwts->sw = timespec_to_tmv(*sw);
		}
	}
...
	switch (hwts->type) {
	case TS_SOFTWARE:
		hwts->ts = timespec_to_tmv(ts[0]);
		break;
	case TS_HARDWARE:
	case TS_ONESTEP:
	case TS_P2P1STEP:
		hwts->ts = timespec_to_tmv(ts[2]);//给msg
		break;
	case TS_LEGACY_HW:
		hwts->ts = timespec_to_tmv(ts[1]);
		break;
	}
}

在udp_recvmsg中会调用

sock_recv_ts_and_drops

        ->__sock_recv_ts_and_drops

                ->sock_recv_timestamp

                        ->__sock_recv_timestamp

在__sock_recv_timestamp 会从skb中取shinfo中的hwtstamps

&skb_shinfo(skb)->hwtstamps

通过ktime_to_timespec_cond转换为 timespec类型

这里总共可以带出来3个时戳,因为 strcu scm_timestamping 定义了一个3个timespec类型元素的数组

1. soft类型的是 index 0 type是timestamp或者timestamps

2. hardware类型的是index 2  type是timestamping

而skb的hwtstamps是在网卡驱动中设置得,x710 是

i40e_process_skb_fields

        ->i40e_ptp_rx_hwtstamp

                ->i40e_ptp_convert_to_hwtstamp(skb_hwtstamps(skb),ns);

但i40e_process_skb_fields 调用i40e_ptp_rx_hwtstamp 的条件是从 desc中获取到tsyncvalid标识,如果网卡的filter没有识别到ptp packet那么就不会置位,i40e驱动也就不会给skb打硬时戳。

那么linuxptp4.1 有什么不同呢,和2.0对比,他们发的SYNC报文 只有一个bit的差异,就是ptp version字段

因为linuxptp 4.1 版本支持了1588-2019 , 把PTP_VERSION设置为了2.1;

但x710 本身比1588-2019早,它不能识别2.1,所以就没有正确处理linuxptp 4.1 发的ptp报文

修改linuxptp 4.1 的PTP_MINOR_VERSION 为0 可以让i40e 给skb打hwstamp,但没细研究

PTP_MINOR_VERSION在linuxptp中的影响,先暂时测试用吧

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值