Commit ea6412b8 authored by Alessandro Rubini's avatar Alessandro Rubini

addd PTPWRd, from svn release 916

parents
This diff is collapsed.
# Makefile for ptpd
ifeq ($(TARGET),ARM)
include ../../Makedefs
CC=$(CROSS_COMPILE_ARM)gcc
else
CC=gcc
endif
RM = rm -f
CFLAGS = -I. -O2 -I../include -DDEBUG -I../../kernel/include -I../wrsw_hal \
-I../libptpnetif -I../libwripc
CPPFLAGS = -DPTPD_NO_DAEMON -DNEW_SINGLE_WRFSM #-DPTPD_DBG
#### use new single state machine (new wrspec) #####
#CPPFLAGS += -DNEW_SINGLE_WRFSM
###################################################
#### show message content ####
CPPFLAGS += #-DPTPD_DBGMSG
#### this one shows function names ####
CPPFLAGS += #-DPTPD_DBG_S_FUN
####detailed debugging: ####
#CPPFLAGS +=-DPTPD_DBGV
#####old flags: ######
#CPPFLAGS +=-DWR_NETIF
#CPPLFAGS +=-DCONFIG_WRPTP
#CPPFLAGS += -DWR_IN_HEADER_AND_ANNBODY
LDFLAGS = -lm
ifeq ($(TARGET),ARM)
LDFLAGS +=-L../libwripc -lwripc # -L../libptpnetif -lptpnetif
endif
PROG = wr_ptpd
OBJ = ptpd.o arith.o bmc.o wr_protocol.o protocol.o display.o\
dep/msg.o dep/net.o dep/servo.o dep/startup.o dep/sys.o dep/timer.o dep/wr_servo.o ptpd_exports.o
ifeq ($(TARGET),ARM)
OBJ += ../libptpnetif/hal_client.o ../libptpnetif/ptpd_netif.o
else
OBJ += dep/ptpd_netif/ptpd_netif_mch.o
endif
HDR = ptpd.h constants.h datatypes.h \
dep/ptpd_dep.h dep/constants_dep.h dep/datatypes_dep.h \
.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
all: $(PROG)
$(PROG): $(OBJ)
$(CC) $(LDFLAGS) -o $@ $(OBJ)
$(OBJ): $(HDR)
pc: all
run: all
scp $(PROG) root@192.168.1.16:/tmp
scp $(PROG) root@192.168.1.6:/tmp
clean:
$(RM) $(PROG) $(OBJ)
deploy:
cp $(PROG) $(WR_INSTALL_ROOT)/bin
\ No newline at end of file
Author: Maciej Lipinski
email : maciej.lipinski@cern.ch
info : implementatin of White Rabbit extension
1)defines:
- IRQ_LESS_TIMER
if this defined, WR uses new implementation of timeouts (not using interrupt)
2)compilation flags:
- DPTPD_NO_DAEMON - original PTPd flag, for WR not tested yet without this
- DPTPD_DBGMSG - debugging of messages, it prints msgPack*() and msgUnpack*() functions
- DPTPD_DBG - most of debugging added by ML
- DPTPD_DBG_S_FUN - if defined along with DPTPD_DBG, info about calling function displayed
- DPTPD_DBGV - original detailed debugging, to detailed to be redeable
- DPTPD_DBGWR - meant to be White Rabbit debugging, but not really used :(
2) compilation
./build_t.sh run T=192.168.1.5 // this builds and runs ptpwrd on target, but without params, useless, kill it, ptpwrd will automaticly build for PC
3) runnig
- WR slave with one port on interface eth2
./ptpv2d -b eth2 -S
- WR master with one port on interface wru1
./ptpv2d -b wru1 -M
- WR multi-node, with slave port on wru1, master ports on wrd0 & wrd1
(when run with -S, WR slave is always port 1, the other ports are WR masters)
./ptpv2d -1 wru1 -2 wrd0 -3 wrd1 -S
4)Files:
PTPWRd
|-- arith.c --------------------- no WR changes
|-- bmc.c ----------------------- WR changed: a lot of WR here:
|
|-- build_p.sh ------------------ WR only:this builds PTPWR for standard PC
|-- build_t.sh ------------------ WR only:this builds PTPWR for the target and standard PC
| (just for convenience, I always need both :)
|-- clean.sh -------------------- ML: I used it for cleaning before commiting, I use Kate
| and it produces tmp files ~
|-- constants.h ----------------- WR changed: constants and enums used in WR are here
|-- datatypes.h ----------------- WR changed: here we have defined PtpClock, so all the WRPTP
| variables that are added to it + FixedDelta typedef
|-- dep
| |-- constants_dep.h --------- WR changed: no significant WR-related changes here
| |-- datatypes_dep.h --------- WR changed: here is NetPath typedef defined, and all the types
| | used in the daemon
| |-- msg.c ------------------- WR changed: White Rabbit management facilities + announce suffix +
| | other method of flipping bits (original one did not work for
| | 32 bits, aligment problems)
| |-- net.c ------------------- WR changed: Absolutelly, thoroughly changed by White Rabbit to
| | adapt to ptpd_netif interface
| |-- ptpd_dep.h -------------- WR changed: some custiom WR DBG facilities are defined here +
| | definitions of functions in /dep folder
| |-- ptpd_netif
| | |-- ptpd_netif.h -------- WR only: does what header should
| | |-- ptpd_netif_mch.c ---- WR only: network interface implemented here + interface to
| | HAL (calibration, locking) + HW timestamps
| |-- PTPWR_INFO
| |-- servo.c ----------------- WR changed: to be implemetned !!!!!!!!!
| |-- startup.c --------------- WR changed: defined new startup parametrs, implementation of multi-port
| | [allocate/free memory for many ports, done here in ptpdStartup()/ptpShutDown()]
| |-- sys.c ------------------- WR changed: here adjtimex() is commented not to mess around with the clock,
| we do it differently
| `-- timer.c ----------------- WR changed: Here WR implements interrupt-less timing (in original ptp daemon irq was used)
|-- display.c ------------------- not used in WR
|-- Doxyfile
|-- Makefile
|-- protocol.c ------------------ WR changed: WR does here a lot:
| 1) modifies UNCALIBRATED state
| 2) adds HW timestamping
| 3) messge issue/handle WR management (see handleManagement() and issueWRManagement())
| 4) implement multi-port
|-- ptpd.8
|-- ptpd.c ---------------------- WR changed: here we set some default WR params and decide if we want single- or multi-port mode
|-- ptpd.h ---------------------- no significant WR-related changes here
|-- TODO ------------------------ :)
|-- wr_protocol.c --------------- WR only: WR FSMs, HW timestamping, and other WR magic is implemented
`-- wr_protocol.h --------------- WR only: just definitions of WR functions
\ No newline at end of file
TODO High Priority
TODO:
- flipping bits in msg.c !!!!!!!
- check that all values are passed properly (especially deltas, calibaration)
- test with standard PTP
- test multiport
- move writing time to netRecvMsg, protocol.c 619 line
- set calibration period as timeout in *_CALIBRATE state
- convert HW timestamps into SW
- test multiport
- implement synchronization of calibratin between different ports
date -s "2010-08-24 14:23" -u
\ No newline at end of file
/* arith.c */
#include "ptpd.h"
void integer64_to_internalTime(Integer64 bigint,TimeInternal *internal)
{
int s_msb;
double ns_msb;
double temp;
int entire;
char *p_lsb,*p_msb;
Boolean negative = FALSE;
p_lsb=&bigint.lsb;
p_msb=&bigint.msb;
/*Test if bigint is a negative number*/
negative = ((bigint.msb & 0x80000000) == 0x80000000);
if (!negative)
{
/*Positive case*/
/*fractional nanoseconds are excluded (see 5.3.2)*/
bigint.lsb = bigint.lsb>>16;
/*copy two least significant octet of msb to most significant octet of lsb*/
*(p_lsb+2)=*p_msb;
*(p_lsb+3)=*(p_msb+1);
bigint.msb = bigint.msb>>16;
internal->nanoseconds = bigint.lsb % 1000000000;
internal->seconds = bigint.lsb / 1000000000;
/*(2^32 / 10^9) = 4,294967296*/
s_msb = 4*bigint.msb;
ns_msb = 0.294967296*(double)bigint.msb;
entire = (int)ns_msb;
s_msb += entire;
ns_msb -= entire;
ns_msb *= 1000000000;
internal->nanoseconds = (float)internal->nanoseconds + (float)ns_msb;
internal->seconds += s_msb;
normalizeTime(internal);
}
/*End of positive Case*/
else
{ /*Negative case*/
/*Take the two complement*/
bigint.lsb = ~bigint.lsb;
bigint.msb = ~bigint.msb;
if (bigint.lsb == 0xffffffff){
bigint.lsb = 0;
bigint.msb++;
}
else{
bigint.lsb++;
}
/*fractional nanoseconds are excluded (see 5.3.2)*/
bigint.lsb = bigint.lsb>>16;
/*copy two least significant octet of msb to most significant octet of lsb*/
*(p_lsb+2)=*p_msb;
*(p_lsb+3)=*(p_msb+1);
bigint.msb = bigint.msb>>16;
internal->nanoseconds = bigint.lsb % 1000000000;
internal->seconds = bigint.lsb / 1000000000;
/*(2^32 / 10^9) = 4,294967296*/
s_msb = 4*bigint.msb;
ns_msb = 0.294967296*(double)bigint.msb;
entire = (int)ns_msb;
s_msb += entire;
ns_msb -= entire;
ns_msb *= 1000000000;
internal->nanoseconds = (float)internal->nanoseconds + (float)ns_msb;
internal->seconds += s_msb;
normalizeTime(internal);
internal->nanoseconds = -internal->nanoseconds;
internal->seconds = -internal->seconds;
}
/*End of negative Case*/
}
void fromInternalTime(TimeInternal *internal, Timestamp *external)
{
/*fromInternalTime is only used to convert time given by the system to a timestamp
* As a consequence, no negative value can normally be found in (internal)
* Note that offsets are also represented with TimeInternal structure, and can be negative,
* but offset are never convert into Timestamp so there is no problem here.*/
if ((internal->seconds & ~INT_MAX) || (internal->nanoseconds & ~INT_MAX))
{
DBGNPI("Negative value canno't be converted into timestamp \n");
return;
}
else
{
external->secondsField.lsb = internal->seconds;
external->nanosecondsField = internal->nanoseconds;
external->secondsField.msb = 0;
}
}
void toInternalTime(TimeInternal *internal, Timestamp *external)
{
/*Program will not run after 2038...*/
if (external->secondsField.lsb < INT_MAX)
{
internal->seconds = external->secondsField.lsb;
internal->nanoseconds = external->nanosecondsField;
}
else
{
DBGNPI("Clock servo canno't be executed : seconds field is higher than signed integer (32bits) \n");
return;
}
}
void normalizeTime(TimeInternal *r)
{
r->seconds += r->nanoseconds/1000000000;
r->nanoseconds -= r->nanoseconds/1000000000*1000000000;
if(r->seconds > 0 && r->nanoseconds < 0)
{
r->seconds -= 1;
r->nanoseconds += 1000000000;
}
else if(r->seconds < 0 && r->nanoseconds > 0)
{
r->seconds += 1;
r->nanoseconds -= 1000000000;
}
}
void addTime(TimeInternal *r, TimeInternal *x, TimeInternal *y)
{
r->seconds = x->seconds + y->seconds;
r->nanoseconds = x->nanoseconds + y->nanoseconds;
normalizeTime(r);
}
void subTime(TimeInternal *r, TimeInternal *x, TimeInternal *y)
{
r->seconds = x->seconds - y->seconds;
r->nanoseconds = x->nanoseconds - y->nanoseconds;
normalizeTime(r);
}
This diff is collapsed.
#!/bin/sh
make clean
make
#!/bin/sh
make clean
make TARGET=ARM $1 $2 $3 $4
#make clean
#make
#!/bin/sh
make TARGET=ARM clean
rm *~
rm */*~
rm */*/*~
echo 'cleaned to be committed'
#ifndef CONSTANTS_H_
#define CONSTANTS_H_
/**
*\file
* \brief Default values and constants used in ptpdv2
*
* This header file includes all default values used during initialization
* and enumeration defined in the spec
*/
#include "ptpd_netif.h"
#define MANUFACTURER_ID \
"MaceG VanKempen;2.0.0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
/* implementation specific constants */
#define DEFAULT_INBOUND_LATENCY 0 /* in nsec */
#define DEFAULT_OUTBOUND_LATENCY 0 /* in nsec */
#define DEFAULT_NO_RESET_CLOCK FALSE
#define DEFAULT_DOMAIN_NUMBER 0
#define DEFAULT_DELAY_MECHANISM E2E //P2P //Note that end to end mechanism is not implemented.
#define DEFAULT_AP 10
#define DEFAULT_AI 1000
#define DEFAULT_DELAY_S 6
#define DEFAULT_ANNOUNCE_INTERVAL 1 //0 in 802.1AS
#define DEFAULT_UTC_OFFSET 0
#define DEFAULT_UTC_VALID FALSE
#define DEFAULT_PDELAYREQ_INTERVAL 1 //-4 in 802.1AS
#define DEFAULT_DELAYREQ_INTERVAL 0
#define DEFAULT_SYNC_INTERVAL 0 //-7 in 802.1AS
#define DEFAULT_SYNC_RECEIPT_TIMEOUT 3
#define DEFAULT_ANNOUNCE_RECEIPT_TIMEOUT 2 //6 // 3 by default
#define DEFAULT_QUALIFICATION_TIMEOUT 2
#define DEFAULT_FOREIGN_MASTER_TIME_WINDOW 4
#define DEFAULT_FOREIGN_MASTER_THRESHOLD 2
#define DEFAULT_CLOCK_CLASS 100
#define DEFAULT_CLOCK_ACCURACY 0xFE
#define DEFAULT_PRIORITY1 100
#define DEFAULT_PRIORITY2 100
#define DEFAULT_CLOCK_VARIANCE -4000 //To be determined in 802.1AS...so same value of ptpdv1 is used
#define DEFAULT_MAX_FOREIGN_RECORDS 5
#define DEFAULT_PARENTS_STATS FALSE
/* features, only change to refelect changes in implementation */
#define NUMBER_PORTS 1
#define VERSION_PTP 2
#define TWO_STEP_FLAG 0x02
#define BOUNDARY_CLOCK FALSE
#define SLAVE_ONLY FALSE
#define NO_ADJUST FALSE
/** \name Packet length
Minimal length values for each message.
If TLV used length could be higher.*/
/**\{*/
#define HEADER_LENGTH 34
#define ANNOUNCE_LENGTH 64
#define SYNC_LENGTH 44
#define FOLLOW_UP_LENGTH 44
#define PDELAY_REQ_LENGTH 54
#define DELAY_REQ_LENGTH 44
#define DELAY_RESP_LENGTH 54
#define PDELAY_RESP_LENGTH 54
#define PDELAY_RESP_FOLLOW_UP_LENGTH 54
#define MANAGEMENT_LENGTH 48
/** \}*/
/** \name White Rabbit staff
Here comes all the constants needed in White Rabbit extension
.*/
/**\{*/
/*White Rabbit staff*/
/*
* if this defined, WR uses new implementation of timeouts (not using interrupt)
*/
#define IRQ_LESS_TIMER
#define WR_NODE 0x80
#define WR_IS_CALIBRATED 0x04
#define WR_IS_WR_MODE 0x08
#define WR_NODE_MODE 0x03
#define WR_TLV_TYPE 0x2004
#define WR_MASTER_PRIORITY1 6
#define WR_DEFAULT_CAL_PERIOD 3000 //[us]
#define WR_DEFAULT_CAL_PATTERN 0x3E0 //1111100000
#define WR_DEFAULT_CAL_PATTERN_LEN 0xA //10 bits
#define WR_DEFAULT_STATE_TIMEOUT_MS 500 //[ms]
#define WR_DEFAULT_STATE_REPEAT 3
#define WR_DEFAULT_INIT_REPEAT 3
/*White Rabbit package Size*/
#ifdef WR_IN_HEADER_AND_ANNBODY
# define WR_ANNOUNCE_TLV_LENGTH 0
#else
# define WR_ANNOUNCE_TLV_LENGTH 6
#endif
#define WR_ANNOUNCE_LENGTH (ANNOUNCE_LENGTH + WR_ANNOUNCE_TLV_LENGTH)
#define WR_MANAGEMENT_TLV_LENGTH 6
#define WR_MANAGEMENT_LENGTH (MANAGEMENT_LENGTH + WR_MANAGEMENT_TLV_LENGTH)
#define MAX_PORT_NUMBER 16
#define MIN_PORT_NUMBER 1
#define WR_PORT_NUMBER 10
#define WR_SLAVE_CLOCK_CLASS 248
#define WR_MASTER_CLOCK_CLASS 5
/** \}*/
/*Enumeration defined in tables of the spec*/
/**
* \brief Domain Number (Table 2 in the spec)*/
enum {
DFLT_DOMAIN_NUMBER = 0, ALT1_DOMAIN_NUMBER, ALT2_DOMAIN_NUMBER, ALT3_DOMAIN_NUMBER
};
/**
* \brief Network Protocol (Table 3 in the spec)*/
enum {
UDP_IPV4=1,UDP_IPV6,IEE_802_3,DeviceNet,ControlNet,PROFINET
};
/**
* \brief Time Source (Table 7 in the spec)*/
enum {
ATOMIC_CLOCK=0x10,GPS=0x20,TERRESTRIAL_RADIO=0x30,PTP=0x40,NTP=0x50,HAND_SET=0x60,OTHER=0x90,INTERNAL_OSCILLATOR=0xA0
};
/**
* \brief PTP State (Table 8 in the spec)*/
enum {
INITIALIZING=1, FAULTY,DISABLED,LISTENING,PRE_MASTER,MASTER,PASSIVE,UNCALIBRATED,SLAVE
};
/**
* \brief Delay mechanism (Table 9 in the spec)*/
enum {
E2E=1,P2P=2,DELAY_DISABLED=0xFE
};
/**
* \brief PTP timers
*/
enum {
PDELAYREQ_INTERVAL_TIMER=0,/**<\brief Timer handling the PdelayReq Interval*/
DELAYREQ_INTERVAL_TIMER,/**<\brief Timer handling the delayReq Interva*/
SYNC_INTERVAL_TIMER,/**<\brief Timer handling Interval between master sends two Syncs messages */
ANNOUNCE_RECEIPT_TIMER,/**<\brief Timer handling announce receipt timeout*/
ANNOUNCE_INTERVAL_TIMER, /**<\brief Timer handling interval before master sends two announce messages*/
TIMER_ARRAY_SIZE /* this one is non-spec */
};
/**
* \brief PTP states
*/
enum {
PTP_INITIALIZING=0, PTP_FAULTY, PTP_DISABLED,
PTP_LISTENING, PTP_PRE_MASTER, PTP_MASTER,
PTP_PASSIVE, PTP_UNCALIBRATED, PTP_SLAVE
};
/**
* \brief PTP Messages
*/
enum {
SYNC=0x0,
DELAY_REQ,
PDELAY_REQ,
PDELAY_RESP,
FOLLOW_UP=0x8,
DELAY_RESP,
PDELAY_RESP_FOLLOW_UP,
ANNOUNCE,
SIGNALING,
MANAGEMENT,
};
enum {
PTP_ETHER,PTP_DEFAULT
};
/**
* \brief Indicates if a node runs as White Rabbit, and what kind (master/slave) [White Rabbit]
*/
/*White Rabbit node */
enum{
NON_WR = 0x0,
WR_SLAVE = PTPD_NETIF_RX, // just for convenient useage with ptpd_netif interface
WR_MASTER = PTPD_NETIF_TX, // just for convenient useage with ptpd_netif interface
};
/**
* \brief Values of Management Actions (extended for WR), see table 38 [White Rabbit]
*/
enum{
GET,
SET,
RESPONSE,
COMMAND,
ACKNOWLEDGE,
WR_CMD, //White Rabbit
};
#ifdef NEW_SINGLE_WRFSM
/**
* \brief WR PTP states (new, single FSM) [White Rabbit]
*/
enum {
WRS_PRESENT = 0, WRS_S_LOCK, WRS_M_LOCK, WRS_LOCKED,
WRS_REQ_CALIBRATION, WRS_CALIBRATED, WRS_RESP_CALIB_REQ ,WRS_WR_LINK_ON,
/*
each WR main state (except IDLE) has an associated timetout
we use state names to manage timeouts as well
*/
WR_TIMER_ARRAY_SIZE, //number of states which has timeouts
WRS_IDLE,
/* here are substates*/
WRS_S_LOCK_1,
WRS_S_LOCK_2,
WRS_REQ_CALIBRATION_1,
WRS_REQ_CALIBRATION_2,
WRS_REQ_CALIBRATION_3,
WRS_RESP_CALIB_REQ_1,
WRS_RESP_CALIB_REQ_2,
WRS_RESP_CALIB_REQ_3,
};
/**
* \brief White Rabbit commands (for new implementation, single FSM), see table 38 [White Rabbit]
*/
enum{
NULL_MANAGEMENT = 0x0000,
SLAVE_PRESENT = 0x6000,
LOCK,
LOCKED,
CALIBRATE,
CALIBRATED,
WR_MODE_ON,
};
#define SEND_CALIBRATION_PATTERN 0X0001
#define NOT_SEND_CALIBRATION_PATTERN 0X0000
#else
/**
* \brief WR PTP states (old wr fsm, two separate FSMs) [White Rabbit]
*/
enum {
PTPWR_PRESENT = 0, PTPWR_LOCK, PTPWR_LOCKED,
PTPWR_M_CALIBRATE, PTPWR_S_CALIBRATE, PTPWR_CAL_COMPLETED,
/*
each WR main state (except IDLE) has an associated timetout
we use state names to manage timeouts as well
*/
WR_TIMER_ARRAY_SIZE, //number of states which has timeouts
PTPWR_IDLE,
/* here are substates*/
PTPWR_LOCK_1,
PTPWR_LOCK_2,
PTPWR_M_CALIBRATE_1,
PTPWR_M_CALIBRATE_2,
PTPWR_S_CALIBRATE_1,
PTPWR_S_CALIBRATE_2,
PTPWR_S_CALIBRATE_3,
};
/**
* \brief White Rabbit commands, see table 38 [White Rabbit]
*/
enum{
NULL_MANAGEMENT = 0x0000,
SLAVE_PRESENT = 0x6000,
LOCK,
LOCKED,
MASTER_CALIBRATE,
MASTER_CALIBRATED,
SLAVE_CALIBRATE,
SLAVE_CALIBRATED,
WR_MODE_ON,
};
#endif
#endif /*CONSTANTS_H_*/
This diff is collapsed.
/* constants_dep.h */
#ifndef CONSTANTS_DEP_H
#define CONSTANTS_DEP_H
/**
*\file
* \brief Plateform-dependent constants definition
*
* This header defines all includes and constants which are plateform-dependent
*
* ptpdv2 is only implemented for linux, NetBSD and FreeBSD
*/
/* platform dependent */
#if !defined(linux) && !defined(__NetBSD__) && !defined(__FreeBSD__)
#error Not ported to this architecture, please update.
#endif
#ifdef linux
#include<netinet/in.h>
#include<net/if.h>
#include<net/if_arp.h>
#define IFACE_NAME_LENGTH IF_NAMESIZE
#define NET_ADDRESS_LENGTH INET_ADDRSTRLEN
#define IFCONF_LENGTH 10
#define BSD_INTERFACE_FUNCTIONS
#include<endian.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define PTPD_LSBF
#elif __BYTE_ORDER == __BIG_ENDIAN
#define PTPD_MSBF
#endif
#endif /* linux */
#if defined(__NetBSD__) || defined(__FreeBSD__)
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <net/if.h>
# include <net/if_dl.h>
# include <net/if_types.h>
# if defined(__FreeBSD__)
# include <net/ethernet.h>
# include <sys/uio.h>
# else
# include <net/if_ether.h>
# endif
# include <ifaddrs.h>
# define IFACE_NAME_LENGTH IF_NAMESIZE
# define NET_ADDRESS_LENGTH INET_ADDRSTRLEN
# define IFCONF_LENGTH 10
//# define adjtimex ntp_adjtime
# include <machine/endian.h>
# if BYTE_ORDER == LITTLE_ENDIAN
# define PTPD_LSBF
# elif BYTE_ORDER == BIG_ENDIAN
# define PTPD_MSBF
# endif
#endif
#define CLOCK_IDENTITY_LENGTH 8
#define ADJ_FREQ_MAX 512000
/* UDP/IPv4 dependent */
#define SUBDOMAIN_ADDRESS_LENGTH 4
#define PORT_ADDRESS_LENGTH 2
#define PTP_UUID_LENGTH 6
#define CLOCK_IDENTITY_LENGTH 8
#define FLAG_FIELD_LENGTH 2
#define PACKET_SIZE 1024 //ptpdv1 value kept because of use of TLV...
#define PTP_EVENT_PORT 319
#define PTP_GENERAL_PORT 320
#define DEFAULT_PTP_DOMAIN_ADDRESS "224.0.1.129"
#define PEER_PTP_DOMAIN_ADDRESS "224.0.0.107"
#define MM_STARTING_BOUNDARY_HOPS 0x7fff
/* others */
#define SCREEN_BUFSZ 128
#define SCREEN_MAXSZ 80
#endif /*CONSTANTS_DEP_H_*/
#ifndef DATATYPES_DEP_H_
#define DATATYPES_DEP_H_
#include "ptpd_netif.h"
/**
*\file
* \brief Implementation specific datatype
*/
typedef enum {FALSE=0, TRUE} Boolean;
typedef char Octet;
typedef signed char Integer8;
typedef signed short Integer16;
typedef signed int Integer32;
typedef unsigned char UInteger8;
typedef unsigned short UInteger16;
typedef unsigned int UInteger32;
typedef unsigned short Enumeration16;
typedef unsigned char Enumeration8;
typedef unsigned char Enumeration4;
typedef unsigned char UInteger4;
typedef unsigned char Nibble;
/**
* \brief Implementation specific of UInteger48 type
*/
typedef struct {
unsigned int lsb;
unsigned short msb;
} UInteger48;
/**
* \brief Implementation specific of Integer64 type
*/
typedef struct {
unsigned int lsb;
int msb;
} Integer64;
/**
* \brief Implementation specific of Integer64 type
*/
typedef struct {
unsigned int lsb;
unsigned int msb;
} UInteger64;
/**
* \brief Struct used to average the offset from master
*
* The FIR filtering of the offset from master input is a simple, two-sample average
*/
typedef struct {
Integer32 nsec_prev, y;
} offset_from_master_filter;
/**
* \brief Struct used to average the one way delay
*
* It is a variable cutoff/delay low-pass, infinite impulse response (IIR) filter.
*
* The one-way delay filter has the difference equation: s*y[n] - (s-1)*y[n-1] = x[n]/2 + x[n-1]/2, where increasing the stiffness (s) lowers the cutoff and increases the delay.
*/
typedef struct {
Integer32 nsec_prev, y;
Integer32 s_exp;
} one_way_delay_filter;
/**
* \brief Struct used to store network datas
*/
typedef struct {
wr_socket_t *wrSock;
char ifaceName[IFACE_NAME_LENGTH];
wr_sockaddr_t multicastAddr, peerMulticastAddr,unicastAddr;
} NetPath;
typedef struct {
char if_name[16];
int state;
int next_state;
wr_timestamp_t prev_t4;
wr_timestamp_t mu;
wr_timestamp_t nsec_offset;
int32_t delta_tx_m;
int32_t delta_rx_m;
int32_t delta_tx_s;
int32_t delta_rx_s;
int32_t cur_setpoint;
int64_t delta_ms;
int64_t delta_ms_prev;
wr_timestamp_t t1, t2, t3, t4;
uint64_t last_tics;
} wr_servo_state_t;
#endif /*DATATYPES_DEP_H_*/
This diff is collapsed.
/* net.c */
/*
Here we have some intermediate layer between platform-independent *PTPd* and *ptpd_netif* library
It's not entirely necessary, it is a consequence of the fact that PTPd was adapted from opensource PTPd
*/
#include "../ptpd.h"
#include "ptpd_netif.h"
#include "hal_exports.h"
const mac_addr_t PTP_MULTICAST_ADDR[6] = {0x01, 0x1b, 0x19, 0 , 0, 0};
const mac_addr_t PTP_UNICAST_ADDR[6] = {0x01, 0x1b, 0x19, 0 , 0, 0};
const mac_addr_t ZERO_ADDR[6] = {0x00, 0x00, 0x00, 0x00, 0x001, 0x00};
/* shut down the UDP stuff */
Boolean netShutdown(NetPath *netPath)
{
PERROR("WR: not implemented: %s\n", __FUNCTION__ );
return TRUE;
#if 0
//original implementation
struct ip_mreq imr;
/*Close General Multicast*/
imr.imr_multiaddr.s_addr = netPath->multicastAddr;
imr.imr_interface.s_addr = htonl(INADDR_ANY);
setsockopt(netPath->eventSock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &imr, sizeof(struct ip_mreq));
setsockopt(netPath->generalSock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &imr, sizeof(struct ip_mreq));
/*Close Peer Multicast*/
imr.imr_multiaddr.s_addr = netPath->peerMulticastAddr;
imr.imr_interface.s_addr = htonl(INADDR_ANY);
setsockopt(netPath->eventSock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &imr, sizeof(struct ip_mreq));
setsockopt(netPath->generalSock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &imr, sizeof(struct ip_mreq));
netPath->multicastAddr = 0;
netPath->unicastAddr = 0;
netPath->peerMulticastAddr = 0;
/*Close sockets*/
if(netPath->eventSock > 0)
close(netPath->eventSock);
netPath->eventSock = -1;
if(netPath->generalSock > 0)
close(netPath->generalSock);
netPath->generalSock = -1;
return TRUE;
#endif
}
/*Test if network layer is OK for PTP*/
UInteger8 lookupCommunicationTechnology(UInteger8 communicationTechnology)
{
PERROR("WR: not implemented: %s\n", __FUNCTION__ );
return PTP_DEFAULT;
//original implementation
#if 0
#if defined(linux)
switch(communicationTechnology)
{
case ARPHRD_ETHER:
case ARPHRD_EETHER:
case ARPHRD_IEEE802:
return PTP_ETHER;
default:
break;
}
#elif defined(BSD_INTERFACE_FUNCTIONS)
#endif
return PTP_DEFAULT;
#endif
}
Boolean netStartup()
{
if(ptpd_netif_init() < 0)
return FALSE;
return TRUE;
}
/* start all of the UDP stuff */
/* must specify 'subdomainName', optionally 'ifaceName', if not then pass ifaceName == "" */
/* returns other args */
/* on socket options, see the 'socket(7)' and 'ip' man pages */
Boolean netInit(NetPath *netPath, RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
mac_addr_t portMacAddress[6];
hexp_port_state_t pstate;
// Create a PTP socket:
wr_sockaddr_t bindaddr;
if(rtOpts->ifaceName[ptpClock->portIdentity.portNumber - 1][0] != '\0')
{
/*interface specified at PTPd start*/
strcpy(bindaddr.if_name, rtOpts->ifaceName[ptpClock->portIdentity.portNumber - 1]); // TODO: network intarface
DBG("Network interface : %s\n",rtOpts->ifaceName[ptpClock->portIdentity.portNumber - 1] );
}
else
{
/*
get interface name (port name) for the port
*/
if( ptpd_netif_get_ifName(bindaddr.if_name,ptpClock->portIdentity.portNumber ) == PTPD_NETIF_ERROR )
{
strcpy(bindaddr.if_name,"wru1"); // TODO: network intarface
DBG("Network interface forced to be wru1, but none of the WR ports seems to be up \n");
}
else
DBG("Network interface retrieved automatically by ptpd_netif: %s\n",bindaddr.if_name);
}
strncpy(netPath->ifaceName,bindaddr.if_name,IFACE_NAME_LENGTH);
DBG("Network interface : %s\n",netPath->ifaceName);
bindaddr.family = PTPD_SOCK_RAW_ETHERNET; // socket type
bindaddr.ethertype = 0x88f7; // PTPv2
memcpy(bindaddr.mac, PTP_MULTICAST_ADDR, 6);
// Create one socket for event and general messages (WR lower level layer requires that
netPath->wrSock = ptpd_netif_create_socket(PTPD_SOCK_RAW_ETHERNET, 0, &bindaddr);
if(netPath->wrSock == NULL)
{
PERROR("failed to initalize sockets");
return FALSE;
}
/* send a uni-cast address if specified (useful for testing) */
if(rtOpts->unicastAddress[0])
{
memcpy(netPath->unicastAddr.mac, PTP_UNICAST_ADDR, 6);
}
else
memcpy(netPath->unicastAddr.mac, ZERO_ADDR, 6);
memcpy(netPath->multicastAddr.mac, PTP_MULTICAST_ADDR, 6);
memcpy(netPath->peerMulticastAddr.mac, PTP_MULTICAST_ADDR, 6);
netPath->unicastAddr.ethertype = 0x88f7;
netPath->multicastAddr.ethertype = 0x88f7;
netPath->peerMulticastAddr.ethertype = 0x88f7;
ptpd_netif_get_hw_addr(netPath->wrSock, portMacAddress);
/* copy mac part to uuid */
memcpy(ptpClock->port_uuid_field,portMacAddress, PTP_UUID_LENGTH);
DBG("[%s] mac: %x:%x:%x:%x:%x:%x\n",__func__,\
ptpClock->port_uuid_field[0],\
ptpClock->port_uuid_field[1],\
ptpClock->port_uuid_field[2],\
ptpClock->port_uuid_field[3],\
ptpClock->port_uuid_field[4],\
ptpClock->port_uuid_field[5]);
// fixme: error handling
halexp_get_port_state(&pstate, netPath->ifaceName);
DBG(" netif_WR_mode = %d\n", pstate.mode);
if(rtOpts->wrNodeMode == NON_WR)
{
switch(pstate.mode)
{
case HEXP_PORT_MODE_WR_MASTER:
DBG("wrNodeMode(auto config) ....... MASTER\n");
ptpClock->wrNodeMode = WR_MASTER;
//tmp solution
break;
case HEXP_PORT_MODE_WR_SLAVE:
DBG("wrNodeMode(auto config) ........ SLAVE\n");
ptpClock->wrNodeMode = WR_SLAVE;
ptpd_init_exports();
//tmp solution
break;
case HEXP_PORT_MODE_NON_WR:
default:
DBG("wrNodeMode(auto config) ........ NON_WR\n");
ptpClock->wrNodeMode = NON_WR;
//tmp solution
break;
}
}else
{
ptpClock->wrNodeMode = rtOpts->wrNodeMode;
DBG("wrNodeMode (............ FORCE ON STARTUP\n");
}
DBG("netInit: exiting OK\n");
return TRUE;
}
/*Check if data have been received*/
int netSelect(TimeInternal *timeout, NetPath *netPath)
{
/*
TODO: ptpd_netif_select improve
*/
struct timeval tv, *tv_ptr;
if(timeout)
{
tv.tv_sec = timeout->seconds;
tv.tv_usec = timeout->nanoseconds/1000;
tv_ptr = &tv;
}
else
tv_ptr = 0;
return ptpd_netif_select(netPath->wrSock);
}
/*store received data from network to "buf" , get and store the SO_TIMESTAMP value in "time" for an event message*/
ssize_t netRecvMsg(Octet *buf, NetPath *netPath, wr_timestamp_t *current_rx_ts)
{
wr_sockaddr_t from_addr;
int ret;
if((ret = ptpd_netif_recvfrom(netPath->wrSock, &from_addr, buf, 1518, current_rx_ts)) > 0)
{
//DBG("RX timestamp %s [ret=%d]\n", format_wr_timestamp(*current_rx_ts), ret);
}
return (ssize_t)ret;
}
ssize_t netSendEvent(Octet *buf, UInteger16 length, NetPath *netPath, wr_timestamp_t *current_tx_ts)
{
int ret;
//Send a frame
ret = ptpd_netif_sendto(netPath->wrSock, &netPath->multicastAddr, buf, length, current_tx_ts);
if(ret <= 0)
DBGNPI("error sending multi-cast event message\n");
return (ssize_t)ret;
}
ssize_t netSendGeneral(Octet *buf, UInteger16 length, NetPath *netPath)
{
wr_timestamp_t ts;
int ret;
//Send a frame
ret = ptpd_netif_sendto(netPath->wrSock, &(netPath->multicastAddr), buf, length, &ts);
if(ret <= 0)
DBGNPI("error sending multi-cast event message\n");
return (ssize_t)ret;
}
ssize_t netSendPeerGeneral(Octet *buf,UInteger16 length,NetPath *netPath)
{
int ret;
//Send a frame
ret = ptpd_netif_sendto(netPath->wrSock, &(netPath->multicastAddr), buf, length, NULL);
if(ret <= 0)
DBGNPI("error sending multi-cast general message\n");
return (ssize_t)ret;
}
ssize_t netSendPeerEvent(Octet *buf,UInteger16 length,NetPath *netPath,wr_timestamp_t *current_tx_ts)
{
int ret;
//Send a frame
// ret = ptpd_netif_sendto(netPath->wrSock, &(netPath->multicastAddr), buf, length, current_tx_ts);
if(ret <= 0)
DBGNPI("error sending multi-cast event message\n");
return (ssize_t)ret;
}
This diff is collapsed.
#include "../ptpd.h"
void initClock(RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
}
void updateDelay (one_way_delay_filter *owd_filt, RunTimeOpts *rtOpts, PtpClock *ptpClock,TimeInternal *correctionField)
{
}
void updatePeerDelay (one_way_delay_filter *owd_filt, RunTimeOpts *rtOpts, PtpClock *ptpClock,TimeInternal *correctionField,Boolean twoStep)
{
}
void updateOffset(TimeInternal *send_time, TimeInternal *recv_time,
offset_from_master_filter *ofm_filt, RunTimeOpts *rtOpts, PtpClock *ptpClock,TimeInternal *correctionField)
{
}
void updateClock(RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
}
This diff is collapsed.
/* sys.c */
#include "../ptpd.h"
void displayStats(RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
static int start = 1;
static char sbuf[SCREEN_BUFSZ];
char *s;
int len = 0;
if(start && rtOpts->csvStats)
{
start = 0;
printf("state, one way delay, offset from master, drift");
fflush(stdout);
}
memset(sbuf, ' ', SCREEN_BUFSZ);
switch(ptpClock->portState)
{
case PTP_INITIALIZING: s = "init"; break;
case PTP_FAULTY: s = "flt"; break;
case PTP_LISTENING: s = "lstn"; break;
case PTP_PASSIVE: s = "pass"; break;
case PTP_UNCALIBRATED: s = "uncl"; break;
case PTP_SLAVE: s = "slv"; break;
case PTP_PRE_MASTER: s = "pmst"; break;
case PTP_MASTER: s = "mst"; break;
case PTP_DISABLED: s = "dsbl"; break;
default: s = "?"; break;
}
len += sprintf(sbuf + len, "%s%s", rtOpts->csvStats ? "\n": "\rstate: ", s);
if(ptpClock->portState == PTP_SLAVE)
{
len += sprintf(sbuf + len,
", %s%d.%09d" ", %s%d.%09d",
rtOpts->csvStats ? "" : "owd: ",
ptpClock->meanPathDelay.seconds,
ptpClock->meanPathDelay.nanoseconds,
//abs(ptpClock->meanPathDelay.nanoseconds),
rtOpts->csvStats ? "" : "ofm: ",
ptpClock->offsetFromMaster.seconds,
ptpClock->offsetFromMaster.nanoseconds);
//abs(ptpClock->offsetFromMaster.nanoseconds));
len += sprintf(sbuf + len,
", %s%d" ,
rtOpts->csvStats ? "" : "drift: ", ptpClock->observed_drift);
}
write(1, sbuf, rtOpts->csvStats ? len : SCREEN_MAXSZ + 1);
}
Boolean nanoSleep(TimeInternal *t)
{
struct timespec ts, tr;
ts.tv_sec = t->seconds;
ts.tv_nsec = t->nanoseconds;
if(nanosleep(&ts, &tr) < 0)
{
t->seconds = tr.tv_sec;
t->nanoseconds = tr.tv_nsec;
return FALSE;
}
return TRUE;
}
void getTime(TimeInternal *time)
{
struct timeval tv;
gettimeofday(&tv, 0);
time->seconds = tv.tv_sec;
time->nanoseconds = tv.tv_usec*1000;
}
void setTime(TimeInternal *time)
{
struct timeval tv;
tv.tv_sec = time->seconds;
tv.tv_usec = time->nanoseconds/1000;
settimeofday(&tv, 0);
NOTIFY("resetting system clock to %ds %dns\n", time->seconds, time->nanoseconds);
}
double getRand()
{
return ((rand() * 1.0)/RAND_MAX);
}
Boolean adjFreq(Integer32 adj)
{
//ML
return 0;
/*
struct timex t;
if(adj > ADJ_FREQ_MAX)
adj = ADJ_FREQ_MAX;
else if(adj < -ADJ_FREQ_MAX)
adj = -ADJ_FREQ_MAX;
t.modes = MOD_FREQUENCY;
t.freq = adj*((1<<16)/1000);
return !adjtimex(&t);*/
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <inttypes.h>
#include <sys/time.h>
#include <wr_ipc.h>
#include "ptpd.h"
#include "ptpd_exports.h"
extern int servo_state_valid;
extern ptpdexp_sync_state_t cur_servo_state;
void ptpdexp_get_sync_state(ptpdexp_sync_state_t *state)
{
if(servo_state_valid)
{
memcpy(state, &cur_servo_state, sizeof(ptpdexp_sync_state_t));
state->valid = 1;
} else
state->valid = 0;
}
void ptpdexp_cmd(int cmd, int value)
{
DBG("GotCMd: %d value %d\n", cmd, value);
if(cmd == PTPDEXP_COMMAND_TRACKING)
wr_servo_enable_tracking(value);
if(cmd == PTPDEXP_COMMAND_MAN_ADJUST_PHASE)
wr_servo_man_adjust_phase(value);
}
static wripc_handle_t wripc_srv;
void ptpd_init_exports()
{
wripc_srv = wripc_create_server("ptpd");
wripc_export(wripc_srv, T_STRUCT(ptpdexp_sync_state_t), "ptpdexp_get_sync_state", ptpdexp_get_sync_state, 0);
wripc_export(wripc_srv, T_VOID, "ptpdexp_cmd", ptpdexp_cmd, 2, T_INT32, T_INT32);
}
void ptpd_handle_wripc()
{
wripc_process(wripc_srv);
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment