Skip to content

Commit 590d9d1

Browse files
yangbolu1991nashif
authored andcommitted
net: dsa: support PTP timestamping in netc tag driver
Supported PTP timestamping in netc tag driver. Signed-off-by: Yangbo Lu <[email protected]>
1 parent 15dc8d7 commit 590d9d1

File tree

4 files changed

+108
-30
lines changed

4 files changed

+108
-30
lines changed

include/zephyr/net/dsa_tag_netc.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
#ifndef ZEPHYR_SUBSYS_DSA_TAG_NETC_H_
77
#define ZEPHYR_SUBSYS_DSA_TAG_NETC_H_
88

9+
struct dsa_tag_netc_data {
10+
#ifdef CONFIG_NET_L2_PTP
11+
void (*twostep_timestamp_handler)(const struct dsa_switch_context *ctx,
12+
uint8_t ts_req_id, uint64_t ts);
13+
#endif
14+
};
15+
916
struct net_if *dsa_tag_netc_recv(struct net_if *iface, struct net_pkt *pkt);
1017
struct net_pkt *dsa_tag_netc_xmit(struct net_if *iface, struct net_pkt *pkt);
1118
#endif /* ZEPHYR_SUBSYS_DSA_TAG_NETC_H_ */

subsys/net/ip/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,7 @@ config NET_PKT_CONTROL_BLOCK
763763
config NET_PKT_CONTROL_BLOCK_SIZE
764764
int "Size of pkt control block in bytes"
765765
depends on NET_PKT_CONTROL_BLOCK
766+
default 1 if DSA_TAG_PROTOCOL_NETC
766767
default 1
767768
help
768769
Size of pkt control block in bytes if there are no other specific control blocks

subsys/net/l2/ethernet/dsa/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ config DSA_TAG_SIZE
3939
config DSA_TAG_PROTOCOL_NETC
4040
bool "Tag protocol - NETC"
4141
default y
42+
select NET_PKT_CONTROL_BLOCK
4243
depends on $(dt_compat_any_has_prop,$(DSA_PORT_COMPAT),dsa-tag-protocol,1)
4344
help
4445
NXP NETC tag protocol.

subsys/net/l2/ethernet/dsa/dsa_tag_netc.c

Lines changed: 99 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,82 @@ LOG_MODULE_REGISTER(net_dsa_tag_netc, CONFIG_NET_DSA_LOG_LEVEL);
1212
#include <zephyr/net/dsa_tag_netc.h>
1313
#include "fsl_netc_tag.h"
1414

15-
/* tag is inserted after DMAC/SMAC fields */
16-
struct dsa_tag_netc_to_host_header {
17-
uint8_t dmac[NET_ETH_ADDR_LEN];
18-
uint8_t smac[NET_ETH_ADDR_LEN];
19-
netc_swt_tag_host_t tag;
20-
};
21-
22-
struct dsa_tag_netc_to_port_header {
23-
uint8_t dmac[NET_ETH_ADDR_LEN];
24-
uint8_t smac[NET_ETH_ADDR_LEN];
25-
netc_swt_tag_port_no_ts_t tag;
26-
};
27-
2815
struct net_if *dsa_tag_netc_recv(struct net_if *iface, struct net_pkt *pkt)
2916
{
3017
struct ethernet_context *eth_ctx = net_if_l2_data(iface);
31-
struct dsa_switch_context *dsa_switch_ctx = eth_ctx->dsa_switch_ctx;
32-
uint16_t header_len = sizeof(struct dsa_tag_netc_to_host_header);
33-
struct dsa_tag_netc_to_host_header *header;
18+
const struct dsa_switch_context *dsa_switch_ctx = eth_ctx->dsa_switch_ctx;
19+
#ifdef CONFIG_NET_L2_PTP
20+
struct dsa_tag_netc_data *tagger_data =
21+
(struct dsa_tag_netc_data *)(dsa_switch_ctx->tagger_data);
22+
#endif
23+
void *header = pkt->frags->data;
24+
uint16_t tag_len = sizeof(netc_swt_tag_host_t);
25+
netc_swt_tag_common_t *tag_common;
3426
struct net_if *iface_dst = iface;
3527
uint8_t *ptr;
3628

37-
if (pkt->frags->len < header_len) {
29+
/* Tag is inserted after DMAC/SMAC fields. Check the smallest tag type header size. */
30+
if (pkt->frags->len < NET_ETH_ADDR_LEN * 2 + tag_len) {
3831
LOG_ERR("tag len error");
3932
return iface_dst;
4033
}
4134

35+
/* Handle tag type */
36+
tag_common = (netc_swt_tag_common_t *)((uintptr_t)pkt->frags->data + NET_ETH_ADDR_LEN * 2);
37+
if (tag_common->type == kNETC_TagForward) {
38+
39+
/* Update tag length per tag type */
40+
tag_len = sizeof(netc_swt_tag_forward_t);
41+
42+
} else if (tag_common->type == kNETC_TagToHost) {
43+
#ifdef CONFIG_NET_L2_PTP
44+
netc_swt_tag_host_rx_ts_t *tag_rx_ts;
45+
netc_swt_tag_host_tx_ts_t *tag_tx_ts;
46+
uint64_t ts;
47+
#endif
48+
/* Handle tag sub-type */
49+
switch (tag_common->subType) {
50+
case kNETC_TagToHostNoTs:
51+
/* Normal case */
52+
break;
53+
case kNETC_TagToHostRxTs:
54+
#ifdef CONFIG_NET_L2_PTP
55+
tag_rx_ts = (netc_swt_tag_host_rx_ts_t *)tag_common;
56+
ts = ntohll(tag_rx_ts->timestamp);
57+
58+
/* Fill timestamp */
59+
pkt->timestamp.nanosecond = ts % NSEC_PER_SEC;
60+
pkt->timestamp.second = ts / NSEC_PER_SEC;
61+
#endif
62+
/* Update tag length per tag type */
63+
tag_len = sizeof(netc_swt_tag_host_rx_ts_t);
64+
break;
65+
case kNETC_TagToHostTxTs:
66+
#ifdef CONFIG_NET_L2_PTP
67+
tag_tx_ts = (netc_swt_tag_host_tx_ts_t *)tag_common;
68+
ts = ntohll(tag_tx_ts->timestamp);
69+
70+
if (tagger_data->twostep_timestamp_handler != NULL) {
71+
tagger_data->twostep_timestamp_handler(dsa_switch_ctx,
72+
tag_tx_ts->tsReqId, ts);
73+
}
74+
#endif
75+
/* Update tag length per tag type */
76+
tag_len = sizeof(netc_swt_tag_host_tx_ts_t);
77+
break;
78+
default:
79+
LOG_ERR("tag sub-type error");
80+
break;
81+
}
82+
} else {
83+
LOG_ERR("tag type error");
84+
}
85+
4286
/* redirect to user port */
43-
header = (struct dsa_tag_netc_to_host_header *)pkt->frags->data;
44-
iface_dst = dsa_switch_ctx->iface_user[header->tag.comTag.port];
87+
iface_dst = dsa_switch_ctx->iface_user[tag_common->port];
4588

4689
/* drop tag */
47-
ptr = net_buf_pull(pkt->frags, sizeof(netc_swt_tag_host_t));
90+
ptr = net_buf_pull(pkt->frags, tag_len);
4891
for (int i = 0; i < (NET_ETH_ADDR_LEN * 2); i++) {
4992
ptr[i] = *(uint8_t *)((uintptr_t)header + i);
5093
}
@@ -56,27 +99,53 @@ struct net_pkt *dsa_tag_netc_xmit(struct net_if *iface, struct net_pkt *pkt)
5699
{
57100
const struct device *dev = net_if_get_device(iface);
58101
struct dsa_port_config *cfg = (struct dsa_port_config *)dev->config;
59-
struct dsa_tag_netc_to_port_header *header;
60102
struct net_buf *header_buf;
103+
size_t header_len = NET_ETH_ADDR_LEN * 2;
104+
netc_swt_tag_common_t *tag_common;
105+
void *tag;
106+
107+
/* Tag is inserted after DMAC/SMAC fields. Decide header size per tag type. */
108+
if (ntohs(NET_ETH_HDR(pkt)->type) == NET_ETH_PTYPE_PTP) {
109+
header_len += sizeof(netc_swt_tag_port_two_step_ts_t);
110+
} else {
111+
header_len += sizeof(netc_swt_tag_port_no_ts_t);
112+
}
61113

62114
/* Allocate net_buf for header */
63115
header_buf = net_buf_alloc_len(net_buf_pool_get(pkt->buffer->pool_id),
64-
sizeof(*header), K_NO_WAIT);
116+
header_len, K_NO_WAIT);
65117
if (!header_buf) {
66118
LOG_ERR("Cannot allocate header buffer");
67119
return NULL;
68120
}
69121

70-
header_buf->len = sizeof(*header);
122+
header_buf->len = header_len;
71123

72124
/* Fill the header */
73-
header = (struct dsa_tag_netc_to_port_header *)header_buf->data;
74-
memcpy(header, pkt->frags->data, NET_ETH_ADDR_LEN * 2);
75-
header->tag.comTag.tpid = NETC_SWITCH_DEFAULT_ETHER_TYPE;
76-
header->tag.comTag.subType = kNETC_TagToPortNoTs;
77-
header->tag.comTag.type = kNETC_TagToPort;
78-
header->tag.comTag.swtId = 1;
79-
header->tag.comTag.port = cfg->port_idx;
125+
memcpy(header_buf->data, pkt->frags->data, NET_ETH_ADDR_LEN * 2);
126+
tag = (void *)((uintptr_t)header_buf->data + NET_ETH_ADDR_LEN * 2);
127+
128+
#ifdef CONFIG_NET_L2_PTP
129+
/* Enable two-step timestamping for gPTP. */
130+
if (ntohs(NET_ETH_HDR(pkt)->type) == NET_ETH_PTYPE_PTP) {
131+
132+
/* Utilize control block for timestamp request ID */
133+
((netc_swt_tag_port_two_step_ts_t *)tag)->tsReqId = pkt->cb.cb[0] & 0xf;
134+
135+
tag_common = &((netc_swt_tag_port_two_step_ts_t *)tag)->comTag;
136+
tag_common->subType = kNETC_TagToPortTwoStepTs;
137+
} else {
138+
tag_common = &((netc_swt_tag_port_no_ts_t *)tag)->comTag;
139+
tag_common->subType = kNETC_TagToPortNoTs;
140+
}
141+
#else
142+
tag_common = &((netc_swt_tag_port_no_ts_t *)tag)->comTag;
143+
tag_common->subType = kNETC_TagToPortNoTs;
144+
#endif
145+
tag_common->tpid = NETC_SWITCH_DEFAULT_ETHER_TYPE;
146+
tag_common->type = kNETC_TagToPort;
147+
tag_common->swtId = 1;
148+
tag_common->port = cfg->port_idx;
80149

81150
/* Drop DMAC/SMAC on original frag */
82151
net_buf_pull(pkt->frags, NET_ETH_ADDR_LEN * 2);

0 commit comments

Comments
 (0)