| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690 |
- /*!
- * Copyright (C) Fraunhofer-Institut for Photonic Microsystems (IPMS)
- * Maria-Reiche-Str. 2
- * 01109 Dresden
- *
- * Unauthorized copying of this file, via any medium is strictly prohibited
- * Proprietary and confidential
- *
- * \file tsn_ptp.c
- * \author zimmerli
- * \date 2019-01-14
- * \brief IEEE 802.1as SW-Implementation, low-level
- *
- */
- #include "tsn_ptp.h"
- // Macros
- // swap endianess
- #define SWAP16(value) (((value & 0xFF) << 8 | (value >> 8)) & 0xFFFF)
- // access memory
- #define MEM8(addr) (*(uint8_t *)(addr))
- #define NS_PER_SEC 1000000000
- // ----------------------------------------------------------------
- // inline functions
- // 32 bit memory access and network to host order conversion
- static inline uint32_t mem32_ntohl(uintptr_t addr)
- {
- uint32_t tmp;
- uint8_t *ptr;
- ptr = (uint8_t *)addr;
- tmp = ptr[0];
- tmp = (tmp << 8) | ptr[1];
- tmp = (tmp << 8) | ptr[2];
- tmp = (tmp << 8) | ptr[3];
- return tmp;
- }
- // 32 bit memory access and host to network order conversion
- static inline void mem32_htonl(uintptr_t addr, uint32_t value)
- {
- uint8_t *ptr;
- ptr = (uint8_t *)addr;
- ptr[0] = (value >> 24) & 0xFF;
- ptr[1] = (value >> 16) & 0xFF;
- ptr[2] = (value >> 8) & 0xFF;
- ptr[3] = (value) & 0xFF;
- }
- // 16 bit memory access and network to host order conversion
- static inline uint16_t mem16_ntohs(uintptr_t addr)
- {
- uint16_t tmp;
- uint8_t *ptr;
- ptr = (uint8_t *)addr;
- tmp = ptr[0] << 8;
- tmp |= ptr[1];
- return tmp;
- }
- // 16 bit memory access and host to network order conversion
- static inline void mem16_htons(uintptr_t addr, uint16_t value)
- {
- uint8_t *ptr;
- ptr = (uint8_t *)addr;
- ptr[0] = (value >> 8) & 0xFF;
- ptr[1] = (value) & 0xFF;
- }
- // ----------------------------------------------------------------
- /**
- * Destination MAC address used by all PTP communication
- */
- const uint8_t tsn_ptp_macaddr[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x0E };
- // ----------------------------------------------------------------
- uint32_t tsn_ptp_set_eth_header(uintptr_t dstaddr, uint8_t *pMacAddr)
- {
- uint8_t *pu8;
- uint32_t idx;
- // point pu8 to dstaddr
- pu8 = (uint8_t *)dstaddr;
- // dst addr
- for (idx = 0; idx < 6; ++idx) {
- pu8[idx] = tsn_ptp_macaddr[idx];
- }
- // src addr
- for (idx = 0; idx < 6; ++idx) {
- pu8[6 + idx] = pMacAddr[idx];
- }
- // eth type (MSB first)
- pu8[12] = ETH_TYPE_PTP >> 8;
- pu8[13] = ETH_TYPE_PTP & 0xFF;
- return 14;
- }
- uint32_t tsn_ptp_set_ptp_header(uintptr_t dstaddr, struct ptp_header_s *pPtp)
- {
- uint32_t ofs;
- uint32_t idx;
- uint8_t *pSrc;
- // start at dstaddr
- ofs = 0;
- // set header
- MEM8(dstaddr + ofs) = pPtp->msgType | (pPtp->majorSdoId << 4);
- ofs++;
- MEM8(dstaddr + ofs) = pPtp->version | (pPtp->minorVersionPTP << 4);
- ofs++;
- mem16_htons(dstaddr + ofs, pPtp->msgLen);
- ofs += 2;
- MEM8(dstaddr + ofs) = pPtp->domainNumber;
- ofs++;
- MEM8(dstaddr + ofs) = pPtp->minorSdoId;
- ofs++;
- mem16_htons(dstaddr + ofs, SWAP16(pPtp->flags)); // flags used in network byte order in system
- ofs += 2;
- pSrc = (uint8_t *)(&(pPtp->correctionField));
- for (idx = 0; idx < 8; ++idx) {
- MEM8(dstaddr + ofs + idx) = pSrc[7 - idx];
- }
- ofs += idx; // inc by 8
- mem16_htons(dstaddr + ofs, 0); // reserved
- ofs += 2;
- mem16_htons(dstaddr + ofs, 0); // reserved
- ofs += 2;
- ofs += tsn_ptp_set_portid(dstaddr + ofs, &(pPtp->sourcePortId));
- mem16_htons(dstaddr + ofs, pPtp->sequenceId);
- ofs += 2;
- MEM8(dstaddr + ofs) = pPtp->control;
- ofs++;
- MEM8(dstaddr + ofs) = pPtp->logMsgInterval;
- ofs++;
- return ofs;
- }
- void tsn_ptp_adjust_timestamp(ptp_timestamp_t *pTimestamp, int32_t adjustNs)
- {
- int32_t ns;
- ns = (int32_t)pTimestamp->nanoseconds;
- ns += adjustNs;
- while (ns < 0) {
- ns += NS_PER_SEC;
- pTimestamp->seconds--;
- }
- while (ns >= NS_PER_SEC) {
- ns -= NS_PER_SEC;
- pTimestamp->seconds++;
- }
- pTimestamp->nanoseconds = ns;
- }
- /**
- * Convert MAC address (EUI-48) to ClockIdentity (EUI-64)
- *
- * @param pMacAddr Pointer to MAC address (u8[6])
- * @param pClockId Pointer to ClockIdentity (u8[8])
- */
- void tsn_ptp_mac_to_clockid(const uint8_t *pMacAddr, uint8_t *pClockId)
- {
- uint32_t idx;
- for (idx = 0; idx < 3; idx++) {
- pClockId[idx] = pMacAddr[idx];
- };
- pClockId[3] = 0xFF;
- pClockId[4] = 0xFE;
- for (idx = 3; idx < 6; idx++) {
- pClockId[idx + 2] = pMacAddr[idx];
- };
- }
- /**
- * Copy timestamp (48 sec, 32 bit nanosec)to memory address
- *
- * @param dstaddr Destination Address
- * @param pTimestamp Pointer to ptp_timestamp_t
- * @return returns number of written bytes (always 10)
- */
- uint32_t tsn_ptp_set_tstamp(uintptr_t dstaddr, ptp_timestamp_t *pTimestamp)
- {
- uint16_t *p16;
- // copy seconds
- p16 = (uint16_t *)(&pTimestamp->seconds);
- mem16_htons(dstaddr + 0, p16[2]);
- mem16_htons(dstaddr + 2, p16[1]);
- mem16_htons(dstaddr + 4, p16[0]);
- // copy nanoseconds
- p16 = (uint16_t *)(&pTimestamp->nanoseconds);
- mem16_htons(dstaddr + 6, p16[1]);
- mem16_htons(dstaddr + 8, p16[0]);
- return 10;
- }
- /**
- * Get Timestamp from PTP frame
- *
- * @param srcaddr Source Address of timestamp
- * @param pTimestamp pointer to ptp_timestamp_t structure
- */
- void tsn_ptp_get_tstamp(uintptr_t srcaddr, ptp_timestamp_t *pTimestamp)
- {
- uint16_t *pDst16;
- // copy seconds
- pDst16 = (uint16_t *)(&pTimestamp->seconds);
- pDst16[3] = 0; // only 48 bit seconds
- pDst16[2] = mem16_ntohs(srcaddr + 0);
- pDst16[1] = mem16_ntohs(srcaddr + 2);
- pDst16[0] = mem16_ntohs(srcaddr + 4);
- // copy nanoseconds
- pDst16 = (uint16_t *)(&pTimestamp->nanoseconds);
- pDst16[1] = mem16_ntohs(srcaddr + 6);
- pDst16[0] = mem16_ntohs(srcaddr + 8);
- }
- /**
- * Copy port identity to memory address
- *
- * @param dstaddr Destination Address
- * @param pPortId Pointer to port_id_t
- * @return returns number of written bytes (always 10)
- */
- uint32_t tsn_ptp_set_portid(uintptr_t dstaddr, port_id_t *pPortId)
- {
- int idx;
- uintptr_t addrClkId;
- // ClockIdentity
- addrClkId = (uintptr_t)(&pPortId->clockIdentity);
- for (idx = 0; idx < 8; ++idx) {
- MEM8(dstaddr + idx) = MEM8(addrClkId + idx);
- }
- // Port Number
- mem16_htons(dstaddr + 8, pPortId->portNumber);
- return 10;
- }
- /**
- * Get PortIdentity from PTP frame
- *
- * @param srcaddr address of portID within PTP frame
- * @param pPortId pointer to portIdentity structure
- */
- void tsn_ptp_get_portid(uintptr_t srcaddr, port_id_t *pPortId)
- {
- int idx;
- uintptr_t addrClkId;
- // ClockIdentity
- addrClkId = (uintptr_t)(&pPortId->clockIdentity);
- for (idx = 0; idx < 8; ++idx) {
- MEM8(addrClkId + idx) = MEM8(srcaddr + idx);
- }
- // Port Number
- pPortId->portNumber = mem16_ntohs(srcaddr + 8);
- }
- /**
- * Get PTP flags from address
- * Flags are defined in network byte order within this stack
- *
- * @param srcaddr address of flags within ptp header
- * @return flags
- */
- uint16_t tsn_ptp_get_flags(uintptr_t srcaddr)
- {
- uint16_t flags;
- flags = mem16_ntohs(srcaddr);
- return SWAP16(flags);
- }
- /**
- * Set Pdelay-Request Payload, 20 reserved bytes (0x00)
- * @param dstaddr Destination Address
- * @return returns number of written bytes (always 20)
- */
- uint32_t tsn_ptp_set_pdelay_req(uintptr_t dstaddr)
- {
- uint32_t ofs;
- // 2*10 bytes reserved
- for (ofs = 0; ofs < 20; ++ofs) {
- MEM8(dstaddr + ofs) = 0x00;
- }
- return ofs;
- }
- /**
- * Set Pdelay-Response Payload, Rx timestamp of request, request port Id
- *
- * @param dstaddr Destination Address
- * @param pRxTstamp rx timestamp, pointer to ptp_timestamp_t
- * @param pReqPortId requesting port id, pointer to port_id_t
- * @return returns number of written bytes (always 20)
- */
- uint32_t tsn_ptp_set_pdelay_resp(uintptr_t dstaddr, ptp_timestamp_t *pRxTstamp, port_id_t *pReqPortId)
- {
- uint32_t ofs;
- ofs = 0;
- ofs += tsn_ptp_set_tstamp(dstaddr + ofs, pRxTstamp);
- ofs += tsn_ptp_set_portid(dstaddr + ofs, pReqPortId);
- return ofs;
- }
- /**
- * Set Pdelay-Response-Followup Payload, Tx timestamp of response, request port Id
- *
- * @param dstaddr Destination Address
- * @param pRespOrigTstamp tx timestamp, pointer to struct ptp_timestamp_s
- * @param pReqPortId requesting port id, pointer to port_id_t
- * @return returns number of written bytes (always 20)
- */
- uint32_t tsn_ptp_set_pdelay_fup(uintptr_t dstaddr, ptp_timestamp_t *pRespOrigTstamp, port_id_t *pReqPortId)
- {
- uint32_t ofs;
- ofs = 0;
- ofs += tsn_ptp_set_tstamp(dstaddr + ofs, pRespOrigTstamp);
- ofs += tsn_ptp_set_portid(dstaddr + ofs, pReqPortId);
- return ofs;
- }
- /**
- * Set Sync Payload, 10 reserved bytes (0x00)
- *
- * @param dstaddr Destination Address
- * @return returns number of written bytes (always 10)
- */
- uint32_t tsn_ptp_set_sync(uintptr_t dstaddr)
- {
- uint32_t ofs;
- // 10 bytes reserved
- for (ofs = 0; ofs < 10; ++ofs) {
- MEM8(dstaddr + ofs) = 0x00;
- }
- return ofs;
- }
- /**
- * Copy FollowUp frame payload (precieOriginTimestamp + followup) to memory address
- *
- * @param dstaddr Destination Address
- * @param pFollowup Pointer to struct ptp_followup_tlv_s
- * @return returns number of written bytes (always 42)
- */
- uint32_t tsn_ptp_set_followup(uintptr_t dstaddr, struct ptp_followup_s *pFollowup)
- {
- uint32_t ofs;
- uint32_t idx;
- uint8_t orgId[6] = { 0x00, 0x80, 0xC2, 0x00, 0x00, 0x01 };
- ofs = 0;
- ofs += tsn_ptp_set_tstamp(dstaddr, &pFollowup->preciseOriginTimestamp); // preciseOriginTimestamp
- // TLV type + length
- mem16_htons(dstaddr + ofs + 0, PTP_TLV_TYPE_ORG_EXT);
- mem16_htons(dstaddr + ofs + 2, 28);
- ofs += 4;
- // Organization
- for (idx = 0; idx < 6; ++idx) {
- MEM8(dstaddr + ofs + idx) = orgId[idx];
- }
- ofs += idx;
- // cumScaledRateOfs
- mem32_htonl(dstaddr + ofs, (uint32_t)pFollowup->cumScaledRateOfs);
- ofs += 4;
- // gmTimeBaseIndicator
- mem16_htons(dstaddr + ofs, pFollowup->gmTimeBaseInd);
- ofs += 2;
- // lastGmPhaseChange 0, 0, ns[8], fns[2]
- mem16_htons(dstaddr + ofs + 0, pFollowup->lastGmPhaseCh.ns_msb);
- mem32_htonl(dstaddr + ofs + 2, pFollowup->lastGmPhaseCh.ns_lsb >> 32);
- mem32_htonl(dstaddr + ofs + 6, (uint32_t)pFollowup->lastGmPhaseCh.ns_lsb);
- mem16_htons(dstaddr + ofs + 10, pFollowup->lastGmPhaseCh.fns);
- ofs += 12;
- // scaledLastGmFreqChange
- mem32_htonl(dstaddr + ofs, (uint32_t)pFollowup->scaledLastGmFreqCh);
- ofs += 4;
- return ofs;
- }
- /**
- * Copy Signaling information to memory address
- *
- * @param dstaddr Destination Address
- * @param pSignaling Pointer to struct ptp_signaling_tlv_s
- * @return returns number of written bytes (always 26)
- */
- uint32_t tsn_ptp_set_signaling(uintptr_t dstaddr, struct ptp_signaling_tlv_s *pSignaling)
- {
- uint32_t ofs;
- uint32_t idx;
- uint8_t orgId[6] = { 0x00, 0x80, 0xC2, 0x00, 0x00, 0x02 };
- ofs = 0;
- // targetPortIdentity - dummy - "value is 0xFF" (ieee802.1as-2011, 10.5.4.2.1)
- for (idx = 0; idx < 10; ++idx) {
- MEM8(dstaddr + ofs + idx) = 0xFF;
- }
- ofs += idx;
- // TLV type + length
- mem16_htons(dstaddr + ofs + 0, PTP_TLV_TYPE_ORG_EXT);
- mem16_htons(dstaddr + ofs + 2, 12);
- ofs += 4;
- // Organization
- for (idx = 0; idx < 6; ++idx) {
- MEM8(dstaddr + ofs + idx) = orgId[idx];
- }
- ofs += idx;
- // Intervals + flags
- MEM8(dstaddr + ofs + 0) = (uint8_t)(pSignaling->linkDelayInterval);
- MEM8(dstaddr + ofs + 1) = (uint8_t)(pSignaling->timeSyncInterval);
- MEM8(dstaddr + ofs + 2) = (uint8_t)(pSignaling->announceInterval);
- MEM8(dstaddr + ofs + 3) = pSignaling->flags;
- ofs += 4;
- mem16_htons(dstaddr + ofs, 0); // reserved
- ofs += 2;
- return ofs;
- }
- /**
- * Copy Announce information to memory address
- * @param dstaddr Destination Address
- * @param pAnnounce announce information, pointer to struct ptp_announce_s
- * @return returns number of written bytes (always 34+8*pathCount)
- */
- uint32_t tsn_ptp_set_announce(uintptr_t dstaddr, struct ptp_announce_s *pAnnounce)
- {
- uint32_t ofs;
- uint32_t idx;
- uint32_t tmp;
- uint8_t *p8;
- ofs = 0;
- // reserved 10 byte
- for (idx = 0; idx < 5; ++idx) {
- mem16_htons(dstaddr + ofs + idx * 2, 0); // reserved
- }
- ofs += (idx * 2);
- mem16_htons(dstaddr + ofs, (uint16_t)pAnnounce->currentUtcOfs); // currentUtcOfs
- ofs += 2;
- MEM8(dstaddr + ofs) = 0; // reserved
- ofs++;
- MEM8(dstaddr + ofs) = pAnnounce->gmPrio1; // prio1
- ofs++;
- // clockQual
- MEM8(dstaddr + ofs) = pAnnounce->clockQuality.clockClass; // clockQual.clockClass
- ofs++;
- MEM8(dstaddr + ofs) = pAnnounce->clockQuality.clockAccuracy; // clockQual.clockAccuracy
- ofs++;
- // clockQual.ofsScaledLogVariance
- mem16_htons(dstaddr + ofs, pAnnounce->clockQuality.offsetScaledLogVariance);
- ofs += 2;
- MEM8(dstaddr + ofs) = pAnnounce->gmPrio2; // prio2
- ofs++;
- // gmid
- p8 = (uint8_t *)(&pAnnounce->gmIdentity);
- for (idx = 0; idx < 8; ++idx) {
- MEM8(dstaddr + ofs + idx) = p8[idx];
- }
- ofs += 8;
- mem16_htons(dstaddr + ofs, pAnnounce->stepsRemoved);
- ofs += 2;
- MEM8(dstaddr + ofs) = pAnnounce->timeSource;
- ofs++;
- // TLV type + length
- mem16_htons(dstaddr + ofs, PTP_TLV_TYPE_PATHTRACE);
- ofs += 2;
- tmp = pAnnounce->pathCount * PTP_PATHTRACE_SZ;
- mem16_htons(dstaddr + ofs, tmp);
- ofs += 2;
- // copy path (ClockIdentity)
- for (idx = 0; idx < tmp; idx++) {
- MEM8(dstaddr + ofs + idx) = pAnnounce->pPathSequence[idx];
- }
- ofs += idx;
- return ofs;
- }
- /**
- * Copy Followup information from frame to structure
- * @param addr address, to followup frame payload
- * @param pFollowup structure, where followup information is written
- * @return 0 on success, -1 on error
- */
- int32_t tsn_ptp_get_followup(uintptr_t addr, struct ptp_followup_s *pFollowup)
- {
- uint32_t tmp;
- uint32_t idx;
- #ifdef TSN_PTP_CFG_FOLLOWUP_TLV_ORG_CHECK
- uint8_t orgId[6] = { 0x00, 0x80, 0xC2, 0x00, 0x00, 0x01 };
- #endif
- // check param for NULL pointer
- if (pFollowup == 0)
- return -1;
- // offset = 0
- // precise origin timestamp
- tsn_ptp_get_tstamp(addr, &pFollowup->preciseOriginTimestamp);
- // offset = 10
- // CHECK TLV TYPE/LEN
- tmp = mem16_ntohs(addr + 10); // TLVTYPE
- if (tmp != PTP_TLV_TYPE_ORG_EXT)
- return -1;
- tmp = mem16_ntohs(addr + 12); // TLVLEN (exp 28)
- if (tmp != 28)
- return -1;
- // ORG
- #ifdef TSN_PTP_CFG_FOLLOWUP_TLV_ORG_CHECK
- for (idx = 0; idx < 6; ++idx) {
- if (MEM8(addr + idx + 14) != orgId[idx])
- return -1;
- }
- #endif // TSN_PTP_CFG_FOLLOWUP_TLV_ORG_CHECK
- // offset = 20
- pFollowup->cumScaledRateOfs = mem32_ntohl(addr + 20); // cumScaledRateOfs
- // offset = 24
- pFollowup->gmTimeBaseInd = mem16_ntohs(addr + 24); // gmTimeBaseIndicator
- // ofs = 26
- pFollowup->lastGmPhaseCh.ns_msb = mem16_ntohs(addr + 26 + 0);
- pFollowup->lastGmPhaseCh.ns_lsb = ((uint64_t)mem32_ntohl(addr + 26 + 2)) << 32;
- pFollowup->lastGmPhaseCh.ns_lsb |= mem32_ntohl(addr + 26 + 6);
- pFollowup->lastGmPhaseCh.fns = mem16_ntohs(addr + 26 + 10);
- // offset = 38
- pFollowup->scaledLastGmFreqCh = mem32_ntohl(addr + 38);
- return 0; // success
- }
- /**
- * Copy Announce frame information to structure
- * @param addr pointer to payload address of frame (first byte of reserve-field)
- * @param pAnnounce pointer to structure
- * @return 0 on success, -1 on error
- */
- int32_t tsn_ptp_get_announce(uintptr_t addr, struct ptp_announce_s *pAnnounce)
- {
- uint32_t idx;
- uint8_t *p8;
- uint16_t tlvType, tlvLen;
- // basic pointer check
- if (pAnnounce == 0) {
- return -1;
- }
- // reserved (10)
- // currentUtcOfs (2)
- pAnnounce->currentUtcOfs = mem16_ntohs(addr + 10);
- // rsv (1)
- // prio1 (1)
- pAnnounce->gmPrio1 = MEM8(addr + 13);
- // clock quality (4)
- pAnnounce->clockQuality.clockClass = MEM8(addr + 14);
- pAnnounce->clockQuality.clockAccuracy = MEM8(addr + 15);
- pAnnounce->clockQuality.offsetScaledLogVariance = mem16_ntohs(addr + 16);
- ;
- // prio2 (1)
- pAnnounce->gmPrio2 = MEM8(addr + 18);
- // gmid (8)
- p8 = (uint8_t *)(&pAnnounce->gmIdentity);
- for (idx = 0; idx < 8; ++idx) {
- p8[idx] = MEM8(addr + 19 + idx);
- }
- // stepsRemoved (2)
- pAnnounce->stepsRemoved = mem16_ntohs(addr + 27);
- // timesource (1)
- pAnnounce->timeSource = MEM8(addr + 29);
- // pathtrace TLV type/len (2/2)
- tlvType = mem16_ntohs(addr + 30);
- tlvLen = mem16_ntohs(addr + 32);
- if (tlvType == PTP_TLV_TYPE_PATHTRACE) {
- pAnnounce->pPathSequence = (uint8_t *)(addr + 34);
- pAnnounce->pathCount = tlvLen / PTP_PATHTRACE_SZ;
- } else {
- pAnnounce->pPathSequence = 0;
- pAnnounce->pathCount = 0;
- }
- return 0; // success
- }
- /**
- * Compare two SystemIdentities A and B
- * @param pSysIdA pointer to SystemIdentitiy A
- * @param pSysIdB pointer to SystemIdentitiy B
- * @return 0 when equal, else -1 if (A < B), else +1 if (A > B)
- */
- int32_t tsn_ptp_cmp_systemid(ptp_system_id_t *pSysIdA, ptp_system_id_t *pSysIdB)
- {
- // 10.3.2
- // a)
- if (pSysIdA->prio1 < pSysIdB->prio1)
- return -1;
- if (pSysIdA->prio1 > pSysIdB->prio1)
- return 1;
- // b)
- if (pSysIdA->clockQuality.clockClass < pSysIdB->clockQuality.clockClass)
- return -1;
- if (pSysIdA->clockQuality.clockClass > pSysIdB->clockQuality.clockClass)
- return 1;
- // c)
- if (pSysIdA->clockQuality.clockAccuracy < pSysIdB->clockQuality.clockAccuracy)
- return -1;
- if (pSysIdA->clockQuality.clockAccuracy > pSysIdB->clockQuality.clockAccuracy)
- return 1;
- // d)
- if (pSysIdA->clockQuality.offsetScaledLogVariance < pSysIdB->clockQuality.offsetScaledLogVariance)
- return -1;
- if (pSysIdA->clockQuality.offsetScaledLogVariance > pSysIdB->clockQuality.offsetScaledLogVariance)
- return 1;
- // e)
- if (pSysIdA->prio2 < pSysIdB->prio2)
- return -1;
- if (pSysIdA->prio2 > pSysIdB->prio2)
- return 1;
- // f
- if (pSysIdA->clockIdentity < pSysIdB->clockIdentity)
- return -1;
- if (pSysIdA->clockIdentity > pSysIdB->clockIdentity)
- return 1;
- return 0;
- }
- /**
- * Compare two priority vectors A and B
- * A is better than B when (A < B)
- *
- * @param pPrioA pointer to priority vector A
- * @param pPrioB pointer to priority vector B
- * @return 0 when equal, else -1 if (A < B), else +1 if (A > B)
- */
- int32_t tsn_ptp_cmp_priovect(ptp_prio_vect_t *pPrioA, ptp_prio_vect_t *pPrioB)
- {
- int32_t cmp;
- // 10.3.5
- // cmp systemId
- cmp = tsn_ptp_cmp_systemid(&(pPrioA->rootSystemId), &(pPrioB->rootSystemId));
- if (cmp != 0)
- return cmp;
- // cmp stepsRemoved
- if (pPrioA->stepsRemoved < pPrioB->stepsRemoved)
- return -1;
- if (pPrioA->stepsRemoved > pPrioB->stepsRemoved)
- return 1;
- // cmp sourcePortId
- if (pPrioA->sourcePortId.clockIdentity < pPrioB->sourcePortId.clockIdentity)
- return -1;
- if (pPrioA->sourcePortId.clockIdentity > pPrioB->sourcePortId.clockIdentity)
- return 1;
- if (pPrioA->sourcePortId.portNumber < pPrioB->sourcePortId.portNumber)
- return -1;
- if (pPrioA->sourcePortId.portNumber > pPrioB->sourcePortId.portNumber)
- return 1;
- // cmp portNum
- if (pPrioA->portNumber < pPrioB->portNumber)
- return -1;
- if (pPrioA->portNumber > pPrioB->portNumber)
- return 1;
- return 0;
- }
|