summaryrefslogtreecommitdiff
path: root/bsp/hpmicro/libraries/misc/lwip_ptp/lwip_ptp_tx_ts.h
blob: 73bc5301114118ebb841cbfa0262ac8c62037a11 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/*
 * Copyright (c) 2026 HPMicro
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef LWIP_PTP_TX_TS_H
#define LWIP_PTP_TX_TS_H

#include <stdbool.h>
#include "lwip/def.h"
#include "lwip/pbuf.h"
#include "lwip/prot/ethernet.h"
#include "lwip/prot/ip.h"
#include "lwip/prot/ip4.h"
#include "lwip/prot/udp.h"

/**
 * @brief True if this Ethernet frame should use ENET TX descriptor TTSE and HW timestamp
 * PTPd sends messages that need precise egress time on UDP event port 319 only.
 * General port 320 (Announce, Follow_Up, Delay_Resp, etc.) does not use TX HW stamp.
 */
static inline bool lwip_ptp_frame_needs_tx_hw_timestamp(const struct pbuf *p)
{
    u8_t hdr[SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR + IP_HLEN + sizeof(struct udp_hdr)];
    u16_t ethertype;
    u16_t ip_off;
    const struct ip_hdr *iph;
    u16_t ip_len;
    const struct udp_hdr *udph;

    if (p == NULL || p->tot_len < (s16_t)(SIZEOF_ETH_HDR + IP_HLEN + UDP_HLEN)) {
        return false;
    }
    if (pbuf_copy_partial(p, hdr, (u16_t)sizeof(hdr), 0) != (u16_t)sizeof(hdr)) {
        return false;
    }
    ethertype = lwip_ntohs(*(u16_t *)(hdr + 12U));
    ip_off = SIZEOF_ETH_HDR;
    if (ethertype == ETHTYPE_VLAN) {
        if (p->tot_len < (s16_t)(SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR + IP_HLEN + UDP_HLEN)) {
            return false;
        }
        ethertype = lwip_ntohs(*(u16_t *)(hdr + (SIZEOF_ETH_HDR + 2U)));
        ip_off = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR;
    }
    if (ethertype != ETHTYPE_IP) {
        return false;
    }
    iph = (const struct ip_hdr *)(hdr + ip_off);
    if (IPH_HL(iph) != 5) {
        return false;
    }
    if (IPH_PROTO(iph) != IP_PROTO_UDP) {
        return false;
    }
    ip_len = IP_HLEN;
    if ((u32_t)ip_off + (u32_t)ip_len + UDP_HLEN > sizeof(hdr)) {
        return false;
    }
    udph = (const struct udp_hdr *)(hdr + ip_off + ip_len);
    return udph->dest == PP_HTONS(319);
}

#endif /* LWIP_PTP_TX_TS_H */