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, void * 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 // lock LWIP core
42 LOCK_TCPIP_CORE();
43
44 // leave current IGMP group if applicable
46
47 // first, close all open connection blocks (zero CBDs won't cause trouble)
48 if (PTP_L4_EVENT != NULL) {
49 udp_disconnect(PTP_L4_EVENT);
50 udp_remove(PTP_L4_EVENT);
51 PTP_L4_EVENT = NULL;
52 }
53 if (PTP_L4_GENERAL != NULL) {
54 udp_disconnect(PTP_L4_GENERAL);
55 udp_remove(PTP_L4_GENERAL);
56 PTP_L4_GENERAL = NULL;
57 }
58
59 // calling either parameter with -1 just closes connections
60 if ((tp == -1) || (dm == -1)) {
61 // message transmission and reception is turned off
62 TP = -1;
63 DM = -1;
64 return;
65 }
66
67 // open only the necessary ones
68 if (tp == PTP_TP_IPv4) {
69 // open event and general connections
71 PTP_L4_EVENT = udp_new();
72 udp_bind(PTP_L4_EVENT, &addr, PTP_PORT_EVENT);
73 udp_recv(PTP_L4_EVENT, ptp_receive_cb, NULL);
74
75 PTP_L4_GENERAL = udp_new();
76 udp_bind(PTP_L4_GENERAL, &addr, PTP_PORT_GENERAL);
77 udp_recv(PTP_L4_GENERAL, ptp_receive_cb, NULL);
78 }
79
80 // store configuration
81 TP = tp;
82 DM = dm;
83
84 // join new IGMP group
86
87 // unlock LWIP core
88 UNLOCK_TCPIP_CORE();
89}
90
91static void ptp_receive_cb(void *pArg, struct udp_pcb *pPCB, struct pbuf *pP, const ip_addr_t *pAddr, uint16_t port) {
92 // put msg into the queue
93 ptp_receive_enqueue(pP->payload, pP->len, pP->time_s, pP->time_ns, PTP_TP_IPv4);
94
95 // release pbuf resources
96 pbuf_free(pP);
97}
98
99static void ptp_transmit_cb(uint32_t ts_s, uint32_t ts_ns, void * tag) {
100 ptp_transmit_timestamp_cb((uint32_t) tag, ts_s, ts_ns);
101}
102
103void ptp_nsd_transmit_msg(RawPtpMessage *pMsg, uint32_t uid) {
104 if (pMsg == NULL) {
105 MSG("NULL!!!\n");
106 return;
107 }
108
109 PtpMessageClass mc = pMsg->tx_mc;
110
111 // allocate buffer
112 struct pbuf *p = NULL;
113 p = pbuf_alloc((TP == PTP_TP_IPv4) ? PBUF_TRANSPORT : PBUF_LINK, pMsg->size, PBUF_RAM);
114
115 // fill buffer
116 memcpy(p->payload, pMsg->data, pMsg->size);
117
118 // set transmit callback
119 p->tag = (void *)uid;
120 p->tx_cb = ptp_transmit_cb;
121
122 // lock LWIP core
123 LOCK_TCPIP_CORE();
124
125 // narrow down by transport type
126 if (TP == PTP_TP_IPv4) {
127 struct udp_pcb *conn = (mc == PTP_MC_EVENT) ? PTP_L4_EVENT : PTP_L4_GENERAL; // select connection by message type
128 uint16_t port = (mc == PTP_MC_EVENT) ? PTP_PORT_EVENT : PTP_PORT_GENERAL; // select port by message class
129 ip_addr_t ipaddr = (DM == PTP_DM_E2E) ? PTP_IGMP_PRIMARY : PTP_IGMP_PEER_DELAY; // select destination IP-address by delmech.
130 udp_sendto(conn, p, &ipaddr, port); // send packet
131 } else if (TP == PTP_TP_802_3) {
132 const uint8_t *ethaddr = (DM == PTP_DM_E2E) ? PTP_ETHERNET_PRIMARY : PTP_ETHERNET_PEER_DELAY; // select destination address by delmech.
133 ethernet_output(netif_default, p, (struct eth_addr *)netif_default->hwaddr, (struct eth_addr *)ethaddr, ETHERTYPE_PTP);
134 }
135
136 // unlock LWIP core
137 UNLOCK_TCPIP_CORE();
138
139 pbuf_free(p); // release buffer
140}
141
142void ptp_transmit_free(struct pbuf *pPBuf) {
143 pbuf_free(pPBuf);
144}
145
147 memcpy(hwa, netif_default->hwaddr, netif_default->hwaddr_len);
148}
149
150#define ETHERNET_HEADER_LENGTH (14)
151
152// hook for L2 PTP messages
153err_t hook_unknown_ethertype(struct pbuf *pbuf, struct netif *netif) {
154 // aquire ethertype
155 uint16_t etherType = 0;
156 memcpy(&etherType, ((uint8_t *)pbuf->payload) + 12, 2);
157 etherType = FLEXPTP_ntohs(etherType);
158 if (etherType == ETHERTYPE_PTP) {
159 // verify Ethernet address
160 if (!memcmp(PTP_ETHERNET_PRIMARY, pbuf->payload, 6) || !memcmp(PTP_ETHERNET_PEER_DELAY, pbuf->payload, 6)) { //
161 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);
162 }
163 }
164
165 pbuf_free(pbuf);
166
167 return ERR_OK;
168}
void ptp_transmit_free(struct pbuf *pPBuf)
Definition: nsd_lwip.c:142
void ptp_nsd_transmit_msg(RawPtpMessage *pMsg, uint32_t uid)
Definition: nsd_lwip.c:103
err_t hook_unknown_ethertype(struct pbuf *pbuf, struct netif *netif)
Definition: nsd_lwip.c:153
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:150
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:146
static void ptp_transmit_cb(uint32_t ts_s, uint32_t ts_ns, void *tag)
Definition: nsd_lwip.c:99
static PtpTransportType TP
Definition: nsd_lwip.c:21
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:38
#define PTP_PORT_EVENT
PTP event message port.
Definition: ptp_defs.h:45
#define FLEXPTP_ntohs(a)
Definition: ptp_defs.h:234
#define PTP_PORT_GENERAL
PTP general message port.
Definition: ptp_defs.h:46
ip4_addr ip_addr_t
Definition: ptp_defs.h:30
const ip_addr_t PTP_IGMP_PEER_DELAY
Peer_Delay IGMP address.
PtpTransportType
PTP transport type enumeration.
Definition: ptp_types.h:136
@ PTP_TP_IPv4
IPv4 Transport Type.
Definition: ptp_types.h:137
@ PTP_TP_802_3
Ethernet Transport Type.
Definition: ptp_types.h:138
PtpMessageClass
Enumeration for different PTP message classes.
Definition: ptp_types.h:160
@ PTP_MC_EVENT
Event Message Class.
Definition: ptp_types.h:161
PtpDelayMechanism
PTP Delay mechanism enumeration.
Definition: ptp_types.h:144
@ PTP_DM_E2E
End-to-End Delay Mechanism.
Definition: ptp_types.h:145
@ PTP_DM_P2P
Peer-to-Peer Delay Mechanism.
Definition: ptp_types.h:146
PtpMessageClass tx_mc
transmit message class
Definition: ptp_types.h:195
uint32_t size
Packet size.
Definition: ptp_types.h:188
uint8_t data[(128)]
raw packet data
Definition: ptp_types.h:198
void ptp_receive_enqueue(const void *pPayload, uint32_t len, uint32_t ts_sec, uint32_t ts_ns, int tp)
Definition: task_ptp.c:457
void ptp_transmit_timestamp_cb(uint32_t uid, uint32_t seconds, uint32_t nanoseconds)
Definition: task_ptp.c:537