flexPTP 1.0
An IEEE 1588 PTP implementation designed for microcontrollers
Loading...
Searching...
No Matches
nsd_lwip.c
Go to the documentation of this file.
1#include "../../network_stack_driver.h"
2
3#include "../../ptp_defs.h"
4#include "../../task_ptp.h"
5
6#include "lwip/err.h"
7#include "lwip/igmp.h"
8#include "lwip/ip4_addr.h"
9#include "lwip/ip_addr.h"
10#include "lwip/netif.h"
11#include "lwip/udp.h"
12#include "netif/ethernet.h"
13
14#include <string.h>
15
16// initialize connection blocks to invalid states
17static struct udp_pcb *PTP_L4_EVENT = NULL;
18static struct udp_pcb *PTP_L4_GENERAL = NULL;
19
20// store current settings
21static PtpTransportType TP = -1;
23
24static void ptp_transmit_cb(uint32_t ts_s, uint32_t ts_ns, uint32_t tag);
25static void ptp_receive_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
26
27void ptp_nsd_igmp_join_leave(bool join) {
28 // only join IGMP if Transport Type is IP
29 if (TP == PTP_TP_IPv4) {
30 err_t (*igmp_fn)(const ip_addr_t *, const ip_addr_t *) = join ? igmp_joingroup : igmp_leavegroup; // join or leave
31
32 if (DM == PTP_DM_E2E) {
33 igmp_fn(&netif_default->ip_addr, &PTP_IGMP_PRIMARY); // join E2E DM message group
34 } else if (DM == PTP_DM_P2P) {
35 igmp_fn(&netif_default->ip_addr, &PTP_IGMP_PEER_DELAY); // join P2P DM message group
36 }
37 }
38}
39
41 // leave current IGMP group if applicable
43
44 // first, close all open connection blocks (zero CBDs won't cause trouble)
45 if (PTP_L4_EVENT != NULL) {
46 udp_disconnect(PTP_L4_EVENT);
47 udp_remove(PTP_L4_EVENT);
48 PTP_L4_EVENT = NULL;
49 }
50 if (PTP_L4_GENERAL != NULL) {
51 udp_disconnect(PTP_L4_GENERAL);
52 udp_remove(PTP_L4_GENERAL);
53 PTP_L4_GENERAL = NULL;
54 }
55
56 // calling either parameter with -1 just closes connections
57 if ((tp == -1) || (dm == -1)) {
58 // message transmission and reception is turned off
59 TP = -1;
60 DM = -1;
61 return;
62 }
63
64 // open only the necessary ones
65 if (tp == PTP_TP_IPv4) {
66 // open event and general connections
68 PTP_L4_EVENT = udp_new();
69 udp_bind(PTP_L4_EVENT, &addr, PTP_PORT_EVENT);
70 udp_recv(PTP_L4_EVENT, ptp_receive_cb, NULL);
71
72 PTP_L4_GENERAL = udp_new();
73 udp_bind(PTP_L4_GENERAL, &addr, PTP_PORT_GENERAL);
74 udp_recv(PTP_L4_GENERAL, ptp_receive_cb, NULL);
75 }
76
77 // store configuration
78 TP = tp;
79 DM = dm;
80
81 // join new IGMP group
83}
84
85static void ptp_receive_cb(void *pArg, struct udp_pcb *pPCB, struct pbuf *pP, const ip_addr_t *pAddr, uint16_t port) {
86 // put msg into the queue
87 ptp_receive_enqueue(pP->payload, pP->len, pP->time_s, pP->time_ns, PTP_TP_IPv4);
88
89 // release pbuf resources
90 pbuf_free(pP);
91}
92
93static void ptp_transmit_cb(uint32_t ts_s, uint32_t ts_ns, uint32_t tag) {
94 RawPtpMessage *pMsg = (RawPtpMessage *)(tag);
95 pMsg->ts.sec = ts_s;
96 pMsg->ts.nanosec = ts_ns;
97
98 // MSG("%u.%09u\n", ts_s, ts_ns);
99
100 if (pMsg->pTs != NULL) {
101 pMsg->pTs->sec = ts_s;
102 pMsg->pTs->nanosec = ts_ns;
103 }
104
105 if (pMsg->pTxCb) {
106 pMsg->pTxCb(pMsg);
107 }
108
110}
111
113 if (pMsg == NULL) {
114 MSG("NULL!!!\n");
115 return;
116 }
117
118 PtpMessageClass mc = pMsg->tx_mc;
119
120 // allocate buffer
121 struct pbuf *p = NULL;
122 p = pbuf_alloc((TP == PTP_TP_IPv4) ? PBUF_TRANSPORT : PBUF_LINK, pMsg->size, PBUF_RAM);
123
124 // fill buffer
125 memcpy(p->payload, pMsg->data, pMsg->size);
126
127 // set transmit callback
128 p->tag = pMsg;
129 p->tx_cb = ptp_transmit_cb;
130
131 // narrow down by transport type
132 if (TP == PTP_TP_IPv4) {
133 struct udp_pcb *conn = (mc == PTP_MC_EVENT) ? PTP_L4_EVENT : PTP_L4_GENERAL; // select connection by message type
134 uint16_t port = (mc == PTP_MC_EVENT) ? PTP_PORT_EVENT : PTP_PORT_GENERAL; // select port by message class
135 ip_addr_t ipaddr = (DM == PTP_DM_E2E) ? PTP_IGMP_PRIMARY : PTP_IGMP_PEER_DELAY; // select destination IP-address by delmech.
136 udp_sendto(conn, p, &ipaddr, port); // send packet
137 } else if (TP == PTP_TP_802_3) {
138 const uint8_t *ethaddr = (DM == PTP_DM_E2E) ? PTP_ETHERNET_PRIMARY : PTP_ETHERNET_PEER_DELAY; // select destination address by delmech.
139 ethernet_output(netif_default, p, (struct eth_addr *)netif_default->hwaddr, (struct eth_addr *)ethaddr, ETHERTYPE_PTP);
140 }
141
142 pbuf_free(p); // release buffer
143}
144
145void ptp_transmit_free(struct pbuf *pPBuf) {
146 pbuf_free(pPBuf);
147}
148
150 memcpy(hwa, netif_default->hwaddr, netif_default->hwaddr_len);
151}
152
153#define ETHERNET_HEADER_LENGTH (14)
154
155// hook for L2 PTP messages
156err_t hook_unknown_ethertype(struct pbuf *pbuf, struct netif *netif) {
157 // aquire ethertype
158 uint16_t etherType = 0;
159 memcpy(&etherType, ((uint8_t *)pbuf->payload) + 12, 2);
160 etherType = FLEXPTP_ntohs(etherType);
161 if (etherType == ETHERTYPE_PTP) {
162 // verify Ethernet address
163 if (!memcmp(PTP_ETHERNET_PRIMARY, pbuf->payload, 6) || !memcmp(PTP_ETHERNET_PEER_DELAY, pbuf->payload, 6)) { //
164 ptp_receive_enqueue(((uint8_t *)pbuf->payload) + ETHERNET_HEADER_LENGTH, pbuf->len - ETHERNET_HEADER_LENGTH, pbuf->time_s, pbuf->time_ns, PTP_TP_802_3);
165 }
166 }
167
168 pbuf_free(pbuf);
169
170 return ERR_OK;
171}
PtpCircBuf gRawTxMsgBuf
Output circular buffers.
void ptp_nsd_transmit_msg(RawPtpMessage *pMsg)
Definition: nsd_lwip.c:112
void ptp_transmit_free(struct pbuf *pPBuf)
Definition: nsd_lwip.c:145
err_t hook_unknown_ethertype(struct pbuf *pbuf, struct netif *netif)
Definition: nsd_lwip.c:156
static PtpDelayMechanism DM
Definition: nsd_lwip.c:22
void ptp_nsd_igmp_join_leave(bool join)
Definition: nsd_lwip.c:27
void ptp_nsd_init(PtpTransportType tp, PtpDelayMechanism dm)
Definition: nsd_lwip.c:40
static struct udp_pcb * PTP_L4_GENERAL
Definition: nsd_lwip.c:18
#define ETHERNET_HEADER_LENGTH
Definition: nsd_lwip.c:153
static void ptp_receive_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
void ptp_nsd_get_interface_address(uint8_t *hwa)
Definition: nsd_lwip.c:149
static PtpTransportType TP
Definition: nsd_lwip.c:21
static void ptp_transmit_cb(uint32_t ts_s, uint32_t ts_ns, uint32_t tag)
Definition: nsd_lwip.c:93
static struct udp_pcb * PTP_L4_EVENT
Definition: nsd_lwip.c:17
const uint8_t PTP_ETHERNET_PEER_DELAY[6]
PTP's L2 Peer_Delay Ethernet address.
Definition: ptp_defs.c:4
const uint8_t PTP_ETHERNET_PRIMARY[6]
PTP's L2 Primary Ethernet address.
Definition: ptp_defs.c:3
const ip_addr_t PTP_IGMP_PRIMARY
Primary IGMP address.
#define ETHERTYPE_PTP
(for lwIP conformity)
Definition: ptp_defs.h:30
#define PTP_PORT_EVENT
PTP event message port.
Definition: ptp_defs.h:37
#define FLEXPTP_ntohs(a)
Definition: ptp_defs.h:175
#define PTP_PORT_GENERAL
PTP general message port.
Definition: ptp_defs.h:38
ip4_addr ip_addr_t
Definition: ptp_defs.h:22
const ip_addr_t PTP_IGMP_PEER_DELAY
Peer_Delay IGMP address.
void ptp_circ_buf_free(PtpCircBuf *pCircBuf)
PtpTransportType
PTP transport type enumeration.
Definition: ptp_types.h:128
@ PTP_TP_IPv4
IPv4 Transport Type.
Definition: ptp_types.h:129
@ PTP_TP_802_3
Ethernet Transport Type.
Definition: ptp_types.h:130
PtpMessageClass
Enumeration for different PTP message classes.
Definition: ptp_types.h:152
@ PTP_MC_EVENT
Event Message Class.
Definition: ptp_types.h:153
PtpDelayMechanism
PTP Delay mechanism enumeration.
Definition: ptp_types.h:136
@ PTP_DM_E2E
End-to-End Delay Mechanism.
Definition: ptp_types.h:137
@ PTP_DM_P2P
Peer-to-Peer Delay Mechanism.
Definition: ptp_types.h:138
Raw PTP message structure.
Definition: ptp_types.h:162
TimestampI ts
Timestamp.
Definition: ptp_types.h:163
PtpMessageClass tx_mc
transmit message class
Definition: ptp_types.h:170
void(* pTxCb)(const struct RawPtpMessage_ *pMsg)
transmit callback function
Definition: ptp_types.h:168
uint32_t size
Packet size.
Definition: ptp_types.h:164
TimestampI * pTs
pointer to timestamp
Definition: ptp_types.h:167
uint8_t data[(128)]
raw packet data
Definition: ptp_types.h:173
int32_t nanosec
nanoseconds
Definition: timeutils.h:31
int64_t sec
seconds
Definition: timeutils.h:30
void ptp_receive_enqueue(const void *pPayload, uint32_t len, uint32_t ts_sec, uint32_t ts_ns, int tp)
Definition: task_ptp.c:141