tlv: Introduce the NetSync Monitor TLVs.
This patch adds support for packing and unpacking the NSM TLVs. In addition, it introduces macros to make the ntoh/htoh boilerplate easier to read. The idea is to reduce the number of monstrous muti-line assignments like: pds->grandmasterClockQuality.offsetScaledLogVariance = htons(pds->grandmasterClockQuality.offsetScaledLogVariance); Signed-off-by: Richard Cochran <richardcochran@gmail.com>master
parent
7a2013360a
commit
3a264e6eec
138
tlv.c
138
tlv.c
|
@ -25,6 +25,11 @@
|
||||||
#include "tlv.h"
|
#include "tlv.h"
|
||||||
#include "msg.h"
|
#include "msg.h"
|
||||||
|
|
||||||
|
#define HTONS(x) (x) = htons(x)
|
||||||
|
#define HTONL(x) (x) = htonl(x)
|
||||||
|
#define NTOHS(x) (x) = ntohs(x)
|
||||||
|
#define NTOHL(x) (x) = ntohl(x)
|
||||||
|
|
||||||
#define TLV_LENGTH_INVALID(tlv, type) \
|
#define TLV_LENGTH_INVALID(tlv, type) \
|
||||||
(tlv->length < sizeof(struct type) - sizeof(struct TLV))
|
(tlv->length < sizeof(struct type) - sizeof(struct TLV))
|
||||||
|
|
||||||
|
@ -56,6 +61,24 @@ static uint16_t flip16(uint16_t *p)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int64_t host2net64_unaligned(int64_t *p)
|
||||||
|
{
|
||||||
|
int64_t v;
|
||||||
|
memcpy(&v, p, sizeof(v));
|
||||||
|
v = host2net64(v);
|
||||||
|
memcpy(p, &v, sizeof(v));
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t net2host64_unaligned(int64_t *p)
|
||||||
|
{
|
||||||
|
int64_t v;
|
||||||
|
memcpy(&v, p, sizeof(v));
|
||||||
|
v = net2host64(v);
|
||||||
|
memcpy(p, &v, sizeof(v));
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
static int mgt_post_recv(struct management_tlv *m, uint16_t data_len,
|
static int mgt_post_recv(struct management_tlv *m, uint16_t data_len,
|
||||||
struct tlv_extra *extra)
|
struct tlv_extra *extra)
|
||||||
{
|
{
|
||||||
|
@ -371,6 +394,111 @@ static void mgt_pre_send(struct management_tlv *m, struct tlv_extra *extra)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nsm_resp_post_recv(struct tlv_extra *extra)
|
||||||
|
{
|
||||||
|
struct nsm_resp_tlv_head *head;
|
||||||
|
struct TLV *tlv = extra->tlv;
|
||||||
|
struct timePropertiesDS *tp;
|
||||||
|
struct PortAddress *paddr;
|
||||||
|
struct currentDS *cds;
|
||||||
|
struct parentDS *pds;
|
||||||
|
unsigned char *ptr;
|
||||||
|
uint16_t expected;
|
||||||
|
|
||||||
|
if (tlv->length < sizeof(*head) + sizeof(*extra->foot)
|
||||||
|
- sizeof(head->type) - sizeof(head->length)) {
|
||||||
|
return -EBADMSG;
|
||||||
|
}
|
||||||
|
head = (struct nsm_resp_tlv_head *) tlv;
|
||||||
|
paddr = &head->parent_addr;
|
||||||
|
NTOHS(paddr->networkProtocol);
|
||||||
|
NTOHS(paddr->addressLength);
|
||||||
|
|
||||||
|
switch (paddr->networkProtocol) {
|
||||||
|
case TRANS_UDP_IPV4:
|
||||||
|
expected = 4;
|
||||||
|
break;
|
||||||
|
case TRANS_UDP_IPV6:
|
||||||
|
expected = 16;
|
||||||
|
break;
|
||||||
|
case TRANS_IEEE_802_3:
|
||||||
|
expected = 6;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EBADMSG;
|
||||||
|
}
|
||||||
|
if (paddr->addressLength != expected) {
|
||||||
|
return -EBADMSG;
|
||||||
|
}
|
||||||
|
if (tlv->length != sizeof(*head) + sizeof(*extra->foot) +
|
||||||
|
paddr->addressLength - sizeof(head->type) - sizeof(head->length)) {
|
||||||
|
return -EBADMSG;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = (unsigned char *) tlv;
|
||||||
|
ptr += sizeof(*head) + paddr->addressLength;
|
||||||
|
extra->foot = (struct nsm_resp_tlv_foot *) ptr;
|
||||||
|
|
||||||
|
pds = &extra->foot->parent;
|
||||||
|
cds = &extra->foot->current;
|
||||||
|
tp = &extra->foot->timeprop;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point the alignment only 2 bytes worst case.
|
||||||
|
* So we need to be careful with the 64 bit words.
|
||||||
|
*/
|
||||||
|
NTOHS(pds->parentPortIdentity.portNumber);
|
||||||
|
NTOHS(pds->observedParentOffsetScaledLogVariance);
|
||||||
|
NTOHL(pds->observedParentClockPhaseChangeRate);
|
||||||
|
NTOHS(pds->grandmasterClockQuality.offsetScaledLogVariance);
|
||||||
|
|
||||||
|
NTOHS(cds->stepsRemoved);
|
||||||
|
net2host64_unaligned(&cds->offsetFromMaster);
|
||||||
|
net2host64_unaligned(&cds->meanPathDelay);
|
||||||
|
|
||||||
|
NTOHS(tp->currentUtcOffset);
|
||||||
|
|
||||||
|
NTOHL(extra->foot->lastsync.seconds_lsb);
|
||||||
|
NTOHS(extra->foot->lastsync.seconds_msb);
|
||||||
|
NTOHL(extra->foot->lastsync.nanoseconds);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nsm_resp_pre_send(struct tlv_extra *extra)
|
||||||
|
{
|
||||||
|
struct nsm_resp_tlv_head *head;
|
||||||
|
struct timePropertiesDS *tp;
|
||||||
|
struct PortAddress *paddr;
|
||||||
|
struct currentDS *cds;
|
||||||
|
struct parentDS *pds;
|
||||||
|
|
||||||
|
head = (struct nsm_resp_tlv_head *) extra->tlv;
|
||||||
|
paddr = &head->parent_addr;
|
||||||
|
|
||||||
|
pds = &extra->foot->parent;
|
||||||
|
cds = &extra->foot->current;
|
||||||
|
tp = &extra->foot->timeprop;
|
||||||
|
|
||||||
|
NTOHS(paddr->networkProtocol);
|
||||||
|
NTOHS(paddr->addressLength);
|
||||||
|
|
||||||
|
HTONS(pds->parentPortIdentity.portNumber);
|
||||||
|
HTONS(pds->observedParentOffsetScaledLogVariance);
|
||||||
|
HTONL(pds->observedParentClockPhaseChangeRate);
|
||||||
|
HTONS(pds->grandmasterClockQuality.offsetScaledLogVariance);
|
||||||
|
|
||||||
|
HTONS(cds->stepsRemoved);
|
||||||
|
host2net64_unaligned(&cds->offsetFromMaster);
|
||||||
|
host2net64_unaligned(&cds->meanPathDelay);
|
||||||
|
|
||||||
|
HTONS(tp->currentUtcOffset);
|
||||||
|
|
||||||
|
HTONL(extra->foot->lastsync.seconds_lsb);
|
||||||
|
HTONS(extra->foot->lastsync.seconds_msb);
|
||||||
|
HTONL(extra->foot->lastsync.nanoseconds);
|
||||||
|
}
|
||||||
|
|
||||||
static int org_post_recv(struct organization_tlv *org)
|
static int org_post_recv(struct organization_tlv *org)
|
||||||
{
|
{
|
||||||
struct follow_up_info_tlv *f;
|
struct follow_up_info_tlv *f;
|
||||||
|
@ -489,6 +617,11 @@ int tlv_post_recv(struct tlv_extra *extra)
|
||||||
case TLV_AUTHENTICATION_CHALLENGE:
|
case TLV_AUTHENTICATION_CHALLENGE:
|
||||||
case TLV_SECURITY_ASSOCIATION_UPDATE:
|
case TLV_SECURITY_ASSOCIATION_UPDATE:
|
||||||
case TLV_CUM_FREQ_SCALE_FACTOR_OFFSET:
|
case TLV_CUM_FREQ_SCALE_FACTOR_OFFSET:
|
||||||
|
case TLV_PTPMON_REQ:
|
||||||
|
break;
|
||||||
|
case TLV_PTPMON_RESP:
|
||||||
|
result = nsm_resp_post_recv(extra);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -527,6 +660,11 @@ void tlv_pre_send(struct TLV *tlv, struct tlv_extra *extra)
|
||||||
case TLV_AUTHENTICATION_CHALLENGE:
|
case TLV_AUTHENTICATION_CHALLENGE:
|
||||||
case TLV_SECURITY_ASSOCIATION_UPDATE:
|
case TLV_SECURITY_ASSOCIATION_UPDATE:
|
||||||
case TLV_CUM_FREQ_SCALE_FACTOR_OFFSET:
|
case TLV_CUM_FREQ_SCALE_FACTOR_OFFSET:
|
||||||
|
case TLV_PTPMON_REQ:
|
||||||
|
break;
|
||||||
|
case TLV_PTPMON_RESP:
|
||||||
|
nsm_resp_pre_send(extra);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
18
tlv.h
18
tlv.h
|
@ -39,6 +39,8 @@
|
||||||
#define TLV_AUTHENTICATION_CHALLENGE 0x2001
|
#define TLV_AUTHENTICATION_CHALLENGE 0x2001
|
||||||
#define TLV_SECURITY_ASSOCIATION_UPDATE 0x2002
|
#define TLV_SECURITY_ASSOCIATION_UPDATE 0x2002
|
||||||
#define TLV_CUM_FREQ_SCALE_FACTOR_OFFSET 0x2003
|
#define TLV_CUM_FREQ_SCALE_FACTOR_OFFSET 0x2003
|
||||||
|
#define TLV_PTPMON_REQ 0x21FE
|
||||||
|
#define TLV_PTPMON_RESP 0x21FF
|
||||||
|
|
||||||
enum management_action {
|
enum management_action {
|
||||||
GET,
|
GET,
|
||||||
|
@ -134,6 +136,21 @@ struct management_error_status {
|
||||||
Octet data[0];
|
Octet data[0];
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
|
struct nsm_resp_tlv_head {
|
||||||
|
Enumeration16 type;
|
||||||
|
UInteger16 length;
|
||||||
|
uint8_t port_state;
|
||||||
|
uint8_t reserved;
|
||||||
|
struct PortAddress parent_addr;
|
||||||
|
} PACKED;
|
||||||
|
|
||||||
|
struct nsm_resp_tlv_foot {
|
||||||
|
struct parentDS parent;
|
||||||
|
struct currentDS current;
|
||||||
|
struct timePropertiesDS timeprop;
|
||||||
|
struct Timestamp lastsync;
|
||||||
|
} PACKED;
|
||||||
|
|
||||||
/* Organizationally Unique Identifiers */
|
/* Organizationally Unique Identifiers */
|
||||||
#define IEEE_802_1_COMMITTEE 0x00, 0x80, 0xC2
|
#define IEEE_802_1_COMMITTEE 0x00, 0x80, 0xC2
|
||||||
extern uint8_t ieee8021_id[3];
|
extern uint8_t ieee8021_id[3];
|
||||||
|
@ -234,6 +251,7 @@ struct tlv_extra {
|
||||||
struct TLV *tlv;
|
struct TLV *tlv;
|
||||||
union {
|
union {
|
||||||
struct mgmt_clock_description cd;
|
struct mgmt_clock_description cd;
|
||||||
|
struct nsm_resp_tlv_foot *foot;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue